camera translation and rotation on its own axis

Started by
32 comments, last by Dotren 20 years, 11 months ago
I''m currently using the mouselook camera class from GameTutorials.com (Camera3 tutorial I believe) and I''ve gotten rid of it''s restricting movement caps so it can rotate 360 degrees. I haven''t reimplemented the movement yet but thats for another post My problem right now is that the camera rotates along the world axis and I need it to rotate along its own axis instead. That way it rotates more according to a 3D space sim game. Right now, when the camera is facing nearly straight up, rotating right should just rotate the camera right but instead its still rotating the camera according to the world''s Y axis and spinning the camera instead. The camera updating itself is called in the display function as:
  
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	
glLoadIdentity();						


glPushMatrix();


gluLookAt(g_Camera.m_vPosition.x, g_Camera.m_vPosition.y, g_Camera.m_vPosition.z,	g_Camera.m_vView.x, g_Camera.m_vView.y,     g_Camera.m_vView.z,	
g_Camera.m_vUpVector.x, g_Camera.m_vUpVector.y, g_Camera.m_vUpVector.z);

.
.
.
  
And the camera class / functions:
  
class CCamera  
{
public:

	CVector m_vPosition;   //camera position

	CVector m_vView;       //camera''s view

	CVector m_vUpVector;   //camera''s up vector



	CCamera();
	virtual ~CCamera();

	void PositionCamera(float positionX, float positionY, float positionZ,
		                float viewX, float viewY, float viewZ,
						float upVectorX, float upVectorY, float upVectorZ);

	void SetViewByMouse();

	void RotateView(float angle, float x, float y, float z);

	void MoveCamera(float speed);




};


void CCamera::PositionCamera(float positionX, float positionY, float positionZ,
		                float viewX, float viewY, float viewZ,
						float upVectorX, float upVectorY, float upVectorZ)
{

	CVector vPosition	= CVector(positionX, positionY, positionZ);
	CVector vView		= CVector(viewX, viewY, viewZ);
	CVector vUpVector   = CVector(upVectorX, upVectorY, upVectorZ);

	m_vPosition = vPosition;
	m_vView = vView;
	m_vUpVector = vUpVector;

}


void CCamera::SetViewByMouse()
{

	POINT mousePosition;

	int middleX = SCREEN_WIDTH >> 1;
	int middleY = SCREEN_HEIGHT >> 1;

	float angleY = 0.0f;
	float angleZ = 0.0f;	

	GetCursorPos(&mousePosition);

	if((mousePosition.x == middleX) && (mousePosition.y == middleY)) return;

	SetCursorPos(middleX, middleY);

	angleY = (float) ((middleX - mousePosition.x)) / 1000.0f;
	angleZ = (float) ((middleY - mousePosition.y)) / 1000.0f;

	RotateView(angleZ, 1, 0, 0);
	RotateView(angleY, 0, 1, 0);
}


void CCamera::RotateView(float angle, float x, float y, float z)
{


  
	CVector vNewView;

	CVector vView = m_vView - m_vPosition;

	float cosTheta = (float)cos(angle);
	float sinTheta = (float)sin(angle);

	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;

	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;

	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;

	m_vView = m_vPosition + vNewView;

}

  
I know thats a lot of code but I figured I wouldn''t get much help if people couldn''t look at the code I was using Any help would be appreciated! Thanks, Dotren
Advertisement
I think the idea here is going to be to do all rotations before you do any translations, so that you rotate the camera around its own axis, then move it to wherever it is in the world. But you are using gluLookAt, and I thought gluLookAt did this....
Where is the popmatrix call? I'm not sure what is wrong it should be fine.
EDIT:
RotateView(angleZ, 1, 0, 0);
should be
RotateView(angleZ, strafe.x, strafe.y, strafe.z);




[edited by - Shadow12345 on April 26, 2003 5:03:01 PM]

[edited by - Shadow12345 on April 26, 2003 5:06:06 PM]
Why don't alcoholics make good calculus teachers?Because they don't know their limits!Oh come on, Newton wasn't THAT smart...
Too much math!!!!

The problem is very simple but you should know something (a bit) about matrix and vector. Of course you need matrix and vector class...it should impossible without!

The general problem is a base-change (I dont know if this is the English term)...

Suppose you have an observer in position POS that look in the direction LOOK and have an UP vector.
To 'compute' the transforming matrix is simpy


          matrix.LoadIdentity();  vector3 side = look^up;  // cross  matrix.SetCol(0, -side	 );  matrix.SetCol(1,  up		 );  matrix.SetCol(2, -look	 );  matrix.SetRow(3, -(matrix*pos) );   


Note that in this 'code' I've used OpenGL notation (as you can see by the translation ROW). So you should pay attention to the product matrix * pos (matrix-column * vector-column).
A GL translation is
1 0 0 0
0 1 0 0
0 0 1 0
Tx Ty Tz 1


