GetMatElement questions.

Blitz3D Forums/Blitz3D Beginners Area/GetMatElement questions.

DH(Posted 2005) [#1]
Alright, so getmatelement has a matrix of 3x4, does anyone know what all this means??

I know that elements (3,0), (3,1) and (3,2) are the position information, however what is the rest?

I thought (0,0), (1,1) and (2,2) were scale information, however I found that when I rotate the mesh, that information skews... My goal is (was) to load in a 3ds file, grab the global position,rotation, and scale values and reset the mesh whilst keeping these values for other reasons (editor of sorts).

Any help would be greatly appreciated. Thanks.


Rottbott(Posted 2005) [#2]
Can't you just use EntityX/Y/Z#(), EntityPitch#(), EntityYaw#(), EntityEntityPitch#() to get the position and rotation?

AFAIK the scale of a newly loaded mesh is always 1, 1, 1 but you can get the size using MeshWidth#(), MeshHeight#() and MeshDepth#().


DH(Posted 2005) [#3]
when I load in a 3ds file, i find that if I get the rotation and position throug the means you described, then set the mesh to 0,0,0 in both and do rotatemesh/movemesh commands it wont show up like it does in 3d studio.

And when a mesh is loaded in from a 3ds file, it isn't always (almost never) a 1,1,1 scale.

Any other thoughts?


Rottbott(Posted 2005) [#4]
Oh yes it is. The mesh size may not be 1, 1, 1 but the entity scale is. In the same way, the mesh origin may not be 0, 0, 0, but the entity position is, and the same applies to rotation.

I just tried it on a 3DS file and it doesn't do anything special. The positions retrieved through GetMatElement#() are the same as through EntityX/Y/Z#(), that is, zero (until you move it yourself).

I think your problem is that you should be PositionENTITY() instead of PositionMESH(), same for rotation and scale. If you do RotateMesh() followed by ScaleMesh(), it will skew.


DH(Posted 2005) [#5]
Oh yes it is. The mesh size may not be 1, 1, 1 but the entity scale is.


Oddly enough, every level I have designed in 3ds Max (6) and imported into my editor and spit out debug info on (when loaded using loadanimmesh to keep all the heirarchy data) has shown to have a non-1 scale. Rarely is the scale a 1,1,1 ratio. If I scale it to 1,1,1 it will be completely different from what I exported it as in max.

As for the positions, yeah, they are all correct (when imported from a max file), however the rotations arent. Thre are plenty of objects I take the pitch,yaw, and roll of (global), re-zero it, and rotatemesh by that amount again and it will not look right.


Rottbott(Posted 2005) [#6]
How are you retrieving the scale values to output?

With an anim mesh the children will have their own scales (didn't realise you were using anim meshes), but the main entity should still have 1, 1, 1.

If you want I'll take a look at one of your meshes and see if I can find the problem.

You may be applying transformations in the wrong order. Also you can still use EntityX/Y/Z#() and the entity rotation commands to extract position/rotation from children - it's only the scale you cannot retrieve.

Also - none of the values in the matrix directly correspond to scale. The matrix is four 3D vectors: a position, and 3 axes. I think the scale is the length of those axis vectors and the rotation is their direction.


DH(Posted 2005) [#7]
http://www.kcstudios.net/testlevel1.zip


I seperate the objects in the 3ds by loading it useing
Function Obj_LoadMesh(FileName$="", MeshHandle=0)
	Local ChlCnt=0,ChlInd=0,ChlHndl=0
	If FileName$ <> "" Then MeshHandle=LoadAnimMesh(FileName$)

	If MeshHandle <> 0 Then
		ChlCnt = CountChildren(MeshHandle)
		If ChlCnt > 0 Then
			For ChlInd = 1 To ChlCnt
				ChlHndl = GetChild(MeshHandle,1)
				If ChlHndl <> 0 Then Obj_LoadMesh("", ChlHndl)
			Next
		Else
			Obj_Add(MeshHandle)	
			EntityParent(MeshHandle,0)
		EndIf	
	EndIf
End Function


for each object that goes into Obj_Add() is is done the following to:
Function Obj_Add(ObjHandle=0)
	Local Obj.ObjList
		Obj.ObjList 		=New ObjList
		Obj\ID 				=ObjID_Index:ObjID_Index=ObjID_Index+1
		Obj\ObjHandle 		=ObjHandle
		Obj\Name$			=EntityName$(Obj\ObjHandle)
		Obj\X#				=EntityX#(Obj\ObjHandle,1)
		Obj\Y#				=EntityY#(Obj\ObjHandle,1)
		Obj\Z#				=EntityZ#(Obj\ObjHandle,1)		
		Obj\ORX#				=EntityPitch#(Obj\ObjHandle,1)
		Obj\ORY#				=EntityYaw#(Obj\ObjHandle,1)	
		Obj\ORZ#				=EntityRoll#(Obj\ObjHandle,1)
		;Set rotation and position to 0,0,0 to extract the scale factor of getmatelement
		RotateEntity(Obj\ObjHandle,0,0,0,1)
		PositionEntity(Obj\ObjHandle,0,0,0,1)
		ESX# = GetMatElement(Obj\ObjHandle,0,0)
		ESY# = GetMatElement(Obj\ObjHandle,1,1)
		ESZ# = GetMatElement(Obj\ObjHandle,2,2)
                ;We have the scale, now put the scale to 1, position and rotate the mesh
		ScaleEntity(Obj\ObjHandle,1,1,1)
		PositionEntity(Obj\ObjHandle,Obj\X#,Obj\Y#,Obj\Z#)
		RotateMesh(Obj\ObjHandle,Obj\ORX#,Obj\ORY#,Obj\ORZ#)
                ;Now scale the mesh by it's scaled value
		ScaleMesh(Obj\ObjHandle,ESX#,ESY#,ESZ#)
		Return Obj\ID

End Function


When I load the 3ds file useing the above 2 functions (the loader to seperate the children from the parent, then adding each to the list to reset the position, rotation, scale) all the platforms are at 90 degree angles along the Y axis. They are all positioned and scaled correctly.

Reason I position entity rather then positionmesh, is that when I save the file (in my own format) i want the mesh relative to its position from the 3ds file.
Reason I use rotatemesh rather then rotateentity, is because I want all rotation and such in the editor done from a 0,0,0 refference that way I am not fighting blitz rotations when doing simple animations with position/rotation. A starting point of 0,0,0 (0,0,0 being the whatever rotation it was placed in 3ds max).
I have tried scaleentity(mesh,1,1,1) and it makes everything really small. Even by doing a conversion to an editable mesh in max, I still get odd scale values by scalin it to 1,1,1 in blitz.

Thanks for your help thus far by the way, I appreciate it.

Any Thoughts?


Rottbott(Posted 2005) [#8]
It seems to work better if you unparent the entity *before* calling Obj_Add(). Was there some particular reason you weren't doing that?

It's still not perfect though, the rotations are correct but the positions seem a bit off.

Edit: Actually, that doesn't fix all the rotations, just the big cross thingy.

Edit 2: Adding a -90.0 to the Y rotation in the RotateMesh() call seems to fix it completely. I think it's a 3DS thing.


My final code:

Function Obj_LoadMesh(FileName$="", MeshHandle=0)
	Local ChlCnt=0,ChlInd=0,ChlHndl=0
	If FileName$ <> "" Then MeshHandle=LoadAnimMesh(FileName$)

	If MeshHandle <> 0 Then
		For ChlInd = 1 To CountChildren(MeshHandle)
			If ChlHndl <> 0 Then Obj_LoadMesh("", GetChild(MeshHandle,1))
		Next
		EntityParent(MeshHandle,0)
		Obj_Add(MeshHandle)	
	EndIf
End Function

Function Obj_Add(ObjHandle=0)
	Local Obj.ObjList
		Obj.ObjList 		=New ObjList
		Obj\ID 				=ObjID_Index:ObjID_Index=ObjID_Index+1
		Obj\ObjHandle 		=ObjHandle
		Obj\Name$			=EntityName$(Obj\ObjHandle)
		Obj\X#				=EntityX#(Obj\ObjHandle,1)
		Obj\Y#				=EntityY#(Obj\ObjHandle,1)
		Obj\Z#				=EntityZ#(Obj\ObjHandle,1)		
		Obj\ORX#				=EntityPitch#(Obj\ObjHandle,1)
		Obj\ORY#				=EntityYaw#(Obj\ObjHandle,1)	
		Obj\ORZ#				=EntityRoll#(Obj\ObjHandle,1)
		;Set rotation and position to 0,0,0 to extract the scale factor of getmatelement
		RotateEntity(Obj\ObjHandle,0,0,0,1)
		PositionEntity(Obj\ObjHandle,0,0,0,1)
		ESX# = GetMatElement(Obj\ObjHandle,0,0)
		ESY# = GetMatElement(Obj\ObjHandle,1,1)
		ESZ# = GetMatElement(Obj\ObjHandle,2,2)
        ;We have the scale, now put the scale to 1, position and rotate the mesh
		ScaleEntity(Obj\ObjHandle,1,1,1,1)
		PositionEntity(Obj\ObjHandle,Obj\X#,Obj\Y#,Obj\Z#,1)
		RotateMesh(Obj\ObjHandle,Obj\ORX#,Obj\ORY#-90,Obj\ORZ#)
        ;Now scale the mesh by it's scaled value
		ScaleMesh(Obj\ObjHandle,ESX#,ESY#,ESZ#)
		Return Obj\ID

End Function



DH(Posted 2005) [#9]

It seems to work better if you unparent the entity *before* calling Obj_Add(). Was there some particular reason you weren't doing that?


There wasn't any reason in particular that I can think of off hand (so many work arounds through the whole design of this editor that its hard to remember why you do certain things the way you did).

So it fixed the -45 degree offset (Y) on the propellar. Thats a start :-)

As you can see, it is getting frustrating.. It can't just be a 3ds thing, because if I load the mesh in straight and do no modifications to it (the 3ds file) everything will look correct in blitz. This means that blitz is returning incorrect values for rotation, or something...

Thanks for your help though Rottbott, its always nice to have a second set of eyes looking at something to prove that I am still in the relm of sanity!


DH(Posted 2005) [#10]
Yeah, by commenting the following lines out:
		RotateEntity(Obj\ObjHandle,0,0,0,1)
		PositionEntity(Obj\ObjHandle,0,0,0,1)
		ESX# = GetMatElement(Obj\ObjHandle,0,0)
		ESY# = GetMatElement(Obj\ObjHandle,1,1)
		ESZ# = GetMatElement(Obj\ObjHandle,2,2)
        ;We have the scale, now put the scale to 1, position and rotate the mesh
		ScaleEntity(Obj\ObjHandle,1,1,1,1)
		PositionEntity(Obj\ObjHandle,Obj\X#,Obj\Y#,Obj\Z#,1)
		RotateMesh(Obj\ObjHandle,Obj\ORX#,Obj\ORY#-90,Obj\ORZ#)
        ;Now scale the mesh by it's scaled value
		ScaleMesh(Obj\ObjHandle,ESX#,ESY#,ESZ#)
		Return Obj\ID


The mesh loads just fine. It is obviously a problem with the information that blitz returns about the entity's rotation info... I think I am going to put in a bug report on it..


Rottbott(Posted 2005) [#11]
Are there any other rotation/positioning/scale problems with the code I posted? It all looked the same as the plain LoadAnimMesh() to me. The -90 thing seems a bit ugly but I think it may be the best you're going to get.

Also, try commenting out that block of code and replace it with:

RotateEntity Obj\ObjHandle, EntityPitch#(Obj\ObjHandle, True), EntityYaw#(Obj\ObjHandle, True), EntityRoll#(Obj\ObjHandle, True)

In theory that should do nothing. If it turns your objects there's a problem.


DH(Posted 2005) [#12]
The -90 thing seems a bit ugly but I think it may be the best you're going to get.

Well, if broken is the best I am going to get, then I am a bit dissapointed :-(

RotateEntity Obj\ObjHandle, EntityPitch#(Obj\ObjHandle, True), EntityYaw#(Obj\ObjHandle, True), EntityRoll#(Obj\ObjHandle, True)

In theory that should do nothing. If it turns your objects there's a problem.


Yeah, tried that as well, it still puts it -90 degrees off on the Y axis. Even after spitting out debug info on the entityyaw i still see it returning 0.

It has to be broken though (entityyaw), cause if i dont do anything to it then the mesh is correct, but once i try to rotate the model by its returned rotated values (entityyaw and such), it goes off by 90...


Rottbott(Posted 2005) [#13]
Yes, seems broken.

There may be another way to do it without resorting to the -90 thing: set a LoaderMatrix for 3DS files.