1

我正在为我的游戏引擎创建一个 3D 相机,我想用一个四元数来表示相机的方向。通过将此四元数转换为旋转矩阵来生成局部上、前和侧摄像机轴。该矩阵的第一行给出了相机的 X 轴(侧向量),第二行给出了 UP 向量,第三行给出了 FRONT 向量。为了移动相机,我的函数需要移动方向,更新数量和位置,并更新视图矩阵()。要旋转相机,我的函数获取要旋转的轴和角度。从这个轴和角度创建一个临时四元数,并应用于我相机的当前方向。我围绕世界 Y 轴旋转以进行偏航,并围绕相机的侧向量进行俯仰。这个投球没有 当我的相机轴未与世界轴对齐时,无法正常工作。如果我改为围绕全局 X 轴进行推销,那么它可以正常工作,但我知道这不是我想要的。此外,当我的相机轴与世界轴不对齐时,运动也会出错。我正在使用基本的“wasd”运动。我的运动和俯仰函数使用局部轴,因此我有一种预感,我从四元数中提取局部轴的方式不正确,但我无法弄清楚出了什么问题。

相机类:

#include "stdafx.h"

Camera * Camera::m_currentCamera = NULL;
    Camera::Camera(vec3 position , double distToNear , double distToFar , double fovy)
{
    m_position = position;
    m_distToNear = distToNear;
    m_distToFar = distToFar;
    m_fovy = fovy;
    // generate the view and projection matrices
    updateViewMatrix();
    projection = glm::perspective(m_fovy, 4.0/3.0, m_distToNear, m_distToFar);
    // in radians
    m_deltaAngle = 10.0 * PIOVER180;

    if(m_currentCamera != NULL)
    {
        delete m_currentCamera;
    }

    m_currentCamera = this;
}

Camera::Camera()
{

}

Camera::~Camera()
{
    // empty for now
}

Camera* Camera::getCurrentCamera()
{
    return m_currentCamera;
}

/** set and get camera position */
vec3 Camera::getPosition()
{
    return m_position;
}

void Camera::setPosition(vec3 pos)
{
    m_position = pos;
}


/** set and get near plane distance */
double Camera::getNearPlaneDist()
{
    return m_distToNear;
}

void Camera::setNearPlaneDist(double dist)
{
    m_distToNear = dist;
}

/** set and get far plane distance */
double Camera::getFarPlaneDist()
{
    return m_distToFar;
}

void Camera::setFarPlaneDist(double dist)
{
    m_distToFar = dist;
}

/** set and get camera field of view */
double Camera::getFovy()
{
    return m_fovy;
}

void Camera::setFovy(double angle)
{
    m_fovy = angle;
}

mat4 Camera::getViewMatrix()
{
    return view;
}

mat4 Camera::getProjectionMatrix()
{
    return projection;
}

Quaternion Camera::getOrientation()
{
    return m_rotation;
}

void Camera::setOrientation(Quaternion *q)
{
    m_rotation.setQuaternion(q);
}

/** this function will be called whenever the camera's position, up vector or lookat vector changes */
void Camera::updateViewMatrix()
{
    mat4 orientation = m_rotation.toMatrix();
    mat4 translation = translate(mat4(1.0f),vec3(-m_position.x,-m_position.y,-m_position.z));
    view = orientation * translation;
}

/** Control Functions */

void Camera::rollCamera(float theta)
{
    Quaternion tempRotation;
    tempRotation.quaternionFromAxis(getFront(), theta);
    tempRotation.normalise();
    m_rotation = m_rotation * &tempRotation;
    m_rotation.normalise();
    updateViewMatrix();
}

void Camera::pitchCamera(float theta)
{
    Quaternion tempRotation;
    // INSTEAD OF LOCAL AXIS IF (1.0,0.0,0.0) GLOBAL X AXIS IS USED THIS WORKS FINE!!!   
    tempRotation.quaternionFromAxis(getSide(), theta);
    tempRotation.normalise();
    m_rotation = m_rotation * &tempRotation;
    m_rotation.normalise();
    updateViewMatrix();
}

void Camera::yawCamera(float theta)
{
    Quaternion tempRotation;
    tempRotation.quaternionFromAxis(vec3(0.0,1.0,0.0), theta);
    tempRotation.normalise();
    m_rotation = m_rotation * &tempRotation;
    m_rotation.normalise();
    updateViewMatrix();
}

void Camera::moveCamera(vec3 dir, float amt)
{
    normalize(dir);
    m_position += dir * amt;
    updateViewMatrix();
}

vec3 Camera::getFront()
{
    m_rotation.normalise();
    mat4 orientation = m_rotation.toMatrix();
    vec3 front(orientation[2][0], orientation[2][1], orientation[2][2]);
    normalize(front);
    cout << "FRONT " << front.x << " " << front.y << " " << front.z << endl;
    return front;
}

vec3 Camera::getSide()
{
    m_rotation.normalise();
    mat4 orientation = m_rotation.toMatrix();
    vec3 side(orientation[0][0], orientation[0][1], orientation[0][2]);
    normalize(side);
    cout << "SIDE " << side.x << " " << side.y << " " << side.z << endl;
    return side;
}

vec3 Camera::getUp()
{
    m_rotation.normalise();
    mat4 orientation = m_rotation.toMatrix();
    vec3 up(orientation[1][0], orientation[1][1], orientation[1][2]);
    normalize(up);
    cout << "UP " << up.x << " " << up.y << " " << up.z << endl;
    return up;
}

移动和旋转相机的功能:

void specialKeyboard(int key, int x, int y)
{
    switch(key)
    {
    case GLUT_KEY_LEFT: 
        Camera::getCurrentCamera()->yawCamera(1.0 * PIOVER180);
        break;

    case GLUT_KEY_RIGHT:
        Camera::getCurrentCamera()->yawCamera(-1.0 * PIOVER180);
        break;

    case GLUT_KEY_UP:
        Camera::getCurrentCamera()->pitchCamera(1.0 * PIOVER180);
        break;
    case GLUT_KEY_DOWN:
        Camera::getCurrentCamera()->pitchCamera(-1.0 * PIOVER180);
        break;
    }

    glutPostRedisplay();
}

void keyboard(unsigned char key, int x, int y)
{
    switch(key)
    {
    case 'w':
        Camera::getCurrentCamera()->moveCamera(Camera::getCurrentCamera()->getFront(), -0.1f);
        break;
    case 's':
        Camera::getCurrentCamera()->moveCamera(Camera::getCurrentCamera()->getFront(), 0.1f);
        break;
    case 'a':
        Camera::getCurrentCamera()->moveCamera(Camera::getCurrentCamera()->getSide(), -0.1f);
        break;
    case 'd':
        Camera::getCurrentCamera()->moveCamera(Camera::getCurrentCamera()->getSide(), 0.1f);
        break;
    }
    glutPostRedisplay();
}

这是我关于堆栈溢出的第一篇文章,所以如果需要更多信息,请告诉我。如果您在我的代码和方法中发现任何错误,请提供帮助。谢谢!

4

0 回答 0