# PureBasic Forum

 It is currently Wed Jun 03, 2020 3:43 am

 All times are UTC + 1 hour

 Page 1 of 1 [ 5 posts ]
 Print view Previous topic | Next topic
Author Message
 Post subject: OpenGL MatrixPosted: Tue Dec 20, 2011 5:57 am
 Enthusiast

Joined: Sat Jul 09, 2011 7:57 am
Posts: 276
Since opengl 3.0 you must deal with matrix on yourself, this code should provide everything you need.

Turn off #TRACEFUNCTION for disabling the debug tracing.

http://pastebin.com/6tFeNXc2

Code:
; *---------------------------------*
; *   OpenGL Matrix                 *
; *   xorc1zt                       *
; *   2011                          *
; *---------------------------------*

; ** IMPORTANT ** : OpenGL Matrix are column-major ordered
;
;   m[0] m[4] m[8]  m[12]     m[Xx] m[Yx] m[Zx] m[Tx]
;   m[1] m[5] m[9]  m[13]     m[Xy] m[Yy] m[Zy] m[Ty]
;   m[2] m[6] m[10] m[14] ==> m[Xz] m[Yz] m[Zz] m[Tz]
;   m[3] m[7] m[11] m[15]     m[Xw] m[Yw] m[Zw] m[Tw]
;
;

EnableExplicit
#MATRIX_SIZEBYTE = 64 ; 16*float
#TRACEFUNCTION = #False

Macro traceFunction(string)
CompilerIf #TRACEFUNCTION
Debug "[ TRACE ]: "+string
CompilerEndIf
EndMacro

Interface MATRIX
debugValues()
identity()
multiply(MATRIX)
rotateX(angledegree.f)
rotateY(angledegree.f)
rotateZ(angledegree.f)
translate(x.f, y.f, z.f)
perspective(angle.f, near.f, far.f, aspect.f)
orthogonal(left.f, right.f, bottom.f, top.f, near.f, far.f)
lookAt(eyeX.f, eyeY.f, eyeZ.f, centerX.f, centerY.f, centerZ.f, upX.f, upY.f, upZ.f)
push()
pop()
destroy()
EndInterface

Structure PARENTSTR
value.f[16]
*parent.PARENTSTR
EndStructure

Structure MATRIXSTR
VTable.l
value.f[16]
label.s
*parent.PARENTSTR
EndStructure

Enumeration
#Xx
#Xy
#Xz
#Xw
#Yx
#Yy
#Yz
#Yw
#Zx
#Zy
#Zz
#Zw
#Tx
#Ty
#Tz
#Tw
EndEnumeration

Declare   crossProduct( Array *a.f(1), Array *b.f(1), Array *result.f(1))
Declare   normalize(Array *a.f(1))
Declare   debugValues(*Self.MATRIXSTR)
Declare   identity(*Self.MATRIXSTR)
Declare   multiply(*self.MATRIXSTR, *matrix.MATRIXSTR)
Declare   rotateX(*Self.MATRIXSTR, angledegree.f)
Declare   rotateY(*Self.MATRIXSTR, angledegree.f)
Declare   rotateZ(*Self.MATRIXSTR, angledegree.f)
Declare   translate(*Self.MATRIXSTR, x.f, y.f, z.f)
Declare   perspective(*Self.MATRIXSTR, angle.f, near.f, far.f, aspect.f)
Declare   orthogonal(*Self.MATRIXSTR, left.f, right.f, bottom.f, top.f, near.f, far.f)
Declare   lookAt(*Self.MATRIXSTR, eyeX.f, eyeY.f, eyeZ.f, centerX.f, centerY.f, centerZ.f, upX.f, upY.f, upZ.f)
Declare   push(*Self.MATRIXSTR)
Declare   pop(*Self.MATRIXSTR)
Declare   destroy(*Self.MATRIXSTR)
Declare.i createMatrix(label.s)

Procedure crossProduct( Array *a.f(1), Array *b.f(1), Array *result.f(1))
traceFunction("crossProduct()")

*result(0) = ( *a(1) * *b(2) ) - ( *b(1) * *a(2) )
*result(1) = ( *a(2) * *b(0) ) - ( *b(2) * *a(0) )
*result(2) = ( *a(0) * *b(1) ) - ( *b(0) * *a(1) )
EndProcedure

Procedure normalize(Array *a.f(1))
traceFunction("normalize()")

Define mag.f = Sqr( *a(0) * *a(0) + *a(1) * *a(1) + *a(2) * *a(2) )
*a(0) / mag
*a(1) / mag
*a(2) / mag
EndProcedure

