| 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
 
 
 |