Sign in to follow this  

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.

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 components
float 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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
A ZIP of the working SDL C++ source is at:
Click Here

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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


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


Vector3 z = direction; // direction should already be normalized
Vector3 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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this