[SOLVED!!]First Person LookAt Location

Started by
12 comments, last by Cakey 15 years, 1 month ago
Okay so here's the deal. I'm using this code(JAVA/JOGL/OpenGL)
public Point3D translateByAngle(float oX, float oY, float oZ,
			float length,
			float angleX,float angleY,float angleZ){
		float rad, xOld, yOld, zOld;
		float x = length, y = 0,z = 0;
		//X ANGLE
		rad = angleX * (float)(Math.PI / 180);		
		xOld = x;zOld = z;
		z = (float)((zOld * Math.cos(rad)) - (xOld * Math.sin(rad)));
		x = (float)((zOld * Math.sin(rad)) + (xOld * Math.cos(rad)));	
		//Y ANGLE
		rad = angleY * (float)(Math.PI / 180);		
		yOld = y; zOld = z;
		y = (float)((yOld * Math.cos(rad))- (zOld * Math.sin(rad)));
		z = (float)((yOld * Math.sin(rad)) + (zOld * Math.cos(rad)));	
		//Z ANGLE
		rad = angleZ * (float)(Math.PI / 180);
		yOld = y; xOld = x;
		x = (float)((xOld * Math.cos(rad)) - (yOld * Math.sin(rad)));
		y = (float)((xOld * Math.sin(rad)) + (yOld * Math.cos(rad)));	
		return new Point3D(oX + x, oY + y, oZ + z);
	}
To calculate the point in 3-Space for my camera to look at. It pretty much takes the angle of the camera and the location of the camera and the distance of sight and calculates a new point. Though there's some minor problems with it for what I am trying to do. such as if I rotate the Y-Axis the angle in which I am looking up at then changes. When I want it to stay at the same "pitch". Is there a Z-Rotation for the camera? Is this not the series of equations I should be using? Is there a better way to do this? [Edited by - Cakey on March 18, 2009 2:43:19 PM]
Advertisement
The three Euler angles are yaw, pitch and roll – often called X, Y and Z angles, although Z/X/Y is probably more accurate (if Y is forwards). Anyway, roll does not affect the forward vector (i.e. the point you want to look at), it only affects the up and right vectors.

The forward vector you want is

(cos yaw cos pitch, sin yaw cos pitch, sin pitch)

The right vector is

(sin yaw cos roll, -cos yaw cos roll, sin roll)

And the up vector is right×forward =

(-sin yaw cos pitch sin roll - cos yaw cos roll sin pitch,
-sin yaw sin pitch cos roll + cos yaw cos pitch sin roll,
cos pitch cos roll)

... all three for a vertical Z axis, if you use vertical Y you need to rearrange the components.

To find a particular point along the camera axis simply do [cameraOrigin + distance*forward]. Alternatively you can use the camera axis vectors directly with a field-of-view parameter to set the GL camera.
Alright I think I can conceptualize the math. But why are there three vectors when I need a point to LookAt? Maybe I'm looking at it wrong haha, I'll give it a try.

Lemme know if this suedo code is near enough..
The forward vector you want is:		x = cos(xAngle) * cos(yAngle)		y = sin(xAngle) * cos(yAngle) 		z = sin(yAngle)The right vector is:		x = sin(yAngle) * cos(xAngle)		y = -cos(xAngle) * cos(zAngle)		z = sin(zAngle)And the up vector is (right×forward):		x = -sin(xAngle) * cos(yAngle) * sin(zAngle) - cos(xAngle) * cos(zAngle) * sin(yAngle)		y = -sin(xAngle) * sin(yAngle) * cos(zAngle) + cos(xAngle) * cos(yAngle) * sin(zAngle)		z = cos(yAngle) * cos(zAngle)


Okay so lemme see if I get it...
if I'm trying to walk forward I use the first one?
if I am trying to rotate the camera on it's Y-Axis I use the second one?
if I'm trying to look up I use the third?

