Ослабление Vector3 до новой позиции

Не уверен, что libgdx предлагает эту функциональность, так что это может быть математический вопрос. У меня есть различные координаты 3D-камеры, хранящиеся как Vector3, и я хочу переместить камеру с одной на другую.

Vector3 CAM_POSITION_DEFAULT = new Vector3(0f, 1f, -5f);
Vector3 CAM_POSITION_TOP = new Vector3(0f, 10f, -5f);

Я мог бы просто установить новое положение камеры, но это слишком резко. Хороший плавный переход с некоторым смягчением (медленное начало, быстрая середина, медленный конец) был бы идеальным.

Это просто манипулирование матрицей или есть удобный способ получить эту функциональность с помощью easing? Во-вторых, если доступно смягчение, можно ли использовать различные формы смягчения (например, в библиотеке jQuery javascript)?

Большое спасибо.


person Jammo    schedule 06.04.2014    source источник
comment
Вы можете взглянуть на code.google.com/p/java-universal. -tween-engine, который обычно используется в libgdx для всех видов интерполяции/замедления.   -  person noone    schedule 06.04.2014


Ответы (1)


То, что вы ищете, это простая линейная интерполяция между двумя позициями.

Для этого вы можете использовать предоставленный libgdx метод lerp(...).

Если вы хотите рассчитать позиции между CAM_POSITION_DEFAULT и CAM_POSITION_TOP, вам просто нужно интерполировать между двумя векторами:

Vector3 inbetween = CAM_POSITION_DEFAULT.lerp(CAM_POSITION_TOP, alpha);

Если вы укажете значение alpha=0, вы вернете CAM_POSITION_DEFAULT, если вы укажете alpha=1, вы получите CAM_POSITION_TOP... alpha=0.5f, следовательно, будет точкой прямо посередине двух позиций...

Хитрость заключается в том, как выбрать альфа-значение для плавного перехода, который занимает определенное количество секунд:

class CameraTransition {

    private final Vector3 startPos;
    private final Vector3 goalPos;
    private final float duration;

    private float stateTime = 0.0f;

    public CameraTransition(final Vector3 startPos, final Vector3 goalPos, float duration) {
        this.startPos = startPos;
        this.goalPos = goalPos;
        this.duration = duration;
    }

    public Vector3 act(float delta) {
        stateTime += delta;

        return startPos.lerp(goalPos, MathUtils.clamp(stateTime/duration, 0.0f,1.0f));
    }

}

Таким образом, вы можете использовать этот код (не тестировался, извините)... Создайте новый CameraTransition и установите продолжительность.

Затем в вашем render(float delta) вам просто нужно вызвать метод act() и передать дельта-время. Конечно, вам следует вызывать метод act() только тогда, когда вы хотите, чтобы переход выполнялся.

Надеюсь это поможет... :)

ОБНОВЛЕНИЕ:

Увидев, что вы ищете плавный переход, который начинается медленно и медленно заканчивается, я изменил интерполяцию на что-то, что использует более плавную кривую вместо линейной интерполяции:

class CameraTransition {

        private final Vector3 startPos;
        private final Vector3 goalPos;
        private final float duration;

        private float stateTime = 0.0f;
        private float alpha;

        public CameraTransition(final Vector3 startPos, final Vector3 goalPos, float duration) {
            this.startPos = startPos;
            this.goalPos = goalPos;
            this.duration = duration;
        }

        public Vector3 act(float delta) {
            stateTime += delta;

            alpha = MathUtils.clamp(stateTime/duration, 0.0f,1.0f);


            return startPos.lerp(goalPos, -2 * alpha*alpha*alpha + 3 * alpha*alpha);
        }

    }

В этой версии я изменяю линейную интерполяцию, чтобы использовать эту кривую:

f(x) = -2*alpha^3 + 3*alpha^2

http://www.wolframalpha.com/input/?i=plot+f%28x%29+%3D+-2x%5E3+%2B3x%5E2+from+0+to+1

person florianbaethge    schedule 06.04.2014
comment
Это не соответствует медленному началу, быстрой середине, медленному концу OP. Скорость линейной интерполяции постоянна. - person More Axes; 06.04.2014
comment
О, извините, я, должно быть, пропустил это условие при чтении... В любом случае, это все еще возможно, используя (почти) приведенный выше код и используя класс Interpolation libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/ - person florianbaethge; 06.04.2014
comment
Хорошо, я добавил исправленную версию... :) - person florianbaethge; 06.04.2014
comment
Спасибо, очевидно, lerp() было именно то, что я искал. Интерполяция между двумя векторами, а затем я могу добавить к ней специальное смягчение. Цените свои усилия. Ваше здоровье - person Jammo; 07.04.2014
comment
Быстрый вопрос: при перемещении камеры в разные положения я всегда устанавливаю lookAt(0,0,0), чтобы она оставалась сфокусированной на одной точке. Однако при перемещении камеры она начинает терять вектор up и начинает опрокидываться. - person Jammo; 07.04.2014
comment
На самом деле игнор. Я не мог установить вектор up, пока не понял, что могу просто сделать это: this.cam.up.set(0, 1, 0); Теперь работает отлично. Спасибо еще раз - person Jammo; 07.04.2014
comment
Ах, хорошо :) Я не уверен, но вы также можете использовать для этого camera.normalizeUp(): libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/ ... Он должен повторно нормализовать вектор вверх, если оно изменилось... - person florianbaethge; 07.04.2014