Анимация (вращение, движение) объекта по щелчку мыши - PullRequest
0 голосов
/ 17 февраля 2019

Принимая во внимание этот пример three.js

https://threejs.org/examples/?q=glt#webgl_loader_gltf

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

Вот код, который я добавил.Должен ли я чрезмерно использовать рендер?

        document.addEventListener( 'mousedown', clickMe, false );
        render();

        function clickMe() {
            rotation();
            render();   
        }


        var gltfModel;


        function rotation() {
            var rotationAnimation = 5 * (Math.PI / 180);
            gltfModel.rotation.x += rotationAnimation;
            render();       
        }

        function render() {
            renderer.render( scene, camera );
        }

, если я добавлю в функциюtate ();requestAnimationFrame (вращение);

            function rotation() {
            requestAnimationFrame( rotation );
            var rotationAnimation = 5 * (Math.PI / 180);
            gltfModel.rotation.x += rotationAnimation;
            render();       
        }

gltfModel продолжает вращать цикл, и каждый раз, когда я нажимаю, скорость удваивается

Вот полный код:

        <script>

        if ( WEBGL.isWebGLAvailable() === false ) {

            document.body.appendChild( WEBGL.getWebGLErrorMessage() );

        }

        var container, stats, controls;
        var camera, scene, renderer, light;




        init();
        animate();

        function init() {

            container = document.createElement( 'div' );
            document.body.appendChild( container );

            camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.25, 20 );
            camera.position.set( - 1.8, 0.9, 2.7 );

            controls = new THREE.OrbitControls( camera );
            controls.target.set( 0, - 0.2, - 0.2 );
            controls.update();

            var urls = [ 'posx.jpg', 'negx.jpg', 'posy.jpg', 'negy.jpg', 'posz.jpg', 'negz.jpg' ];
            var loader = new THREE.CubeTextureLoader().setPath( 'textures/cube/Bridge2/' );
            var background = loader.load( urls );

            scene = new THREE.Scene();
            scene.background = background;

            light = new THREE.HemisphereLight( 0xbbbbff, 0x444422 );
            light.position.set( 0, 1, 0 );
            scene.add( light );

            // model
            var loader = new THREE.GLTFLoader().setPath( 'models/gltf/DamagedHelmet/glTF/' );
            loader.load( 'DamagedHelmet.gltf', function ( gltf ) {

                gltf.scene.traverse( function ( child ) {

                    if ( child.isMesh ) {

                        child.material.envMap = background;

                        gltfModel = child;

                    }

                } );

                scene.add( gltf.scene );

            }, undefined, function ( e ) {

                console.error( e );

            } );

            renderer = new THREE.WebGLRenderer( { antialias: true } );
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize( window.innerWidth, window.innerHeight );
            renderer.gammaOutput = true;
            container.appendChild( renderer.domElement );

            window.addEventListener( 'resize', onWindowResize, false );

            //MY LINE OF CODE
            document.addEventListener( 'mousedown', clickMe, false );
            render();


            // stats
            stats = new Stats();
            container.appendChild( stats.dom );

        }

        function onWindowResize() {

            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();

            renderer.setSize( window.innerWidth, window.innerHeight );

        }

        //MY LINE OF CODE
        ///////////////////////////////////////

        function clickMe() {

            rotation();

            render();



        }


        var gltfModel;


        function rotation() {

            var rotationAnimation = 5 * (Math.PI / 180);

            gltfModel.rotation.x += rotationAnimation;

            render();

        }




        ///////////////////////////////////////



        function animate() {

            requestAnimationFrame( animate );


            render();

            stats.update();


        }


        function render() {
            renderer.render( scene, camera );
        }

    </script>

Может ли этобыть достигнуто с EventDispatcher?Если так, то как?https://threejs.org/docs/#api/en/core/EventDispatcher

Но я предпочитаю, может быть, первый метод?

Ответы [ 2 ]

0 голосов
/ 17 февраля 2019

Простой пример кода коробки, которая вращается при наведении мыши, чтобы начать работу.Вы можете легко применить его к вашей модели GLTF.Что касается метода рендеринга, да, вы используете его в своих функциях без причины.Вы должны взглянуть на основные примеры сцен.

https://threejs.org/docs/#manual/en/introduction/Creating-a-scene

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>

</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/101/three.min.js"></script>
<script> 
    var box;
    var isMouseDown = false;
    var rotateSpeed = 0;

    init();
    animate();

    function init() {

        container = document.createElement('div');
        document.body.appendChild(container);

        camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.25, 20);
        camera.position.set(5,5,5);
        camera.lookAt(new THREE.Vector3(0,0,0));

        scene = new THREE.Scene();

        light = new THREE.HemisphereLight(0xbbbbff, 0x444422);
        light.position.set(0, 1, 0);
        scene.add(light);
        
        var geometry = new THREE.BoxBufferGeometry( 1, 1, 1 );
        var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
        box = new THREE.Mesh( geometry, material );
        scene.add( box );

        renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(window.innerWidth, window.innerHeight);
        container.appendChild(renderer.domElement);

        window.addEventListener('mousedown', () => isMouseDown = true,false);
        window.addEventListener('mouseup', () => isMouseDown = false,false);
        
        animate();

    }

    function animate() {

        requestAnimationFrame(animate);

        if(isMouseDown) rotateSpeed += 0.001;
        else rotateSpeed /= 1.01;
        box.rotation.y += rotateSpeed;

        render();

    }
    
    function render() {

        renderer.render(scene, camera);

    }
</script>

</html>
0 голосов
/ 17 февраля 2019

Да, вам нужно позвонить render только один раз, чтобы вы могли принять эти три вызова из rotation() и clickMe() и после document.addEventListener( 'mousedown', clickMe, false );.

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

Если вы хотите сделать это, вы можете просто установить логическое значение на mousedown.

Так что внутриclickMe, вы можете сделать что-то вроде:

function clickMe() {
  rotating = true; // declare this as a global variable
}

и затем в своей функции рендеринга вы можете сделать:

function render() {
  if (rotating) {
    var rotationAnimation = 5 * (Math.PI / 180);
    gltfModel.rotation.x += rotationAnimation;
  }
  renderer.render( scene, camera );
}

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

function handleMouseUp() {
  rotating = false;
}

document.addEventListener('mouseup', handleMouseUp);
...