javascript - tween.js 和 Three.js 的未对齐平滑旋转

标签 javascript rotation three.js tween

使用 Three.js 和 tween.js我正在尝试创建一个魔方。它由 27 个小立方体组成,这些小立方体组合在一起,通过 +Math.PI/2-Math.PI/2 进行旋转。补间库用于获得平滑的旋转。

我的问题是,如果一张脸旋转多次(超过 10 次),它会明显错位,我不明白如何修复它(link 到问题的视觉图像)。

这是旋转下面示例中的对象的函数:

function rotate( ii ) {
    // Creates a dummy object to group multiple objects together and
    // rotate (only one object in this example).
    var rotationGroup = new THREE.Object3D();
    scene.add(rotationGroup);
    THREE.SceneUtils.attach( box[ ii ], scene, rotationGroup );
    rotationGroup.updateMatrixWorld();

    // Checks that no other animations are active. If so stops the
    // function (this is rude, but it's not the focus of the example).
    if( TWEEN.getAll().length>0 )
        return;

    // Creates the tween object for animation.
    var tween;
    var duration = 300;
    var radiants = Math.PI/2;
    tween = new TWEEN.Tween( rotationGroup.rotation ).to( { z: radiants }, duration );
    tween.easing( TWEEN.Easing.Quadratic.InOut );
    tween.onComplete(
        function() {
            THREE.SceneUtils.detach( box[ ii ], rotationGroup, scene );
            box[ii].updateMatrixWorld();
            scene.remove(rotationGroup);
        }
    );

    // Starts the animation.
    tween.start();
}
<小时/>

我不知道如何在 stackoverflow 上创建一个正在运行的代码片段,所以现在我将粘贴一些复制问题的代码(而不是 rubick 的代码,它更长而且更困惑)。

var camera, scene, renderer;
var canvas;

var cameraControls;
var clock = new THREE.Clock();

var box = [];

function main() {
    init();
    fillScene();
    addToDOM();
    animate();

    function init() {
        var canvasWidth = window.innerWidth;
        var canvasHeight = window.innerHeight;
        var canvasRatio = canvasWidth / canvasHeight;

        // RENDERER
        renderer = new THREE.WebGLRenderer( { antialias: true } );
        renderer.gammaInput = true;
        renderer.gammaOutput = true;
        renderer.setSize(canvasWidth, canvasHeight);
        renderer.setClearColor( 0xAAAAAA );

        // CAMERA
        camera = new THREE.PerspectiveCamera( 45, canvasRatio, 1, 1000 );
        camera.position.set(20,15,10);
        camera.lookAt( new THREE.Vector3(0,0,0) );

        // CONTROLS
        cameraControls = new THREE.OrbitControls(camera, renderer.domElement);

        document.onkeydown = function(ev) {onKeyDown(ev);};

    }

    function addToDOM() {
        var container = document.getElementById('WebGL-output');
        var canvas = container.getElementsByTagName('canvas');
        if (canvas.length>0) {
            container.removeChild(canvas[0]);
        }
        container.appendChild( renderer.domElement );
    }

    function animate() {
        requestAnimationFrame( animate );
        render();
    }

    function render() {
        var delta = clock.getDelta();
        cameraControls.update(delta);

        TWEEN.update();

        renderer.render(scene, camera);
    }

    function onKeyDown(ev) {
        switch( ev.keyCode) {

            case 65: // a
                rotate(0);
                break;
            case 83: // s
                rotate(1);
                break;
            case 68: // d
                rotate(2);
                break;

            default: break;
        }
    }

}

function rotate( ii ) {

    var rotationGroup = new THREE.Object3D();
    scene.add(rotationGroup);
    THREE.SceneUtils.attach( box[ ii ], scene, rotationGroup );
    rotationGroup.updateMatrixWorld();

    if( TWEEN.getAll().length>0 )
        return;
    var tween;
    var duration = 300;
    var radiants = Math.PI/2;

    tween = new TWEEN.Tween( rotationGroup.rotation ).to( { z: radiants }, duration );

    tween.easing( TWEEN.Easing.Quadratic.InOut );
    tween.onComplete(
        function() {
            THREE.SceneUtils.detach( box[ ii ], rotationGroup, scene );
            box[ii].updateMatrixWorld();
            scene.remove(rotationGroup);
        }
    );

    tween.start();
}

function fillScene() {
    scene = new THREE.Scene();
    scene.fog = new THREE.Fog( 0xAAAAAA, 2000, 4000 );

    var axisHelper = new THREE.AxisHelper( 20 );
    scene.add( axisHelper );

    // LIGHTS
    scene.add( new THREE.AmbientLight(0x333333) );
    var light = new THREE.PointLight( 0x333333, 2 );
    light.position.set(15,15,15);
    scene.add(light);
    light = new THREE.PointLight( 0x333333, 2 );
    light.position.set(-15,-15,-15);
    scene.add(light);

    var boxGeometry = new THREE.BoxGeometry( 10, 3, 10);
    var red   = new THREE.MeshPhongMaterial({ color: 0xff0000 });
    var blue  = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
    var green = new THREE.MeshPhongMaterial({ color: 0x0000ff });
    var black = new THREE.MeshPhongMaterial({ color: 0x000000 });
    var materials = [
        [ red, red, red, red, black, black ],
        [ green, green, green, green, black, black ],
        [ blue, blue, blue, blue, black, black ]
    ];
    for( var ii=0; ii<3; ii++ ) {
        box[ii] = new THREE.Mesh( boxGeometry, new THREE.MeshFaceMaterial(materials[ii]) );
        box[ii].rotation.x = Math.PI/2;
        box[ii].position.set(0,0,3-(ii*3));
        scene.add( box[ii] );
    }

}
<小时/>

在js控制台上打印rotationGroupbox[ii]的旋转,它们似乎不匹配:Object3D的旋转在第四个小数位上引入了一点错误。

最佳答案

我修改了补间完成后执行的匿名函数,添加了一些代码来检查旋转并设置正确的旋转值(感谢@WestLangley发现解决方案)。

 function() {
     THREE.SceneUtils.detach( box[ ii ], rotationGroup, scene );
     box[ii].updateMatrixWorld();
     scene.remove(rotationGroup);

     // Checks the rotation value and sets the correct one accordingly
     var check = Math.floor( box[ii].rotation.z );
     if( check==1 )
         box[ii].rotation.z = Math.PI/2;
     else if( check==3 )
         box[ii].rotation.z = Math.PI;
     else if( check==-2 )
         box[ii].rotation.z = -Math.PI/2;
     else
         box[ii].rotation.z = 0;
 }

关于javascript - tween.js 和 Three.js 的未对齐平滑旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28028617/

相关文章:

javascript 从计算机 onclick 在地板上添加纹理

javascript - 使用 Three.js 将站点更改为连续动画

JavaScript onload() 函数

javascript - 在运行时添加 Knockout 模板会清空 HTML DOM

c++ - 计算 3D 对象和点之间的角度

圆上两度之间最短行进方向的算法或公式?

javascript - 为什么要使用 (function() { .... }());

javascript - AngularJS 当一个单选按钮值被选择为 true 时,如何将所有单选按钮值更新为 false?

iphone - 如何旋转 UIWebView 嵌入的视频

javascript - three.js 透明 map 问题