Как правильно использовать функцию settimeout для вращения куба с three.js - PullRequest
1 голос
/ 25 марта 2019

Программа, которую я пишу, будет использоваться для вращения куба. HTML-файл позволит пользователю вводить CSV-файл с кватернионными данными. Затем код javascript вращает куб, используя каждый кватернион в файле данных с постоянной скоростью. В этом случае каждый новый кватернион применяется к кубу каждые 16,7 миллисекунды (60 кадров в секунду). Текущая программа, которую я написал, использует setTimeout для выполнения этой цели.

Вот код JavaScript, который у меня сейчас есть:

    <script>

    var scene = new THREE.Scene();
    var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );

    var renderer = new THREE.WebGLRenderer();
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );

    var geometry = new THREE.BoxGeometry( 1, 1, 1 );
    var material = new THREE.MeshBasicMaterial( { color: 0x00ff70 } );
    var cube = new THREE.Mesh( geometry, material );
    scene.add( cube );

    camera.position.z = 5;
    renderer.render(scene,camera);


    var animate = function() {

        quat_data = [];

        var rotate = function(quat) {
          cube.applyQuaternion(quat);
        }

        for(i=0; i<quat_data.length; i++) {
            time = 16.7;
            var next_quat = quat_data[i];
            setTimeout(rotate(next_quat), time);
        }


    }



    </script>

Пользователь нажимает кнопку в верхней части экрана браузера, чтобы выполнить функцию анимации. Также обратите внимание, что quat_data в настоящее время пусто. Чтобы проверить код JavaScript, я установил quat_data равным массиву кватернионов образца. Я еще не написал код для преобразования введенного CSV-файла в массив. Как только я это сделаю, я буду использовать это вместо кватернионов образца.

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

renderer.render(scene,camera);

внутри функции поворота и в нескольких других местах кода, но это не произвело повторную визуализацию куба.

Какой код я должен включить в функцию animate для повторного рендеринга куба после применения каждого кватерниона? Или есть ли способ выполнить ту же задачу с requestAnimationFrame?

1 Ответ

1 голос
/ 26 марта 2019

Во-первых, вам нужно использовать renderer.render(scene,camera); внутри функции rotate, потому что после изменения ориентации куба вам необходимо повторно визуализировать сцену.

Во-вторых, вы неправильно используете функцию setTimeout. Вы хотите вызывать функцию поворота после каждого из 16,7, 33,4, 50,1 ... миллисекунд. Таким образом, вы должны провести время таким образом. Также вы должны передать функцию обратного вызова вместо прямого вызова функции. Попробуйте следующий код -

let time = 0;
 for(let i=0; i<quat_data.length; i++) {
     time += 16.7;
     setTimeout(function() { 
         rotate(quat_data[i])
     }, time);
 }

Последнее, попробуйте избежать функции setTimeout для анимации, вместо этого используйте window.requestAnimationFrame. Эта функция будет вызываться браузером до следующей перерисовки, и вы можете изменить ориентацию куба в этой функции и визуализировать сцену. Вот пример кода -

let i= 0;
var animate = function () {
    requestAnimationFrame( animate );

    i++;
    if (i >= quat_data.length)
        i = quat_data.length - 1;

    let quat = quat_data[i];
    cube.applyQuaternion(quat);

    renderer.render( scene, camera );
};

animate(); 
...