Universal Tween Engine / LibGDX: модели с потерей трансформации и вращения между подростками в последовательности

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

Я работал с каким-то кодом, который написал сам, но анимация не была плавной, и модель часто выходила за пределы / не соответствовала пункту назначения, а затем дергалась назад или вперед на место. Раньше я работал только с движком Universal Tween над 2D-анимацией, но решил попробовать. Это решило проблемы, связанные с рывками, и вращение и трансформация работают отлично, но я не могу заставить их работать вместе в определенной последовательности.

Если я включаю только код, который вращает модель, он работает нормально (ну, почти нормально, что-то становится странным с определением вращения по часовой стрелке или против часовой стрелки под определенными углами, но это еще одна проблема позже): я нажимаю на местоположение, модель поворачивается лицом к нему и сохраняет новое вращение до следующего щелчка, затем поворачивается лицом к этому месту. То же самое с включенным только переводом: я щелкаю точку, модель перемещается к ней и сохраняет свой новый перевод, пока я не нажму снова, затем она перемещается в это место и т. Д.

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

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

Вот соответствующий код из моего TweenAccessor:

public class GameModelTweenAccessor implements TweenAccessor<DynamicModel> {    
    public int getValues(DynamicModel target, int tweenType, float[] returnValues) {
        trans = target.model.transform.getTranslation(trans);
        switch (tweenType) {
            ...
            case POSITION_XYZ:
                returnValues[0] = trans.x;
                returnValues[1] = trans.y;
                returnValues[2] = trans.z;
                return 3;
            case ROTATION:
                axisVec = new Vector3();
                angle = target.model.transform.getRotation(new Quaternion()).getAxisAngle(axisVec) * axisVec.nor().y;
                returnValues[0] = angle;
                return 1;
            ...
        }

    }

    public void setValues(DynamicModel target, int tweenType, float[] newValues) {
        trans = target.model.transform.getTranslation(trans);
        switch (tweenType) {
            ...
            case POSITION_XYZ:
                target.model.transform.setToTranslation(newValues[0], newValues[1], newValues[2]);
                break;
            case ROTATION:
                target.model.transform.setToRotation(Vector3.Y, newValues[0]);
                break;
            ...
        }
    }
}

А вот код, который запускает временную шкалу и анимацию (она находится в этом файле):

Timeline.createSequence()
    .push(Tween.to(screen.ghost, GameModelTweenAccessor.ROTATION, Math.abs(angle - newRotation) / 200)
        .target(newRotation)
        .ease(TweenEquations.easeNone))
    .push(Tween.to(screen.ghost, GameModelTweenAccessor.POSITION_XYZ, duration).
        target(intersection.x, intersection.y, intersection.z)
        .ease(TweenEquations.easeNone))
    .start(screen.ghostManager);

Кто-нибудь может указать мне на решение?

РЕДАКТИРОВАТЬ: кажется, что преобразования, устанавливаемые по завершении каждой анимации, сбрасываются в 0 после завершения другой анимации. Это журналы этих значений из getValues а также setValues функции в TweenAccessor:

Get Rot: 0.0

Get Trans: x: 0.0          y: 0.0          z: 0.0

Get Rot: 0.0

Get Trans: x: 0.0          y: 0.0          z: 0.0

Get Rot: 0.0

Set Rot: 9.598349
Set Rot: 9.814415
Set Rot: 10.052449
...
Set Rot: 39.99417
Set Rot: 43.397423
Set Rot: 46.62333

Get Trans: x: 0.0          y: 0.0          z: 0.0

Set Trans: x: 0.0012489144 y: 0.0          z: 0.001180494
Set Trans: x: 0.024489587  y: 0.0          z: 0.023147952
Set Trans: x: 0.04921494   y: 0.0          z: 0.04651875
...
Set Trans: x: 6.4197707    y: 0.0          z: 6.06807
Set Trans: x: 6.444479     y: 0.0          z: 6.091425
Set Trans: x: 6.453598     y: 0.0          z: 6.1000443

Get Rot: 0.0

Get Trans: x: 6.453598     y: 0.0          z: 6.1000443

Get Rot: 0.0

Get Trans: x: 6.453598     y: 0.0          z: 6.1000443

Get Rot: 0.0

Set Rot: 3.4318955
Set Rot: 6.795984
Set Rot: 10.0074415
...
Set Rot: 156.79567
Set Rot: 159.99591
Set Rot: 162.38742

