TurnEntity (Around Axis)

BlitzMax Forums/MiniB3D Module/TurnEntity (Around Axis)

FreetimeCoder(Posted 2009) [#1]
Hi,

so I tried it myself, searched for it and tried it again, but I cannot figure out how I am able to acheive what I want.
The "local" Rotation is a real mess. In my opinion local means to rotate around the axis of an object. But thats not the case. Instead it rotates around the local Z axis, the global Y axis and an weird yaw-dependant X axis.
I know, it is like in B3D, i found that out so far, but can someone please help me to implement a _real_ local rotation?

I tried so far:

(Dirty code, I know)
Import sidesign.minib3d

Graphics3D(640, 480)
Type rotater
	Field cone:TEntity
	Field axisX:TEntity
	Field axisY:TEntity
	Field axisZ:TEntity
	Method init()
		cone:TEntity = CreateCone()
		axisX:TEntity = CreateCylinder(8, 1, cone)
		ScaleEntity(axisX, 0.1, 3, 0.1)
		EntityColor(axisX, 255, 0, 0)
		RotateEntity(axisX, 0, 0, 90)
		
		axisY:TEntity = CreateCylinder(8, 1, cone)
		ScaleEntity(axisY, 0.1, 3, 0.1)
		EntityColor(axisY, 0, 255, 0)
		
		axisZ:TEntity = CreateCylinder(8, 1, cone)
		ScaleEntity(axisZ, 0.1, 3, 0.1)
		EntityColor(axisZ, 0, 0, 255)
		RotateEntity(axisZ, 90, 0, 0)
EndMethod
End Type

rot1:rotater = New rotater
rot1.init()
rot1.cone.PositionEntity(5, 0, 0)
rot1.cone.EntityColor(255, 255, 255)

rot2:rotater = New rotater
rot2.init()
rot2.cone.PositionEntity(- 5, 0, 0)
rot2.cone.EntityColor(150, 150, 150)


camera:TEntity = CreateCamera()
PositionEntity(camera, 0, 0, - 10)

'Wireframe(True)

While Not KeyHit(KEY_ESCAPE)
    Cls
    TurnEntityAroundAxis(rot1.cone, KeyDown(KEY_UP) - KeyDown(KEY_DOWN), KeyDown(KEY_LEFT) - KeyDown(KEY_RIGHT), KeyDown(KEY_PAGEUP) - KeyDown(KEY_PAGEDOWN))
    TurnEntity(rot2.cone, KeyDown(KEY_UP) - KeyDown(KEY_DOWN), KeyDown(KEY_LEFT) - KeyDown(KEY_RIGHT), KeyDown(KEY_PAGEUP) - KeyDown(KEY_PAGEDOWN))
    RenderWorld
    Flip
Wend
End

Function TurnEntityAroundAxis(pEntity:TEntity, Pitch:Float, Yaw:Float, Roll:Float)
    Local fPitch:Float = EntityPitch(pEntity) + Pitch * Cos(EntityRoll(pEntity))
    Local fYaw:Float = Yaw + EntityYaw(pEntity) + Pitch * Sin(EntityRoll(pEntity))
	DebugLog Sin(EntityRoll(pEntity))
    Local fRoll:Float = EntityRoll(pEntity) + Roll
	RotateEntity(pEntity, fPitch, fYaw, fRoll)
	
End Function


Since the Z - Axis is the only real local axis, my plan was to rotate the object around the others dependant from EntityRoll but I have to admit I did not get the concept behind the rotation function.
Then I looked up the source but hell I don't know no nothing about matrices :(

Is here anyone who can give me some advices to solve my problem?

greetings
FTC


Warner(Posted 2009) [#2]
I've just made these routines, they use Matrices and Quaternions for rotation. There is an internal function, called MQ_Turn, that rotates an entity around an axis:
http://www.blitzmax.com/codearcs/codearcs.php?code=2498
Hopefully they help you.


FreetimeCoder(Posted 2009) [#3]
Thats great man! I really needed it.

THANKS!

greetings


FreetimeCoder(Posted 2009) [#4]
Uhm there is a problem still... When using the code with collision the Object's rotation is resetted. EntityYaw2 etc are delivering correct values though and MoveEntity2 local does work as well, but the Mesh itself is stuck in an fixed rotation. I guess there it has something to do with the matrices.

greetings


slenkar(Posted 2009) [#5]
do you mean that the collisions are happening to an entity as if it isnt rotated?

please provide code sample and model.


Warner(Posted 2009) [#6]
It is possible that the code is not (fully) compatible with animated meshes? An example would be a good idea, since I only tested the code with standard CreateCube/CreateCone objects.

Maybe you could try this version of TEntity. UpdateMat is changed to read the new matrix, and all the original commands refer to their counterparts.
That could allready solve some of these issues, since for example TCollisions.bmx uses EntityX/Y/Z. Still, I would have to get further into it to be able to say more about it.

Note that the commands are wrapped in an ugly manner at this point. As I said, it's just experimental code so far, and I'm cautious when it comes down to building in anything before it is properly tested and working.

TEntity.bmx



slenkar(Posted 2009) [#7]
Blitz3d didnt support animated mesh collision, the collisions happened to the original mesh with no animation.


Warner(Posted 2009) [#8]
Right, I looked into it and I saw indeed there was a problem with collisions. Now I've posted an update that I have tested with the minib3d samples/demo's. So collisions should be working properly now.


FreetimeCoder(Posted 2009) [#9]
I created a sample of my problem:
http://www.freetimestudio.de/col_test.zip
I do not want it to be animated, but LoadAnimMesh solves a few Renderingproblems Minib3d has.
It uses the old version. With the new version however it does not render anything...

greetings


Warner(Posted 2009) [#10]
That's very nice, thanks. I don't have the older version anymore, but I tried the .exe you compiled, and it does indeed work incorrectly. When I tried the latest version, it then works correct, and renders.
Try my .exe:
http://abcbasic.comyr.com/col_test.zip


FreetimeCoder(Posted 2009) [#11]
I don't know whats wrong :( Even with the latest version I have nothing displayed. But the programm does not crash (I use Debuglog to find out that)

greetings


Warner(Posted 2009) [#12]
But the .exe I compiled, does it work?


Warner(Posted 2009) [#13]
Ah, I know what it is .. My fault, sorry :/ stupid, I forgot to add UpdateEntities(). You can call it manually before using RenderWorld(), but it should be built-in. The reason I forgot that, is that RenderWorld is part of TGlobal.
In TGlobal.bmx, in the Function RenderWorld, add the line: UpdateEntities(). Example here:

TGlobal.bmx



Warner(Posted 2009) [#14]
Does it work now?


FreetimeCoder(Posted 2009) [#15]
Patience with me please :) I don't have much time to work with Blitz at the moment.

Yes it works now and your .exe workd as well :)
But, like in Science, a solved Question creates more Questions, I got another thing to solve.

Standard EntityPitch() gives me values from -"infinite" to +"infinite" and yours provide -90 to 90. Is it possible to get at least values from 0 to 360? ( or to infinite;-) )
That would make it much easier to handle the rotation.

greetings, and great work!


Warner(Posted 2009) [#16]
Thank you. I'm afraid that's not possible, because EntityPitch/Yaw/Roll extract their values from the matrix. That means the pitch is affected by the roll and yaw.
I got those routines from the math library that is posted in the b3d thread.
However, depending on what you are trying to do, you can work around that limitation by keeping track of this pitch yourself, for instance like this:



FreetimeCoder(Posted 2009) [#17]
Thanks for this suggestion. I tried it, but it revealed something bad :(

With the original minib3d i have ~60 fps but with the modified one i have a maximum of 25 fps.
Same Code, I just used different minib3d versions to compile it.
		actualRot:float = actualRot + (curRot:float - actualRot) * 0.1
		Cube.RotateEntity(actualRot, 0, 0)

The code itself works, just the thing with the lower frame rate.

greetings


Warner(Posted 2009) [#18]
!? That is a big difference indeed. The reason might be that my RotateEntity is slower. I tried to optimise the code for TEntity. You might give that a try. I replaced the my 'Rotate' with the original Rotate code:



FreetimeCoder(Posted 2009) [#19]
Whatever you did, that was the solution. I have stable 60 fps now.
Still, when going up with the "rate" parameter of Graphics3D I am able to get about 250 fps with the original and 65 with yours. Of course there is more than one object and a scene and everything, but still, I think thats quite a difference.
I don't have problems with the fps, it fits for me, but maybe, when using more objects it could become a problem.

greetings :)


Warner(Posted 2009) [#20]
Could you send an example? Then I could have a look later on this week. (At work tomorrow..) I believe there shouldn't be such a big difference between the two.


simonh(Posted 2009) [#21]
I think quaternion rotations are always going to be slightly slower than euler ones as there is simply more calculations involved.


FreetimeCoder(Posted 2009) [#22]
I would have to make an example, because it is a big programm I am using the rotation in. I can't just cut out a little sample ;)
But I am not at home for a couple of days. After that I will make a sample.

If simonh is right, the definition of "slightly" has to be redone :D

greetings


FreetimeCoder(Posted 2009) [#23]
I am back.

here is my sample:
SuperStrict

Import sidesign.minib3d

'standard minib3d ~120 fps
'modded minib3d ~37 fps

Type TTurningThingy
	Field HoldPivot:TEntity = CreateSphere()
	Field RotPivot:TEntity = CreateSphere(8, HoldPivot)
	Field ChildObjects:TList = CreateList()
	Function init:TTurningThingy(Pos:TVector, count:Int = 4, dist:Float = 10)
		Local tmp:TTurningThingy = New TTurningThingy
		For Local i:Int = 1 To count
			Local alpha:Float = ((360.0 / count)) * i	
			Local y:Float = Sin(alpha) * dist
			Local z:Float = Cos(alpha) * dist 
			Local ChildObject:TEntity = CreateSphere(8, tmp.RotPivot)
			ChildObject.EntityColor(Rnd(10, 255), Rnd(10, 255), Rnd(10, 255))
			ChildObject.ScaleEntity(1, 2, 1)
			ChildObject.PositionEntity(0, y, z)
			ChildObject.RotateEntity(rnd(0,360),rnd(0,360),rnd(0,360))
			tmp.ChildObjects.AddLast(ChildObject)
			
			Local someSprite:TSprite = CreateSprite(ChildObject)
			someSprite.PositionEntity(0, 5, 0)
			
			tmp.HoldPivot.PositionEntity(Pos.x, Pos.y, Pos.z)
		Next
		Return tmp
	End Function
	Method update()
		For Local tmp:TEntity = EachIn ChildObjects
			tmp.TurnEntity(0, 1, 1)
		Next
		RotPivot.TurnEntity(1, 0, 0)
		HoldPivot.TurnEntity(0, 1, 0)
	End Method
End Type

Graphics3D(640, 480, 32, 2, 1000)

Local camera:TCamera = CreateCamera()
camera.PositionEntity(0, 0, - 20)

Local TurningList:TList = CreateList()
For Local i:Int = 0 To 40
	TurningList.AddLast(TTurningThingy.init(TVector.Create(Rnd(- 50, 50), Rnd(- 50, 50), Rnd(0, 100))))
Next

Local old_ms:Int = MilliSecs()
Local renders:Int
Local fps:Int

While Not KeyHit(KEY_ESCAPE)
	Cls
	For Local tmp:TTurningThingy = EachIn TurningList
		tmp.update()
	Next
	UpdateWorld()
	RenderWorld()
	Flip()
	
	renders = renders + 1
	If MilliSecs() - old_ms >= 1000
		old_ms = MilliSecs()
		fps = renders
		DebugLog fps + " FPS"
		renders=0
	EndIf
Wend
ClearWorld()
End


I know, a little bit stupid maybe, but it is an abstraction of what I am doing. In my real code I use Models and Textures, thats why I increased the polys of the sample.

I guess that it has much to do with the sprites, removing them does make the modded minib3d much faster while with simonh's version does not produce such a difference.


Warner(Posted 2009) [#24]
Thank you, your example is quite helpful. I tried optimizing the code. It would need testing to see if everything still works properly, but maybe it runs faster? On my laptop, the original version runs at 7-8 fps, and the previous modded version 6-7 fps. With this adjustment, both run on 7-8 fps.

TEntity.bmx



slenkar(Posted 2009) [#25]
it says 'interpolate matrix not found'


Warner(Posted 2009) [#26]
This is just TEntity.bmx. It also requires TMatrix/TGlobal/TAnimation from the archive entry to work. "InterpolateMatrix" is part of TMatrix.bmx.


FreetimeCoder(Posted 2009) [#27]
Hm there is a speed-increase. But not a big one. I get ~ 44 fps. But there are no errors an everything seems to work just as well as before.

greetings


Warner(Posted 2009) [#28]
Right, well back to the drawing board.. I'll look further into it.


ziggy(Posted 2009) [#29]
I need this too, but I don't know where to get the TMatrix class code. I feel like I'm missing something??


Warner(Posted 2009) [#30]
It's in the archive:
http://www.blitzmax.com/codearcs/codearcs.php?code=2498


ziggy(Posted 2009) [#31]
Thanks!