通用补间引擎/ LibGDX:模型在补间之间按顺序丢失变换和旋转

时间:2015-01-04 22:10:55

标签: java libgdx tween translate-animation rotateanimation

我正在制作一款3D游戏并尝试正确设置角色动作。交互很简单,屏幕上有一个单一的模型,用户点击屏幕上的一个点,模型旋转面对点击的点(此时模型是一个有点眼睛的幽灵,所以眼睛转向面对点击,并且,一旦面对该点,模型将移动到那里。

我使用了一些我自己编写的代码,但动画并不平滑,模型经常会超出/低于目的地,然后向后或向前猛拉到位。我以前只在2d动画上使用Universal Tween引擎,但决定尝试一下。它解决了急躁问题,并且可以自行旋转和转换两种工作方式,但是我无法让它们按顺序一起工作。

如果我只启用旋转模型的代码,它可以正常工作(好吧,几乎没问题,某些东西变得奇怪,在某些角度确定顺时针或逆时针旋转,但这是以后的另一个问题) :我单击一个位置,模型旋转以面向它并保持新的旋转直到下一次单击,然后它转向面向该位置。与仅启用翻译相同:我点击一个点,模型移动到它并保留它的新翻译,直到我再次点击,然后它移动到该位置等。

当翻译和旋转都启用时,我遇到了问题。模型将首先旋转以面向单击的点,然后设置回其初始旋转,然后移动到单击的点。在随后的点击中,模型将首先返回其初始平移,然后旋转以面向单击的点(实际上是相对于重新初始化的位置的点击点的位置),然后移动到单击的点。

我尝试重新排列代码,使用回调,将新的翻译和轮换缓存到游戏模型类的成员,然后在开始补间之前使用set()及其值,但没有任何效果。< / p>

以下是我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;
            ...
        }
    }
}

以下是启动时间轴和补间的代码(它在this file中):

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。这些是来自getValuessetValuesTweenAccessor函数的值的日志:

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)之后才会通过其补间运行。

getValues的4次调用可能是件事。我不确定在我的设置中会导致Timeline在补间开始之前抓取翻译的值,如果它们应该按顺序运行,因为它们会被推入Timeline。我也不确定为什么getValues为每个补间调用两次,但是在补间过程中Tween引擎会调用它两次并不是不可行的。

我非常确定我使用的LibGDX的翻译/旋转功能都很好,他们坚持使用#&#39;对于模型而言,我使用与非Tween-Engine版本相同的翻译。旋转类似,但功能不同。

在第二次翻译期间改变Y值是值得研究的。

1 个答案:

答案 0 :(得分: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;
    }
}