or do I use all of these to calculate what I need? Thanks for taking your time and helping me understand this math(which I haven't reached in school yet)!!

Side-note: Is there any good web-site/learning resources for this kind of mathematics?
If you just want the look-at point, you just need the forward vector (and a distance). This is the vector pointing from the camera along its line of sight.

Edit: Specifically,
lookatPoint = cameraOrigin + (distance * camera.forward)
as I mentioned in the first post. If you don't have a vector class that allows you to perform simple arithmetic operations on vectors by operator overloading, get one ;) ... there are plenty of examples in C++ or C#, and I imagine in Java also, that you can use to augment your Point3D class.

Typically, you need to pass an up-vector to a look-at function, because without that you do not know whether the view is rotated around the forward axis. If you are content for the global up direction to always be upwards on your view, i.e. no camera roll, then you can just use the up vector. The up vector is pointing out of the 'top' of the camera, so if you pitch or roll the camera it may no longer be straight upwards in global terms (and in fact could even be directly downwards).

The right-vector is the vector pointing out of the side of the camera. It is included for completeness. As you can calculate any one of these vectors from the other two (u=r×f, r=f×u, f=u×r) you won't ever need to pass all three to anything, and it's usually forward and up. (If you don't know about vector operations like the vector cross product I use here then look at an A-level maths textbook, or search for 'vector maths'.)

The three vectors together make up the local coordinate space of the object, and the matrix consisting of all three vectors and the opposite of the origin of the object is the transformation matrix to take world-space coordinates and make them local-space coordinates. Look up 'coordinate transformations' to find more about that.

As for your implementation: That is a direct transliteration of the formulae I gave you, so assuming I got them right, that will be right for a coordinate system with a vertical Z axis. (Specifically, my default object has Up=[0,0,1], Forward=[0,1,0], Right=[1,0,0].) Judging by the naming of your angles, you have a default system where Forward=[0,0,1], Up=[1,0,0], Right=[0,1,0] and would therefore need to rearrange the components of the vectors. That would be rather unusual so perhaps you have just named your angles confusingly ;) ... I always name them yaw, pitch and roll instead of X, Y, Z because I find it clearer that way.
Ahhh I think I understand much more clearly now. Yes I just named my angles very poorly haha. Thanks again! and wish me luck as I try to implement this. :D

I am interested in that overloading thing for vector classes. I'll definitely have to look into it(for Java)!

edit: wait OpenGL doesn't render Z as vertical...Does it????

Okay so I got the "forward" one to work but... When I alter the x Angle(to look up or down) it makes the screen focus on some invisible circle or something(it's focus point goes around an invisible circle). So do I need to also use the Up vector? This is pretty similar to the same problem I was having before.

[Edited by - Cakey on March 17, 2009 8:34:21 PM]
Okay here' I'll specify the problem I was having more clearly.
When I rotate on my Y-Axis it effects the angle I am looking at on my X-Axis. By means of if I have say an Xangle where I am looking over a tree's height then I turn on my Yaxis I am now looking at perhaps some of it's top branches height-wise...
Are you using gluLookAt? The behaviour you describe sounds as though either your angles mean something I don't understand, or you are passing something wrong. Can you post the code that you have after assigning the point to look at?

Quote:When I alter the x Angle(to look up or down)

Your X-angle is the pitch, then? In that case, you need to check you have used the correct substitutions for the angles in my formulae. Also, it's possible that the up-vector is wrong as I have not done the complete expansion including roll before. The substitutions you made in your previous post were:
yaw (looking left and right) -> x-angle
pitch (looking up and down) -> y-angle
roll (tilting) -> z-angle

Quote:wait OpenGL doesn't render Z as vertical...Does it????

All graphics libraries render a 2D scene in X and Y. What that means in terms of your 3D space depends on your projection matrix. I think that in OGL Y is vertical by default, it's a while since I used it though. You can either work in a Y-vertical world (and switch the Y and Z components of the vectors I gave you) or you can set your projection matrix to
( 1 0 0 0)(0 0 1 0)(0 -1 0 0)(0 0 0 1)

... to turn a Z-vertical 3D world into a Y-vertical 2D one.
I'm gonna gaurentee you your math is right, I'm just probably applying not enough of it or going about it the wrong way. I see what you mean by the Z thing now.
Where Camera and CameraLook at vectors(a class that has a XYZ locations and XYZ angle's).
	public void display(GLAutoDrawable drawable) {		GL gl = drawable.getGL();		gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);		gl.glLoadIdentity();		glu.gluLookAt(Camera.X, Camera.Y, Camera.Z,				CameraLook.X, CameraLook.Y, CameraLook.Z, 0,1,0); }	public void handleKeyboardInput(int keyInput) {		float ANGLE_INCR = 2.5f;		float SPEED = 0.5f;		float yHolder = Camera.Y;//So you can't fly around			switch (keyInput) {				case KeyEvent.VK_RIGHT:					Camera.angleY = wrapValue(Camera.angleY + ANGLE_INCR);					CameraLook = movePointForward(Camera, LOOK_AT_DIST);					break;				case KeyEvent.VK_LEFT:					Camera.angleY = wrapValue(Camera.angleY - ANGLE_INCR);					CameraLook = movePointForward(Camera, LOOK_AT_DIST);					break;				case KeyEvent.VK_UP:					Camera = movePointForward(Camera, SPEED);					Camera.Y = yHolder;//So you can't fly around					CameraLook = movePointForward(Camera, LOOK_AT_DIST);					break;				case KeyEvent.VK_DOWN:					Camera = movePointForward(Camera, -SPEED);					Camera.Y = yHolder;//So you can't fly around					CameraLook = movePointForward(Camera, LOOK_AT_DIST);					break;				case KeyEvent.VK_A:					Camera.angleX += ANGLE_INCR;					CameraLook = movePointForward(Camera, LOOK_AT_DIST);					break;				case KeyEvent.VK_Z:					Camera.angleX -= ANGLE_INCR; 					CameraLook = movePointForward(Camera, LOOK_AT_DIST);					break;				case KeyEvent.VK_SPACE:					shoot();					break;				case KeyEvent.VK_ENTER:					break;			}	}			/*The forward vector you want is:	x = cos(xAngle) * cos(yAngle)	y = sin(xAngle) * cos(yAngle) 	z = sin(yAngle)The right vector is:	x = sin(yAngle) * cos(xAngle)	y = -cos(xAngle) * cos(zAngle)	z = sin(zAngle)And the up vector is (right×forward):	x = -sin(xAngle) * cos(yAngle) * sin(zAngle) - cos(xAngle) * cos(zAngle) * sin(yAngle)	y = -sin(xAngle) * sin(yAngle) * cos(zAngle) + cos(xAngle) * cos(yAngle) * sin(zAngle)	z = cos(yAngle) * cos(zAngle)		*/		public Point3D movePointForward(Point3D p, float distance){		double origX = Math.toRadians(p.angleX),			origY = Math.toRadians(p.angleY),			origZ = Math.toRadians(p.angleZ);		float tempX = 0f, tempY = 0f, tempZ = 0f;		Point3D point = new Point3D();		tempX = (float)(Math.cos(origX) * Math.cos(origY));		tempY = (float)(Math.sin(origX) * Math.cos(origY));		tempZ = (float) Math.sin(origY);				point.X = p.X + (distance * tempX);		point.Y = p.Y + (distance * tempY);		point.Z = p.Z + (distance * tempZ);				point.angleX = p.angleX;		point.angleY = p.angleY;		point.angleZ = p.angleZ;		return point;	}


I'm really sorry to be bothering you about this but I am reallly really greatful. Any hints, suggestions or what step should I take now?

|edit:|I also tried strictly using the UpVector and it was weird to control. Really weird. Haha

[Edited by - Cakey on March 17, 2009 9:38:37 PM]
Ok, looking at your code you are using these axes:

Up: Y; Yaw: Y-angle
Right: X; Pitch: X-angle
Forward: -Z; Roll: Z-angle (though you don't allow roll atm)

So the forward-vector will be

[-cos pitch sin yaw, cos pitch cos yaw, sin pitch]

= [ -Math.cos(xAngle)*Math.sin(yAngle), Math.cos(xAngle)*Math.cos(yAngle), Math.sin(xAngle) ]

Hmm, it looks like Java doesn't support operator overloading, which is kind of crappy. You can still add methods called things like add, subtract, multiply, dotProduct and crossProduct to your Point3D class though.
Good tip on the Point3D vector thing.

Hmmm.. It's still doing the same thing. I mean the equation is probably right. But I don't think it translates to first person perspective well.. For several reasons all involving Looking Up/Down.
Reasons:
1. If your within' a 180 degree region(of a Y-Axis rotation) up becomes down and down becomes up.
2. If you look up/down and turn left/right It it alters your up and down angle when in any first person game it stays level just adjusts the perspective.

*sigh*

[Edited by - Cakey on March 18, 2009 1:10:17 PM]

This topic is closed to new replies.

Advertisement