For example I've used another notation and to load a gl matrix I must transpose it before

To use the matrix you must call glLoadMatrix(camera_matrix) as first command (you know the reverse order) before object transform.

Of course an analog problem is to set an object in position POS with direction LOOK...the solution is similar


        matrix.LoadIdentity();  vector3 side = look^up;  // cross  matrix.SetRow(0,  side   ); // we use row and not col!  matrix.SetRow(1,  up	   );  matrix.SetRow(2,  look   );  matrix.SetRow(3,  pos    );   


In this case you must call glMultMatrix(object_matrix) as last.

To move your camera/object viewer you can create some functions like Roll(angle), Pitch(angle),....

Do you know how setup a rotation angle?

This is my code (transposed version)


      // I get the code from OpenGL spec...// but I must transpose it!// The rotation is performed around a vector v// with an angle iangle// AC_REAL are float (#define type)// acCos is a look up table and iangle is an// integer AC_REAL cosA 	 = acCos(iangle);  // cos(angle)AC_REAL sinA 	 = acSin(iangle);AC_REAL icosA    = (1-cosA);		if(v.Len2()!=(AC_REAL)1.0){   v.Normalize();}		AC_REAL	 x   = v.m_x;AC_REAL	 y   = v.m_y;AC_REAL	 z   = v.m_z;				AC_REAL  xsinA = x * sinA;AC_REAL  ysinA = y * sinA;AC_REAL  zsinA = z * sinA;	// m_elem is a float[16] array in the matrix object	AC_REAL* m = m_elem;		m[0]  = cosA + x*x*icosA;m[1]  = x*y*icosA - zsinA;m[2]  = x*z*icosA + ysinA;m[3]  = 0.0f;		 m[4]  = x*y*icosA + zsinA;m[5]  = cosA + y*y*icosA;m[6]  = y*z*icosA - xsinA;m[7]  = 0.0f;		 m[8]  = x*z*icosA - ysinA;m[9]  = y*z*icosA + xsinA;m[10] = cosA + z*z*icosA;m[11] = 0.0f; 		m[12] = 0.0f;m[13] = 0.0f;m[14] = 0.0f;m[15] = 1.0f;   


I spent some time to check my matrix op with OpenGL ones and they work!

Your problem : SOLVED!

Ciao!



>

[edited by - blizzard999 on April 26, 2003 7:19:33 PM]
When I re-insert this into the code:


  	CVector vAxis = vAxis.Cross(m_vView - m_vPosition, m_vUpVector);	vAxis = vAxis.Normalize(vAxis);	RotateView(angleZ, vAxis.x, vAxis.y, vAxis.z );  


it prevents the camera from moving past the straight up and straight down angle.

The popmatrix is called towards the bottom of the display function before some masking stuff I do for the targeting...should I move it to right after the gluLookAt?

And as for gluLookAt itself...someone at the following thread posting exactly what it does:

http://www.gamedev.net/community/forums/topic.asp?topic_id=117930

Dotren
You, my friend, need quaternions.
I forget to say that when you perform a rotation around a vector you should rotate look and up vector by a little rotation angle (that you store somewhere in your view class).
Imagine you have a plane and you trig the cloche...at every frame you rotate by an angle around the side vector (look^up) and get new look and up vectors.

look = rotation_matrix * look;
up = rotation_matrix * up;

and ''sometime'' do a normalization (an accuracy error may occur)
that is

look.Normalize();
up = up - look * (up * look); // we are sure up orthogonal
up.Normalize();


P.S: you cannot describe a free orientation with Eulerian angles
I knew quaternions would pop up here at some point I looked at the gametutorial7 on nehe''s which seemed to have everything I needed minus the mouselook (shouldn''t be hard to add I would think)... problem was I didn''t understand any of it and I''ve read others had the same problem with that tutorial, source code was confusing.

I''m really really trying to understand some of this, the project is for a graphics class but he doesn''t mind if we use pieces of other code since most of his tutorials he showed in class were from online sources My particular problem is I haven''t had a math course in a few semesters..only up to cal II which I barely passed. I''ve tried linear algebra and discreet math but that only convinced me to change majors to something a bit less math oriented I really want to understand some of this but I realize some of it also I''ll have to treat as a ''black box'' to meet my deadline.

On the quaternions, if anyone knows of a good tutorial on how to use these for a camera class please let me know. As for the matrices, these are a bit easier for me to understand but does OpenGL have a matrix class pre done?

Thanks,
Dotren
quote:Original post by Dotren
As for the matrices, these are a bit easier for me to understand but does OpenGL have a matrix class pre done?


Do you have seen classes in OpenGL?
Lol come to think of it no...was kind of a stupid question for me to ask, completely forgot

hehe see what this is doing to my head?

What I SHOULD have asked was, is there a nice matrix class or a good tutorial somewhere online?

Dotren

This topic is closed to new replies.

Advertisement