Procedure debugValues(*Self.MATRIXSTR)
traceFunction("debugValues()")

Debug "---- MATRIX: "+*self\label+" ----"
Debug StrF( *self\value[#Xx] )+" "+StrF( *self\value[#Yx] )+" "+StrF( *self\value[#Zx] )+" "+StrF( *self\value[#Tx] )
Debug StrF( *self\value[#Xy] )+" "+StrF( *self\value[#Yy] )+" "+StrF( *self\value[#Zy] )+" "+StrF( *self\value[#Ty] )
Debug StrF( *self\value[#Xz] )+" "+StrF( *self\value[#Yz] )+" "+StrF( *self\value[#Zz] )+" "+StrF( *self\value[#Tz] )
Debug StrF( *self\value[#Xw] )+" "+StrF( *self\value[#Yw] )+" "+StrF( *self\value[#Zw] )+" "+StrF( *self\value[#Tw] )
EndProcedure

ProcedureReturn @*self\value[0]
EndProcedure

Procedure identity(*Self.MATRIXSTR)
traceFunction("indentity()")

CompilerIf 1
With *Self
\value[#Xx] = 1
\value[#Xy] = 0
\value[#Xz] = 0
\value[#Xw] = 0

\value[#Yx] = 0
\value[#Yy] = 1
\value[#Yz] = 0
\value[#Yw] = 0

\value[#Zx] = 0
\value[#Zy] = 0
\value[#Zz] = 1
\value[#Zw] = 0

\value[#Tx] = 0
\value[#Ty] = 0
\value[#Tz] = 0
\value[#Tw] = 1
EndWith
CompilerElse
CopyMemory(?MatrixIdentity, @*self\value[0], #MATRIX_SIZEBYTE)
CompilerEndIf
EndProcedure

Procedure multiply(*self.MATRIXSTR, *matrix.MATRIXSTR)
Define tempmatrix.MATRIXSTR

traceFunction("multiply()")

tempmatrix\value[#Xx] = (*self\value[0]  * *matrix\value[0])
tempmatrix\value[#Xx] + (*self\value[4]  * *matrix\value[1])
tempmatrix\value[#Xx] + (*self\value[8]  * *matrix\value[2])
tempmatrix\value[#Xx] + (*self\value[12] * *matrix\value[3])

tempmatrix\value[#Xy] = (*self\value[1]  * *matrix\value[0])
tempmatrix\value[#Xy] + (*self\value[5]  * *matrix\value[1])
tempmatrix\value[#Xy] + (*self\value[9]  * *matrix\value[2])
tempmatrix\value[#Xy] + (*self\value[13] * *matrix\value[3])

tempmatrix\value[#Xz] = (*self\value[2]  * *matrix\value[0])
tempmatrix\value[#Xz] + (*self\value[6]  * *matrix\value[1])
tempmatrix\value[#Xz] + (*self\value[10] * *matrix\value[2])
tempmatrix\value[#Xz] + (*self\value[14] * *matrix\value[3])

tempmatrix\value[#Xw] = (*self\value[3]  * *matrix\value[0])
tempmatrix\value[#Xw] + (*self\value[7]  * *matrix\value[1])
tempmatrix\value[#Xw] + (*self\value[11] * *matrix\value[2])
tempmatrix\value[#Xw] + (*self\value[15] * *matrix\value[3])

tempmatrix\value[#Yx] = (*self\value[0]  * *matrix\value[4])
tempmatrix\value[#Yx] + (*self\value[4]  * *matrix\value[5])
tempmatrix\value[#Yx] + (*self\value[8]  * *matrix\value[6])
tempmatrix\value[#Yx] + (*self\value[12] * *matrix\value[7])

tempmatrix\value[#Yy] = (*self\value[1]  * *matrix\value[4])
tempmatrix\value[#Yy] + (*self\value[5]  * *matrix\value[5])
tempmatrix\value[#Yy] + (*self\value[9]  * *matrix\value[6])
tempmatrix\value[#Yy] + (*self\value[13] * *matrix\value[7])

tempmatrix\value[#Yz] = (*self\value[2]  * *matrix\value[4])
tempmatrix\value[#Yz] + (*self\value[6]  * *matrix\value[5])
tempmatrix\value[#Yz] + (*self\value[10] * *matrix\value[6])
tempmatrix\value[#Yz] + (*self\value[14] * *matrix\value[7])

tempmatrix\value[#Yw] = (*self\value[3]  * *matrix\value[4])
tempmatrix\value[#Yw] + (*self\value[7]  * *matrix\value[5])
tempmatrix\value[#Yw] + (*self\value[11] * *matrix\value[6])
tempmatrix\value[#Yw] + (*self\value[15] * *matrix\value[7])

tempmatrix\value[#Zx] = (*self\value[0]  * *matrix\value[8])
tempmatrix\value[#Zx] + (*self\value[4]  * *matrix\value[9])
tempmatrix\value[#Zx] + (*self\value[8]  * *matrix\value[10])
tempmatrix\value[#Zx] + (*self\value[12] * *matrix\value[11])

tempmatrix\value[#Zy] = (*self\value[1]  * *matrix\value[8])
tempmatrix\value[#Zy] + (*self\value[5]  * *matrix\value[9])
tempmatrix\value[#Zy] + (*self\value[9]  * *matrix\value[10])
tempmatrix\value[#Zy] + (*self\value[13] * *matrix\value[11])

tempmatrix\value[#Zz] = (*self\value[2]  * *matrix\value[8])
tempmatrix\value[#Zz] + (*self\value[6]  * *matrix\value[9])
tempmatrix\value[#Zz] + (*self\value[10] * *matrix\value[10])
tempmatrix\value[#Zz] + (*self\value[14] * *matrix\value[11])

tempmatrix\value[#Zw] = (*self\value[3]  * *matrix\value[8])
tempmatrix\value[#Zw] + (*self\value[7]  * *matrix\value[9])
tempmatrix\value[#Zw] + (*self\value[11] * *matrix\value[10])
tempmatrix\value[#zw] + (*self\value[15] * *matrix\value[11])

tempmatrix\value[#Tx] = (*self\value[0]  * *matrix\value[12])
tempmatrix\value[#Tx] + (*self\value[4]  * *matrix\value[13])
tempmatrix\value[#Tx] + (*self\value[8]  * *matrix\value[14])
tempmatrix\value[#Tx] + (*self\value[12] * *matrix\value[15])

tempmatrix\value[#Ty] = (*self\value[1]  * *matrix\value[12])
tempmatrix\value[#Ty] + (*self\value[5]  * *matrix\value[13])
tempmatrix\value[#Ty] + (*self\value[9]  * *matrix\value[14])
tempmatrix\value[#Ty] + (*self\value[13] * *matrix\value[15])

tempmatrix\value[#Tz] = (*self\value[2]  * *matrix\value[12])
tempmatrix\value[#Tz] + (*self\value[6]  * *matrix\value[13])
tempmatrix\value[#Tz] + (*self\value[10] * *matrix\value[14])
tempmatrix\value[#Tz] + (*self\value[14] * *matrix\value[15])

tempmatrix\value[#Tw] = (*self\value[3]  * *matrix\value[12])
tempmatrix\value[#Tw] + (*self\value[7]  * *matrix\value[13])
tempmatrix\value[#Tw] + (*self\value[11] * *matrix\value[14])
tempmatrix\value[#Tw] + (*self\value[15] * *matrix\value[15])

CopyMemory(@tempmatrix\value[0], @*self\value[0], #MATRIX_SIZEBYTE)
EndProcedure

Procedure rotateX(*Self.MATRIXSTR, angledegree.f)
Define tempmatrix.MATRIXSTR
Define sine.f
Define cosine.f

traceFunction("rotateX()")

sine = Sin(angledegree)
cosine = Cos(angledegree)

identity(tempmatrix)

With tempmatrix
\value[#Yy] = cosine
\value[#Yz] = -sine
\value[#Zy] = sine
\value[#Zz] = cosine
EndWith

multiply(*self, tempmatrix)
EndProcedure

Procedure rotateY(*Self.MATRIXSTR, angledegree.f)
Define tempmatrix.MATRIXSTR
Define sine.f
Define cosine.f

traceFunction("rotateY()")

sine = Sin(angledegree)
cosine = Cos(angledegree)

identity(tempmatrix)

With tempmatrix
\value[#Xx] = cosine
\value[#Zx] = sine
\value[#Xz] = -sine
\value[#Zz] = cosine
EndWith

multiply(*self, tempmatrix)
EndProcedure

Procedure rotateZ(*Self.MATRIXSTR, angledegree.f)
Define tempmatrix.MATRIXSTR
Define sine.f
Define cosine.f

traceFunction("rotateZ()")

sine = Sin(angledegree)
cosine = Cos(angledegree)

identity(tempmatrix)

With tempmatrix
\value[#Xx] = cosine
\value[#Xy] = -sine
\value[#Yx] = sine
\value[#Yy] = cosine
EndWith

multiply(*self, tempmatrix)
EndProcedure

Procedure translate(*Self.MATRIXSTR, x.f, y.f, z.f)
Define tempmatrix.MATRIXSTR

traceFunction("translate()")

identity(tempmatrix)

With tempmatrix
\value[#Tx] = x
\value[#Ty] = y
\value[#Tz] = z
EndWith

multiply(*self, tempmatrix)
EndProcedure

Procedure perspective(*Self.MATRIXSTR, angle.f, near.f, far.f, aspect.f)
Define y_scale.f
Define x_scale.f
Define frustum_length.f

traceFunction("perspective()")

x_scale = y_scale/aspect
frustum_length = (far-near)

With *self
\value[#Xx] = x_scale
\value[#Yy] = y_scale
\value[#Zz] = -( (near+far)/frustum_length )
\value[#Zw] = -1
\value[#Tz] = -( (2*near*far)/frustum_length )

\value[#Xy] = 0
\value[#Xz] = 0
\value[#Xw] = 0
\value[#Yx] = 0
\value[#Yz] = 0
\value[#Yw] = 0
\value[#Zx] = 0
\value[#Zy] = 0
\value[#Tx] = 0
\value[#Ty] = 0
\value[#Tw] = 0
EndWith
EndProcedure

Procedure orthogonal(*Self.MATRIXSTR, left.f, right.f, bottom.f, top.f, near.f, far.f)
traceFunction("orthogonal()")

With *Self
\value[#Xx] = 2/(right-left)
\value[#Yy] = 2/(top-bottom)
\value[#Zz] = -2/(far-near)
\value[#Tx] = -( (right+left)/(right-left) )
\value[#Ty] = -( (top+bottom)/(top-bottom) )
\value[#Tz] = -( (far+near)/(far-near) )
\value[#Tw] = 1

\value[#Xy] = 0
\value[#Xz] = 0
\value[#Xw] = 0
\value[#Yx] = 0
\value[#Yz] = 0
\value[#Yw] = 0
\value[#Zx] = 0
\value[#Zy] = 0
EndWith
EndProcedure

Procedure lookAt(*Self.MATRIXSTR, eyeX.f, eyeY.f, eyeZ.f, centerX.f, centerY.f, centerZ.f, upX.f, upY.f, upZ.f)
Dim axe.f(2)
Dim regard.f(2)
Dim normal.f(2)
Dim newaxe.f(2)
Define tempmatrix.MATRIXSTR

traceFunction("lookAt()")

axe(0) = upX
axe(1) = upY
axe(2) = upZ
regard(0) = centerX-eyeX
regard(1) = centerY-eyeY
regard(2) = centerZ-eyeZ

crossProduct( regard(), axe(), normal() )
crossProduct( normal(), regard(), newaxe() )

normalize( normal() )
normalize( newaxe() )
normalize( regard() )

With tempmatrix
\value[#Xx] = normal(0)
\value[#Xy] = newaxe(0)
\value[#Xz] = -regard(0)
\value[#Yx] = normal(1)
\value[#Yy] = newaxe(1)
\value[#Yz] = -regard(1)
\value[#Zx] = normal(2)
\value[#Zy] = newaxe(2)
\value[#Zz] = -regard(2)
\value[#Tw] = 1.0
EndWith

multiply(*self, tempmatrix)
translate(*self, -eyeX, -eyeY, -eyeZ)
EndProcedure

Procedure push(*Self.MATRIXSTR)
Define *tempstr.PARENTSTR = AllocateMemory( SizeOf(PARENTSTR) )

traceFunction("push()")
CopyMemory(@*Self\value[0], @*tempstr\value[0], #MATRIX_SIZEBYTE)

If *Self\parent
*tempstr\parent = *Self\parent
EndIf

*Self\parent = *tempstr
EndProcedure

Procedure pop(*Self.MATRIXSTR)
Define *tempstr.PARENTSTR = *Self\parent

traceFunction("pop()")

If Not *Self\parent
Debug "No matrix to restore"
ProcedureReturn
EndIf

CopyMemory(@*tempstr\value[0], @*Self\value[0], #MATRIX_SIZEBYTE)

If *tempstr\parent
*Self\parent = *tempstr\parent
Else
*self\parent = #Null
EndIf

FreeMemory(*tempstr)
EndProcedure

Procedure destroy(*Self.MATRIXSTR)
traceFunction("destroy()")
FreeMemory(*self)
EndProcedure

Procedure.i createMatrix(label.s)
Define *temp.MATRIXSTR

traceFunction("createMatrix()")

*temp.MATRIXSTR = AllocateMemory( SizeOf( MATRIXSTR ) )
*temp\VTable = ?VTable
*temp\label = label
ProcedureReturn *temp
EndProcedure

DataSection
VTable:
Data.l @debugValues()
Data.l @identity()
Data.l @multiply()
Data.l @rotateX()
Data.l @rotateY()
Data.l @rotateZ()
Data.l @translate()
Data.l @perspective()
Data.l @orthogonal()
Data.l @lookAt()
Data.l @push()
Data.l @pop()
Data.l @destroy()

MatrixIdentity:
Data.f 1, 0, 0, 0
Data.f 0, 1, 0, 0
Data.f 0, 0, 1, 0
Data.f 0, 0, 0, 1
EndDataSection

here is a example of use
Code:
;-- example --
Define projection.MATRIX = CreateMatrix("projection")
Define modelview.MATRIX = CreateMatrix("modelview")

projection\identity()
modelview\identity()

projection\perspective(75, 1, 100, 800/600)
modelview\lookAt(5, 5, 5, 0, 0, 0, 0, 1, 0 )

projection\debugValues()
modelview\debugValues()

projection\destroy()

; projection\debugValues()  *** Will produce a crash because projection is no more ***

Code:
glUniformMatrix4fv( glGetUniformLocation(programgl_id, "projection"), 1, #GL_FALSE, projection\getAddress() )

Top

 Post subject: Re: OpenGL MatrixPosted: Tue Dec 20, 2011 5:29 pm
 Enthusiast

Joined: Sat Jul 09, 2011 7:57 am
Posts: 276
added a stack with push() and pop() like opengl 1.1

Code:
Procedure push(*Self.MATRIXSTR)
Define *tempstr.PARENTSTR = AllocateMemory( SizeOf(PARENTSTR) )

traceFunction("push()")
CopyMemory(@*Self\value[0], @*tempstr\value[0], #MATRIX_SIZEBYTE)

If *Self\parent
*tempstr\parent = *Self\parent
EndIf

*Self\parent = *tempstr
EndProcedure

Procedure pop(*Self.MATRIXSTR)
Define *tempstr.PARENTSTR = *Self\parent

traceFunction("pop()")

If Not *Self\parent
Debug "No matrix to restore"
ProcedureReturn
EndIf

CopyMemory(@*tempstr\value[0], @*Self\value[0], #MATRIX_SIZEBYTE)

If *tempstr\parent
*Self\parent = *tempstr\parent
Else
*self\parent = #Null
EndIf

FreeMemory(*tempstr)
EndProcedure

Top

 Post subject: Re: OpenGL MatrixPosted: Tue Dec 20, 2011 7:38 pm

Joined: Wed Aug 31, 2005 11:09 pm
Posts: 3698
Location: Italy
Thanks for sharing it

_________________

Top

 Post subject: Re: OpenGL MatrixPosted: Tue Dec 20, 2011 7:55 pm
 Always Here

Joined: Fri Oct 23, 2009 2:33 am
Posts: 6188
Location: Wales, UK
Excellent stuff - I think it really belongs in the Game Math post.

_________________
IdeasVacuum
If it sounds simple, you have not grasped the complexity.

Top

 Post subject: Re: OpenGL MatrixPosted: Thu Feb 23, 2017 7:57 pm
 Enthusiast

Joined: Tue Jan 31, 2006 9:43 am
Posts: 495
Location: France
Thank you VERY much ! (6 years later )

_________________
Niffo

Top

 Display posts from previous: All posts1 day7 days2 weeks1 month3 months6 months1 year Sort by AuthorPost timeSubject AscendingDescending
 Page 1 of 1 [ 5 posts ]

 All times are UTC + 1 hour

#### Who is online

Users browsing this forum: No registered users and 2 guests

 You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forum

Search for:
 Jump to:  Select a forum ------------------ PureBasic    Coding Questions    Game Programming    3D Programming    Assembly Programming    The PureBasic Editor    The PureBasic Form Designer    General Discussion    Feature Requests and Wishlists    Tricks 'n' Tips Bug Reports    Bugs - Windows    Bugs - Linux    Bugs - Mac OSX    Bugs - IDE    Bugs - Documentation OS Specific    AmigaOS    Linux    Windows    Mac OSX Miscellaneous    Announcement    Off Topic Showcase    Applications - Feedback and Discussion    PureFORM & JaPBe    TailBite