Камера в opengl не работает - PullRequest
1 голос
/ 03 апреля 2012

Проблема в том, что когда я смотрю на свою камеру, например, вниз по оси z и делаю шаг, это работает нормально, однако, после того, как я закончил подачу и хотел бы поворачиваться по этой новой оси, он начинает вращаться по неизвестной причине = s.

    void FrustumCamera::xAxisRotation(float angle)
{
//  angle = angle * (double)degToRad;
    Vector3<float> x = m_orientation.getXAxis();
    Vector3<float> y = m_orientation.getYAxis();
    Vector3<float> z = m_orientation.getZAxis();

    y.rotateAroundAxis(x,angle);
    x = m_orientation.getXAxis();
    z.rotateAroundAxis(x,angle);

    m_orientation.setYAxis(y);
    m_orientation.setZAxis(z);

}
void FrustumCamera::yAxisRotation(float angle)
{
//  angle = angle * (double)degToRad;

    Vector3<float> x = m_orientation.getXAxis();
    Vector3<float> y = m_orientation.getYAxis();
    Vector3<float> z = m_orientation.getZAxis();

    x.rotateAroundAxis(y,angle);
    y = m_orientation.getYAxis();
    z.rotateAroundAxis(y,angle);

    m_orientation.setXAxis(x);
    m_orientation.setZAxis(z);
}
void FrustumCamera::zAxisRotation(float angle)
{
    Vector3<float> x = m_orientation.getXAxis();
    Vector3<float> y = m_orientation.getYAxis();
    Vector3<float> z = m_orientation.getZAxis();

    x.rotateAroundAxis(z,angle);
    z = m_orientation.getYAxis();
    y.rotateAroundAxis(z,angle);

    m_orientation.setXAxis(x);
    m_orientation.setYAxis(y);
}

template <class Type>
void Vector3<Type>::rotateAroundAxis(Vector3<Type> axis, const float angle)
{
    float radians = static_cast<Type>(angle * degToRad);
    Type sinAngle = static_cast<Type>(sin(radians));
    Type cosAngle = 0.0;

    if (angle == 90 || angle == -90)
        cosAngle = 0.0;
    else
        cosAngle = cos(radians); 

    normalise(axis);    // normalise the axis

    Type oneMinusCos = 1 - cosAngle;        // (1 - cos(theta))

    // construct the rotation matrix
    Type tempMatrix[3][3];
    tempMatrix[0][0] = (axis.x * axis.x) * oneMinusCos + cosAngle;
    tempMatrix[0][1] = (axis.x * axis.y) * oneMinusCos + axis.z * sinAngle;
    tempMatrix[0][2] = (axis.x * axis.z) * oneMinusCos - axis.y * sinAngle;
    tempMatrix[1][0] = (axis.x * axis.y) * oneMinusCos - axis.z * sinAngle;
    tempMatrix[1][1] = (axis.y * axis.y) * oneMinusCos + cosAngle;
    tempMatrix[1][2] = (axis.y * axis.z) * oneMinusCos + axis.x * sinAngle;
    tempMatrix[2][0] = (axis.x * axis.z) * oneMinusCos + axis.y * sinAngle;
    tempMatrix[2][1] = (axis.y * axis.z) * oneMinusCos - axis.x * sinAngle;
    tempMatrix[2][2] = (axis.z * axis.z) * oneMinusCos + cosAngle;

    Vector3<Type> temp(*this);
    Vector3<Type> result;

    result.x = (temp.x * tempMatrix[0][0]) + (temp.y * tempMatrix[1][0]) + (temp.z * tempMatrix[2][0]);
    result.y = (temp.x * tempMatrix[0][1]) + (temp.y * tempMatrix[1][1]) + (temp.z * tempMatrix[2][1]);
    result.z = (temp.x * tempMatrix[0][2]) + (temp.y * tempMatrix[1][2]) + (temp.z * tempMatrix[2][2]); 

    *this = result;
}

void OpenGLRenderer::startDraw(unsigned long mask)
{
    //sortBuffer();                                     // sort draw queue
    clearBuffers(mask);                                 // clear buffers
    loadIdentity();
    glTranslatef(-1*m_frustumCamera->getViewMatrix().getTranslationAxis().x,-1*m_frustumCamera->getViewMatrix().getTranslationAxis().y,-1*m_frustumCamera->getViewMatrix().getTranslationAxis().z);
    glMultMatrixf(m_frustumCamera->getViewMatrix().getMatrix());
    glTranslatef(m_frustumCamera->getViewMatrix().getTranslationAxis().x,m_frustumCamera->getViewMatrix().getTranslationAxis().y,m_frustumCamera->getViewMatrix().getTranslationAxis().z);// load identity

    //

    // push matrix stack
    matrixStackPush();                                          
}

1 Ответ

3 голосов
/ 03 апреля 2012

Возможно, вы испытываете Замок карданного подвеса ;это может произойти, если вы наклонитесь полностью вверх или вниз, чтобы ваш вектор взгляда стал параллельным вашему вектору вверх, и в этом случае рыскание будет таким же, как и при крене.

Это может быть недостатком построения поворотовпо частям через углы Эйлера.Вы можете посмотреть на кватернионы.(Обратите внимание, что вы не можете вращаться с углами Эйлера; они являются просто представлением для поворота (вам нужно преобразовать его в матрицу или квадраты), но то, как вы справляетесь с этим, очень похоже на «угол Эйлера»)

Сила умножения матриц заключается в том, что любая последовательность из нескольких вращений может быть представлена ​​(и объединена) в виде одной матрицы вращения.Вам нужно сделать что-то вроде этого:

void Transformable::yaw(float angle)
{
    float4x4 rot; // temp rotation matrix
    float3 translate(&_transform._41); // save our translation
    float3 up(&_transform._21); // y axis

    // build the rotation matrix for rotation around y
    MatrixRotationAxis(&rot, &up, angle);

    // multiply our transform by the rotation matrix
    // note that order of multiplication matters and depends on
    // if your matrices are column-major or row-major
    MatrixMultiply(&_transform, &_transform, &rot);

    // write back our original translation
    memcpy(&_transform._41, &translate, sizeof(float3));

    // might want to reorthogonalise every now and then
    // to make sure basis vectors are orthonormal
    // or you will probably get matrix creep after a few operations
}

вместо попытки поворота одного базисного вектора за раз.В этом случае _transform будет однородной матрицей 4x4, представляющей матрицу преобразования.(ротация и перевод).Подматрица вершины 3х3 - это просто базисные векторы пространства ориентации.

...