I'm trying to make a flight simulator in opengl but I just cannot make my camera follow the airplane properly. I thought that if I apply the same set of transformations both on the camera and on he airplane it would work but it doesn't. When I'm saying transformations I'm talking about the rotations using pith, and yaw angles (I have ignored roll angle for the moment) and the translations the are required to move the airplane around. This is my Camera class:
namespace gps {
Camera::Camera(glm::vec3 cameraPosition, glm::vec3 cameraTarget)
{
this->cameraPosition = cameraPosition;
this->cameraTarget = cameraTarget;
this->cameraDirection = glm::normalize(cameraTarget - cameraPosition);
this->cameraRightDirection = glm::normalize(glm::cross(this->cameraDirection, glm::vec3(0.0f, 1.0f, 0.0f)));
}
glm::mat4 Camera::getViewMatrix()
{
return glm::lookAt(cameraPosition, cameraPosition + cameraDirection , glm::vec3(0.0f, 1.0f, 0.0f));
}
glm::vec3 Camera::getCameraPosition()
{
return cameraPosition;
}
void Camera::move(MOVE_DIRECTION direction, float speed)
{
switch (direction) {
case MOVE_FORWARD:
cameraPosition += cameraDirection * speed;
break;
case MOVE_BACKWARD:
cameraPosition -= cameraDirection * speed;
break;
case MOVE_RIGHT:
cameraPosition += glm::normalize(glm::cross(cameraDirection, glm::vec3(0.0f, 1.0f, 0.0f))) * speed;
break;
case MOVE_LEFT:
cameraPosition -= glm::normalize(glm::cross(cameraDirection, glm::vec3(0.0f, 1.0f, 0.0f))) * speed;
break;
}
}
void Camera::rotate(float pitch, float yaw)
{
glm::vec3 front;
front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
front.y = sin(glm::radians(pitch));
front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
cameraDirection = glm::normalize(front);
}
}
I have created 2 cameras: one that is supposed to follow the airplane around and the other one that is supposed to apply the set of transformations on the plane.
gps::Camera myCamera(glm::vec3(0.0f, 0.0f, 2.5f), glm::vec3(0.0f, 0.0f, -10.0f));
gps::Camera planeCamera(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, -10.0f));
This is my renderScene function:
void renderScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
processMovement();
//initialize the view matrix
view = myCamera.getViewMatrix();
//send view matrix data to shader
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
//plane
model = glm::mat4(1.0f);
model = planeCamera.getViewMatrix();
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
normalMatrix = glm::mat3(glm::inverseTranspose(view*model));
//send normal matrix data to shader
glUniformMatrix3fv(normalMatrixLoc, 1, GL_FALSE, glm::value_ptr(normalMatrix));
planeModel.Draw(myCustomShader);
}
processMovement goes something like this:
void processMovement()
{
if (pressedKeys[GLFW_KEY_W]) {
myCamera.move(gps::MOVE_FORWARD, cameraSpeed);
planeCamera.move(gps::MOVE_BACKWARD, cameraSpeed);
}
if (pressedKeys[GLFW_KEY_S]) {
myCamera.move(gps::MOVE_BACKWARD, cameraSpeed);
planeCamera.move(gps::MOVE_FORWARD, cameraSpeed);
}
...
}
And these are are my model, view, projection matrices:
model = glm::mat4(1.0f);
modelLoc = glGetUniformLocation(myCustomShader.shaderProgram, "model");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
view = myCamera.getViewMatrix();
viewLoc = glGetUniformLocation(myCustomShader.shaderProgram, "view");
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
normalMatrix = glm::mat3(glm::inverseTranspose(view*model));
normalMatrixLoc = glGetUniformLocation(myCustomShader.shaderProgram, "normalMatrix");
glUniformMatrix3fv(normalMatrixLoc, 1, GL_FALSE, glm::value_ptr(normalMatrix));
projection = glm::perspective(glm::radians(45.0f), (float)retina_width / (float)retina_height, 0.1f, 1000.0f);
projectionLoc = glGetUniformLocation(myCustomShader.shaderProgram, "projection");
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));