I was looking through the source and I noticed that bone rotations are done with quaternions. is there any chance you could do entity rotations with quaternions please?
heres a demo:
Type Entity
' X/Y/Z camera position
Field X:Float
Field Y:Float
Field Z:Float
' X/Y/Z camera rotation
Field RX:Float
Field RY:Float
Field RZ:Float
Field LocalMatrix:Float[16]
Field vertx:Float[1000]
Field verty:Float[1000]
Field vertz:Float[1000]
Field vertexists[1000]
Field normalx:Float[1000]
Field normaly:Float[1000]
Field normalz:Float[1000]
Field normalexists[1000]
Method CalcTransformation:Int ( Inverse:Int, Apply:Int, Save:Int )
If Not Apply Then glPushMatrix
Local M:Float[16]
If Not Inverse Then
Local qRX:TQuaternion = TQuaternion.CreateFromAxisAngle(1.0, 0.0, 0.0, -Self.RX)
Local qRY:TQuaternion = TQuaternion.CreateFromAxisAngle(0.0, 1.0, 0.0, -Self.RY)
Local qRZ:TQuaternion = TQuaternion.CreateFromAxisAngle(0.0, 0.0, 1.0, -Self.RZ)
Local qRes1:TQuaternion = qRX.Multiply(qRY)
Local qRes:TQuaternion = qRes1.Multiply(qRZ)
qRes.CreateMatrix(Varptr M[0])
glMultMatrixf M
glTranslatef -Self.X, -Self.Y, -Self.Z
Else
Local qRX:TQuaternion = TQuaternion.CreateFromAxisAngle(1.0, 0.0, 0.0, Self.RX)
Local qRY:TQuaternion = TQuaternion.CreateFromAxisAngle(0.0, 1.0, 0.0, Self.RY)
Local qRZ:TQuaternion = TQuaternion.CreateFromAxisAngle(0.0, 0.0, 1.0, Self.RZ)
Local qRes1:TQuaternion = qRZ.Multiply(qRY)
Local qRes:TQuaternion = qRes1.Multiply(qRX)
qRes.CreateMatrix(Varptr M[0])
glTranslatef Self.X, Self.Y, Self.Z
glMultMatrixf M
EndIf
If Save Then glGetFloatv(GL_MODELVIEW_MATRIX, Self.LocalMatrix)
If Not Apply Then glPopMatrix
End Method
Method SaveTransformation:Int ( Inverse:Int=False )
CalcTransformation Inverse, False, True
End Method
Method add_floor_verts()
normalexists[0]=True
normaly[0]=1.0
normalz[0]=0.5
vertexists[0]=True
VertX[0]= -10.0
verty[0]= -1.5
vertz[0]= -10.0
vertexists[1]=True
VertX[1]= -10.0
verty[1]= -1.5
vertz[1]= 10.0
vertexists[2]=True
VertX[2]= 10.0
verty[2]= -1.5
vertz[2]= 10.0
vertexists[3]=True
VertX[3]= 10.0
verty[3]= -1.5
vertz[3]= -10.0
EndMethod
Method add_cube_Verts()
normalexists[0]=True
Normaly[0]=1
vertexists[0]=True
VertX[0]= -1.0
verty[0]= -1.0
vertz[0]= 1.0
vertexists[1]=True
Vertx[1]=1.0
verty[1]=-1.0
verty[1]=1.0
vertexists[2]=True
Vertx[2]= 1.0
verty[2]= 1.0
vertz[2]= 1.0
vertexists[3]=True
Vertx [3]=-1.0
verty[3]= 1.0
vertz[3]= 1.0
EndMethod
Method Move ( MoveX:Float, MoveY:Float, MoveZ:Float, AttendLocalMatrix:Int=True )
' create a movement Vector
Local V:Float[4] ; V[0]=MoveX ; V[1]=MoveY ; V[2]=MoveZ
If AttendLocalMatrix Then
glLoadIdentity
Self.SaveTransformation True
VectorMatrixMultiply(Varptr V[0], Varptr Self.LocalMatrix[0])
EndIf
Self.X = Self.X + V[0]
Self.Y = Self.Y + V[1]
Self.Z = Self.Z + V[2]
End Method
EndType
Type TCamera
Field X:Float
Field Y:Float
Field Z:Float
Field RX:Float
Field RY:Float
Field RZ:Float
Field FOV:Float
Field Aspect:Float
Field Near:Float
Field Far:Float
Field LocalMatrix:Float[16]
Function Create:TCamera ( GraphWidth:Int, GraphHeight:Int, FOV:Float=45.0 )
Local C:TCamera = New TCamera
C.FOV = FOV
C.Aspect = Float(GraphWidth) / Float(GraphHeight)
C.Near = 0.1
C.Far = 100
Return C
End Function
Method Move ( MoveX:Float, MoveY:Float, MoveZ:Float, AttendLocalMatrix:Int=True )
Local V:Float[4] ; V[0]=MoveX ; V[1]=MoveY ; V[2]=MoveZ
If AttendLocalMatrix Then
glLoadIdentity
Self.SaveTransformation True
VectorMatrixMultiply(Varptr V[0], Varptr Self.LocalMatrix[0])
EndIf
Self.X = Self.X + V[0]
Self.Y = Self.Y + V[1]
Self.Z = Self.Z + V[2]
End Method
Method Turn ( TurnX:Float, TurnY:Float, TurnZ:Float, AttendLocalMatrix:Int=True )
Local V:Float[4] ; V[0]=TurnX ; V[1]=TurnY ; V[2]=TurnZ
If AttendLocalMatrix Then
glLoadIdentity
Self.SaveTransformation True
VectorMatrixMultiply(Varptr V[0], Varptr Self.LocalMatrix[0])
EndIf
Self.RX = (Self.RX + V[0]) Mod 360
Self.RY = (Self.RY + V[1]) Mod 360
Self.RZ = (Self.RZ + V[2]) Mod 360
End Method
Method ApplyProjection:Int ( )
gluPerspective Self.FOV, Self.Aspect, Self.Near, Self.Far
End Method
Method ApplyTransformation:Int ( Inverse:Int=False )
CalcTransformation Inverse, True, False
End Method
Method SaveTransformation:Int ( Inverse:Int=False )
CalcTransformation Inverse, False, True
End Method
Method CalcTransformation:Int ( Inverse:Int, Apply:Int, Save:Int )
If Not Apply Then glPushMatrix
Local M:Float[16]
If Not Inverse Then
Local qRX:TQuaternion = TQuaternion.CreateFromAxisAngle(1.0, 0.0, 0.0, -Self.RX)
Local qRY:TQuaternion = TQuaternion.CreateFromAxisAngle(0.0, 1.0, 0.0, -Self.RY)
Local qRZ:TQuaternion = TQuaternion.CreateFromAxisAngle(0.0, 0.0, 1.0, -Self.RZ)
Local qRes1:TQuaternion = qRX.Multiply(qRY)
Local qRes:TQuaternion = qRes1.Multiply(qRZ)
qRes.CreateMatrix(Varptr M[0])
glMultMatrixf M
glTranslatef -Self.X, -Self.Y, -Self.Z
Else
Local qRX:TQuaternion = TQuaternion.CreateFromAxisAngle(1.0, 0.0, 0.0, Self.RX)
Local qRY:TQuaternion = TQuaternion.CreateFromAxisAngle(0.0, 1.0, 0.0, Self.RY)
Local qRZ:TQuaternion = TQuaternion.CreateFromAxisAngle(0.0, 0.0, 1.0, Self.RZ)
Local qRes1:TQuaternion = qRZ.Multiply(qRY)
Local qRes:TQuaternion = qRes1.Multiply(qRX)
qRes.CreateMatrix(Varptr M[0])
glTranslatef Self.X, Self.Y, Self.Z
glMultMatrixf M
EndIf
If Save Then glGetFloatv(GL_MODELVIEW_MATRIX, Self.LocalMatrix)
If Not Apply Then glPopMatrix
End Method
'#End Region
End Type
Type TQuaternion
Field X:Float
Field Y:Float
Field Z:Float
Field W:Float
Function CreateFromAxisAngle:TQuaternion ( X:Float,Y:Float,Z:Float, Deg:Float )
Local Quat:TQuaternion = New TQuaternion
Local Angle:Float = Deg
Local Result:Float = Sin(Angle/2.0)
Quat.W = Cos(Angle/2.0)
Quat.X = X * Result
Quat.Y = Y * Result
Quat.Z = Z * Result
Return Quat
End Function
Method Multiply:TQuaternion ( Q2:TQuaternion )
Local Q1:TQuaternion = Self
Local Result:TQuaternion = New TQuaternion
Result.W = Q1.W*Q2.W - Q1.X*Q2.X - Q1.Y*Q2.Y - Q1.Z*Q2.Z
Result.X = Q1.W*Q2.X + Q1.X*Q2.W + Q1.Y*Q2.Z - Q1.Z*Q2.Y
Result.Y = Q1.W*Q2.Y + Q1.Y*Q2.W + Q1.Z*Q2.X - Q1.X*Q2.Z
Result.Z = Q1.W*Q2.Z + Q1.Z*Q2.W + Q1.X*Q2.Y - Q1.Y*Q2.X
Return Result
End Method
Method CreateMatrix ( M:Float Ptr )
Local Q:TQuaternion = Self
M[ 0] = 1.0 - 2.0 * ( Q.Y * Q.Y + Q.Z * Q.Z )
M[ 1] = 2.0 * (Q.X * Q.Y + Q.Z * Q.W)
M[ 2] = 2.0 * (Q.X * Q.Z - Q.Y * Q.W)
M[ 3] = 0.0
M[ 4] = 2.0 * ( Q.X * Q.Y - Q.Z * Q.W )
M[ 5] = 1.0 - 2.0 * ( Q.X * Q.X + Q.Z * Q.Z )
M[ 6] = 2.0 * (Q.Z * Q.Y + Q.X * Q.W )
M[ 7] = 0.0
M[ 8] = 2.0 * ( Q.X * Q.Z + Q.Y * Q.W )
M[ 9] = 2.0 * ( Q.Y * Q.Z - Q.X * Q.W )
M[10] = 1.0 - 2.0 * ( Q.X * Q.X + Q.Y * Q.Y )
M[11] = 0.0
M[12] = 0
M[13] = 0
M[14] = 0
M[15] = 1.0
End Method
End Type
' Helper function which multiplicates a vector with a matrix.
Function VectorMatrixMultiply(V:Float Ptr, M:Float Ptr)
Local Res:Float[4]
Res[0] = M[ 0]*V[0] + M[ 4]*V[1] + M[ 8]*V[2] + M[12]*V[3]
Res[1] = M[ 1]*V[0] + M[ 5]*V[1] + M[ 9]*V[2] + M[13]*V[3]
Res[2] = M[ 2]*V[0] + M[ 6]*V[1] + M[10]*V[2] + M[14]*V[3]
Res[3] = M[ 3]*V[0] + M[ 7]*V[1] + M[11]*V[2] + M[15]*V[3]
V[0] = Res[0]
V[1] = Res[1]
V[2] = Res[2]
V[3] = Res[3]
End Function
' Example of usage
InitGL
Global Camera:TCamera = TCamera.Create(800, 600)
Camera.Z = 5
Global cube:entity=New entity
cube.add_cube_verts()
Global Floorent:entity=New entity
Floorent.add_floor_verts()
MoveMouse 400,300 ; Global PMX:Int = MouseX(), PMY:Int = MouseY()
HideMouse()
While Not KeyHit(KEY_ESCAPE)
' Clear OpenGL Color and Depth Buffer.
glClear GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
' Apply camera projection and transformation.
glMatrixMode GL_PROJECTION
glLoadIdentity
Camera.ApplyProjection
glMatrixMode GL_MODELVIEW
glLoadIdentity
Camera.CalcTransformation False, True, True 'non-inverse matrix
' Update light position
glLightfv GL_LIGHT0, GL_POSITION, [2.5, 0.7, 1.7, 0.0]
CUBE.CALCTRANSFORMATION True,True,True
' Draw the scene
Drawcube
glloadidentity
camera.calctransformation False,True,True
Floorent.calctransformation True,True,True
drawfloor
' Text
glColor4f 1.0, 1.0, 1.0, 1.0
glDisable GL_LIGHTING
GLDrawText "W, A, S, D and Mouse to move", 10, 10
GLDrawText "KP+ and KP- to change FOV: " + String(Int(Camera.FOV)) + " Degrees", 10, 30
GLDrawText "ESC to Exit", 10, 50
glEnable GL_LIGHTING
' Swap buffers
Flip
' Controls
Local MOVE_SPEED:Float = 0.05
If KeyDown(KEY_A) Then camera.Move(-MOVE_SPEED, 0.0, 0.0)
If KeyDown(KEY_D) Then Camera.Move( MOVE_SPEED, 0.0, 0.0)
If KeyDown(KEY_W) Then Camera.Move( 0.0, 0.0,-MOVE_SPEED)
If KeyDown(KEY_S) Then Cube.Move( 0.0, 0.0, MOVE_SPEED)
If KeyDown(KEY_NUMADD) Then Camera.FOV :+ .05
If KeyDown(KEY_NUMSUBTRACT) Then Camera.FOV :- .05
Local MouseXSpeed:Int=MouseX()-PMX
Local MouseYSpeed:Int=MouseY()-PMY
MoveMouse 400,300; PMX=MouseX(); PMY=MouseY()
Camera.Turn(0.1*Float(-MouseYSpeed),0.1*Float(-MouseXSpeed),0,False)
If Camera.RX < -90 Then Camera.RX = -90
If Camera.RX > 90 Then Camera.RX = 90
Wend
Function InitGL()
GLGraphics 800, 600, 0
glClearColor 0.35686, 0.13333, 0.08627, 1.0
glEnable GL_DEPTH_TEST
glEnable GL_LIGHTING
glEnable GL_LIGHT0
glLightfv GL_LIGHT0, GL_AMBIENT, [0.2, 0.2, 0.2, 1.0]
glLightfv GL_LIGHT0, GL_DIFFUSE, [0.8, 0.8, 0.8, 1.0]
glLightfv GL_LIGHT0, GL_SPECULAR, [1.0, 1.0, 1.0, 1.0]
End Function
Function drawfloor()
glenable GL_LIGHTING
glColor3f 1.0, 1.0, 1.0
' Cube and Floor
glBegin GL_QUADS
For Local x=0 To floorent.vertx.length-1
If floorent.vertexists[x]=True
glvertex3f floorent.vertx[x],floorent.verty[x],floorent.vertz[x]
EndIf
Next
glend
EndFunction
Function Drawcube()
glEnable GL_LIGHTING
glColor3f 1.0, 1.0, 1.0
' Cube and Floor
glBegin GL_QUADS
' Front Face
glnormal3f cube.normalx[0],cube.normaly[0],cube.normalz[0]
For Local x=0 To cube.vertx.length-1
If cube.vertexists[x]=True
glvertex3f cube.vertx[x],cube.verty[x],cube.vertz[x]
EndIf
Next
' Floor
glEnd
End Function
If you press S the triangle will move as an entity if you press W A or D the camera will move independently and the triangle will keep its position in space
|