Ambrosius Topor

Notiz
(2017-10-03)

Dive into WebGL with Three.js

Experiments with WebGL using the Three.js library.

ThreeJS Scene 1
ThreeJS Scene 2

Create HTML document

<!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>Three.js Example</title>
    <script src="vendorjs/threejs-0.87.1/three.min.js"></script>
</head>
<body>
    <canvas id="myCanvas"></canvas>
    <script src="scripts/main.js"></script>
</body>
</html>

Create a renderer

function createRenderer() {

    var renderer = new THREE.WebGLRenderer({
        canvas: document.querySelector('#myCanvas'),
        antialias: true
    });

    renderer.setClearColor(0x000000);
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);

    return renderer;
}

Create a camera

function createPerspectiveCamera() {

    var camera = new THREE.PerspectiveCamera(
        35,
        window.innerWidth / window.innerHeight,
        0.1,
        3000
    );
    camera.position.set(0, 0, 1000);

    return camera;
}

Avoid impure function and have options for configuration:

function createPerspectiveCamera(options) {

    var camera = new THREE.PerspectiveCamera(
        35,
        options.ratio,
        0.1,
        3000
    );
    camera.position.set(0, 0, 1000);

    return camera;
}

createPerspectiveCamera({
    ratio: window.innerWidth / window.innerHeight
});

Create a light

function createAmbientLight() {

    return new THREE.AmbientLight(0xffffff, 0.5);
}

Create a cube object

function createCube() {

    var geometry = new THREE.BoxGeometry(100, 100, 100);
    //var material = new THREE.MeshBasicMaterial();
    //var material = new THREE.MeshLambertMaterial();
    var material = new THREE.MeshPhongMaterial();
    var mesh = new THREE.Mesh(geometry, material);

    mesh.position.set(-150, 0, 0);

    return mesh;
}

Create a plane

function createPlane() {

    var geometry = new THREE.PlaneGeometry(10000, 10000, 100, 100);
    var material = new THREE.MeshBasicMaterial({
        color: 0xffffff
    });
    var mesh = new THREE.Mesh(geometry, material);

    mesh.position.y = -100;
    mesh.rotation.x = -90 * Math.PI / 180;
    //mesh.position.set(0, -100, -1000);

    return mesh;
}

Create scene and animate

Create scene objects

function createSceneObjects(scene) {

    var cube = createCube();
    scene.add(cube);

    var sphere = createSphere();
    scene.add(sphere);

    return {
        cube: cube,
        sphere: sphere
    };
}
var renderer = createRenderer();
var camera = createPerspectiveCamera();

var scene = new THREE.Scene();

createSceneLights(scene);
var sceneObjects = createSceneObjects(scene);

var plane = createPlane();
scene.add(plane);

requestAnimationFrame(render);

function translateCube(cube, position) {

    cube.rotation.x = ( position / 100 );
    cube.rotation.y = ( position / 1000 ) * 7;

}

function translateSphere(sphere, position) {

    sphere.rotation.x = ( position / 100 ) * 2;
    sphere.rotation.y = ( position / 100 );
}

var n = 0;
var d = 0.1;

function render() {

    translateCube(sceneObjects.cube, n);
    translateSphere(sceneObjects.sphere, n);
    //sceneObjects.cube.rotation.x += 0.01;
    //sceneObjects.cube.rotation.y += 0.007;

    n++;

/*
    n += d;

    if (n > 250 && d > 0) {
        d *= -1;
    }
    else if (n < 0 && d < 0) {
        d *= -1;
    }

    d = d + 0.01;
*/

    renderer.render(scene, camera);

    requestAnimationFrame(render);

}

Animation: Rotation

To rotate an object, we can increment the value of the axis:

function animate(cube) {
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.007;
}

Animation function

Instead of just incrementing the rotation values, we can use a function describing the animation to have more control over the animation:

function animateXY(cube, position) {
    cube.rotation.x = ( position / 100 );
    cube.rotation.y = ( position / 1000 ) * 7;
}

This way we can seek through the animation sequence, adjust the speed, or even play it in reverse by passing the correspending position parameter.

Generic rotation function using Euler

function rotate(object, position, factorX, factorY, factorZ) {

    var ax = position * factorX,
        ay = position * factorY,
        az = position * factorZ;

    var euler = new THREE.Euler( ax, ay, az, 'XYZ' );

    object.setRotationFromEuler(euler);

}

rotate(cube, position, (1/100), (1/1000)*7, 0);

Using a factor object to make parameters more clear:

function rotate(object, position, factor) {

    var ax = position * factor.x,
        ay = position * factor.y,
        az = position * factor.z;

    var euler = new THREE.Euler( ax, ay, az, 'XYZ' );

    object.setRotationFromEuler(euler);

}

var factor = {
    x: (1/100),
    y: (1/1000)*7,
    z: 0
};
rotate(cube, position, factor);