PDA

View Full Version : linear algebra + trig problem arrow on line



garyw
07-30-2008, 12:35 PM
So I've run into some coding trouble, and tried asking the folks at GameDev.net, but they don't seem to get it, so I thought I'd go for the experts....any help would be much appreciated! Description below. Thanks! Gary


So I am trying to draw a line with an arrow at the end. For the lines I am using GL_LINES, and for the arrow at the end, I am using gluCylinder(), with the base set to zero to make a cone for the arrow head. What I cannot for the life of me seem to figure out, is how to orient the cone so that it is coincident with the original line. This is the approach suggested in the Red Book, using a scalar and cross product to find the angle and axis of rotation.

Psuedocode looks something like:

1. Draw line
2. Calculate 3-vector coincident with line: N = TO - FROM
3. glTranslate from origin to TO
4. glRotate so the z-axis (where gluCylinder draws) is coincident with N
5. call gluCylinder()

Results: the point of the cone in every case is located at TO, but the angle of rotation for each cone is different, and not at all coincident with N. For the rotation I am using:


vector<float> normal(3);
float vx =tTo[0]-tFrom[0]; // tTo and tFrom are the endpoints of the line
float vy =tTo[1]-tFrom[1];
float vz =tTo[2]-tFrom[2];
float dr = sqrt(vx*vx+vy*vy+vz*vz); // use dr to normalize the vector
normal[0]=vx/dr;
normal[1]=vy/dr;
normal[2]=vz/dr;
...
...

float rTd = 180.0 / 3.14159265; // conversion from radians to degrees
glPushMatrix();
glTranslatef(x, y, z);
float mag_n = sqrt (n[1]*n[1]+n[2]*n[2]+n[0]*n[0]);
float theta = rTd*acos(n[2]/mag_n); // angle through which to rotate, from dot product
glRotatef(theta,-1.0*n[1],-1.0*n[0],0); // axis of rotation from cross product
gluCylinder(gluNewQuadric(), 0, .05, .2, 30, 20);
glPopMatrix();

dletozeun
07-30-2008, 12:51 PM
Your code seems incomplete, what is the 'n' vector?

EDIT:

Never tried, but what I'd do is:

Assuming that N is the arrow direction, the cone is draw pointing to Z negative (or positive doesn"t matter).

Then compute the cross product between N and Z and (N and Z should be normalized) to find the vector V.

Then norm(V) = sin (Z,N)
dot(Z,N) = cos (Z,N)
And you find the angle a=(Z,N).

Then rotate around normalized V with angle a in degree with:

glRotatef(a, V[0], V[1], V[2]);

garyw
07-30-2008, 02:38 PM
oh yes, the n vector is the normal vector, just called something else farther up in the code. i'm not familiar with your notation... i believe that IS the approach i tried, but it doesn't come through, not sure why...

help anyone?

thanks,
g

dletozeun
07-30-2008, 02:42 PM
To make it clear, (Z,N) is for example the angle between vector Z and vector N.
dot means dot product
norm is the vector norm or length.
Don't hesitate to ask more question, if it is still not clear.

garyw
07-30-2008, 02:58 PM
ok, I think I get the approach, but for some reason this code doesn't work...any idea where I went wrong in the implementation?

thanks so much for helping out!
g

ps. here 'n' is the vector coincident with the line being drawn, V2 - V1

-------------------

float rTd = 180.0 / 3.14159265; // conversion to degrees
glPushMatrix();
glTranslatef(x, y, z); // translate to endpoint of line

float mag_n = sqrt (n[1]*n[1]+n[2]*n[2]+n[0]*n[0]); // magnitude of normal vector

float theta = rTd*acos(n[2]/mag_n);
glRotatef(theta, n[1]/mag_n, n[0]/mag_n, 0);

gluCylinder(gluNewQuadric(), 0, .05, .2, 30, 20);

glPopMatrix();

dletozeun
07-31-2008, 12:15 AM
I don't understand, your approach, I suggested you to rotate around the normalized V vector (which is the normalization of the cross product between N and Z) and, you simply rotate around N.

Then, I don't understand, why you mix indices when using the 'n' vector in your code. At least, I would do: lRotatef(theta, n[0]/mag_n, n[1]/mag_n, 0);, but rotating around 'n' is not the solution, if I am not mistaken.

Finally, you should compute cross product and dot product as I said, to find the cosinus angle AND the sinus angle, because you can't find the angle just with acos.