Welcome! Log In Create A New Profile

Advanced

Realistic ball rotation

Posted by copete23 
Realistic ball rotation
February 12, 2010 03:25PM
Hi, I'm trying to rotate a sphere according to the direction in which it moves (x, z), but I can not work properly, I have implemented the physics, but i am unable to make the sphere rotate well XD.

I tried this:

Mtx mX, mY, mZ;
Vector axisX = (1.0, 0.0, 0.0);
Vector axisY = (0.0, 1.0, 0.0);
Vector axisZ = (0.0, 0.0, 1.0);

......
...
guMtxIdentity ....

guMtxRotAxisDeg (mX, & axisX, ball.z);
guMtxRotAxisDeg (mY, & axisY, 0);
guMtxRotAxisDeg (mZ, & axisZ, ball.x);
....
..
But this does not work, because if you rotate on the x axis for example, the z axis going berserk .....
Then I tried with this:

Mtx mR;
Vector axis = (ball.z, 0.0,-ball.x);

where ball.x + = acelx and ball.z + = acelz;

guMtxRotAxisDeg (mR, & axis, ball.z + ball.x);


This works better but is doing weird things: (.
Does anyone have any idea on how to calculate angle of rotation?

Thanks! :)



Edited 1 time(s). Last edit at 02/12/2010 03:31PM by copete23.
Re: Realistic ball rotation
February 12, 2010 04:19PM
Looks like you're using x/z like yaw/pitch? That will never work right, even if you solve most problems you'll still run into Gimbal lock at some point: [en.wikipedia.org]
And you'll create lots of hard math.

One way to solve this is with quaternions. Which is some heavy duty math if you google it. But it's not that hard to use, once you have the code ;)
You can use the following classes I created some time ago: [daid.mine.nu]
TQuat ballRotation;

... in you main loop...
ball.x + = acelx;
ball.z + = acelz;
ballRotation *= TQuat(TVector(acelx, 0, acelz), ballRadius);
You need to tweak the ballRadius, and the acelx, 0, acelz might be in the wrong order.

I'm not sure how to modify the guMtx with the final TQuat, but in openGL this works: glRotatef(acosf(Quat.W) * 360.0f / PI, Quat.Z, Quat.Y, Quat.X);
Re: Realistic ball rotation
February 12, 2010 04:19PM
I think what you are describing is a common Euler angle problem called "Gimbal Lock".

[en.wikipedia.org]

If you use a Quaternions based system to rotate objects, you will have better luck.

EDIT: Doh... All I hear is "You're too slow!" in my ears...



Edited 1 time(s). Last edit at 02/12/2010 04:21PM by Ksmiler.
Re: Realistic ball rotation
February 13, 2010 02:50AM
:D Thanks for the classes Daid, i try to use it in my project, wow, if that is difficult to rotate a simple ball XD

Thanks!



Edited 2 time(s). Last edit at 02/13/2010 04:10AM by copete23.
Re: Realistic ball rotation
February 13, 2010 11:39AM
Actually there's a simple way to do it physically correct. You just have to calculate a vector that is parallel (is that the correct spelling?) to the displacement plane and perpendicular to the rotation direction. Then rotate around it an angle alpha equal to displacement over radius.
for example if the sphere is on a horizontal floor and moving in the direction (1, 0, 0), the vector (the axis of rotation) would be (0, 1, 0). You can calculate these perpendicular vectors using guVecCrossProduct(); Axis = moveDir X surfaceNormal
Then rotation would be calculated as rotation = moveDistance/ballRadius

You would do guMtxRotAxisRad(mR, &Axis, rotation);

It's quite fast to compute, conceptually easy, flexible and just a few lines of code. Moreover, it's perfectly physically correct.

Hope that helps
Re: Realistic ball rotation
February 13, 2010 03:56PM
Hi Technik , I do not find that function, maybe it guVecCross ()?. anyway I have not understood how to do what you say XD sorry, could you give me more details?.

for the direction of the ball I use
ball.x + = ball.acelx;
ball.z + = ball.acely;

acelx and acelz depend on the angle of the wiimote and gravity, perhaps there is the error.

I added Daid classes, to use quaternions, but the result is the same, the axis going berserk (?), Maybe I do something wrong.

TQuat br;
br *= TQuat (TVector (ball.acelx, 0, ball.acelz), (ball.acelz + ball.acelx) / 2);
Vector axis = (br.Z, br.Y,-br.X);

in the the model transformation :
......
..
guMtxRotAxisDeg (ry, & axis, acosf (br.W) * 360.0f / M_PI);
....
..
but does´t work.



Edited 1 time(s). Last edit at 02/13/2010 04:00PM by copete23.
Re: Realistic ball rotation
February 13, 2010 09:20PM
Ok, my fault because I didn't look the function names in libogc.
I'll try to explain:
first: Create a vector containing moving direction of your ball.
guVector moveDir = {ball.accelx, 0, ball.accely};

