Jump to content
  • Advertisement
Sign in to follow this  
b3rs3rk

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.

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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:


void
Quaternion::
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; }
};


void
PO::
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.
void
PO::
translate(const Vector3& v) {
m_position += v;
}

// Rotate the camera :
void
PO::
rotate(const Quaternion& q) {
// apply the rotation to the orientation.
m_orientation *= q;
update_vectors();

}

// Set the camera's position.
void
PO::
set_position(const Vector3& p) {
m_position = p;
}

// Set the camera's orientation.
void
PO::
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 :
bool
Tutorial::
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 !

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!