0

I have the following code and I'm wondering why it speeds out of control when I resize the window.

        <!DOCTYPE html>
        <html>
        <head>
        <title>Page Title</title>
        </head>
        <body>
        
        <h1>FooBarBaz</h1>
        <p>LaDeDa</p>
        <script src="http://threejs.org/build/three.min.js"></script>
        <script src="https://threejs.org/examples/js/controls/TrackballControls.js"></script>
        <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 );
        
        var objects = [
            {
                name : "earth",
                mesh : new THREE.Mesh(new THREE.SphereGeometry(1, 32, 32), new THREE.MeshPhongMaterial()),
                init : function(scene){
                this.mesh.position.set(0,0,0);
                //this.material.map = THREE.ImageUtils.loadTexture('../earth.jpg');
                scene.add(this.mesh);
                },
                animate : function(t){return}
            },
            {
                name : "satellite",
                mesh : new THREE.Mesh(new THREE.SphereGeometry(0.1, 32, 32), new THREE.MeshPhongMaterial()),
                init : function(scene){
                this.mesh.position.set(1.5,0,0);
                //this.material.map = THREE.ImageUtils.loadTexture('../earth.jpg');
                scene.add(this.mesh);
                },
                animate : function(t){this.mesh.position.set(Math.sin(t)*1.5,Math.cos(t)*1.5,0);}
            }];
        objects.forEach(object => object.init(scene));
        
        var light = new THREE.HemisphereLight(0xf6e86d, 0x404040, 0.5);
        scene.add(light);
        
        camera.position.x = 0;
        camera.position.y = -5;
        camera.position.z = 0;
        camera.lookAt(new THREE.Vector3( 0, 0, 0));
        var timeStep = 0.01;
        var time = 0;
        var controls = new THREE.TrackballControls( camera, renderer.domElement );
        controls.target.set( 0, 0, 0 );
        var render = function () {
            time += timeStep;
            requestAnimationFrame( render );
            objects.forEach(object => object.animate(time));
            controls.update();
            renderer.render(scene, camera);
        }
        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight
            camera.updateProjectionMatrix()
            renderer.setSize(window.innerWidth, window.innerHeight)
            render()
        }
        window.addEventListener('resize', onWindowResize, false)
        
        document.body.appendChild( renderer.domElement );
        render();</script>
        </body>
        </html>
        

As you can see every time you resize the window it starts going faster and faster... Why?

kpie
  • 9,588
  • 5
  • 28
  • 50

1 Answers1

0

Because resize calls render and render calls request animation frame(render) you end up with multiple reclusive loops of render overlapping. By adding a function renderOnce that doesn't request animation frame and using that for resizing the problem is solved. The animation will still move slightly faster while resizing but once resizing is complete the animation speed is back to normal.

    var renderOnce = function () {
        time += timeStep;
        objects.forEach(object => object.animate(time));
        controls.update();
        renderer.render(scene, camera);
    }
    var render = function () {
        renderOnce();
        requestAnimationFrame( render );
    }
    window.addEventListener('resize', onWindowResize, false)
    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderOnce();
    }

Also the acceleration while resizing can be solved by moving time+=timeStep from renderOnce to render.

kpie
  • 9,588
  • 5
  • 28
  • 50
  • The [resize event](https://html.spec.whatwg.org/multipage/webappapis.html#event-loop-processing-model:run-the-resize-steps) is tied to animation frames anyway, no need to call render at all from there. – Kaiido Mar 15 '22 at 02:20