Я пытаюсь сделать симулятор полета в opengl, но я просто не могу заставить свою камеру правильно следить за самолетом. Я думал, что если я применю один и тот же набор трансформаций как к камере, так и к его самолету, это будет работать, но это не так. Когда я говорю о преобразованиях, я имею в виду повороты с использованием сердцевины и углов поворота (на данный момент я не учел угол крена) и сдвиги, необходимые для перемещения самолета.
Это мой класс камеры:
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);
}
}
Я создал 2 камеры: одну, которая должна следовать за самолетом, и другую, которая должна применять набор преобразований на плоскости.
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));
Это моя функция renderScene:
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 выглядит примерно так:
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);
}
...
}
И это моя модель, вид, проекционные матрицы:
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));
Задача ещё не решена.
Других решений пока нет …