В настоящее время я заканчиваю реализацию для камеры, которая функционирует так же, как камера в Maya. Часть, я застрял в функциональности кувырком.
Проблема заключается в следующем: функция поворота работает нормально, пока положение камеры не параллельно вектору вверх (в настоящее время определено как (0, 1, 0)
). Как только камера становится параллельной этому вектору (поэтому она смотрит прямо вверх или вниз), камера фиксируется на месте и будет вращаться только вокруг вектора вверх, а не продолжать вращение.
Этот вопрос уже задавался Вот, к сожалению, нет реального решения проблемы. Для справки, я также попытался обновить вектор подъема при повороте камеры, но полученное поведение не соответствует требуемому (вид переворачивается в результате новой ориентации).
Вот код для моей камеры:
using namespace glm;
// point is the position of the cursor in screen coordinates from GLFW
float deltaX = point.x - mImpl->lastPos.x;
float deltaY = point.y - mImpl->lastPos.y;
// Transform from screen coordinates into camera coordinates
Vector4 tumbleVector = Vector4(-deltaX, deltaY, 0, 0);
Matrix4 cameraMatrix = lookAt(mImpl->eye, mImpl->centre, mImpl->up);
Vector4 transformedTumble = inverse(cameraMatrix) * tumbleVector;
// Now compute the two vectors to determine the angle and axis of rotation.
Vector p1 = normalize(mImpl->eye - mImpl->centre);
Vector p2 = normalize((mImpl->eye + Vector(transformedTumble)) - mImpl->centre);
// Get the angle and axis
float theta = 0.1f * acos(dot(p1, p2));
Vector axis = cross(p1, p2);
// Rotate the eye.
mImpl->eye = Vector(rotate(Matrix4(1.0f), theta, axis) * Vector4(mImpl->eye, 0));
Я использую векторную библиотеку GLM. Вот краткая справка о пользовательских типах, используемых здесь:
typedef glm::vec3 Vector;
typedef glm::vec4 Vector4;
typedef glm::mat4 Matrix4;
typedef glm::vec2 Point2;
mImpl
это PIMPL, который содержит следующие члены:
Vector eye, centre, up;
Point2 lastPoint;
Вот что я думаю. Это как-то связано с замком карданного подвеса, что происходит с углами Эйлера (и, следовательно, сферическими координатами).
Если вы превысили свой минимальный (0, -zoom, 0) или максимальный (0, zoom, 0), вы должны переключить логическое значение. Это логическое значение скажет вам, должны ли вы относиться к дельте положительно или нет.
Это также может быть вызвано особенностью, поэтому просто ограничьте значения полярного угла между 89,99 ° и -89,99 °.
Ваша проблема может быть решена следующим образом.
Поэтому, если ваша камера находится точно выше (0, zoom, 0) или ниже (0, -zoom, 0) вашего объекта, то камера только катится.
(Я также предполагаю, что ваш объект имеет значение (0,0,0) и вектор повышения установлен на (0,1,0).)
Там может быть какой-то математический прием для решения этой проблемы, я бы сделал это с линейной алгеброй
Вам нужно ввести новый правый вектор. Если вы сделаете перекрестный продукт, вы получите камеру-вектор. Camera-vector = up-vector x camera-vector. Представьте, что эти векторы начинаются с (0,0,0), а затем легко, чтобы получить положение вашей камеры, просто сделайте это вычитание (0,0,0) — (вектор камеры).
Так что, если вы получаете какой-то deltaX, вы поворачиваетесь к правому вектору (вокруг вектора вверх) и обновляете его.
Любое влияние deltaX не должно менять ваш ап-вектор.
Если вы получаете некоторую дельту Y, вы поворачиваетесь к вектору вверх (вокруг правого вектора) и обновляете его. (Это не влияет на правый вектор).
https://en.wikipedia.org/wiki/Rotation_matrix в матрице вращения от оси и угла вы можете найти важную формулу.
Вы говорите, что u — ваш вектор, который вы хотите вращать, а theta — это сумма, которую вы хотите повернуть. Размер тета пропорционален deltaX / Y.
Например: мы получили вход от deltaX, поэтому мы вращаемся вокруг вектора вверх.
up-vector:= (0,1,0)
right-vector:= (0,0,-1)
cam-vector:= (0,1,0)
theta:=-1*30° // -1 due to the positive mathematical direction of rotationR={[cos(-30°),0,-sin(-30°)],[0,1,0],[sin(-30°),0,cos(-30°)]}
new-cam-vector=R*cam-vector // normal matrix multiplication
Осталось сделать одну вещь: обновить правый вектор.
right-vector=camera-vector x up-vector .
Других решений пока нет …