Page 1 of 1

1st person camera (limiting pitch problem)

Posted: Wed May 11, 2005 9:54 am
by rocifier
Hey guys, pretty new to OGRE here.

I've been playing around, and I'm trying to make a first person camera view. I set up a camera to track the position of a node (the player). I want a camera similar to games like half-life, where you can rotate with the mouse, and move with the keys, but the camera only moves on a 2d axis despite it's orientation.

This is the code i have so far to limit the view vertically (so you can't spin backwards upside-down. The constant is a fraction of a full revolution.

Code: Select all

void MyListener::moveCamera()
{        
	// Make all the changes to the camera
	// Note that YAW direction is around a fixed axis (freelook style) rather than a natural YAW (e.g. airplane)
	mCamera->yaw(mRotX);
	mCamera->pitch(mRotY);

	//Limit pitch vertically
	Real mViewLimit = Vars.getRealVariable("ViewYLimit");
	if (mCamera->getOrientation().getPitch().valueRadians() > (Math::PI - mViewLimit))
	{
		mCamera->pitch( -mRotY );
		mRotY = 0;
	}
	if (mCamera->getOrientation().getPitch().valueRadians() < -(Math::PI - mViewLimit))
	{
		mCamera->pitch( -mRotY );
		mRotY = 0;
	}

	mCamera->moveRelative(mTranslateVector);

}
The reason it doesn't work; is because I don't know much about ogre so I don't really know what I'm doing. It seems to make sense reason the code though (except maybe inside the if statements). Can someone guide me in the right direction? Anyone have any code for a first person shooter style game already?

My other major problem will be physics.. detecting collision between the player and the world. Would I just use a few rays around the player in different directions and integrate 1 step ahead, then if a collision is found, move out of the wall to the polygon's plane?

Posted: Wed May 11, 2005 11:04 pm
by sevensevens
Try replacing

mRotY = 0

with

mRotY = mRotY % (Math::PI - mViewLimit)

Exactly what is your problem (do you get rotation along the z axis?, does the camera's movements jerk sometimes?).

Posted: Thu May 12, 2005 1:41 am
by rocifier
The if statements never return true. Therefore the camera still rotates free with the mouse (but with a fixed yaw axis) as in the exampleApplication. I want to know what the correct way is to get the pitch of the camera.. and then limit it to that angle I guess (maybe the code you gave)

Posted: Sat May 14, 2005 12:57 am
by rocifier
Ok, I've got the camera to limit it's y value based on a value from 0-1 (the y of the foward vector), not sure how linear this is but it suits my needs. My only problem now is limiting the camera's pitch to that value. I can do it, with the below code, but it doesn't update instantly. If I move the mouse fast it overshoots and springs back over the next frame or 2 resulting in an oscillating view that you see as flickering. Does anyone know how I could modify the code inside the if statements so that the camera is updated on the same frame the function is called? It should be but it's not.. or maybe that's not my problem, maybe it's just numerical accuracy using lookAt() or something. I'd also prefer a less expensive function to do this so any ideas are welcome..

Code: Select all

void MyListener::moveCamera()
{        
	/* Make all the changes to the camera */
	// Note that YAW direction is around a fixed axis (freelook style) rather than a natural YAW (e.g. airplane)
	mCamera->yaw(mRotX);
	mCamera->pitch(mRotY);

	/* Limit pitch vertically */
	Real mViewLimit = Vars.getRealVariable("ViewYLimit");

	//Compute camera's forward vector
	Vector3 camForward = mCamera->getUp().crossProduct( mCamera->getRight() );

	if (camForward.y > mViewLimit)
	{
		Vector3 viewlimit = camForward;
		viewlimit.y = mViewLimit;
		viewlimit += mCamera->getDerivedPosition();
		mCamera->lookAt(viewlimit);
	}
	else if (camForward.y < -mViewLimit)
	{
		Vector3 viewlimit = camForward;
		viewlimit.y = -mViewLimit;
		viewlimit += mCamera->getDerivedPosition();
		mCamera->lookAt(viewlimit);
	}

	mCamera->moveRelative(mTranslateVector);

}

Posted: Sun May 15, 2005 9:51 am
by Tsh't
Why don't you update it inside unbuferred input? like:

Code: Select all


VectY=(cam->getChild("PC_Pitch")->getOrientation()*Vector3(0,0,1)).y;
VectZ=(cam->getChild("PC_Pitch")->getOrientation()*Vector3(0,0,1)).z;
Real depY=mInputDevice->getMouseRelativeY();
if((VectY>0.1)&&(VectY<0.9)&&(VectZ>0)) //vertical
     cam->getChild("PC_Pitch")->pitch(Degree(depY*mMouseSensibility));
VectY=(cam->getChild("PC_Pitch")->getOrientation()*Vector3(0,0,1)).y;
VectZ=(cam->getChild("PC_Pitch")->getOrientation()*Vector3(0,0,1)).z;
if((VectY<0.1)||(VectY>0.9)||(VectZ<0))     
     cam->getChild("PC_Pitch")->pitch(Degree(-depY*mMouseSensibility));