0

我正在用 Three.js 渲染一个 obj 文件(来自搅拌机),我遇到的问题是动画随着时间的推移而变慢(相当戏剧化!)。

这是我使用的代码:

<script>

            var objcontainer, stats;

            var camera, scene, renderer;

            var mouseX = 0, mouseY = 0;

            var windowHalfX = window.innerWidth / 2;
            var windowHalfY = window.innerHeight / 2;

            init(); 
            animate();


            function init() {

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

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

                camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 2000 );
                camera.position.z = 300;
                camera.position.x = 0;
                camera.position.y = 0;
                scene.add( camera );

                /*var ambient = new THREE.AmbientLight( 0x101030 );
                scene.add( ambient );*/

                var directionalLight = new THREE.DirectionalLight( 0xffffff );
                directionalLight.position.set( 1, 1, 1 ).normalize();
                scene.add( directionalLight );

                var loader = new THREE.OBJMTLLoader();
                loader.addEventListener( 'load', function ( event ) {
                    var object = event.content;

                    object.position.y = 20;
                    object.position.x = 0;
                    object.position.z = 0;
                    object.rotation.x = -(Math.PI / 2);
                    scene.add( object );
                }, false);
                loader.load('objects/coque.obj', 'objects/coque.mtl');
                loader.load('objects/ecran_int.obj', 'objects/ecran_int.mtl');
                loader.load('objects/ecran_tour.obj', 'objects/ecran_tour.mtl');
                loader.load('objects/app_photo.obj', 'objects/app_photo.mtl');


                renderer = new THREE.WebGLRenderer({
                    antialias       : true // to get smoother output
                });
                renderer.setClearColorHex( 0xe5e5e5, 1 );
                renderer.setSize( window.innerWidth, window.innerHeight );
                objcontainer.appendChild( renderer.domElement );            
            }

            $('#left').bind('mouseenter', function() {
                this.iid = setInterval(function() {
                camera.position.x = camera.position.x + 10;
                camera.lookAt( scene.position );
                renderer.clear();
                renderer.render( scene, camera );                 
            }, 25);
            }).bind('mouseleave', function(){
                this.iid && clearInterval(this.iid);
            });


            $('#right').bind('mouseenter', function() {
                this.iid = setInterval(function() {
                camera.position.x = camera.position.x - 10;
                camera.lookAt( scene.position );
                renderer.clear();
                renderer.render( scene, camera );              
            }, 25);
            }).bind('mouseleave', function(){
                this.iid && clearInterval(this.iid);
            });

            $('#up').bind('mouseenter', function() {
                this.iid = setInterval(function() {
                camera.position.y = camera.position.y - 10;
                camera.lookAt( scene.position );
                renderer.clear();
                renderer.render( scene, camera );              
            }, 25);
            }).bind('mouseleave', function(){
                this.iid && clearInterval(this.iid);
            });

            $('#down').bind('mouseenter', function() {
                this.iid = setInterval(function() {
                camera.position.y = camera.position.y + 10;
                camera.lookAt( scene.position );
                renderer.clear();
                renderer.render( scene, camera );              
            }, 25);
            }).bind('mouseleave', function(){
                this.iid && clearInterval(this.iid);
            });

            $('#zoom-in').bind('mouseenter', function() {
                this.iid = setInterval(function() {
                camera.position.z = camera.position.z - 10;
                camera.lookAt( scene.position );
                renderer.clear();
                renderer.render( scene, camera );              
            }, 25);
            }).bind('mouseleave', function(){
                this.iid && clearInterval(this.iid);
            });

            $('#zoom-out').bind('mouseenter', function() {
                this.iid = setInterval(function() {
                camera.position.z = camera.position.z + 10;
                camera.lookAt( scene.position );
                renderer.clear();
                renderer.render( scene, camera );              
            }, 25);
            }).bind('mouseleave', function(){
                this.iid && clearInterval(this.iid);
            });

            $('#init').bind('click', function() {
                camera.position.z = 300;
                camera.position.x = 0;
                camera.position.y = 20;
                camera.lookAt( scene.position );
                renderer.clear();
                renderer.render( scene, camera );              
            });

            function animate() {

                requestAnimationFrame( animate );
                render();
            }

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

        </script>

在 Safari 上,性能下降的速度有点慢,在 Chrome 上它很快。

任何帮助表示赞赏:)

杰弗里

4

1 回答 1

0

一个 jsfiddle 会更容易调试。但我高度怀疑这是因为您正在从事件处理程序 setInterval 函数调用 render() 。这根本不是必需的,因为您已经在动画函数中渲染了每一帧。

我认为您的代码可以使每一帧的场景被多次渲染,因为间隔没有正确清除。这可以解释为什么它会随着时间的推移而减慢;冗余渲染()调用的数量不断增长......

尝试删除所有

            renderer.clear();
            renderer.render( scene, camera );    

从您的事件处理程序/setintervals。

编辑:您可以检查一些控制文件(https://github.com/mrdoob/three.js/blob/master/examples/js/controls/FirstPersonControls.js),了解它们如何使用事件处理程序实现运动(动画) . 事件中没有逻辑发生,他们只设置了一个变量,如movingForward = true;. 然后在单个 update() 循环中完成实际移动。在您的情况下,这种方法也可能更好。

编辑#2:实际上只是注意到你的主动画循环设置不正确,这可能是主要问题(关于事件处理程序的东西仍然值得考虑)。它还会导致冗余的渲染调用。尝试从您的 render() 函数中删除 requestAnimationFrame 调用,就像您在 animate() 中所做的那样。

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

        function render() { 
            // requestAnimationFrame(render); <-- remove this
            renderer.render(scene, camera); 
        } 
于 2013-04-19T10:51:48.937 回答