second: calculate the vector that is normal to the surface tha ball is moving along.
I assume the sphere is moving through X and Z axes in a plane surface.
guVector planeNormal = {0, 1, 0}

third: Calculate the rotation vector
guVector rotationDir;
guVecCross( &moveDir, &planeNormal, &rotationDir);

fourth: Calculate the rotation amount
f32 rotation = sqrt( ball.accelx * ball.accelx + ball.accely * ball.accely);

fifth: Actually rotate it
guMtxRotAxisDeg (mR, &rotationDir, rotation);

That should work fine (assuming I didn't make mistakes). It's all about Newton's mechanics. It's like a wheel in a bike: the axis of rotation (the axis of the wheel) is alwais perpendicular to the move direction (the wheel direction).

Tell me about any doubt or things i may have missed.
Re: Realistic ball rotation
February 14, 2010 05:50PM
It's perfect !! :D, but something must be wrong with my code, because when put
sqrt (ball.accelx * ball.accelx + ball.accely * ball.accely),

the ball does not rotate, perhaps my acceleration Equation is wrong. ....
if I put for example, rotation + = sqrt (ball.accelx * ball.accelx + ball.accely * ball.accely) * 20, the ball rotates fine, but when changing direction, the angles are reversed, and the effect is slightly rare, but it works.

I think maybe I'm not using either the acceleration, to create the acceleration I do this:

ball.acelx + = sinf ((wiimote0-> orient.pitch) * (2 * 3.1416/360)) * ball.gravity;
ball.acelz + = sinf ((wiimote0-> orient.roll) * (2 * 3.1416/360)) * ball.gravity;

ball.x + = ball.acelx;
ball.z + = ball.acelz;
...
..
In my game, the ball moves according to the inclination of the ground, so I use the gravity XD, to move the command the ground moves as the angle XD

Saludos! XD
Re: Realistic ball rotation
February 14, 2010 07:19PM
oh, right, I think I know how to fix that rotation. Intead of applying the guMtxRotAxisRad to your matrix, you have to apply it to a different matrix and then concat those two matrices. Applying directly to your matrix will set your model's rotation to the rotation angle. Instead, applying to another matrix and concatenating them will ADD the rotation to the old position.

There's something else you have to take into account: if your old matrix is not set to the origin when applying rotations, results will be weird so the steps would be:

-Set model matrix to origin (translating functions)
-Concat matrices
-Set model matrix to the ball's position again.

By the way, how do you calculate the normal vector?
Re: Realistic ball rotation
February 14, 2010 07:43PM
Quote

By the way, how do you calculate the normal vector?

I have put only Vector normal={0,1,0} (?)
Re: Realistic ball rotation
February 15, 2010 04:06PM
Ok, just remember that vector will work fine as long as your floor doesn't get completely vertical.
Re: Realistic ball rotation
February 15, 2010 06:37PM
I can`t fix the little mistakes of rotation : (, I applied guMtxRotAxisRad in one of the matrix, and I have concatenated, but does not work, probably because I've done wrong XD

guMtxIdentity (model);

guMtxRotAxisDeg (Mt_1, & dir, rotation);
guMtxRotAxisRad (Mt_2, & dir, rotation);
guMtxConcat (Mt_1, Mt_2, model);

Is this correct?



Edited 1 time(s). Last edit at 02/15/2010 06:37PM by copete23.
Re: Realistic ball rotation
February 15, 2010 08:45PM
No, it's not correct, I need a little bit more of information to help you.
Which matrix do you use to render your ball, how do you calculate it? and how do you handle position? is it stored as a separated vector or in the same matrix?, do you apply it after rotating?

those questions are important because this method is somehow recurrent, it produces correct results when aplied ona alredy correct state.

We're so near to fix this problem, don't worry.
Re: Realistic ball rotation
February 16, 2010 01:16AM
Ok, it´s true, sorry, to draw the ball i use this:

The main mtrix to render the ball and the rest of the scenary is "view"
This is how I have it now:


Vector dir={-ball.acelx,0,-ball.acelz};
Vector normal={0,1,0};
Vector rotationDir;
guVecCross( &dir, &normal, &rotationDir);
rotation +=sqrt(( ball.acelz * ball.acelz + ball.acelx * ball.acelx));

guMtxIdentity(model);

guMtxRotAxisRad (Mt_1, &rotationDir, rotation*20);
guMtxRotAxisDeg(Mt_2, &rotationDir, rotation*20);
guMtxConcat(Mt_1, Mt_2, model);

guMtxTransApply(model, model, x, y, z);
guMtxConcat(view, model, mv);
GX_LoadPosMtxImm(mv, GX_PNMTX0);

guMtxInverse(mv, mvi);
guMtxTranspose(mvi, mv);
GX_LoadNrmMtxImm(mv, GX_PNMTX0);

GX_Begin(GX_TRIANGLES, GX_VTXFMT0, 960);

// draw the ball polygons//

I think that's all :)
Re: Realistic ball rotation
February 16, 2010 01:06PM
Ok, this is what you have to do:
You must have a matrix that is specific to your ball. You don't use it for other objects, for example
Mtx ballMtx; You have to do guMtxIdentity(ballMtx) just once, when you create the ball, for example. Don't do it every frame cause it wouldn't work.
then, every frame, BEFORE updating x, y and z variables, you do this

guMtxRotAxisRad(Mt_1, &rotationDir, rotation);
guMtxTransApply(ballMtx, ballMtx, -x, -y, -z);
guMtxConcat(ballMtx, Mt_1, ballMtx);

//Here you update x, y, z to their new values and:
guMtxTransApply(ballMtx,, ballMtx, x, y, z);
guMtxCopy(ballMtx, model);

those lines must replace these ones:

guMtxRotAxisRad (Mt_1, &rotationDir, rotation*20);
guMtxRotAxisDeg(Mt_2, &rotationDir, rotation*20);
guMtxConcat(Mt_1, Mt_2, model);
guMtxTransApply(model, model, x, y, z);

and rotation must equal the square root, not add it. rotation = sqrt(...) instead of rotation += sqrt(...)
Because it's not an angle, it's an angular speed. and the addition is done in the concat operation.
I think that's all. remember that x, y and z must keep their old values for the first guMtxTransApply, ok?

I think that will work
Re: Realistic ball rotation
February 16, 2010 05:45PM
Ok, then would have to put it that way, does it?

guMtxIdentity(ballMtx);

guMtxRotAxisRad(Mt_1, &rotationDir, rotation);
guMtxTransApply(ballMtx, ballMtx, -x, -y, -z);
guMtxConcat(ballMtx, Mt_1, ballMtx);

//Here you update x, y, z to their new values and:
guMtxTransApply(ballMtx,, ballMtx, x, y, z);
guMtxCopy(ballMtx, model);

guMtxConcat(view, model, mv);
GX_LoadPosMtxImm(mv, GX_PNMTX0);

guMtxInverse(mv, mvi);
guMtxTranspose(mvi, mv);

Anyway, I think there is a problem with my code, because when I set rotation = sqrt (...), the ball does not move, or moves very slowly, I have to, for example, rotation * 800, in guMtxRotAxisDeg, or * 20 on guMtxRotAxisRad, to move ...... I'll explain better with a video XD:

if I put:
rotation = sqrt (...);
guMtxRotAxisDeg (Mt_1, & rotationDir, rotation * 800); or guMtxRotAxisRad (Mt_1, & rotationDir, rotation * 20)

this is what happens: [www.youtube.com]


if I put:
rotation + = sqrt (...);
guMtxRotAxisDeg (Mt_1, & rotationDir, rotation * 20);

this is what happens: [www.youtube.com]
Re: Realistic ball rotation
February 17, 2010 04:16PM
Ok, you have to use Radians, not degrees, since we're computing angles from displacement. I had forgotten that rotation speed is also dependent on radius, wich explains why you have to multiply by 20. What is the radius of you sphere?
As you can see, when using += sqrt(...) instead of = sqrt(...) there are some weird rotations, so obviously the first option is the correct.
Re: Realistic ball rotation
February 17, 2010 07:12PM
:) Ok, the sphere radius is 2 (in pixels), anyway in video 1 when I change the angle of the wiimote, the rotation changes the direccicion immediately, not gradually as the direction of the ball, or what is the same, the ball has an inertia, against the faster it goes, more difficult to reverse its direction, but whith "rotation = sqrt (...);" the direction of rotation is reversed very quickly. XD
Re: Realistic ball rotation
February 18, 2010 03:29PM
hmmm...let me think...Ok, I know what happens (I think)
The effect of gravity on a rigid body can be represented as an acceleration applied to the center of mass of the body. So we should store in a vector the position of the sphere and in another vector it's current speed. Every frame we should add the acceleration components (obtained from the wiimote) to the speed of the ball, then use the new speed to compute both the new position and the angular velocity (our rotation variable). All the problems related to inertia etc are likely to be due to the fact that we're using gravity acceleration as a velocity instead of a force. change that and the simulation will should be physically (and numerically) correct assuming the units are correct. One more thing, the factor to multiply the rotation by should be one over the radius.

PD: I'm sure that if we had a paper to write a couple of equations and draw a few things this problem would have been solved in 5 minutes instead of days...xD

PD: Congratulations for those cool 3D grafics ;)
Re: Realistic ball rotation
February 18, 2010 06:11PM
XD Ok, I'll try to do that, he, he, he, I never thought that would be so difficult to rotate a ball XDD
Sorry, only registered users may post in this forum.

Click here to login