gluCylinder look at (solved)

This topic is 4485 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Hello, I have a normalized direction vector, but I'm having problems coming up with the rotation matrix needed to make a tapered gluCylinder (a cone basically) point in the same direction. Does anyone have any idea on how to do this? Any help would be much appreciated. [Edited by - taby on September 1, 2005 12:04:53 AM]

Share on other sites
There are a couple ways to get an appropriate rotation matrix. You can decompose the direction vector into spherical coordinates, map them to a Euler angle pair, and then use glRotate(). Or, you could construct an orthonormal basis from the direction vector and load it directly to OpenGL.

Let me know if you need more details.

[Oop, one more method, and probably the easiest: call glRotate() with an axis-angle pair constructed from the direction vector and whichever world axis your object is aligned with.]

[Edited by - jyk on August 31, 2005 3:16:15 PM]

Share on other sites
To be honest, any of these sound appealing, but I don't have the OpenGL know-how to go about performing any of them.

So far I've tried performing a cross product of the cylinder's direction (0, 0, 1) and the direction vector, then used that as the axis for glRotatef, but no luck.

Thanks very much for the head-start. I'll try looking into these methods if you don't get back with a more hands-on explanation. :)

Share on other sites
Quote:
 So far I've tried performing a cross product of the cylinder's direction (0, 0, 1) and the direction vector, then used that as the axis for glRotatef, but no luck.
How exactly does it not work?

Here are a few things to keep in mind:

1. I think glRotate() normalizes the axis for you, but you might normalize it yourself to be sure.

2. You should detect the case where the direction vector is very nearly equal to (0,0,1), and load the identity matrix instead.

3. Given your input, the angle can be found as acos(a.Dot(b)). There are other, perhaps better, ways to get the angle, but that should work. Don't forget to clamp the input to acos() to the range [-1,1].

4. OpenGL uses degrees rather than radians, so you'll probably have to convert before calling glRotate().

If none of the above clears up your problem, you might post the relevant code.

Share on other sites
This is the code I have so far, based on some help from ETG #opengl, where temp_ are my normalized direction vector components:

float lenx = sqrtf(temp_z*temp_z + temp_y*temp_y);float leny = sqrtf(temp_x*temp_x + temp_z*temp_z);glRotatef( acos( temp_x/leny )*180.0f/3.14f, 0, 1, 0 );glRotatef( acos( temp_z/lenx )*180.0f/3.14f, 1, 0, 0 );

Someone also told me it would be easiest to convert the vector to Euler angles, but I'm not sure how to do that.

Share on other sites
Quote:
 Someone also told me it would be easiest to convert the vector to Euler angles, but I'm not sure how to do that.
That was actually one of my initial suggestions. Here's an implementation:

// x,y,z are direction vector componentsfloat yaw;if (fabs(x) < epsilon && fabs(z) < epsilon) // epsilon is some small number    yaw = 0.0f;else    yaw = atan2(x,z);float pitch = -atan2(y,sqrt(x*x+z*z));// * Convert to degrees here *glRotatef(yaw, 0.0f, 1.0f, 0.0f);glRotatef(pitch, 1.0f, 0.0f, 0.0f);

Can't guarantee I got that right, but you might give it a try.

Share on other sites
It's working now...

The colour of the cone is determined by hue. that is: direction vector . static reference vector* -- Add 1.0 to the result, then multiply by 180 to get a value between 0 and 360 (colour circle)

At least the colouring is working :)

// * static reference vector is:static const float orientor_x = 0.57735f;static const float orientor_y = 0.57735f;static const float orientor_z = -0.57735f;

A no license implementation of the code is available for performing HSBtoRGB, if requested.

[Edited by - taby on September 1, 2005 11:49:35 AM]

Share on other sites
Are the cones supposed to be aligned with the lines passing through them? If so, I think the problem is not (necessarily) how you're constructing the rotation matrix, but how you're handling the cone transformation in general. If I were you I'd post the code that sets up the transform for and renders a single cone. I'm guessing there may be an obvious error in there somewhere that will be easy to fix.

Share on other sites
A ZIP of the working SDL C++ source is at:

Hopefully it doesn't lock up on you, like reported elsewhere.
Controls are in the console window launched via main. 'v' for velocity cones, in particular.

[Edited by - taby on September 1, 2005 11:07:42 AM]

Share on other sites
Quick question. When you tried the last bit of code I posted, did you convert yaw and pitch from radians to degrees before calling glRotate()?

If so, and it still didn't work, I would try the following. Stick some simple rotation in there, such as 90 degrees about a world axis, and see if it works. If it doesn't, the problem is probably somewhere else, rather than in the rotation code itself.

Share on other sites
I did not think to convert them to degrees, even though it was right in front of my eyes. I am terribly sorry.

Thank you very much. It works perfectly!!

I have updated the screenshot from above to show that it works.

Edit:
If you want to be listed as a reference, please send me a private message.

