gmseed
JGO n00b  Posts: 11
|
 |
«
on:
2008-07-29 15:43:55 » |
|
Hi
I have the following method that draws a cylinder using gluCylinder().
The GL quadric is oriented so that its axis is along the z-axis (0,0,1). Since my Cylinder object can be arbitrarily oriented it is necessary to correctly rotate the cylinder. This is done using the method directionAngles(), which computes the direction angles between the rotated cylinder z-axis and the fixed global axes (1,0,0), (0,1,0) and (0,0,1).
For cylinder axes (1,0,0) and (0,1,0) the cylinder is correctly oriented. However, if I set the axis to lie along th z-axis (0,0,1) then it incorrectly points in the x-direction.
Can anyone see what I'm doing wrong?
Thanks
Graham
public void toOpenGL(final javax.media.opengl.GLAutoDrawable gLDrawable) { javax.media.opengl.GL gl = gLDrawable.getGL(); javax.media.opengl.glu.GLU glu = new javax.media.opengl.glu.GLU(); // cylinder base circle 1 centre and axis Point3D base1Centre = getEndCircle1Centre(); Vector3D cylinderAxis = getAxisVector(); double baseCircle1Radius = getEndCircle1Radius(); double baseCircle2Radius = getEndCircle2Radius(); double axisLength = axisLength(); Double alpha = new Double(); Double beta = new Double(); Double gamma = new Double(); cylinderAxis.directionAngles(alpha,beta,gamma,true); gl.glTranslated(base1Centre.getX(),base1Centre.getY(),base1Centre.getZ()); // translate wrt base circle 1 gl.glRotated(alpha.getValue(),1.0,0.0,0.0); // rotate the cylinder on the x axis gl.glRotated(beta.getValue(),0.0,1.0,0.0); // rotate the cylinder on the y axis gl.glRotated(gamma.getValue(),0.0,0.0,1.0); // rotate the cylinder on the z axis
javax.media.opengl.glu.GLUquadric quadric = glu.gluNewQuadric(); // create a pointer to the quadric object glu.gluQuadricNormals(quadric,javax.media.opengl.glu.GLU.GLU_SMOOTH); // create smooth normals glu.gluQuadricTexture(quadric,true); // Create Texture Coords glu.gluQuadricOrientation(quadric,javax.media.opengl.glu.GLU.GLU_OUTSIDE); // normals acting outwards if (joglObject.getIsWireframe()) glu.gluQuadricDrawStyle(quadric,javax.media.opengl.glu.GLU.GLU_LINE); else glu.gluQuadricDrawStyle(quadric,javax.media.opengl.glu.GLU.GLU_FILL); glu.gluCylinder(quadric,baseCircle1Radius,baseCircle2Radius,axisLength,25,15); // quadric - base1 radius - base2 radius - axis length - circ div - axis div
glu.gluDeleteQuadric(quadric); // free up quadric memory }
public void directionAngles(Double alpha, Double beta, Double gamma, final boolean degrees) { double n = norm(); if (Functions.abs(n) > Tolerances.TOLERANCE) { if (!degrees) { alpha.setValue(Functions.acos(ma/n)); beta.setValue(Functions.acos(mb/n)); gamma.setValue(Functions.acos(mc/n)); } else { alpha.setValue(Functions.radiansToDegrees(Functions.acos(ma/n))); beta.setValue(Functions.radiansToDegrees(Functions.acos(mb/n))); gamma.setValue(Functions.radiansToDegrees(Functions.acos(mc/n))); } } }
|
|
|
|
|
lhkbob
JGO Neuromancer     Posts: 1174 Medals: 35
|
 |
«
Reply #1 on:
2008-07-30 00:30:43 » |
|
Just off of the top of my head, I believe that this is referred to as gimbal lock (experienced when trying to represent every rotation as a sequence of x,y,z angle rotations). You may want to switch to arbitrary axis angles or using quaternions. openmali and javax have a vecmath package that provides good support for these math objects.
BTW I didn't check your code, it's just the problem you described seemed to fit gimbal lock very well.
|
|
|
|
gmseed
JGO n00b  Posts: 11
|
 |
«
Reply #2 on:
2008-07-30 04:23:45 » |
|
Hi Thanks for your reply. An object such as a cylinder is stored as: public class Cylinder3D { /** End cap 1. */ protected PlanarCircle3D mEndCircle1; /** End cap 2. */ protected PlanarCircle3D mEndCircle2; /** Cylinder axis. */ protected Curve3D mAxis; /** Specifies whether or not the cylinder is open. */ protected boolean mIsOpen; //... } It's then the mapping of this object to the opengl representation that I'm not clear about. It's one thing using glRotate() to rotate an object about an arbitrary vector but it's another thing to map an object from one orthogonal coordinate system to another. Thanks for suggesting gimbal lock. I found a useful description at: http://en.wikipedia.org/wiki/Gimbal_lockGraham
|
|
|
|
|
Games published by our own members! Go get 'em!
|
|
gouessej
JGO Kernel      Posts: 3558 Medals: 30
TUER
|
 |
«
Reply #3 on:
2008-07-30 07:38:25 » |
|
Quaternions are not enough to solve the problem of gimbal lock. You need to use non eulerian transforms to avoid gimbal lock and it is easier to use this kind of transform with quaternions. A lot of people use quaternions + eulerian transforms, that leads to gimbal lock, I proved it, I worked on gimbal lock during 6 months in 2006. I can show you the formula (given by Pascal Mignot, teacher and researcher at the University of Reims, France) if you want, I need to have a look at my report.
|
Julien Gouesse
|
|
|
gmseed
JGO n00b  Posts: 11
|
 |
«
Reply #4 on:
2008-07-30 11:00:54 » |
|
Hi gouessej I'd be very interested in seeing the equations. I've spent all day trying all sorts of coordinate transformations between local and global axes, using quaternions, euler angles, etc. and still can't get it to work. Any rotation can be reducd to an angular rotation about an arbitrary axis but this is an unnatural way of thinking of mapping one orthogonal coordinate system to another. I also tried converting an orthogonal 3x3 rotation matrix to axis-angle form which I then fed into glRotate(angle,(axis)) but still can't get it to work!! My email address is gmseed@gmail.com. Thanks for your assistance as this is driving me crazy!! Graham
|
|
|
|
|
lhkbob
JGO Neuromancer     Posts: 1174 Medals: 35
|
 |
«
Reply #5 on:
2008-07-30 13:59:37 » |
|
I've had good success using 3x3 rotation matrices, you just have to make sure that the angle you give opengl is in degrees. If I'm starting with the identity as my transform, or I'm pushing relative rotation transforms, it's helpful to create the 3x3 matrix by envisioning the axis of the desired basis. Then the columns of the rotation are those axis, if you want to convert a local coordinate system into a world or parent system.
|
|
|
|
gouessej
JGO Kernel      Posts: 3558 Medals: 30
TUER
|
 |
«
Reply #6 on:
2008-07-31 04:22:40 » |
|
I've had good success using 3x3 rotation matrices, you just have to make sure that the angle you give opengl is in degrees. If I'm starting with the identity as my transform, or I'm pushing relative rotation transforms, it's helpful to create the 3x3 matrix by envisioning the axis of the desired basis. Then the columns of the rotation are those axis, if you want to convert a local coordinate system into a world or parent system.
It reduces the risk of gimbal lock as it decreases the accumulation of errors (you start with the identity) but it doesn't solve the problem completely. It is not so simple. I'm going to post the formula today, I'm at work, I need to find the report.
|
Julien Gouesse
|
|
|
gouessej
JGO Kernel      Posts: 3558 Medals: 30
TUER
|
 |
«
Reply #7 on:
2008-08-01 07:22:10 » |
|
http://www.univie.ac.at/cga/faq/angles.htmlThe answer is here: The current rotations must respect the previous rotations to avoid gimbal lock to prevent any alignment of rotation axis which causes this problem. This problem doesn't depend on the mathematical way you choose to express rotations, it depends on the way to combine rotations. The problem comes from Euler's classical transform: R=Rx.Ry.Rz Implicitely or explicitly you use it with matrices, quaternions, Euler or Cardan angles, ... You should correct this transform and it works whatever you used to express your rotations: R=R[R[R[Ox,a]Oy,b]R[Ox,a]Oz,c] . R[R[Ox,a]Oy,b] .R[Ox,a]. Contributed by Julien Gouesse
|
Julien Gouesse
|
|
|
lhkbob
JGO Neuromancer     Posts: 1174 Medals: 35
|
 |
«
Reply #8 on:
2008-08-01 12:32:23 » |
|
Interesting, but could you explain the notation when you wrote the equation: Specifically, what math operations are you doing when you say R[Ox, a], or R[ R[Ox, a]Oy, b]
Thanks,
|
|
|
|
gouessej
JGO Kernel      Posts: 3558 Medals: 30
TUER
|
 |
«
Reply #9 on:
2008-08-06 07:48:34 » |
|
Interesting, but could you explain the notation when you wrote the equation: Specifically, what math operations are you doing when you say R[Ox, a], or R[ R[Ox, a]Oy, b]
Thanks,
R[Ox,a] is a rotation around the X axis of an angle measuring a. Then you can apply such a tranform on another axis. I have a source code that uses this algorithm but it is very complicated and it is in C++ as I haven't put this in TUER for the moment. If you're interested, let me know.
|
Julien Gouesse
|
|
|
Games published by our own members! Go get 'em!
|
|
|
|
lhkbob
JGO Neuromancer     Posts: 1174 Medals: 35
|
 |
«
Reply #11 on:
2008-08-07 00:17:52 » |
|
The link seemed broken, and would eventually redirect to lycos.fr's homepage. I can't say exactly what happened since I can't speak French. Is there anyway you could e-mail me the zip?
|
|
|
|
gouessej
JGO Kernel      Posts: 3558 Medals: 30
TUER
|
 |
«
Reply #12 on:
2008-08-07 01:07:54 » |
|
The link seemed broken, and would eventually redirect to lycos.fr's homepage. I can't say exactly what happened since I can't speak French. Is there anyway you could e-mail me the zip?
Now the link should work. If not, I will transfer the zip onto another server because I want to allow everyone to download the source code.
|
Julien Gouesse
|
|
|
|