rolling ball

BlitzMax Forums/MiniB3D Module/rolling ball

ima747(Posted 2009) [#1]
I would like a sphere to roll as it moves. I've made the sphere a child of a pivot so I can use moveentity on the pivot to steer. Then I get the difference in movement along X and Z and use turnentity to roll the sphere based on how much it's moved (pitch for Z change, and roll for X change) however since changing one changes the angle of rotation for the other (i.e. pitch forward 90 and now roll is actually yaw) this obviously doesn't work. Does anyone have a way of doing this (seemingly) simple rotation? I tried doing some parenting and un-parenting things with a second pivot but I just ended up with gimbal lock and a mess.


Floyd(Posted 2009) [#2]
There's an example here.

Unfortunately this site doesn't provide a good way to search the Code Archives. It's better to use google. I found the example by using this search query:

rolling site:http://blitzbasic.com/codearcs



ima747(Posted 2009) [#3]
thanks for the link. I've dug around in it and after much poking I got it to compile but it dies right away saying signal 10 so I can't see exactly what it's supposed to do.

what I've got for single axis is
mesh.TurnEntity((changeZ / circumference) * 360, 0, 0) ' pitch

Does anyone know of a way to calculate the yaw and roll based on the pitch? i.e. when the pitch is 90 then the yaw becomes the roll (but inverted I think...) and the roll becomes yaw. My brain is not being helpful in getting a handle on the math behind this.


ima747(Posted 2009) [#4]
I've got a hacky work around going that suits my needs.

I parent the sphere to a pivot and then pitch the pivot based on movement on the Z axis. then clear the sphere's parent, reset the pivot to 0,0,0 rotation, parent the sphere to the pivot again and roll the pivot based on the movement on the X axis, then return the sphere to it's proper parent. This doesn't take into account changes along the Y axis so I'm not sure it will work long term, but for now it's convincing enough for my needs.


simonh(Posted 2009) [#5]
The way I do it is to use RotateMesh for the ball.


ima747(Posted 2009) [#6]
Thanks simon, that's how I did it last time I needed a rolling ball as well, but this time I needed to stick things to it and have them spin too, and adding meshes together wasn't an option because I had to keep moving them once they're stuck. but clear, rotate 1, clear rotate 2 is working quite well so far.


Rob Pearmain(Posted 2012) [#7]
ima747, Any chance I see the code as RotateMesh seems really slow on the device


ima747(Posted 2012) [#8]
Simon uses rotate mesh in a production product so while it is a heavy method it is usable, first step I would take is trying to trim from elsewhere if it gives you the look you want.

I don't really understand the old code at a glance, haven't worked on it in a year and a half it looks like... I'm not positive it works flawlessly since the project was abandoned and I have no idea why (I think it was a combination of lazy making assets and a technical glitch I don't remember...)

Here's a snipped of I think what's relevant with a couple comments for what I *think* is going on...
	//Get the position of the thing, core is a pivot
	float fx = core->EntityX();
	float fz = core->EntityZ();
	
	// Reset the position of the "turner" which is a pivot used to help with the rotation. have to put everything in the same place or the rotation origin will change... bad things
	turner->PositionEntity(core->EntityX(), core->EntityY(), core->EntityZ()); // there's a reason that it wasn't just parented to the core but I don't recall why... possibly I used the core orientation to calculate movements using move entity... not sure
	float circumference = PI * (radius*2); // for my game the ball could change size so this has to be updated constantly, normally this could just be static
	turner->RotateEntity(0, 0, 0);// reset the turner orientation
	meshCore->EntityParent(turner);// attach the actual visible mesh to the turner
	turner->TurnEntity((fz / circumference) * 360, 0, 0); // pitch the turner based on the core's position along the Z axis
	meshCore->EntityParent(core); // clear the mesh's parent
	turner->RotateEntity(0, 0, 0); // reset the turner orientation so it's not dirty with the pitch change
	meshCore->EntityParent(turner);// set the mesh parent again
	turner->TurnEntity(0, 0, (-fx / circumference) * 360); // roll the turner based on the core's position along the X axis
	meshCore->EntityParent(core); // reset the mesh's parent so it moves with the core in the next frame

Hope that helps, and god help you if it doesn't :0)


ima747(Posted 2012) [#9]
Thinking about it, you might be able to do it more easily with 3 parented objects, just using one for each axis... not sure if that would work or not... I should look into it at some point.

Optimally official minib3d will eventually use quats and bring about world peace (in my mind), but the quat implementations haven't worked for me so far... at least not applied to existing projects and it's only for BMax to my knowledge.


Rob Pearmain(Posted 2012) [#10]
ima747, (Logan) awesome! :-) It works, and a smooth 60 FPS on the iPhone 3GS

Many, MANY thanks

Rob

Last edited 2012


ima747(Posted 2012) [#11]
glad it helped. The problem is that the Euler rotation can cause gimbal lock due to how it processes changes in orientations. By forcing each change to be in it's own space, that is not cumulative, but one axis per object, each object avoids gimbal lock, and when you put the results together you get an orientation. It's more like a snap shot of an orientation than a calculated offset, but it's, in theory, good enough for a ball rolling in a game (we're not simulating the universe on a particle level here, just making a sphere go "WHEE!!!").

It's ugly and hacky, but as long as one doesn't need to do it a lot it seems to work. A space sim sould still be tricky with this approach because a) it's inherently innacurate and b) you'd have to apply it to every object that spins every frame... it would get heavy fast.