🔒 Locked
Rolling balls
Advertisement
Original Post
I''m trying to create the effect of balls rolling in my Pong game. I thought his would do it:
glPushMatrix();
glTranslatef(xcoord,ycoord,zcoord);
glRotatef( xcoord * 360.0f/(2 * PI * radius), 0, 1, 0);
glRotatef(-ycoord * 360.0f/(2 * PI * radius), 1, 0, 0);
glCallList(ballList);
glPopMatrix();
If the ball rolls in just one "direction" i.e. purely up and down or purely left and right then the above code works. But if it''s rolling at an angle, say 45° between x and y then it does very bizarre things.
Is this an example of gimbal lock, or am I just doing something stupid?
- seb
You''re doing it wrong. You need to rotate it about a horizontal (i.e. in the x-y plane) axis which is perpendicular to the direction of motion. The direction of motion is given by the velocity, which also dictates how quickly it rotates.
So do something like
vDir = vCoord - vLastCoord [velocity in units per frame]
fRot = sqrt(vDir.x + vDir.x + vDir.y * vDir.y) [speed]
vAxis = {vDir.y, -vDir.x, 0} [ axis perpendicular to direction of travel
and use these to build your matrix like this
glRotatef(fRot * 360.0f/(2 * PI * radius), vAxis.x, vAxis.y, 0);
You may need to change a sign, e.g. of fRot in the glRotatef, but otherwise this should work.
So do something like
vDir = vCoord - vLastCoord [velocity in units per frame]
fRot = sqrt(vDir.x + vDir.x + vDir.y * vDir.y) [speed]
vAxis = {vDir.y, -vDir.x, 0} [ axis perpendicular to direction of travel
and use these to build your matrix like this
glRotatef(fRot * 360.0f/(2 * PI * radius), vAxis.x, vAxis.y, 0);
You may need to change a sign, e.g. of fRot in the glRotatef, but otherwise this should work.
No it's not that simple johnB.
Think about it. If the ball's moving in a constant direction and redrawing with that lot each time then the ball will rotate (from what it would look like as if stationary) but will always rotate by the same amount. I need to adapt your code so that it's cumulative, if you see what I mean.
- seb
Edited by - bsxrider on February 13, 2002 1:23:47 PM
Think about it. If the ball's moving in a constant direction and redrawing with that lot each time then the ball will rotate (from what it would look like as if stationary) but will always rotate by the same amount. I need to adapt your code so that it's cumulative, if you see what I mean.
- seb
Edited by - bsxrider on February 13, 2002 1:23:47 PM
This sort of works:
glPushMatrix();
glTranslatef(xcoord,ycoord,zcoord);
static float r=0;
float length = sqrt(vx*vx + vy*vy);
rot += length * seconds;
glRotatef(rot * 360.0f/(2 * PI * radius), -vy, vx, 0);
glCallList(ballList);
glPopMatrix();
Rolls nicely, but looks horrible when the ball changes direction.
- seb
glPushMatrix();
glTranslatef(xcoord,ycoord,zcoord);
static float r=0;
float length = sqrt(vx*vx + vy*vy);
rot += length * seconds;
glRotatef(rot * 360.0f/(2 * PI * radius), -vy, vx, 0);
glCallList(ballList);
glPopMatrix();
Rolls nicely, but looks horrible when the ball changes direction.
- seb
I have a similar quesition, although i dont need to calculate the angles, i already have them. i have 2 angles to rotate tthe ball in.
angle one around X-axis
angle two around Z-axis
note these are axises of the WORLD, not the ball.
im using opengl for gfx and am doing like this now.
glRotatef(m_xrot,1.0f,0.0f,0.0f);
glRotatef(-m_zrot,0.0f,0.0f,1.0f);
DrawBall();
this works only if one of the angles is 0.
thanks in advance and sorry if the answer has been given already.
[edited by - Blechx on November 16, 2003 2:30:05 PM]
angle one around X-axis
angle two around Z-axis
note these are axises of the WORLD, not the ball.
im using opengl for gfx and am doing like this now.
glRotatef(m_xrot,1.0f,0.0f,0.0f);
glRotatef(-m_zrot,0.0f,0.0f,1.0f);
DrawBall();
this works only if one of the angles is 0.
thanks in advance and sorry if the answer has been given already.
[edited by - Blechx on November 16, 2003 2:30:05 PM]
I actually had to do this for a homework assignment.
What I did was store the direction as a vector (I made a class for that), and then I found the cross product of the UP vector and the vector representing the distance, this will give you the axis of rotation (think about it, the cross product will be perpendicular to both vectors). Then to find the distance to translate it, just remember that the displacement (ie: the arc of the sphere) is equal to r*angle in radians, or Pi*r*angle/180 in degrees. Find this value, and multiply it by the unit vector in the direction of the rolling. I can post some code if you need it.
What I did was store the direction as a vector (I made a class for that), and then I found the cross product of the UP vector and the vector representing the distance, this will give you the axis of rotation (think about it, the cross product will be perpendicular to both vectors). Then to find the distance to translate it, just remember that the displacement (ie: the arc of the sphere) is equal to r*angle in radians, or Pi*r*angle/180 in degrees. Find this value, and multiply it by the unit vector in the direction of the rolling. I can post some code if you need it.
Okay, here some code from the program I wrote (I had to roll a ball from point A to B, B to C and then B to A), however it seems as if you are intending to do this a different way. If this doesn''t help you out let me know and I can code up something that will work with the parameters you have.
I have two classes, Vector3f and Vertex3f. g_AB, g_VUP, g_dir and g_rot are vectors whereas g_sphereLoc and g_aLoc are vertices. g_angleSphere is just a float representing the angle that the ball has rotated so far. PI180 is a constant set to Pi/180 (to convert degrees to radians).
In the initialization code you can see I am setting g_unit equal to the unit vector pointed in the same direction as the vector AB (which is the direction that the ball is rolling). I have set the initial location of the sphere to point A. The angle of rotation has been set to 0, and the axis of rotation is set to the cross product of the UP vector and the vector AB (you could also use the g_unit vector).
In the updating code, I have incrimented the angle by which to rotate the ball, and then calculated the magnitude of the displacement of the ball (which as I said before is equal to the radius*angle). Since the radius is one all I have to do find the angle in radians. After finding the magnitude I multiplied the unit vector by the magnitude so that the translate has both a direction and a distance.
In the drawing code I first rotated the ball by the angle specified around the axis I computed in the initialization. I then translated the ball the appropriate distance in the appropriate direction and also translated it to point A.
// initializing code
g_unit = g_AB.unitVector(); // set the unit vector in the direction of AB
g_sphereLoc = g_aLoc;
// reset the angle
g_angleSphere = 0.0f;
// change the rotational vector to VUP x AB
g_rot = g_VUP.cross(g_AB);
// ...
// updating code
// incriment the angle of rotation
g_angleSphere += 0.5f;
// update the direction vector
g_dir = g_unit*(PI180*g_angleSphere);
// ...
// drawing code
// translate the sphere
glPushMatrix();
glTranslatef(g_sphereLoc.x, g_sphereLoc.y, g_sphereLoc.z);
glTranslatef(g_dir.i, g_dir.j, g_dir.k);
glRotatef(g_angleSphere, g_rot.i, g_rot.j, g_rot.k);
// set the color to golden yellow for the sphere
glColor3f(1.0, 0.84, 0.0);
// draw the sphere
drawSphere();
glPopMatrix();
I have two classes, Vector3f and Vertex3f. g_AB, g_VUP, g_dir and g_rot are vectors whereas g_sphereLoc and g_aLoc are vertices. g_angleSphere is just a float representing the angle that the ball has rotated so far. PI180 is a constant set to Pi/180 (to convert degrees to radians).
In the initialization code you can see I am setting g_unit equal to the unit vector pointed in the same direction as the vector AB (which is the direction that the ball is rolling). I have set the initial location of the sphere to point A. The angle of rotation has been set to 0, and the axis of rotation is set to the cross product of the UP vector and the vector AB (you could also use the g_unit vector).
In the updating code, I have incrimented the angle by which to rotate the ball, and then calculated the magnitude of the displacement of the ball (which as I said before is equal to the radius*angle). Since the radius is one all I have to do find the angle in radians. After finding the magnitude I multiplied the unit vector by the magnitude so that the translate has both a direction and a distance.
In the drawing code I first rotated the ball by the angle specified around the axis I computed in the initialization. I then translated the ball the appropriate distance in the appropriate direction and also translated it to point A.
I dont think taht code applies to my problem really :/ (or im just to stupid to understand it) 
you seem to be using one angle only, i use 2.
i basicly just need a way of rotating it according to those 2 angles, this distance calculation and translating i have no use for. The ball will only rotate vertical or horizontal, never diagonal, if this helps.
you seem to be using one angle only, i use 2.
i basicly just need a way of rotating it according to those 2 angles, this distance calculation and translating i have no use for. The ball will only rotate vertical or horizontal, never diagonal, if this helps.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement