Request for help with 3D vector math
I can't seem to get the steering for my ship to work right. Here's the problem:- I want to use glRotate() to rotate the ship around the y-axis a certain number of degrees so that the ship faces the direction (in the x-z plane) it's traveling.
- I have two vectors: the direction vector represents the direction I'm currently going, and the goal vector represents the direction I want to go.
- I want to calculate the angle (in degrees) between the two vectors. This is the angle I need to rotate the ship.
old_direction = direction.normalize() direction = goal.normalize() angle = math.acos(old_direction.dot(direction)) * (180.0 / 3.1415927) if steer_left: rot.y += angle * -1 else: rot.y += angle glRotate(rot.y, 0, 1, 0) # Draw the shipWhen I do this, the rotatation of the ship lags behind the direction it's actually moving. Any ideas about what I'm doing wrong?
(log in to comment)
Comments
The columns of the rotation matrix (or rows, if you're using OpenGL's column-major matrix convention) are unit vectors representing the axis directions of the old coordinate system in the new coordinate system. (Or it might be the other way around, I haven't got time to think it through properly right now.)
The one thing I would do most differently is to have the actual heading maintained by your ship object, and then every time you go to draw it, rotate to that heading. So, if you're turning from 90 degrees to 95 degrees, the draw code will issue a glRotate(95, 0, 1, 0) call instead of a glRotate(5, 0, 1, 0) call.
In some code I'm working on right now (for work, not the competition), I do something very similar:
def drawVector(self): glColor3f(*self.color) glPushMatrix() x,y=self.pos glTranslate(x,y,0) glRotate(self.heading, 0, 0, 1) glBegin(GL_LINE_LOOP) glVertex2f(-5.0, -3.0) glVertex2f( 5.0, 0.0) glVertex2f(-5.0, 3.0) glEnd() glPopMatrix()So, if I were to take that draw code and plug it in to your steering code, it'd probably look a little like this:
self.heading=math.degrees(math.atan2(direction[2],direction[0])) self.drawVector()I don't know if that's at all helpful, but maybe it's worth trying.
player_dir = self.player.collision.c - baddie.collision.c # direction I would like to face facing_dir = baddie.get_facing_ray().v # direction I am currently facing n = facing_dir.cross(euclid.Vector3(0, 1, 0)) # normal of plane dividing universe along facing_dir direction = n.dot(player_dir) # sign gives direction (left or right) to turn angle = math.acos(player_dir.dot(facing_dir)) # magnitude of angle
alex on 2007/04/04 08:49:
You're not converting the result of math.acos from radians to degrees.