Newer
Older
infinity-rain / public / index.js
///<reference path="../node_modules/three/build/three.js" />
//<reference path="../node_modules/three/examples/js/loaders/GLTFLoader.js" />

"use strict";

/**
 * Loads a GLTF resource and retruns the data as a promise.
 * @param {THREE.GLTFLoader} loader instance of the loader to use.
 * @param {string} path URL from where to download.
 * @returns {Promise<{scene: THREE.Scene}>}
 */
function downloadModel(loader, path)
{
    return new Promise(function(resolve, reject){
        loader.load(
            path,
            function onLoadModel(gltf){
                resolve(gltf);
            },
            null,
            function(error){
                reject(error);
            }
        );
    });
}


document.addEventListener("DOMContentLoaded", async function pageInit(){

    /** @type {HTMLCanvasElement} */
    const canvas = document.getElementById("playground");
    const canvasWidth = Math.floor(canvas.clientWidth);
    const canvasHeight = Math.floor(canvas.clientHeight);

    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0x020202);
    const camera = new THREE.PerspectiveCamera(50, canvasWidth / canvasHeight, 0.1, 1000);

    const renderer = new THREE.WebGLRenderer({
        canvas: document.getElementById("playground"),
        antialias: true
    });
    renderer.setSize(canvasWidth, canvasHeight);
    // renderer.shadowMap.enabled = true;
    // renderer.shadowMap.type = THREE.PCFSoftShadowMap;

    document.body.appendChild(renderer.domElement);

    const geometry = new THREE.BoxGeometry(1,1,1);
    const material = new THREE.MeshPhongMaterial({color: 0x4512ff})
    const cube = new THREE.Mesh(geometry, material);
    cube.position.set(2,0,0);
    cube.castShadow = true;
    scene.add(cube);

    camera.position.z = 5;

    const light = new THREE.PointLight(0xffffff, 1, 50);
    light.position.set(5,5,5);
    light.castShadow = true;
    light.shadow.mapSize.width = 1024;
    light.shadow.mapSize.height = 1024;
    scene.add(light);

    const backLight = new THREE.PointLight(0xffffff, 0.1, 50);
    backLight.position.set(-5,5,5);
    scene.add(backLight);

    // const plane = new THREE.Mesh(
    //     new THREE.PlaneBufferGeometry(5, 5, 10, 10), 
    //     new THREE.MeshPhongMaterial({color: 0xffffff})
    // );
    // plane.rotateX(-Math.PI/2);
    // plane.position.y = -1;
    // plane.receiveShadow = true;
    // scene.add(plane);

    const loader = new THREE.GLTFLoader();

    const wordGLTF = await downloadModel(loader, "models/infinity-symbol.gltf");
    const word = wordGLTF.scene.children.find(c => c.name == "infinity");
    word.castShadow = true;
    // word.receiveShadow = true;
    word.rotation.set(0,0,0);
    word.position.set(-2,0,0);
    scene.add(word);

    /** @type {THREE.Object3D} */
    let clonedWord = null;
    const randomScatter = (r) => (r || 5)*(Math.random()-0.5);
    const wordCloud = [];
    const wordGroup = new THREE.Group();

    for(let i=0;i<100;i++)
    {
        clonedWord = word.clone(false);
        clonedWord.position.set(randomScatter(),randomScatter(),randomScatter());
        clonedWord.rotation.set(randomScatter(Math.PI),randomScatter(Math.PI),randomScatter(Math.PI));
        clonedWord.scale.set(1,1,1);
        wordGroup.add(clonedWord);
        wordCloud.push(clonedWord);
    }
    scene.add(wordGroup);

    renderer.gammaInput = true;
    renderer.gammaOutput = true;

    // const helper = new THREE.CameraHelper(light.shadow.camera);
    // scene.add(helper);

    // renderer.render(scene, camera);

    function animate(){
        requestAnimationFrame(animate);
        word.rotation.x += 0.01;
        word.rotation.y += 0.01;
        cube.rotation.x += 0.01;
        cube.rotation.y -= 0.01;

        wordGroup.rotation.x -= 0.01;
        wordGroup.rotation.y += 0.01;

        wordCloud.forEach(w => {
            w.rotation.x += 0.02;
            w.rotation.y += 0.02;
        });

        renderer.render(scene, camera);
    }
    animate();

});