PDA

View Full Version : Ball Rolling effect



CLoNA
02-22-2003, 07:52 PM
Hi
I'm creating a 3d billiard game and I want the ball to have a rolling effect (e.g. Texture appears to be rolling). The balls are moving only on the X-Z plane.

I have tried to find a perpendicular vector to the direction of moving ball.
How can I make the ball roll around this vector if it is not paralle to the X,Z plane? and
How do I calculate the angle of rotation?

Btw a sample code may be easier to understand.

Thkx

rgpc
02-23-2003, 12:42 AM
First, to calculate the axis around which the ball will be rotating, take the y axis, and do a cross product with the normalized velocity vector.

A = Y x v

Then the amount of the rotation is equal to the length of time (since the last frame or since the last update of the balls position) multiplied by the velocity divided by the radius of the ball.

R = vT/r

Then we use quaternions to add this rotation to the total rotation of the ball. (See the "AddRotation" bit...

For a good description of Quaternions (one of the MANY) see www.delphi3d.net (http://www.delphi3d.net)




// Get the per second velocity of the ball
fLen = velocity.Magnitude();
// Rotation = (Time * velocity) / radius
fAngle = (fLen * utilGlobal.fSeconds) / (pLevels[0]->boundingsphere.radius);

vVertical.y = 1.0f;
vVelocity.x = velocity.x / fLen;
vVelocity.y = velocity.y / fLen;
vVelocity.z = velocity.z / fLen;
vAxis = vVelocity.CrossProduct(&vVertical);

rotation.AddRotation(&vAxis, fAngle);



AddRotation(VECTOR, ANGLE)

This is part of a larger class used to represent a Quaternion rotation.





void QUATERNION::AddRotation(VERTEX *vAxis, float fAngle)
{
QUATERNION qTemp;
float fS;

// Convert Axis/Angle to Quaternion
fS = (float)sin((double)(fAngle / 2.0f));
qTemp.w = (float)cos((double)(fAngle / 2.0f));
qTemp.x = fS * vAxis->x;
qTemp.y = fS * vAxis->y;
qTemp.z = fS * vAxis->z;

// Multiply two Quats.
Multiply(&qTemp);

} // End of QUATERNION::AddRotation()


void QUATERNION::Multiply(QUATERNION *qOther)
{
VERTEX v1;
VERTEX v2;
VERTEX vCross;
float fW;
float fX;
float fY;
float fZ;

v1.x = x;
v1.y = y;
v1.z = z;
v2.x = qOther->x;
v2.y = qOther->y;
v2.z = qOther->z;
vCross = v1.CrossProduct(&v2);

fW = (w * qOther->w) - v1.DotProduct(&v2);
fX = (w * qOther->x) + (qOther->w * x) + vCross.x;
fY = (w * qOther->y) + (qOther->w * y) + vCross.y;
fZ = (w * qOther->z) + (qOther->w * z) + vCross.z;

w = fW;
x = fX;
y = fY;
z = fZ;
} // End of QUATERNION::GetRotation()

/***
* Use this to get the values for use in glRotatef() when drawing your primitive.
***/
void QUATERNION::GetRotation(VERTEX *vAxis, float *fAngle)
{
float fS;

Normalise();

fS = (x * x) + (y * y) + (z * z);
if (fS < FLOAT_TOLERANCE)
{
vAxis->x = vAxis->z = 0.0f;
vAxis->y = 1.0f;
*fAngle = 0.0f;
}
else
{
vAxis->x = x / fS;
vAxis->y = y / fS;
vAxis->z = z / fS;
*fAngle = 2.0f * (float)acos(w);
}
} // End of QUATERNION::GetRotation()




[This message has been edited by rgpc (edited 02-23-2003).]

rgpc
02-23-2003, 04:08 PM
Oh yeah and I forgot to mention, this is not an OpenGL question (let alone an advanced one).

Don't do it again.