Rolling ball

Started by
5 comments, last by haegarr 18 years ago
Hello, I am trying to ceate a rolling ball(textured in the future) with OpenGL and GLUT, but don't know how to make it rotate correctly. My main obstacle is that if I use glRotatef(...), then the whole coordinate system moves and I cannot rotate around other axises correctly. One solution is to use an Angle Axis. Then all I need is vector laying in the plane parallel to the ground. All I have to do is to orientate this vetor in the direction perpendicular to when I want to roll and then give it the correct rotation anlge. But how do I keep this vector in this plane and furthermore, how do I orientate it, if the coordinate system is always changing? Somebody suggested using quaternions, but I don't quite understand how they can help my case? I read Quaternion Powers and understood that I can represent the start orientation as a quaternion. Given the input, I convert it to quaternion, multiply those 2 quaternions, get the final orientation quaternion, set it as the current orientation, convert it to Axis Angle representaion, perform the rotaion(or maybe convert quaternion to matrix and just load the matrix with glLoadMatrix*() ?). But what if I want to roll it somewhere else after that? OK, I convert the 2nd rotation into quaterion, multiply them .... just repeat the procedure, but still the rotation will be done with respect to coordinate axises of the changed coordinate system, or not? I am getting confused here. Could you help me, please? Also what is publicly available good library representing quaternions? Thank you very much! Kostya.
Advertisement
Quote:Original post by kostyabkg
My main obstacle is that if I use glRotatef(...), then the whole coordinate system moves and I cannot rotate around other axises correctly. One solution is to use an Angle Axis.

But glRotate does exactly that: an axis/angle rotation.

Quote:Original post by kostyabkg
Then all I need is vector laying in the plane parallel to the ground. All I have to do is to orientate this vetor in the direction perpendicular to when I want to roll and then give it the correct rotation anlge. But how do I keep this vector in this plane and furthermore, how do I orientate it, if the coordinate system is always changing?

Assume a planar, horizontal ground for now, so that
n := [ 0 1 0 ]
denotes its normal, so that is extending in the x/z plane. If furthurmore
d := [ dx 0 dz ]
denotes the vector you push the ball at this moment (i.e. it is the the current displacement vector, computed e.g. as the product of the current velocity vector and the time period elapsed since the latest ball position update), then
a := n x d / ||d||
(where x denotes the cross product) is the axis of rotation. Notice that n is assumed to be of unit length here.

The angle is given from the rolled distance and the radius R of the ball (okay, I assume a straight movement here) as
β := ||d|| / R from ||d|| = ( β / 2π ) * 2π R
So an axis/angle pair is given.

Quote:Original post by kostyabkg
Somebody suggested using quaternions, but I don't quite understand how they can help my case?

Store the current orientation of the ball in a (unit) quaternion. Make a rotation representing quaternion from the axis angle/pair above. Multiply the current orientation with the rotation to yield in the updated current orientation. Convert the updated quaternion into a matrix, and multiply that matrix by glMultMatrix as substitute for glRotate.

Moreover, track the position of the ball's center analoguously. Store the current position in a (positional) vector. Add the displacement vector d from the explanation above to the current position to yield in the updated current position. glTranslate the ball by the updated current position.

Notice that the "current orientation" and "current position" as defined above store absolute values. So the overall transformation may look like
// here the ball is located at the world's originglMultMatrixf( matrixFromOrientationQuaternion );glTranslatef( vectorFromPosition );glTranslatef( 0, R, 0 ); // to have the ball's center R units above the ground


Notice that the ball's orientation and location are tracked by yourself but not by OpenGL. That is a wise principle as many people here at GDnet will suggest you. For a more advanced handling (e.g. a not flat and horizontal ground a little bit more effort is to be taken, but that is a piece of work following later ;) For now I hope you have a push in the correct direction.


EDIT: An accidentally introduced v is corrected: It became n.

[Edited by - haegarr on March 29, 2006 7:11:50 AM]
Thank you very much!

I just have a few more questions here regarding your answer:
In this equasion:
a := v x d / ||d||
What is "v" and what do you demark with ||d||? Is it the length of the vector? Right? So it will be sqrt(x*x+y*y+z*z).
Oh, also what do you mean by saying cross-product - is it a vector multiplication, correct? And dot-product would be scalar multiplication.
I am sorry, I studied math in Russia and not quite familiar with some details of western notation.
Yes, this is quite simple, your answer. Shame on me I didn't get it myself. I wish so much for my math books to be with me, I regretted thousand times maybe I left them.
Is there any good web-site with geometry stuff in english that you might recommend?

And also about the library: could you recommend me some library with vectors and quaternions?

And thank you again!
Kostya.
Quote:Original post by kostyabkg
a := v x d / ||d||
What is "v" and what do you demark with ||d||? Is it the length of the vector? Right? So it will be sqrt(x*x+y*y+z*z).

Yes. In fact it is the general symbol for a norm. The length of a vector is its 2-norm, to be precise:
|v| = ||v||2 := sqrt( Πi vi )
Sorry for that little confusion; I have the tendency to complicate things ;)

v is, ahem, an error; it should be n. I'm going to correct that in the original post.

Quote:Original post by kostyabkg
Oh, also what do you mean by saying cross-product - is it a vector multiplication, correct? And dot-product would be scalar multiplication.

Right you are: Cross product and vector product are synonyms.

Quote:Original post by kostyabkg
I am sorry, I studied math in Russia and not quite familiar with some details of western notation.
Yes, this is quite simple, your answer. Shame on me I didn't get it myself. I wish so much for my math books to be with me, I regretted thousand times maybe I left them.

No matter. But be aware that the posted stuff isn't complete. The interesting part comes when forces are applied to the ball, e.g. gravity forces the ball to roll "by iteself" down a slope...

Quote:Original post by kostyabkg
Is there any good web-site with geometry stuff in english that you might recommend?

This site was helpful to me in the one or other situation.

Quote:Original post by kostyabkg
And also about the library: could you recommend me some library with vectors and quaternions?

I think there are dozens out there, but I don't know any. I've written the stuff I need myself.
I got it rolling, thank you!

My problem actually was that I wasn't quite realising what Multiplication of Matrices would do. I was trying to figure out how to rotate the ball AFTER it has been rotated, but I should rotate it first and only then to multiply the rotation by the saved matrix and then to multiply that matrix by the current "view" matrix.

Thank you very much anyways! This web-site you pointed at seems to be very helpful as well.

Kostya.

[Edited by - kostyabkg on March 31, 2006 4:04:47 AM]
Just one more question: why when I draw floor first and then the ball, the floor covers the ball? Isn't OpenGL supposed to test all of the objects for z-depth value before drawing?

Thank you.
Quote:Original post by kostyabkg
why when I draw floor first and then the ball, the floor covers the ball? Isn't OpenGL supposed to test all of the objects for z-depth value before drawing?

Perhaps depth test isn't enabled or otherwise not correctly set-up.

Do you have a line like
glEnable(GL_DEPTH_TEST);
anywhere before rendering? (I don't know whether depth test is enabled at default, but I think it isn't.)

Less likely, have you changed the depth comparison function? It should be
glDepthFunc(GL_LESS);
for passing less depth values. Here I know that GL_LESS is the default, so you don't need setting GL_LESS if you have not altered it before.

EDIT: I assume you have claimed a depth buffer on creation of the context, but have you actually got one?

[Edited by - haegarr on March 31, 2006 4:24:51 AM]

This topic is closed to new replies.

Advertisement