How to 'Point' a matrix?

BlitzMax Forums/BlitzMax Programming/How to 'Point' a matrix?

AntonyWells(Posted 2005) [#1]
I've nicked some of trinity's matrix stuff for the basis of v2's entity system. It's working fine, with sub-entities etc, but I really need to figure out how to point a matrix towards a point in 3d space.

Any links or tutorials or even code that cover this or anyone here know?

Here's the matrix code as is, fairly simple, but works.
Type Matrix
	
	Method New()
	
		Mat=New Double[16]
			
	End Method
	
	Method Delete()
	
	'	Release Mat
		Mat=Null
	
	End Method
	
	Method Identity()
	
		Local Index:Int
		
		Mat[ 0 ] = 1
		For Index=1 To 15
			Mat[ Index ]=0
		Next
	
	End Method
	
	Method Pitch( nPitch:Double )
	
		Self.Identity()
		mat[5]=Cos( nPitch )
		mat[6]=Sin( nPitch )
		mat[9]=-Sin( nPitch )
	    mat[10]=Cos( nPitch )
	    mat[15]=1
	
	End Method
	
	Method Yaw( nYaw:Double )
	
	   Self.Identity()
		mat[0]=Cos( nYaw )
		mat[2]=-Sin( nYaw )
		mat[5]=1
		mat[8]=Sin( nYaw )
		Mat[10]=Cos( nYaw )
	
	End Method
	
	Method Roll( nRoll:Double )
	
	   Self.Identity()
		mat[0]=Cos( nRoll )
		mat[1]=Sin( nRoll )
		mat[4]=-Sin( nRoll )
		mat[5]=Cos( nRoll )
	
	End Method
		
	Method Position( nX:Double,nY:Double,nZ:Double )
	
		Self.Identity()
		mat[0] = 1
		mat[3] = nX
		mat[5] = 1
		mat[7] = nY
		mat[11] = nZ
		mat[15] = 1
	
	End Method
	
	Method Copy( IN:Matrix)
	
	   Local Index:Int,Val:Double
	
	   For Index=0 To 15
		Mat[Index]=IN.Mat[Index]
	   Next	
	
	End Method
	
	Method Rotate( nPitch:Double,nYaw:Double,nRoll:Double,X:Double=0,Y:Double=0,Z:Double=0 )
		
		Self.identity()
		Local Temp:Matrix = New Matrix
				
		Self.Pitch( nPitch )
		Temp.Copy( Self )
		Self.Yaw( nYaw ) 
		Temp.Multiply( Self )
		Self.Roll( nRoll )
		Temp.Multiply( Self )
		Self.Position( X,Y,Z )
		Temp.Multiply( Self )
		
		Self.Copy( Temp )
		
	End Method
		
	Method TForm_Point( X:Double,Y:Double,Z:Double )
	
		tFormX = (mat[0] * X) + (mat[1] * Y) + (mat[2] * Z) + mat[3]
		tFormY = (mat[4] * X) + (mat[5] * Y) + (mat[6] * Z) + mat[7]
		tFormZ = (mat[8] * X) + (mat[9] * Y) + (Mat[10] * Z) + mat[11]
	
	End Method
	
	Method TForm_Point2D( X:Double,Y:Double )
		
		Local Z=0
		tFormX = (mat[0] * X) + (mat[1] * Y) + (mat[2] * Z) + mat[3]
		tFormY = (mat[4] * X) + (mat[5] * Y) + (mat[6] * Z) + mat[7]
		
	End Method
	
	
	
	Method Multiply( With:Matrix )
	
		Local Temp:Matrix = New Matrix
		Local M:Int,m1:Int,m2:Int
	
		For m=0 To 3
			For m1=0 To 3
				Temp.Mat[ m1*4+m]=0
				For m2=0 To 3
					Temp.Mat[ m1*4+m]:+With.Mat[m2*4+m]*Mat[m1*4+m2]
				Next
			Next
	   Next
	
	   Local Index:Int,Val:Double 
	
	   For Val:Double =EachIn Temp.mat
		Mat[Index]=Val
		Index:+1
	   Next
	   'Release Temp
	
	End Method
	
	Method Debug( PrintFunc:Int(Out:String) )
		
		For Local J=0 To 15
			
			printFunc (J+1)+":"+Mat[J]
			
		Next
			
	End Method
	
	Field Mat:Double[]
	Field tFormX:Double,tFormY:Double,tFormZ:Double,tW:Double
End Type




Sweenie(Posted 2005) [#2]
This is how DirectX's MatrixLookat function works...

zaxis = normal(At - Eye)
xaxis = normal(cross(Up, zaxis))
yaxis = cross(zaxis, xaxis)

 xaxis.x           yaxis.x           zaxis.x          0
 xaxis.y           yaxis.y           zaxis.y          0
 xaxis.z           yaxis.z           zaxis.z          0
-dot(xaxis, eye)  -dot(yaxis, eye)  -dot(zaxis, eye)  1



AntonyWells(Posted 2005) [#3]
Thanks.

I'm a little bit confused tbh..never used directx code before. Would still be grateful for any help people have on this.


Sweenie(Posted 2005) [#4]
zaxis, xaxis and yaxis are three vectors.
At is a vector defining the lookat/target position.
Up is a vector defining what axis is considered to be "Up".
Eye is a vector defining what position you are looking from.
zaxis = differencevector(At - Eye) normalized.
xaxis = Normalized crossproduct of Up and zaxis
yaxis = crossproduct of zaxis and xaxis.

Then put the resulting x,y & z values from these vectors in the matrix(as above).
-dot(xaxis,eye) = dotproduct of xaxis and eye
-dot(yaxis,eye) = dotproduct of yaxis and eye
-dot(zaxis,eye) = dotproduct of zaxis and eye

I believe a DirectX Transformmatrix looks different from an OpenGL matrix.
Is the OpenGL transformmatrix a Transposed DirectX Matrix?


Sweenie(Posted 2005) [#5]
Or if you could get your hands on the sourcecode for the gluLookAt() function.


AntonyWells(Posted 2005) [#6]
Thanks again, it makes sense now. Not sure on any differences between gl/directx matrixes tbh.
I'll post up my function based on the above to this thread for anyone interested, and to make sure i've not made any mistakes which i no doubt will.


DStastny(Posted 2005) [#7]
The big difference you need to worry about between DirectX and OpenGL is Left hand coordinate systems or right Hand. That will affect the signs in your matrixs.

Off top of my head I dont remember what changes but know that causes issues with the Z Axis.

Direct X help files actually go into detail on how to move between the different coordinate systems.

Doug Stastny


Sweenie(Posted 2005) [#8]
According to the Dx-helpfile, to make the above MatrixLookat function "Right-Handed?" you just switch zaxis = normal(At-Eye) to zaxis = normal(Eye-At).
Almost sounds too easy, but on the other hand, it might just be that easy.


REDi(Posted 2005) [#9]
I'm a bit confused why you're using all this matrix stuff like this anthony, Opengl has a great builtin matrix system that you must be using all the time anyway, why not use that.
I'm just wondering, because my gl engine is coming on fine (cameras,entitys,meshs,lights,textures,materials ect) and it only uses the gl matrixs. For example pointing a matrix would be done with glRotatef().


AntonyWells(Posted 2005) [#10]
Yeah well, I'm kind of using it to some extent.

I use the local rotational matrixes and use glLoad/MultiMat to create the rotation needed.

In theory this should allow easier shader-centricisity as you can pass matrices directly to Shaders.

Btw, how would glRotatef help with point exactly? You'd still need to do the underlying maths unless you use gluLookAt..which is pretty limiting.
-

As for left-right hand coords, it can be fixed(at least visually) by scaling everything 1,1,-1


REDi(Posted 2005) [#11]
In theory this should allow easier shader-centricisity as you can pass matrices directly to Shaders

You can use glGetFloatv(GL_MODELVIEW_MATRIX, Varptr(afMatrix[0])) to get a matrix.

Btw, how would glRotatef help with point exactly?

Yes you would need to do the math :) *EDIT* just checked my entity code and it turns out I used gluLookAt *EDIT*


Bot Builder(Posted 2005) [#12]
Opengl has a great builtin matrix system
Wha? not really... more like passing 12 floats to ogl. I'd have a matrix class if I was making an engine. I suppose you've got the glrotate/move/etc, but there is really so much more you could add to a matrix class.


REDi(Posted 2005) [#13]
Opengl has a great built-in matrix system

Yeah "great" is a bit over the top lol, should read "Opengl has a built-in matrix system" :)

Don't get me wrong, I'm sure Antony knows what he's doing, I'm not saying that using the gl matrix is any better than Antonys class, I was being more inquisitive as to why a matrix class would be needed, what are the advantages?
I'm only just learning this stuff myself, and it seems a bit strange to use a matrix class when your already using gl matrix anyway.


AntonyWells(Posted 2005) [#14]
No worries Papa, I actually did it your way for my last two engines so I'm not even dismissing the idea. Just trying it a new way this time around :)