Bug with RotateEntity() and ScaleEntity()

BlitzMax Forums/MiniB3D Module/Bug with RotateEntity() and ScaleEntity()

klepto2(Posted 2007) [#1]
I think I have found a bug:
If you have scaled an Entity to another value than 1,1,1, then
If you use RotateEntity the mesh is scaled wrong the way. eg: a sphere looks more like an oval than a sphere.

here is a modified primitives sample which should demonstrate the problem.

Import "../MiniB3D.bmx"

Strict

Local width=640,height=480,depth=16,mode=0

Graphics3D width,height,depth,mode

Local cam:TCamera=CreateCamera()
PositionEntity cam,0,0,-10

Local light:TLight=CreateLight(1)

Local tex:TTexture=LoadTexture("media/test.png")

Local cube:TMesh=CreateCube()
Local sphere:TMesh=CreateSphere()
Local cylinder:TMesh=CreateCylinder()
Local cone:TMesh=CreateCone() 

PositionEntity cube,-6,0,0
PositionEntity sphere,-2,0,0
PositionEntity cylinder,2,0,0
PositionEntity cone,6,0,0

ScaleEntity sphere,3,3,3

EntityTexture cube,tex
EntityTexture sphere,tex
EntityTexture cylinder,tex
EntityTexture cone,tex

' used by camera code
Local mxs#=0
Local mys#=0
Local move#=0.5
MouseXSpeed() ' flush
MouseYSpeed() ' flush

' used by fps code
Local old_ms=MilliSecs()
Local renders
Local fps

While Not KeyDown(KEY_ESCAPE)		

	If KeyHit(KEY_ENTER) Then DebugStop

	'' control camera
	
	' mouse look
	
	mxs#=mxs#+(MouseXSpeed()/5.0)
	mys#=mys#+(MouseYSpeed()/5.0)

	RotateEntity cam,mys#,-mxs#,0

	MoveMouse width/2,height/2
	MouseXSpeed() ' flush
	MouseYSpeed() ' flush

	' move camera forwards/backwards/left/right with cursor keys
	
	If KeyDown(KEY_UP)=True Then MoveEntity cam,0,0,move# ' move camera forward
	If KeyDown(KEY_DOWN)=True Then MoveEntity cam,0,0,-move# ' move camera back

	If KeyDown(KEY_LEFT)=True Then MoveEntity cam,-move#,0,0 ' move camera left
	If KeyDown(KEY_RIGHT)=True Then MoveEntity cam,move#,0,0 ' move camera right
	
	''
	
	TurnEntity cube,0,1,0
	
	RotateEntity(sphere,EntityPitch(sphere)+0.7,EntityYaw(sphere)+0.7,EntityRoll(sphere)+0.7)
	

	RenderWorld
	renders=renders+1

	' calculate fps
	If MilliSecs()-old_ms>=1000
		old_ms=MilliSecs()
		fps=renders
		renders=0
	EndIf
	
	
	
	Text 0,0,"FPS: "+String(fps)

	Flip

Wend
End



Chris C(Posted 2007) [#2]
i see it when looking from the side of the objects, it looks like the kind of problem you get then a set of values are applied incorrectly to a maxtrix


simonh(Posted 2007) [#3]
Yikes...Very odd. Will look into it.


Chris C(Posted 2007) [#4]
si.

bit confused about what you are doing with the scaling. especialy in Tmatrix.Tform

to scale a matrix start with identity then set
mat[0,0]=sx
mat[1,1]=sx
mat[2,2]=sx
and multiply this with the matrix to scale


simonh(Posted 2007) [#5]
TMatrix.TForm was my attempt to reduce the matrix multiplications into as few calculations as possible. Anyway, I obviously messed up somewhere, so as an easy fix, in TEntity replace UpdateMat with this:

	Method UpdateMat(load_identity=False)

		If load_identity=True
			mat.LoadIdentity()
			mat.Translate(px,py,pz)
			mat.Rotate(rx,ry,rz)
			mat.Scale(sx,sy,sz)
		Else
			mat.Translate(px,py,pz)
			mat.Rotate(rx,ry,rz)
			mat.Scale(sx,sy,sz)
		EndIf
	
	End Method

Likely to be a little slower but not much, the Translate/Rotate/Scale functions are already optimised and TForm was only used for orphan entities anyway.


Chris C(Posted 2007) [#6]
I wouldnt feel to bad, just about every time I've tried to munge matrix operations together I seem to get unstuck, unfortunately not all operations can be mixed like you'd think .its just the sort of math we all *love* soooo much..... NOT!


bradford6(Posted 2007) [#7]
Just a thought (maybe an ignorant one) Would it be more efficient to use the internal OPENGL Matrix/vector systems?


Chris C(Posted 2007) [#8]
I wouldn't say an ignorant thought at all, I've often used opengl to calculate stuff of my own, but you do tend to end up throwing chunks of 16 floats around with that approach.

ie load up a matrix do a calculation store the matrix

as opposed to using the entities matrix directly...

I'm not convinced that updatemat above is *vastly* slower it could be improved sure but at least it works :D !