Повернуть вектор

8

Я хочу, чтобы камера от первого лица плавно меняла направление просмотра с направления d1 на направление d2. Последнее направление указывается целевой позицией t2.

До сих пор я реализовал вращение, которое работает нормально, но скорость вращения замедляется по мере приближения текущего направления к желаемому. Это то, чего я хочу избежать.

Вот два очень простых метода, которые я написал до сих пор:

// this method initiates the direction change and sets the parameter
public void LookAt(Vector3 target) {

        _desiredDirection = target - _cameraPosition;
        _desiredDirection.Normalize();

        _rotation = new Matrix();

        _rotationAxis = Vector3.Cross(Direction, _desiredDirection);

        _isLooking = true;
    }


// this method gets execute by the Update()-method if _isLooking flag is up.
private void _lookingAt() {

        dist = Vector3.Distance(Direction, _desiredDirection);

        // check whether the current direction has reached the desired one.
        if (dist >= 0.00001f) {

            _rotationAxis = Vector3.Cross(Direction, _desiredDirection);
            _rotation = Matrix.CreateFromAxisAngle(_rotationAxis, MathHelper.ToRadians(1));


            Direction = Vector3.TransformNormal(Direction, _rotation);
        } else {

            _onDirectionReached();
            _isLooking = false;
        }
    }

Опять вращение работает нормально; камера достигает желаемого направления. Но скорость не равна на протяжении движения -> она замедляется.

Как добиться вращения с постоянной скоростью?

Марк Веллман
источник

Ответы:

3
_rotationAxis = Vector3.Cross(Direction, _desiredDirection);
_rotation = Matrix.CreateFromAxisAngle(_rotationAxis, MathHelper.ToRadians(1));

Как Direction& _desiredDirectionизменить, чтобы указывать почти в том же направлении (как они сходятся), тем меньше _rotationAxisбудет величина . Он все еще будет указывать в правильном направлении, чтобы быть осью, но будет иметь меньшую длину. Такова природа перекрестного расчета.

Суть CreateFromAxisAngleметода использует длину оси как фактор количества вращения, к которому она приводит. Когда длина оси равна 1, это приводит к правильному количеству вращения.

Поэтому, если бы вы нормализовались _rotationAxisмежду двумя линиями, которые я цитировал выше, вы бы получили постоянную скорость вращения.

Стив Н
источник
6

Я бы предложил, чтобы фреймворк сделал всю работу за вас. Начните с вычисления матрицы вращения для вашей начальной и конечной ориентаций и конвертируйте их в кватернионы. Вы делаете это только один раз в начале движения и сохраняете значения.

Matrix start = /* calculate current rotation matrix */;
Matrix end = /* calculate desired rotation matrix */;
Quaternion startQ = Quaternion.CreateFromRotationMatrix(start);
Quaternion endQ = Quaternion.CreateFromRotationMatrix(end);

Теперь интерполируйте между этими двумя ориентациями, используя сферическую линейную интерполяцию. Для этого есть метод, поэтому вам не нужно ничего реализовывать самостоятельно:

// Animate the progress parameter between 0 and 1
Quaternion currentQ = Quaternion.Slerp(startQ, endQ, progress);

Наконец, пересчитайте ваше направление, используя кватернион выше, или преобразовайте его обратно в матрицу вращения. Примерно так, например:

Vector3 direction = Vector3.Transform(Vector3.Forward, currentQ);
Дэвид Гувея
источник
Большое спасибо за подробный совет! Я попробую это после обеда;)
Марк Велман
Quaternion.SlerpЭто только я, или это звучит как имя в действительно плохом или действительно хорошем фэнтезийном романе? Минус точка, конечно.
Фонд Моника иск