# spaceship camera (like Descent..)

This topic is 5138 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

i'm trying to write a small game like Xwing vs Tie Fighter and i've got some problems with the camera: basically when i try to rotate up or down i need to CONTINUE the rotation (not to stop like when i look up/down in a fps)... this way i could complete a circle if i wish. in my old fps engine i used this function to rotate the camera with the mouse:
void CCamera::SetViewByMouse()
{
POINT mousePos;							// This is a window structure that holds an X and Y
int middleX = g_Width  >> 1;					// This is a binary shift to get half the width
int middleY = g_Height >> 1;					// This is a binary shift to get half the height
float angleY = 0.0f;							// This is the direction for looking up or down
float angleZ = 0.0f;							// This will be the value we need to rotate around the Y axis (Left and Right)
static float currentRotX = 0.0f;

GetCursorPos(&mousePos);

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

SetCursorPos(middleX, middleY);
angleY = (float)( (middleX - mousePos.x) ) / 500.0f;
angleZ = (float)( (middleY - mousePos.y) ) / 500.0f;
currentRotX -= angleZ;

if(currentRotX > 2)
currentRotX = 2;
else if(currentRotX < -1.0f)
currentRotX = -1.0f;

else{
CVector3 vAxis = Cross(m_vView - m_vPosition, m_vUpVector);
vAxis.Normalize();

RotateView(angleZ, vAxis.x, vAxis.y, vAxis.z);
RotateView(angleY, 0, 1, 0);
}
}


what should i modify? Does someone know a tutorial or a link?

##### Share on other sites
There is a very simple way to do this. I had it on my old Tie Fighter game, lol. All u need to do is comment this line:

SetCursorPos(middleX, middleY);

This will stop the mouse being set to middle. And the distance will keep being added the further away u are from middle. Good Luck

##### Share on other sites
Doesn't work. I don't think this is what i was searching for..

##### Share on other sites
basically nothing changes, but the rotation speed is near light speed :P

##### Share on other sites
Basically, I can see 2 problems in your approach :
- you calculate the angles using the mouse movement only. You should "add" the mouse movement to previous values of the angles ;
- you might want to use a quaternion to store the orientation. You will avoid gimbal lock problems.

Tell me if you want me to post some code. I have a class that handles the position and orientation of objects/cameras that is pretty easy to use.

##### Share on other sites
What I do in those cases is store the orientation of the ship as a 4x4 matrix (a quaternion works too).

From this matrix, I can extract the up/side/forward vectors through matrix multiplication so I can move the ship the right way.

To rotate, I simply generate a new rotation matrix (around the X Y or Z axis) and multiply the previous matrix by the new one: this changes the orientation as by a real rotation.

The "view" matrix is the inverse of the orientation matrix multiplied by the translation matrix (which you get from the position of the ship).

##### Share on other sites
@rodzilla: it would be very nice if you post your camera class :)

anyway, i've changed my approach: i don't need anymore to rotate the camera with the mouse, i have to use only the keyboard. So now for example, if i keep pressed the UP key, the camera view changes doing a complete circle if necessary.

I hope i've been clear...

##### Share on other sites
Here's the class I use to handle camera/objects movement.

First the math-related stuff ; you probably have your own classes so I won't put mine in here. All you need is a Vector3 and a Quaternion classes. You should define glTranslate and inv_glTranslate for the Vector3 and glRotate and inv_glRotate for the Quaternion.
glTranslate is straightforward, glRotate is:

voidQuaternion::glRotate() const {	float scale_2 = x*x+y*y+z*z;	if (scale_2 != 0.0) {		float angle = acos(w);		float inv_scale = inv_sqrt(scale_2);		glRotatef(114.59155902616464175358*angle, x*inv_scale, y*inv_scale, z*inv_scale);	}}

Here's the PO (position-orientation) class:

class PO {protected:	//!	Position.	Vector3		m_position;	//!	Orientation.	Quaternion	m_orientation;	//!	A vector facing forward.	Vector3		m_forward;	//!	A vector facing up.	Vector3		m_up;	//!	A vector facing right.	Vector3		m_right;	void update_vectors();public:	//!	Default constructor.	PO();	//!	Get the position.	/*!	\return the position.	*/	const Vector3& get_position() const { return m_position; }	//!	Set the position.	/*!	\param p the new position.	*/	void set_position(const Vector3& p);	//!	Get the orientation.	/*!	\return the orientation.	*/	const Quaternion& get_orientation() const { return m_orientation; }	//!	Set the orientation.	/*!	\param p the new orientation.	*/	void set_orientation(const Quaternion& q);	//!	Move the PO.	/*!	\param v the translation vector in world coordinates.	*/	void translate(const Vector3& v);	//!	Rotate the PO.	/*!	\param q the rotation quaternion in world coordinates.	*/	void rotate(const Quaternion& q);	//!	Return the PO's forward vector.	/*!	\return the PO's forward vector in world coordinates.	*/	const Vector3& forward() const { return m_forward; }	//!	Return the PO's up vector.	/*!	\return the PO's up vector in world coordinates.	*/	const Vector3& up() const { return m_up; }	//!	Return the PO's right vector.	/*!	\return the PO's right vector in world coordinates.	*/	const Vector3& right() const { return m_right; }};voidPO::update_vectors() {	m_right.x = 1.0f - 2.0f * ( m_orientation.y * m_orientation.y + m_orientation.z * m_orientation.z );  	m_up.x = 2.0f * ( m_orientation.x * m_orientation.y - m_orientation.w * m_orientation.z );  	m_forward.x = -2.0f * ( m_orientation.x * m_orientation.z + m_orientation.w * m_orientation.y );  	m_right.y = 2.0f * ( m_orientation.x * m_orientation.y + m_orientation.w * m_orientation.z );  	m_up.y = 1.0f - 2.0f * ( m_orientation.x * m_orientation.x + m_orientation.z * m_orientation.z );  	m_forward.y = -2.0f * ( m_orientation.y * m_orientation.z - m_orientation.w * m_orientation.x );  	m_right.z = 2.0f * ( m_orientation.x * m_orientation.z - m_orientation.w * m_orientation.y );  	m_up.z = 2.0f * ( m_orientation.y * m_orientation.z + m_orientation.w * m_orientation.x );  	m_forward.z = 2.0f * ( m_orientation.x * m_orientation.x + m_orientation.y * m_orientation.y ) - 1.0f;  }// The default construtor initializes the forward, up and right vectors.PO::PO() : m_forward(0, 0, -1),       m_up(0, 1, 0),       m_right(1, 0, 0) {}// Moving the camera means adding a given vector to its position.voidPO::translate(const Vector3& v) {	m_position += v;}// Rotate the camera :voidPO::rotate(const Quaternion& q) {	// apply the rotation to the orientation.	m_orientation *= q;	update_vectors();}// Set the camera's position.voidPO::set_position(const Vector3& p) {	m_position = p;}// Set the camera's orientation.voidPO::set_orientation(const Quaternion& q) {	m_orientation = q;	update_vectors();}

Here's how to use the PO:

// If the PO is used for a camera you can do the following// before drawing your scene :glMatrixMode(GL_MODELVIEW);glLoadIdentity();			// Set it to identity.po.get_orientation().inv_glRotate();	// Apply the inverted rotation po.get_position().inv_glTranslate();	// Apply the inverted translation// If the PO is used for an object you can do the// following before drawing it :po.get_orientation().glRotate();	// Apply the rotation po.get_position().glTranslate();	// Apply the translation// If you want to translate the camera/object, just use// the translate() method and forward, right, up vectors.// Here's how I handle keyboard-controlled time-based movement:float forward_move = (key_state(SDLK_e)-key_state(SDLK_x));float right_move = (key_state(SDLK_d)-key_state(SDLK_s));float up_move = (key_state(SDLK_r)-key_state(SDLK_c));Vector3 tmp =   forward_move*m_camera.po.forward()	      + right_move*m_camera.po.right()	      + up_move*m_camera.po.up();m_camera.po.translate(dt*50.0*tmp);// Rotating is nearly as easy :boolTutorial::handle_mouse_motion(const int x, const int y) {	if (mouse_button_state(SDL_BUTTON_RIGHT)) {		// If right mouse button is pressed the mouse		if (x != 0) {					// rotates the camera around its forward vector.			Vector3 v(0, 0, -1);			// This is the forward vector (in camera coordinates).			Quaternion q(v, x*0.001);		// Create a quaternion that holds a rotation								// around this vector.			m_camera[m_current_camera].po.rotate(q);// Rotate the camera.		}	} else {						// If right mouse button is not pressed the mouse		if (x != 0) {					// rotates the camera around its up and right vectors.			Vector3 v(0, 1, 0);			Quaternion q(v, -x*0.001);			m_camera[m_current_camera].po.rotate(q);		}		if (y != 0) {			Vector3 v(1, 0, 0);			Quaternion q(v, -y*0.001);			m_camera[m_current_camera].po.rotate(q);		}	}	return true;}

Sure this class could be made easier-to-use (add rotate_x, rotate_y and rotate_z functions for example).

Any feedback welcome !

thank you!

1. 1
Rutin
35
2. 2
3. 3
4. 4
5. 5

• 12
• 14
• 9
• 9
• 14
• ### Forum Statistics

• Total Topics
633343
• Total Posts
3011430
• ### Who's Online (See full list)

There are no registered users currently online

×