Advertisement

OpenGL Space Shooter game 3rd person Camera problems

Started by January 09, 2021 11:42 AM
0 comments, last by paokakis 3 years, 9 months ago

I am making a 3D space shooter game using OpenGL and Bullet Physics. I am having a hard time with the 3rd person Camera though. If you take a look at the video above you can see that the camera follows the spaceship rotating on the X axis without a problem and rotating on Z axis also without a problem when the spaceship is is oriented towards the horizon and parallel to the ground. When I roll to the right and move the spaceship up I am totally losing it from the camera. The code for my camera is as follows :

float CalculateHorizontalDistance() {
	if (!mpPlayer) return 0.f;

	return distanceFromPlayer * glm::cos(glm::radians(-UpAngle));
}

float CalculateVerticalDistance() {
	if (!mpPlayer) return 0.f;

	return distanceFromPlayer * glm::sin(glm::radians(-UpAngle));
}

void calculateCameraPosition(float horizDistance, float verticDistance)
{
	if (!mpPlayer) return;

	glm::vec3 playerFront = mpPlayer->GetFront();
	glm::vec3 playerPos = mpPlayer->GetPosition();

	Position = playerPos + ((-playerFront) * distanceFromPlayer);

	UpAngle = 180.f - mpPlayer->GetRoll();
	//RightAngle = -mpPlayer->GetPitch();
	RollAngle =  mpPlayer->GetYaw() - 180.f;

	//float theta = mpPlayer->GetRotationY() + angleAroundPlayer;
	//float offsetX = horizDistance * glm::sin(glm::radians(theta));
	//float offsetZ = horizDistance * glm::cos(glm::radians(theta));

	//Position.x = mpPlayer->GetPosition().x - offsetX;
	//Position.y = mpPlayer->GetPosition().y + verticDistance;
	//Position.z = mpPlayer->GetPosition().z - offsetZ;
}

The above code is used to calculate the position and rotation of the camera. The commented out code was used to calculate the position based on trigonometrical calculations for the x and z sides of the triangle created from the camera position to the player position. This didn't work right because I could never set the camera behind the spaceship, only the position worked well.

On the non-commented out code I use as a camera position the player position - back vector * offset. This works fine for the simple purpose that the camera is always on the back side of the spaceship. I also update pitch and roll which works almost fine and here is where I need help mostly to get this right. I also never update the yaw of the camera.

This is how I get yaw, pitch and roll from Bullet Physics rigid body of the player (spaceship):

btScalar yaw;
btScalar pitch;
btScalar roll;
body->getCenterOfMassTransform().getBasis().getEulerZYX(yaw, pitch, roll, 1);

The following code is how the orientation of the camera is calculated :

void updateCameraVectors()
{
	// Yaw
	glm::quat aroundY = glm::angleAxis(glm::radians(-RightAngle), glm::vec3(0, 1, 0));

	// Pitch
	glm::quat aroundX = glm::angleAxis(glm::radians(UpAngle), glm::vec3(1, 0, 0));

	// Roll
	glm::quat aroundZ = glm::angleAxis(glm::radians(RollAngle), glm::vec3(0, 0, 1));

	Orientation = aroundY * aroundX * aroundZ;

	glm::quat qF = Orientation * glm::quat(0, 0, 0, -1) * glm::conjugate(Orientation);
	Front = { qF.x, qF.y, qF.z };
	Right = glm::normalize(glm::cross(Front, WorldUp));
	Up = glm::normalize(glm::cross(Right, Front));

}

and lastly how the view matrix of the camera is calculated:

glm::mat4 GetViewMatrix()
{
	// You should know the camera move reversely relative to the user input.
	// That's the point of Graphics Camera

	glm::quat reverseOrient = glm::conjugate(Orientation);
	glm::mat4 rot = glm::mat4_cast(reverseOrient);
	glm::mat4 translation = glm::translate(glm::mat4(1.0), -Position);

	return rot * translation;
}

Can someone help me fix the rotational problems that I am facing. I am open to modify also the Camera Class to make it work better with Bullet's quaternions instead of the Euler's angles that I am trying to use. Any code or ideas are very welcomed. Thank you for reading through.

This topic is closed to new replies.

Advertisement