[Edited by - taby on September 1, 2005 12:43:51 AM]

Share on other sites
Great, I'm glad it works :)

(Are you sure you updated your image, though? It looks the same to me...)

Share on other sites
I had to refresh my browser to see the new image.

I hope that the colouring system might be something novel for you.

Share on other sites
Ah, there it is :) Very nice!

Share on other sites
Quote:
Original post by jyk
Quote:
 Someone also told me it would be easiest to convert the vector to Euler angles, but I'm not sure how to do that.
That was actually one of my initial suggestions. Here's an implementation:

*** Source Snippet Removed ***
Can't guarantee I got that right, but you might give it a try.

that takes care of yaw and pitch, but what about roll?

Share on other sites
Quote:
Original post by godecho
Quote:
Original post by jyk
Quote:
 Someone also told me it would be easiest to convert the vector to Euler angles, but I'm not sure how to do that.
That was actually one of my initial suggestions. Here's an implementation:

*** Source Snippet Removed ***
Can't guarantee I got that right, but you might give it a try.

that takes care of yaw and pitch, but what about roll?

If you set it to some constant non-zero number, the cones will spin like ballerinas? :)

Share on other sites
Quote:
 that takes care of yaw and pitch, but what about roll?
It's irrelevant. The problem as originally stated was to construct a rotation matrix to align the z axis with an arbitrary vector, for which there is no unique solution. We can however find a solution to the problem; to do so, we need only consider two rotation axes, not three.

Share on other sites
Hi again,

I was wondering... what is the name of the law or identity or postulation or whatever it is that says that arctan can retrieve those angles?

Anyway, thanks again for your help jyk, the program is working beautifully.

Share on other sites
Quote:
 I was wondering... what is the name of the law or identity or postulation or whatever it is that says that arctan can retrieve those angles?
It's basically just trigonometry. The c++ atan2() function takes the (possibly scaled) sine and cosine of an angle, and returns the angle. In programming terms, it's more useful than atan() because there are fewer degenerate cases.

To extract yaw and pitch from a direction vector, you can find the yaw by projecting the vector onto the 'ground' plane and using atan2(). For pitch, you form a triangle between the tip of the vector, the origin, and the projection of the tip onto the ground plane. Then you can use atan2() again to find the angle.

Since you've got everything working nicely, you probably won't want to hear this! But, if this were my program I'd actually use a different method than the one I gave you. The reason I posted the yaw/pitch method is that it's only a few lines of code, and you can use glRotate(). However, a more stable solution is to construct an orthonormal basis from the direction vector and submit it to OpenGL via glMultMatrix(). It wouldn't cost you anything to try it - you could just comment out the yaw/pitch version and substitute the orthonormal basis version, and see if it worked.

If you're interested, I could probably post some code for this other method later this evening.

Share on other sites
I would be more than interested to know more about this type of thing. The better I understand it, the easier other things will come.

Share on other sites
I'll attempt to sketch out the orthonormal basis code:

Vector3 z = direction; // direction should already be normalizedVector3 axis; if (fabsf(z.x) <= fabsf(z.y) && fabsf(z.x) <= fabsf(z.z))     axis.Set(1, 0, 0); else if (fabsf(z.y) <= fabsf(z.x) && fabsf(z.y) <= fabsf(z.z))     axis.Set(0, 1, 0); else     axis.Set(0, 0, 1); Vector3 x = z.Cross(axis);x.Normalize();Vector3 y = z.Cross(x);float m[16];m[0] = x.x;m[1] = x.y;m[2] = x.z;m[3] = 0.0f;m[4] = y.x;m[5] = y.y;m[6] = y.z;m[7] = 0.0f;m[8] = z.x;m[9] = z.y;m[10] = z.z;m[11] = 0.0f;m[12] = 0.0f;m[13] = 0.0f;m[14] = 0.0f;m[15] = 1.0f;glMultMatrixf(m);

This isn't the most elegant or efficient implementation, but it should work just fine. I would recommend this method over yaw/pitch or axis/angle, as it's a little more consistent and stable.

Share on other sites
That method works just as good. I can't really tell the difference, since I haven't noticed any anomolies in the first version of the source.

Thank you very much for both pieces of code. The second version uses operations that I'm familiar with, so this is perfect.

I really appreciate it. Thanks go to you.

Share on other sites
Quote:
 That method works just as good. I can't really tell the difference, since I haven't noticed any anomolies in the first version of the source.Thank you very much for both pieces of code. The second version uses operations that I'm familiar with, so this is perfect.
Great, I'm glad it worked. It's unlikely you would have run into problems with the first version. But with too small an epsilon it could conceivably fail, whereas the second version should always be stable given valid input.

Share on other sites

This topic is 4485 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Create an account

Register a new account

• Forum Statistics

• Total Topics
628703
• Total Posts
2984301

• 23
• 10
• 9
• 13
• 13