Matrix camera issues

Started by
1 comment, last by sirSolarius 19 years, 11 months ago
I''m trying to migrate my Camera class to use OrientMatrix, a 4x4 matrix class that all objects (including the camera) inherit. The code I wrote, however, makes my camera really screwy... it goes all over the place when I use SetViewByMouse, moveForward and moveRight. Here''s the OrientMatrix code:

class OrientMatrix
{
public:
	OrientMatrix()
	{
		// Create the matrix

		matrix=new float[16];

		// Fill it with the default values

		matrix[0]=1.0f;
		matrix[5]=1.0f;
		matrix[10]=1.0f;
		matrix[15]=1.0f;

		for(int x=1;x<5;x++)
			matrix[x]=0;
		for(x=6;x<10;x++)
			matrix[x]=0;
		for(x=11;x<15;x++)
			matrix[x]=0;
	}
	
	OrientMatrix(Vector3 right,Vector3 up,Vector3 forward, Vector3 pos)
	{
		matrix= new float[16];
		setVectors(right, up, forward, pos);
	}

	~OrientMatrix()
	{
		delete [] matrix;
	}

	////////////////////////////////////////////////////////

	//			MUTATOR METHODS

	////////////////////////////////////////////////////////



	void setVectors(Vector3 right,Vector3 up,Vector3 forward, Vector3 pos)
	{
		setPos(pos);
		setUp(up);
		setRight(right);
		setForward(forward);

	}

	void setPos(Vector3 pos)
	{
		matrix[12]=pos.x;
		matrix[13]=pos.y;
		matrix[14]=pos.z;
		matrix[15]=1;
	}

	void setRight(Vector3 right)
	{
		matrix[0]=right.x;
		matrix[1]=right.y;
		matrix[2]=right.z;
		matrix[3]=0;
	}

	void setUp(Vector3 up)
	{
		matrix[4]=up.x;
		matrix[5]=up.y;
		matrix[6]=up.z;
		matrix[7]=0;
	}

	void setForward(Vector3 forward)
	{
		matrix[8]=forward.x;
		matrix[9]=forward.y;
		matrix[10]=forward.z;
		matrix[11]=0;
	}

	void move(float x, float y, float z)
	{
		matrix[12]+=x;
		matrix[13]+=y;
		matrix[14]+=z;
	}

	void rot(float x, float y, float z)
	{
		
		/////////// Do the x rotations//////////////

		if(x!=0.0f)
		{
			Vector3 vTemp=getForward();
			vTemp.rotVect(x, getRight());
			setForward(vTemp);
			
			vTemp=getRight().cross(getForward());
			vTemp.normalise();
			setUp(vTemp);		// Set the up vector			

		}
		if(y!=0.0f)
		{
			Vector3 vTemp=getForward();
			vTemp.rotVect(y, getUp());
			setForward(vTemp);
			
			vTemp=getForward().cross(getUp());
			vTemp.normalise();
			setRight(vTemp);		// Set the right vector

			
		}
		if(z!=0.0f)
		{
			Vector3 vTemp=getUp();
			vTemp.rotVect(z, getForward());
			setUp(vTemp);

			vTemp=getForward().cross(getUp());
			vTemp.normalise();
			setRight(vTemp);		// Set the right vector

		}
	}

	
	////////////////////////////////////////

	//		ACCESSOR METHODS

	////////////////////////////////////////

	Vector3 getPos()
	{
		return (Vector3(matrix[12], matrix[13], matrix[14]));
	}

	Vector3 getRight()
	{
		return (Vector3(matrix[0], matrix[1], matrix[2]));
	}

	Vector3 getUp()
	{
		return (Vector3(matrix[4], matrix[5], matrix[6]));
	}

	Vector3 getForward()
	{
		return (Vector3(matrix[8], matrix[9], matrix[10]));
	}

	///////////////////////////////////

	//			MULT TIMES WORLD

	///////////////////////////////////

	void multTimesWorld()
	{
		glMultMatrixf(matrix);
	}

	void moveForward(float amount)
	{
		move(amount*matrix[8], amount*matrix[9], amount*matrix[10]);
	}

	void moveRight(float amount)
	{
		move(amount*matrix[0], amount*matrix[1], amount*matrix[2]);
	}

	float *matrix;
};




#endif //define

And the new Camera class:

Camera::Camera()
{
	orientation.setForward(Vector3(0, 0, -1));
}

