3D Quaternion Camera

Started by
4 comments, last by John Stuart 14 years, 6 months ago
Can anyone here give me a link or book, much better, that teaches on how to create a fps camera on 3d space with no gimbal lock?? I hope that it also explain how did he get the formula on it. I got this camera RotateView Function from a md2 model but didn't understand how he derived that.


			void RotateView(float angle, float x, float y, float z)
			{
				core::vector3df vNewView;

				// Get the view vector (The direction we are facing)
				core::vector3df vView = cView - cPosition;		

				// Calculate the sine and cosine of the angle once
				float cosTheta = (float)cos(angle);
				float sinTheta = (float)sin(angle);

				// Find the new x position for the new rotated point
				vNewView.x  = (cosTheta + (1 - cosTheta) * x * x)		* vView.x;
				vNewView.x += ((1 - cosTheta) * x * y - z * sinTheta)	* vView.y;
				vNewView.x += ((1 - cosTheta) * x * z + y * sinTheta)	* vView.z;

				// Find the new y position for the new rotated point
				vNewView.y  = ((1 - cosTheta) * x * y + z * sinTheta)	* vView.x;
				vNewView.y += (cosTheta + (1 - cosTheta) * y * y)		* vView.y;
				vNewView.y += ((1 - cosTheta) * y * z - x * sinTheta)	* vView.z;

				// Find the new z position for the new rotated point
				vNewView.z  = ((1 - cosTheta) * x * z - y * sinTheta)	* vView.x;
				vNewView.z += ((1 - cosTheta) * y * z + x * sinTheta)	* vView.y;
				vNewView.z += (cosTheta + (1 - cosTheta) * z * z)		* vView.z;

				// Now we just add the newly rotated vector to our position to set
				// our new rotated view of our camera.
				cView = cPosition + vNewView;
			}


Thanks John Stuart [Edited by - John Stuart on October 18, 2009 6:42:18 PM]
Advertisement
There are so many articles about 3D cameras, I wouldn't know where to begin. Remember that most of them will be tailored to a specific graphics API, such as OpenGL.

The two methods that I've used for a 3D camera without using Euler angles (which suffer from Gimbal Lock) are Quaternions. In general I have a vector position of my camera and a Quaternion for it's orientation.

GDnet hosts this article:

http://www.gamedev.net/reference/programming/features/quatcam/
I have a question. Why did he use sin in x,y,z and cos in w? Is there any geometric explanation how he did that? He just states that here's the formula. http://www.gamedev.net/reference/programming/features/quatcam/page3.asp


Thanks for the link. :D
Glad I could help. I also thought that some of the stuff at GPWiki helped me understand some things, since the general Wiki article is rather math dense:

http://gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation

http://en.wikipedia.org/wiki/Quaternion

I didn't study the code you posted too closely, but from the looks it's basically building a rotation matrix.

http://en.wikipedia.org/wiki/Rotation_matrix
Thanks nullmind for the help. Sorry for the late reply. I'm quite busy this past few days because of college stuffs.

I tried playing around with the first link you posted. I don't know what is happening but my screen is rotating so so so so fast.

The code is exactly the same with what was posted on the article page 3. Page 3

I checked:
1) formula for Cross Product
2) see if the frame is too high. so i enabled the vsnyc but no luck
3) put MouseSensitivity to 1,10,100,1000...
3) check the code line by line...
4) rewrite everything again... still no luck...

Can anyone here help me?
The problem above is I forgot to put glLoadIdentity() before calling camera update... O.o

Now.. Here's my problem... The camera rotating weirdly.. Can anyone here check my codes? I don't know any person who can help me.

camera()	{		Position.set(0.0, 0.0, 0.0);		View.set(0.0, 1.0, 0.5);		Up.set(0.0, 0.0, 1.0);	}	void SetViewByMouse()	{	  POINT mousePosition;	  int MiddleX = 800/2;	  int MiddleY = 600/2;	  vector3d MouseDirection(0, 0, 0);	  static float CurrentRotationX = 0.0;	  GetCursorPos(&mousePosition);	  if((mousePosition.x == MiddleX) && (mousePosition.y == MiddleY))		return;	  SetCursorPos(MiddleX, MiddleY);	  MouseDirection.x = (float)(MiddleX - mousePosition.x)/100.0f; 	  MouseDirection.y = (float)(MiddleY - mousePosition.y)/100.0f;	  CurrentRotationX += MouseDirection.y;	  	  // We don't want to rotate up more than one radian, so we cap it.	  if(CurrentRotationX > 1)	  {		CurrentRotationX = 1;		return;	  }	  // We don't want to rotate down more than one radian, so we cap it.	  if(CurrentRotationX < -1)	  {		CurrentRotationX = -1;		return;	  }	  else	  {		// get the axis to rotate around the x-axis. 		vector3d Axis;		// To be able to use the quaternion conjugate, the axis to		// rotate around must be normalized.		Axis = Axis.Normalize( (View - Position).Cross(Up) );		// Rotate around the y axis		RotateCamera(MouseDirection.y, Axis.x, Axis.y, Axis.z);		// Rotate around the x axis		RotateCamera(MouseDirection.x, 0, 1, 0);	  }	}	void RotateCamera(float angle, float x, float y, float z)	{		quaternion temp, quat_view, result;		temp.x = x * sin(angle/2);		temp.y = y * sin(angle/2);		temp.z = z * sin(angle/2);		temp.w = cos(angle/2);		quat_view.x = View.x;		quat_view.y = View.y;		quat_view.z = View.z;		quat_view.w = 0;		result = (temp*quat_view)*temp.Conjugate();		View.x = result.x;		View.y = result.y;		View.z = result.z;	}	void CameraLook()	{		gluLookAt(Position.x, Position.y, Position.z, View.x, View.y, View.z, Up.x, Up.y, Up.z);	}

This topic is closed to new replies.

Advertisement