Rotation animation, requestAnimationFrame periodic rendering

The development of online games, product displays, and indoor roaming based on WebGL technology often involves animation.

1. Periodic rendering

In order to achieve periodic rendering, you can use a method setInterval() of the browser global object window object. You can call this method window.setInterval(), you can also call setInterval() directly in function form. setInterval() is a periodic function, like a timer, that executes a function every few milliseconds.

// Call function fun periodically at 20ms intervals
setInterval("render()",20)

In order to achieve the cube rotation animation effect, look at the following code

function render(){
     renderer.render(scene,camera);//Perform rendering operation
     mesh.rotateY(0.01);//Rotate 0.01 radians around the y-axis each time
}
setInterval("render()",20);

The above code defines a rendering function render(). Three statements are defined in the function, which can be implemented through setInterval("render()",20); The function render() is called every 20 milliseconds. Each time the rendering function is called, execute renderer.render(scene,camera); to render a frame of image and execute The mesh.rotateY(0.01); statement rotates the cubic mesh model around the y-axis by 0.01 radians.

2. Rendering frequency

The rendering frequency of calling the rendering method .render() cannot be too low, for example, setInterval("render()",200); calls rendering every 200 milliseconds. The function is rendered once, which is equivalent to rendering 5 times per second, and it will feel laggy. The rendering frequency should not be too low, nor should it be too high. If it is too high, the computer's hardware resources cannot keep up, and the rendering method set by the function setInterval() may not be able to be implemented normally. Generally, the rendering frequency of calling the rendering method .render() for rendering is controlled at 30 to 60 times per second. The human visual effect is normal and the rendering performance can also be taken into consideration.

//Set the period for calling the render function to 200ms, and the refresh frequency is equal to 5. You can clearly feel the lag.
setInterval("render()",200);
3. Function requestAnimationFrame()

The requestAnimationFrame() parameter is the function name of the function to be called. requestAnimationFrame() Calling a function does not call it immediately but initiates a request to the browser to execute a certain function. What? The execution time is determined by the browser. Generally, the frequency of 60FPS is maintained by default. The function specified by the requestAnimationFrame() method is called approximately every 16.7ms. 60FPS is ideal. If the rendered scene is more complex or It is said that the hardware performance is limited and may be lower than this frequency.

function render() {
        renderer.render(scene,camera);//Perform rendering operation
        mesh.rotateY(0.01);//Rotate 0.01 radians around the y-axis each time
        requestAnimationFrame(render);//Request to execute the rendering function render again
    }
render();
4. Uniform rotation

When actually executing the program, the function requested by requestAnimationFrame(render) may not be executed at the ideal 60FPS frequency, and the time interval between two executions of the rendering function may not be the same. If the rotation command is executed The time interval of rotateY is different, and the rotation motion is uneven. In order to solve this problem, it is necessary to record the time interval between executing the drawing function twice.

Just use the following rendering function to replace the original rendering function. The parameter of rotateY() is 0.001*t, which also means the interval between two calls to the rendering function to perform the rendering operation. In t milliseconds, the cube rotates 0.001*t radians. Obviously, the angular velocity of the cube is 0.001 radians per millisecond (0.0001 rad/ms = 1 rad/s = 180 degrees/s). The time it takes for CPU and GPU to execute an instruction is nanoseconds ns, which is 6 orders of magnitude lower than milliseconds ms. Therefore, it is generally not necessary to consider the time occupied by several timing statements in the rendering function unless you write something that is accurate to nanoseconds ns. Level standard clock program.

let T0 = new Date();//Last time
function render() {
    let T1 = new Date();//This time
    let t = T1-T0;//time difference
    T0 = T1;//Assign this time to the last time
    requestAnimationFrame(render);
    renderer.render(scene,camera);//Perform rendering operation
    mesh.rotateY(0.001*t);//Rotation angular speed 0.001 radians per millisecond
}
render();
5. Complete example
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>The first ThreeJS</title>
    <!--Introducing three.js three-dimensional engine-->
    <!-- <script src="http://www.yanhuangxueyuan.com/versions/threejsR92/build/three.js"></script> -->
    <script src="../js/three.js"></script>
    <script src="../js/OrbitControls.js"></script>
</head>
<style>
    body {
        margin: 0;
        overflow: hidden
            /*Hide body window area scroll bar*/
        ;
    }
</style>

<body>
    <script>
        //Create scene object
        var scene = new THREE.Scene();
        //Create grid model
        var geometry = new THREE.BoxGeometry(50, 100, 100);//Create a cubic geometry object
        // var geometry = new THREE.SphereGeometry(60, 40, 40);
        var material = new THREE.MeshLambertMaterial({
            color: 0x0000ff
        }) //Create material object Material

        var mesh = new THREE.Mesh(geometry, material); //Mesh object model
        scene.add(mesh);//Add the mesh model to the scene

        //Light source settings: point light source
        var point = new THREE.PointLight(0xffffff);
        point.position.set(400, 200, 300); //Point light source position
        scene.add(point); //Add point light source to the scene

        //Ambient light
        var ambient = new THREE.AmbientLight(0x444444);
        scene.add(ambient); //Add ambient light to the scene

        //Camera settings
        var width = window.innerWidth; //Create width
        var height = window.innerHeight;//Window height
        var k = width / height;//window aspect ratio
        var s = 200; //Three-dimensional scene display range control coefficient. The larger the coefficient, the greater the display range.

        var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000); //Create camera object
        camera.position.set(250, 300, 200); //Set camera position
        camera.lookAt(scene.position); //Set the camera direction (pointing scene object)

        var renderer = new THREE.WebGLRenderer();//Create renderer object
        renderer.setSize(width, height); //Set the rendering area size
        renderer.setClearColor(0xb9d3ff, 1);//Set the background color
        document.body.appendChild(renderer.domElement);//Insert canvas object into body element
        // renderer.render(scene, camera);//Perform the rendering operation and specify the scene and camera as parameters

        // function render(){
        // renderer.render(scene,camera);//Perform rendering operation
        //mesh.rotateY(0.01);//Rotate 0.01 radians around the y-axis each time
        // requestAnimationFrame(render);//Request to execute the rendering function render again
        // }
        // render();
        // let T0 = new Date();//Last time
        // function render() {
        // let T1 = new Date();//This time
        // let t = T1-T0; // time difference
        // T0 = T1; // Assign this time to the last time
        // requestAnimationFrame(render);
        // renderer.render(scene,camera);//Perform rendering operation
        //mesh.rotateY(0.001*t);//Rotation angular speed 0.001 radians per millisecond
        // }
        // render();
        function render() {
            renderer.render(scene, camera);//Perform rendering operation
            //mesh.rotateY(0.01);//Rotate 0.01 radians around the y-axis each time
            requestAnimationFrame(render);//Request to execute the rendering function render again
        }
        render();
        var controls = new THREE.OrbitControls(camera, renderer.domElement);//Create a control object
        // The render function has been executed periodically through requestAnimationFrame(render);, there is no need to execute the render function by listening to mouse events.
        // controls.addEventListener('change', render)
    </script>
</body>

</html>
syntaxbug.com © 2021 All Rights Reserved.