Camera::~Camera()
{
}

///////////////////////////////// POSITION CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

/////

/////	This function sets the camera''s position and view and up vector.

/////

///////////////////////////////// POSITION CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*


void Camera::PositionCamera(float positionX, float positionY, float positionZ,
				  		     float viewX,     float viewY,     float viewZ,
							 float upVectorX, float upVectorY, float upVectorZ)
{
	Vector3 vPosition	= Vector3(-positionX, -positionY, -positionZ);
	Vector3 vView		= Vector3(-viewX, -viewY, -viewZ);
	Vector3 vUpVector	= Vector3(upVectorX, upVectorY, upVectorZ);

	Vector3 vStrafe = vView.cross(vUpVector);
	vStrafe.normalise();

	orientation.setVectors(vStrafe, vUpVector, vView, vPosition);
}

///////////////////////////////// SET VIEW BY MOUSE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

/////

/////	This allows us to look around using the mouse, like in most first person games.

/////

///////////////////////////////// SET VIEW BY MOUSE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

void Camera::SetViewByMouse(float mouseX, float mouseY)
{
	orientation.rot(mouseX, mouseY, 0);
}

///////////////////////////////// UPDATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

/////

/////	This updates the camera''s view and strafe vector

/////

///////////////////////////////// UPDATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*


void Camera::Update() 
{
	
}


///////////////////////////////// DRAW \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

/////

/////	Required by the object class

/////

///////////////////////////////// DRAW \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

void Camera::draw()
{
	orientation.multTimesWorld();

	m_Moved_public=m_Moved;

	  if(m_Moved)	// Recalculate the frustum if moved

		{
			viewFrust.getFrustum();
			m_Moved=false;
		}
}


///////////////////////////////// PLACE/MOVE/CALCBOUNDING \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

/////

/////	Required by the object class

/////

///////////////////////////////// PLACE/MOVE/CALCBOUNDING \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*


void Camera::place(GLfloat newX, GLfloat newY, GLfloat newZ)
{
	m_Moved=true;
	orientation.setPos(Vector3(-newX, -newY, -newZ));
}

void Camera::move(GLfloat newX, GLfloat newY, GLfloat newZ)
{
	m_Moved=true;

	orientation.move(-newX, -newY, -newZ);
}

void Camera::calcBounding()
{
	boundingRadius=6.0f;
	boundingBox.setVals(-1.2, 1.2, -1.2, 1.2, -1.2, 1.2);
}

///////////////////////////////// SPIN/ROT \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

/////

/////	Required by the object class

/////

///////////////////////////////// SPIN/ROT \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

void Camera::spin(GLfloat xRot, GLfloat yRot, GLfloat zRot)
{
	m_Moved=true;
	orientation.rot(xRot, yRot, zRot);
}

void Camera::rot(GLfloat xRot, GLfloat yRot, GLfloat zRot)
{
	m_Moved=true;
	orientation.setForward(Vector3(0, 0, -1));
	orientation.setRight(Vector3(1, 0, 0));
	orientation.setUp(Vector3(0, 1, 0));

	orientation.rot(xRot, yRot, zRot);
}


///////////////////////////////// moveForward \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

/////

/////	Moves along the view axis

/////

///////////////////////////////// moveForward \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

void Camera::moveForward(float amount)
{
	m_Moved=true;
	orientation.moveForward(-amount);
}

///////////////////////////////// moveRight \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

/////

/////	Moves along the strafe axis

/////

///////////////////////////////// moveRight \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*

void Camera::moveRight(float amount)
{
	orientation.moveRight(-amount);
}

Advertisement
add some debug output checking
a) the length of the three vector (dot vec*vec is ok too)
b) the dot product between r-u, r-f, u-f

if a) is not 1 or really close to it and b isnt 0 or really close to it your matrix was screwed by rounding errors and needs to be "fixed" from time to time.

if youre lazy you can load the matrix to opengl and let it do the math. the matrix will always be fine, but doing that more than a few times per frame isnt exactly fast. but then, calling half a dozen functions to set a few vectors isnt either (unless you keep them inline like they are).
f@dzhttp://festini.device-zero.de
What''s the "amount" you''re using for MoveForward and MoveRight and also how do you determine how much to rotate the camera via the mouse ?

~Urayami
~Urayami

This topic is closed to new replies.

Advertisement