Get Trans: x: 0.0          y: 0.0          z: 0.0

Set Trans: x: 0.03550978   y: 3.836017E-8  z: 0.021066409
Set Trans: x: 0.15527377   y: 1.6773768E-7 z: 0.092117175
...
Set Trans: x: 6.848614     y: 7.3983565E-6 z: 4.062985
Set Trans: x: 6.961268     y: 7.5200533E-6 z: 4.129818
Set Trans: x: 7.0624847    y: 7.6293945E-6 z: 4.189865

Get Rot: 0.0

Get Trans: x: 7.0624847    y: 7.6293945E-6 z: 4.189865

Get Rot: 0.0

Get Trans: x: 7.0624847    y: 7.6293945E-6 z: 4.189865

Get Rot: 0.0

Set Rot: -3.2620814
Set Rot: -6.8205137
Set Rot: -9.834579
...
Set Rot: -76.57533
Set Rot: -79.91388
Set Rot: -80.610855

Get Trans: x: 0.0          y: 0.0          z: 0.0

Set Trans: x: 0.01940876   y: 0.0          z: 0.033669088
Set Trans: x: 0.04174851   y: 0.0          z: 0.07242267
Set Trans: x: 0.06332677   y: 0.0          z: 0.109855264
...
Set Trans: x: 2.7853239    y: 0.0          z: 4.8318033
Set Trans: x: 2.808029     y: 0.0          z: 4.8711905
Set Trans: x: 2.827034     y: 0.0          z: 4.9041595

getValues вызывается дважды для каждого типа анимации (перевод и вращение) до начала анимации. На этом этапе значения для перевода остаются такими же, какими они были установлены в конце последней анимации перевода. Значение для поворота было установлено обратно в 0 (хотя я предполагаю, что в результате следующей группы вызовов setValues для вращения).

setValues затем вызывается несколько раз для вращения, пока не достигнет цели вращения. Это (кроме сброса вращения) работает так, как я ожидал и надеюсь. После getRotation хотя звонки перевод переводится обратно в 0,0,0, но не путем вызова setValues (нет записи об этом). Затем перевод анимируется к цели с несколькими setValues звонки.

После этого цикл перезапускается по другому клику и getValues вызывается дважды для ротации и перевода. Перевод имеет значения, которые были установлены при последнем вызове setValues напоследок Timeline, но только до тех пор, пока вращение (вернувшееся в 0) не пройдет через анимацию движения.

4 звонка getValues может быть что-то. Я не уверен, что в моей настройке вызовет Timeline будет захватывать значения перевода до того, как начнется его анимация, если предполагается, что они будут выполняться последовательно, когда они помещаются в Timeline, Я также не уверен, почему getValues вызывается дважды для каждой анимации, но не исключено, что Tween Engine будет вызывать его дважды в течение анимации.

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

Изменение значений Y во время второго перевода - это то, на что стоит обратить внимание.

1 ответ

Решение

Таким образом, решение не имело ничего общего с Universal Tween Engine или тем, как оно было реализовано. Это было только мое плохое понимание функций матричного преобразования в LibGDX. Призыв к setToRotation сбрасывает матрицу преобразования, а затем просто применяет вращение, таким образом обнуляя предыдущий перевод. setToTranslation делает то же самое, что вызвало потерю вращения.

Для перевода я использовал setTranslation вместо этого, и вращение не теряется. Я не думаю, что есть сопоставимая функция для вращения (используя rotate вызывает все виды проблем), поэтому вместо этого я получаю новый Vector3 с сохранением в нем положения модели, затем примените setToRotation, затем установите перевод на новый вектор. Вот обновленный код из TweenAccessor:

public void setValues(DynamicModel target, int tweenType, float[] newValues) {
    trans = target.model.transform.getTranslation(trans);
    switch (tweenType) {
        ...
        case POSITION_XYZ:
            target.model.transform.setTranslation(newValues[0], newValues[1], newValues[2]);
            break;
        case ROTATION:
            // store the position
            Vector3 position = target.model.transform.getTranslation(new Vector3());
            // then set the rotation and reset the translation
            target.model.transform.setToRotation(Vector3.Y, newValues[0]).setTranslation(position);
            break;
        default:
            assert false;
            break;
    }
}
Другие вопросы по тегам