Understanding rotation

I’m having trouble with rotating things. I have what I feel should be a simple problem. I’m using gluCylinder to draw a cone (make top radius 0), but I want to rotate it so it faces the direction I want it to face.

My purpose here is to draw an arrow. I draw a line with a cone on top. I have a size vector for the line, and if I normalize it I have a unit vector in the direction I want the cylinder to face.

My problem is I don’t know how to use glRotatef to make the cylinder face the direction of this vector. It’s been a little while since I’ve had the math classes to explain how this is done, so I’ll save myself the embarrassment of sharing what I’ve tried. Can someone just spoil it for me and tell me what I need to do? Thanks!

What you need is a glLookAt function that works on a model and not the camera. It’s basicly the oposite thing. You could try glLookAt with origin as position and then transposing the matrix.

Have a look at the glLookAt source in LWJGL if you wan’t to brush up on the math.

I use (but in lwjgl) glMultMatrix for rotating models. You need to construct a 4x4 matrix first.

Then something like…


glPushMatrix();
{
    glMultMatrix(....);

   ...
}
glPopMatrix();

@tom: I’m sorry I don’t know how to do that. I tried looking for it in the source and couldn’t find it :stuck_out_tongue:

@Alan_W: OK, what goes in my 4x4 matrix? I have no idea :stuck_out_tongue:

Could you guys point me to some examples or some resources that explain this sort of thing? You guys are giving me the theory behind your suggestions as if I already know how to code this stuff :slight_smile: I am brand new in this field and need some extra help.

I reckon the sequence of operations should be

  1. Translate so that the start point is at the origin
  2. Rotate so that the end point is on the z-axis
    2.1) Rotate so that the end point is on the z = 0 plane
    2.2) Rotate so that the end point is on the z-axis
  3. Scale so that the end point is at ( 0, 0, 1 )
  4. Draw your stuff

Off the top of my head…


Vector heading = end - start;

glTranslatef( -start.x, -start.y, -start.z );
glRotatef( Math.toDegrees( Math.atan2( heading.z, heading.x ) ) + 90, 0, 1, 0 ); 
glRotatef( Math.toDegrees( Math.atan2( heading.y, Math.sqrt( heading.x * heading.x + heading.z * heading.z ) ), 1, 0, 0 );
glScalef( 0, 0, heading.magnitude() );

// draw stuff

… with appropriate pushing and popping of course.

well they’re facing different directions now… but still not the correct directions. Eh? ???

Is the problem in my question? Am I asking to do something needlessly difficult? What’s the right way to handle this and how can I learn how to do it? To me this feels like a day one question, but going by the standard delay between question/solution on these forums it seems like maybe I’m going about this the wrong way.

You need to figure out the axis along which to perform your rotation. Looking at the man page for gluCylinder, the cylinder starts at the origin and is aligned along the Z axis. It sounds like you already know the destination orientation you want for your cylinder. To figure out the axis along which to rotate, take the cross product of the Z axis (0, 0, 1) and the direction you want the cylinder / cone to face. The number of radians to rotate is the arc cosine of the dot product of the two axes. You’ll then need to convert that to degrees to feed into glRotatef.

Yay! That’s what I needed :slight_smile: My world is now complete ;D

Interesting discovery. Rotating NaN degrees results in a disappearing object. That took me a while to discover :slight_smile:

@Ken: but this only works nicely in 1 plane. I did this as well for a game where a gun would turn always leaving its barrel pointed at you. Doing this with rotations worked perfectly if I only rotated the gun about its y-axis but the moment I tried to make it point up or down it would just screw up: the barrel always wound up rotated about it’s “view-axis” (the vector pointing at the target).

Using glLookAt actually gave me the same kind of problem. So like tom said: you would need something like glLookAt but for objects instead of cameras :wink:

But I haven’t figured it out yet anyway :wink:

I’ll try to explain how you can create a matrix with the functionality of the lookAt function. The top left 3x3 of the 4x4 matrix contains the rotation of the matrix. In fact it contains the 3 unit vectors (x, y, z) that are perpendicular to eachother. If they are not one unit in size then there is a scale applied to the matrix. If they are not perpendicular then the matrix is scewed. So by filling in the forward, up and side vector of the object you want to orientate, you’ve got yourself a lookAt matrix.

First take the direction you wan’t to aim and normalize. This will be the z vector in the matrix. We get the horizontal (x) part of the matrix by applying the crossproduct between the forward vector and the up vector. We don’t know the real up vector, but can use (0, 1, 0) instead. The crossproduct will be correct as long as you don’t aim up or down. That can not happen in my game so I don’t handle this special case in my source. We can’t use up (0, 1, 0) in the matrix, but we can get the perpendicular up vector by crossing the z and x vectors. Stick the x, y and z vectors along with the position into the matrix and thats it.

Here some code:


	public static float[] getMatrix(Vector3f eye, Vector3f pos) {
		Vector3f zAxis = new Vector3f(pos);
		zAxis.sub(eye);
		zAxis.normalize();
		Vector3f yAxis = new Vector3f(0, 1, 0);
		// Build the X axis vector based on the two existing vectors
        Vector3f xAxis = new Vector3f();
		xAxis.cross(yAxis, zAxis);
		xAxis.normalize();
		// Correct the Y reference vector
		yAxis.cross(xAxis, zAxis);
		yAxis.normalize();
		yAxis.scale(-1);
		float m[] = new float[16];
		m[0] = xAxis.x; m[1] = xAxis.y; m[2] = xAxis.z; m[12] = pos.x;
		m[4] = yAxis.x; m[5] = yAxis.y; m[6] = yAxis.z; m[13] = pos.y;
		m[8] = zAxis.x; m[9] = zAxis.y; m[10] = zAxis.z; m[14] = pos.z;
		m[15] = 1;
		return m;
	}
	
	
	public static void applyMatrix(Vector3f eye, Vector3f pos) {
		float m[] = getMatrix(eye, pos);
		matBuff.rewind();
		matBuff.put(m);
		matBuff.flip();
		GL11.glMultMatrix(matBuff);
	}

I have to admit that the atan2 code looks clearer :slight_smile:

@quintesse:
You had different requirements, you needed gun to stay aligned vertically while turning at you. It all depends on the task at hand, and original question was about a rotation that would align the two verctors and this question was answered perfectly, IMO.
One note: make sure to check that vectors are not aligned in which case you will get 0 vector as a cross product and it will screw up your picture.
@Malohkan:
Use Ken’s suggestion, unless you know why you can’t (additional requirements you have not metioned).

The simple code works for my simple purpose so far. However I can imagine things will get more complicated, in which case Tom’s code will not be ignored :slight_smile: Thank you all for the valuable responses.

After having some other difficulties, I decided to try Tom’s code. I position my object, apply the rotation matrix according to your code, and then render the object. No good. It moves the object, doesn’t just rotate it. It also points it in the wrong direction. Not sure what to think about that…

Yes it moves the object. It’s a lookAt functions. If you don’t want it to move you can pass in (0, 0, 0) for eye and the direction in pos. Or you could remove the part where m[12], m[13] and m[14] is set to pos.x, pos.y and pos.z.

It’s hard to know what you mean by “points in the wrong direction” without seeing it in action. Is there any pattern to the movement. Is the rotation chaotic or is the wrong side of your object facing the target.

edit: You could try using my function for both positioning and rotating your object. First set the identity matrix then pass in the world coordinates for the eye and the target (pos).