Обзор
Я какое-то время оглядывался по сторонам и не нашел ответа, так что, надеюсь, сообщество здесь может мне помочь. Я перерабатываю свою камеру для наблюдения (написано до 2000 года) и испытываю трудности с устранением проблемы, когда векторы обзора и поворота выровнены, из-за чего камера выходит из-под контроля. Первоначально я понимал, что это блокировка карданного подвеса, но теперь я не уверен в этом.
Из моего понимания блокировки карданного подвеса, когда высота звука выравнивается по крену, высота становится креном; и, по сути, это то, чем оно кажется, но проблема в том, что скорость изменения не должна увеличиваться только потому, что оси выровнены, я должен просто получить плавный крен. Вместо этого я получаю жестокий бросок, в котором я не могу точно сказать, в каком направлении идет бросок.
Обновление положения камеры
Когда пользователь перемещает мышь, я перемещаю камеру на основе координат X
и Y
мыши:
Vector2 mousePosition = new Vector2(e.X, e.Y);
Vector2 delta = mousePosition - mouseSave;
mouseSave = mousePosition;
ShiftOrbit(delta / moveSpeed);
В методе ShiftOrbit
я вычисляю новую позицию на основе векторов обзора, справа и вверх по отношению к delta
, переданному из события мыши выше:
Vector3 lookAt = Position - Target;
Vector3 right = Vector3.Normalize(Vector3.Cross(lookAt, Up));
Vector3 localUp = Vector3.Normalize(Vector3.Cross(right, lookAt));
Vector3 worldYaw = right * delta.X * lookAt.Length();
Vector3 worldPitch = localUp * delta.Y * lookAt.Length();
Position = Vector3.Normalize(Position + worldYaw + worldPitch) * Position.Length();
Это работает плавно, как и должно, и перемещает камеру вокруг цели в любом направлении по моему выбору.
Матрица просмотра
Здесь я испытываю проблему, упомянутую в обзоре выше. Мое свойство Up
ранее было установлено всегда 0, 0, 1
из-за того, что мои данные были в координатах ECR. Тем не менее, это то, что вызывает выравнивание оси, когда я перемещаю камеру, и матрица вида обновляется. Я использую SharpDX
метод Matrix.CreateLookAtRH(Position, Target, Up)
, чтобы создать свою матрицу вида.
Обнаружив, что вектор Up
, используемый при создании матрицы представления, должен обновляться, а не всегда быть 0, 0, 1
, я столкнулся с другой проблемой. Я теперь вызвал крен, когда были введены рыскание и тангаж. Это не должно происходить из-за требования, поэтому я немедленно начал искать исправление.
Первоначально я выполнил проверку, чтобы убедиться, что она приближается к выравниванию по оси, если я это сделал, тогда я установил Up
, использованный для создания моей матрицы просмотра, на локальную поверхность камеры, и если я не был затем я использовал только локальную ось Z
, чтобы убедиться, что вверх или вниз.
float dot = Math.Abs(Vector3.Dot(Up, Position) / (Up.Length() * Position.Length()));
if (dot > 0.98)
Up = localUp;
else
Up = new Vector3(0, 0, localUp.Z);
Однако, это было немного нервно и все еще не казалось правильным. После некоторых проб и ошибок, наряду с обширными исследованиями в Интернете, пытаясь найти потенциальные решения, я вспомнил, как линейная интерполяция может плавно переходить от одного значения к другому в течение определенного периода времени. Затем я перешел к использованию Vector3.Lerp
вместо:
float dot = Math.Abs(Vector3.Dot(Up, Position) / (Up.Length() * Position.Length()));
Up = Vector3.Lerp(new Vector3(0, 0, localUp.Z), localUp, dot);
Это очень плавно и вызывает любой крен, только когда я очень близок к выравниванию по оси, что недостаточно для того, чтобы быть заметным для повседневного пользователя.
Проблема
Моя камера также может прикрепляться к точке, отличной от 0, 0, 0
, и в этом случае вектор повышения для камеры устанавливается на нормализованное положение цели. Это вызывает исходную проблему в обзоре при использовании Vector3.Lerp
, как указано выше; Итак, в случае, когда моя камера подключена к точке, отличной от 0, 0, 0
, вместо этого я делаю следующее:
Up = Vector3.Lerp(Vector3.Normalize(Target), localUp, dot);
Однако даже это не работает, и я понятия не имею, как заставить это сделать это. Я работал над этой проблемой уже несколько дней и приложил немало усилий, чтобы ее исправить, и это пока большое улучшение.
Что я могу сделать, чтобы предотвратить насильственное вращение, используя Vector3.Lerp
, когда повышение не эквивалентно 0, 0, z
?