Когда я вращаю мышь CW, объекты на экране вращают CCW и наоборот. Это не огромная ошибка, но это кажется неправильным.Маленькая ошибка камеры Quaternion? (слегка вращается по оси Z)
Я использую Eigen для кватернионов и векторов, поэтому проблема должна просто подпадать под код, который я опубликовал.
камеры:
#include <Eigen/Dense>
#include <cstring>
#include <math.h>
typedef Eigen::Vector3f vec3;
typedef Eigen::Quaternionf Quaternion;
namespace vec
{
//
// Constants
//
const vec3 i(1, 0, 0);
const vec3 j(0, 1, 0);
const vec3 k(0, 0, 1);
const vec3 zero(0, 0, 0);
const vec3 ones(1, 1, 1);
}
class Camera
{
void init();
void moveX(float dist);
void moveY(float dist);
void moveZ(float dist);
void rotateX(float radians); //yaw
void rotateY(float radians); //pitch
void rotateZ(float radians); //roll
void moveLeft(float dist);
void moveForward(float dist);
void moveUp(float dist);
void rotateLeft(float radians); //yaw
void rotateUp(float radians); //pitch
void rollLeft(float radians); //roll
void setPosition(const vec3 &pos);
void setDirection(const vec3 &dir);
void lookAt(const vec3 &pos); //changes direction
// Camera Vectors
vec3 left() const;
vec3 right() const;
vec3 up() const;
vec3 down() const;
vec3 forward() const;
vec3 backward() const;
const vec3 &pos() const;
protected:
Quaternion mRotation;
vec3 mPos;
void rotateL(float radians, const vec3 &axis);
void rotateR(float radians, const vec3 &axis);
};
Реализация:
void Camera::init()
{
mPos.setZero();
mRotation.setIdentity();
}
inline void Camera::rotateL(float radians, const vec3 &axis)
{
Quaternion q(Eigen::AngleAxis<float>(radians, axis));
mRotation = (q * mRotation).normalized();
}
inline void Camera::rotateR(float radians, const vec3 &axis)
{
Quaternion q(Eigen::AngleAxis<float>(radians, axis));
mRotation = (mRotation * q).normalized();
}
void Camera::moveX(float dist)
{
mPos.x() += dist;
}
void Camera::moveY(float dist)
{
mPos.y() += dist;
}
void Camera::moveZ(float dist)
{
mPos.z() += dist;
}
void Camera::rotateX(float radians)
{
rotateL(radians, vec::i);
}
void Camera::rotateY(float radians)
{
rotateL(radians, vec::j);
}
void Camera::rotateZ(float radians)
{
rotateL(radians, vec::k);
}
void Camera::moveLeft(float dist)
{
mPos += dist * left();
}
void Camera::moveUp(float dist)
{
mPos += dist * up();
}
void Camera::moveForward(float dist)
{
mPos += dist * forward();
}
void Camera::rotateLeft(float radians)
{
rotateL(radians, up());
}
void Camera::rotateUp(float radians)
{
rotateL(radians, left());
}
void Camera::rollLeft(float radians)
{
rotateL(radians, forward());
}
void Camera::setPosition(const vec3 &pos)
{
mPos = pos;
}
void Camera::setDirection(const vec3 &dir)
{
mRotation.setFromTwoVectors(vec::k, dir);
mRotation.normalize();
}
void Camera::lookAt(const vec3 &pos)
{
setDirection(mPos - pos);
}
// Camera Vectors
vec3 Camera::left() const
{
return mRotation._transformVector(vec::i);
}
vec3 Camera::right() const
{
return -left();
}
vec3 Camera::up() const
{
return mRotation._transformVector(vec::j);
}
vec3 Camera::down() const
{
return -up();
}
vec3 Camera::forward() const
{
return mRotation._transformVector(vec::k);
}
vec3 Camera::backward() const
{
return -forward();
}
const vec3 &Camera::pos() const
{
return mPos;
}
Обновления Функции:
void App::onMouseMotion(int x, int y, int dx, int dy)
{
cam.rotateUp(dy * ROTATE_SCALE);
cam.rotateLeft(-dx * ROTATE_SCALE);
}
void App::update()
{
cam.moveLeft(((int)Keyboard::isKeyDown('a')) * MOVE_SCALE * mDt);
cam.moveLeft(((int)Keyboard::isKeyDown('d')) * -MOVE_SCALE * mDt);
cam.moveForward(((int)Keyboard::isKeyDown('w')) * MOVE_SCALE * mDt);
cam.moveForward(((int)Keyboard::isKeyDown('s')) * -MOVE_SCALE * mDt);
cam.rollLeft(((int)Keyboard::isKeyDown('q')) * -ROLL_SCALE * mDt);
cam.rollLeft(((int)Keyboard::isKeyDown('e')) * ROLL_SCALE * mDt);
}
I'v читайте, что некоторые проблемы связаны с объединением кватернионов с неправильной стороны ... например, Q R вместо R Q. Переключение оси X, как было предложено here, определенно не помогает.
Я также ценю любые предложения с моей реализацией. Я рассматриваю переход на матрицы для вращения, но нормализация и комбинирование их дороже.
Я полагаю, что у меня нет большого опыта в играх, где доступно свободное вращение. Было бы невозможно сказать, было ли это проблемой в летных симах, так как вы всегда будете двигаться. Я предполагаю, что я думал, что это осталось/равно как equiv для X/Y ... но они относительны в моем случае. – ffhighwind
Даже после замены его на rotateX и rotateY у него все еще есть проблема ... так что я думаю, что это что-то еще. Попробует один флоат-рывок/шаг/рулон или просто используйте Эйлеров с минимальным/максимальным шагом. – ffhighwind