Эмуляция gluLookAt с glm::Quat(ernions)

Я пытался эмулировать функциональность gluLookAt, но с Quaternions. Каждый из моих игровых объектов имеет TranslationComponent. Этот компонент хранит позицию объекта (glm::vec3), вращение (glm::quat) и масштаб (glm::vec3). Камера рассчитывает свою позицию каждый тик, выполняя следующие действия:

// UP = glm::vec3(0,1,0); 
//FORWARD = glm::vec3(0,0,1);
cameraPosition = playerPosition - (UP * distanceUP) - (FORWARD * distanceAway);

Этот код положения работает как и положено, камера находится на 3 метра позади игрока и на 1 метр вверх. Теперь Quaternion камеры настроен на следующее:

//Looking at the player's feet  
cameraRotation = quatFromToRotation(FORWARD, playerPosition); 

Теперь механизм рендеринга принимает эти значения и генерирует ViewMatrix (камера) и ModelMatrix (проигрыватель), а затем визуализирует сцену. Код выглядит так:

 glm::mat4 viewTranslationMatrix = 
         glm::translate(glm::mat4(1.0f), cameraTransform->getPosition());
 glm::mat4 viewScaleMatrix = 
         glm::scale(glm::mat4(1.0f), cameraTransform->getScale());
 glm::mat4 viewRotationMatrix = 
         glm::mat4_cast(cameraTransform->getRotation());

 viewMatrix = viewTranslationMatrix * viewRotationMatrix * viewScaleMatrix;

quatFromToRotation (glm:: vec3 from, glm:: vec3 to) определяется следующим образом:

glm::quat quatFromToRotation(glm::vec3 from, glm::vec3 to)
{
    from = glm::normalize(from); to = glm::normalize(to);

    float cosTheta = glm::dot(from, to);
    glm::vec3 rotationAxis;

    if (cosTheta < -1 + 0.001f)
    {
        rotationAxis = glm::cross(glm::vec3(0.0f, 0.0f, 1.0f), from);
        if (glm::length2(rotationAxis) < 0.01f)
            rotationAxis = glm::cross(glm::vec3(1.0f, 0.0f, 0.0f), from);

        rotationAxis = glm::normalize(rotationAxis);
        return glm::angleAxis(180.0f, rotationAxis);
    }

    rotationAxis = glm::cross(from, to);

    float s = sqrt((1.0f + cosTheta) * 2.0f);
    float invis = 1.0f / s;

    return glm::quat(
            s * 0.5f,
            rotationAxis.x * invis,
            rotationAxis.y * invis,
            rotationAxis.z * invis
        );
}

У меня проблемы с тем, что CameraRotation настроен неправильно. Независимо от того, где находится игрок, впереди камеры всегда (0,0,-1)

1 ответ

Решение

Ваша проблема в линии

//Looking at the player's feet  
cameraRotation = quatToFromRotation(FORWARD, playerPosition);

Вы должны смотреть из положения камеры на ноги игрока, а не "на один метр выше игрока" (при условии, что игрок находится на уровне (0,0,0), когда вы изначально делаете это). замещать FORWARD с cameraPosition:

cameraRotation = quatToFromRotation(cameraPosition, playerPosition);

РЕДАКТИРОВАТЬ Я полагаю, у вас есть ошибка в вашем quatToFromRotation функция также. См. /questions/17061971/nahozhdenie-kvaterniona-predstavlyayuschego-vraschenie-ot-odnogo-vektora-k-drugomu/17061985#17061985 для очень хорошего объяснения (и некоторого псевдокода) вращения кватернионов.

Другие вопросы по тегам