1. 程式人生 > >Three.js響應和移動物體

Three.js響應和移動物體

效果圖

demo

import './index.css';


// stats
var stats;
(function(){
    stats = new Stats();
    document.body.appendChild( stats.dom );
})();

// gui
var gui;
(function(){
    gui = new dat.GUI();
    // var fn = new function() {
    //     this.rotationSpeed = 0.02;
    //     this.bouncingSpeed = 0.03 ; 
    // }
    // gui.add(fn,'rotationSpeed', 0, 0.5); 
    // gui.add(fn,'bouncingSpeed', 0, 0.5); 
})();

// renderer
var renderer;
(function(){
    renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.shadowMap.enabled = true;
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.gammaInput = true;
    renderer.gammaOutput = true;
    document.body.appendChild(renderer.domElement);
})();

// scene
var scene;
(function(){
    scene = new THREE.Scene();
    scene.background = new THREE.Color( 0xcce0ff );
    scene.fog = new THREE.Fog( 0xcce0ff, 500, 10000 );
})();

// 相機
var camera;
(function(){
    camera = new THREE.PerspectiveCamera( 30, window.innerWidth / window.innerHeight, 1, 10000 );
    camera.position.set( 1000, 50, 1500 );
    camera.updateMatrix();
})();

// controls
var dragcontrols;
var mouse = new THREE.Vector2();
var raycaster;
var INTERSECTED;
var objects = [];

(function(){
    // var controls = new THREE.OrbitControls( camera, renderer.domElement );
    // controls.maxPolarAngle = Math.PI * 0.5;
    // controls.minDistance = 1000;
    // controls.maxDistance = 5000;
    dragcontrols = new THREE.TrackballControls( camera );
    dragcontrols.rotateSpeed = 1.0;
    dragcontrols.zoomSpeed = 1.2;
    dragcontrols.panSpeed = 0.8;
    dragcontrols.noZoom = false;
    dragcontrols.noPan = false;
    dragcontrols.staticMoving = true;
    dragcontrols.dynamicDampingFactor = 0.3;

    var dragControls = new THREE.DragControls( objects, camera, renderer.domElement );
    dragControls.addEventListener( 'dragstart', function ( event ) { dragcontrols.enabled = false; } );
    dragControls.addEventListener( 'dragend', function ( event ) { dragcontrols.enabled = true; } );

    document.addEventListener( 'mousemove', function(){
        event.preventDefault();
        mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
        mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
    }, false );

    raycaster = new THREE.Raycaster();
    raycaster.params.Points.threshold = 0.1;

    window.addEventListener('resize', function(){
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
    }, false);
})();

// 設定光源
(function(){
    // 設定光源
    var light = new THREE.DirectionalLight( 0xbbbbff, 1.5 );

    light.position.set( -1000, 50, -1000 );
    light.position.multiplyScalar( 1.3 );
    light.castShadow = true;

    var textureLoader = new THREE.TextureLoader();

    var textureFlare0 = textureLoader.load( "./static/textures/lensflare/lensflare0.png" );
    var textureFlare1 = textureLoader.load( "./static/textures/lensflare/lensflare2.png" );
    var textureFlare2 = textureLoader.load( "./static/textures/lensflare/lensflare3.png" );

    var lensflare = new THREE.Lensflare();

    lensflare.addElement( new THREE.LensflareElement( textureFlare0, 512, 0 ) );
    lensflare.addElement( new THREE.LensflareElement( textureFlare1, 512, 0 ) );
    lensflare.addElement( new THREE.LensflareElement( textureFlare2, 60, 0.6 ) );

    light.add( lensflare );

    scene.add( light );

    var light = new THREE.HemisphereLight( 0xbbbbff, 0x444422 );
    scene.add( light );
})();

// 載入模型
(function(){
    // 地面
    var loader = new THREE.TextureLoader();
    var groundTexture = loader.load( './static/textures/terrain/grasslight-big.jpg' );
    groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping;
    groundTexture.repeat.set( 25, 25 );
    groundTexture.anisotropy = 16;
    var groundMaterial = new THREE.MeshLambertMaterial( { map: groundTexture } );
    var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 20000, 20000 ), groundMaterial );
    mesh.position.y = - 250;
    mesh.rotation.x = - Math.PI / 2;
    mesh.receiveShadow = true;
    mesh.name = "ground";
    scene.add( mesh );

    var geometry;
    var object;
    // 隨機幾何體
    for(var i = 0; i < 10; i++) {
        geometry = new THREE.BoxBufferGeometry( 50, 50, 50 );
        object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) );
        object.position.x = Math.random() * 800 - 400;
        object.position.y = Math.random() * 800 - 400;
        object.position.z = Math.random() * 800 - 400;

        object.rotation.x = Math.random() * 2 * Math.PI;
        object.rotation.y = Math.random() * 2 * Math.PI;
        object.rotation.z = Math.random() * 2 * Math.PI;
        object.scale.x = Math.random() + 0.5;
        object.scale.y = Math.random() + 0.5;
        object.scale.z = Math.random() + 0.5;

        object.castShadow = true;
        scene.add( object );
        objects.push(object);
        
    }

})();


// var rotateY = new THREE.Matrix4().makeRotationY( 0.005 );
var step = -2;
var flag = true;
var animate = function () {
    requestAnimationFrame(animate);

    // camera.applyMatrix( rotateY );
    // camera.updateMatrixWorld();

    raycaster.setFromCamera( mouse, camera );

    //calculate objects intersecting the picking ray
    var intersects = raycaster.intersectObjects( scene.children );
    
    if ( intersects.length > 0 ) {
        if ( INTERSECTED != intersects[ 0 ].object ) {
            if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
            INTERSECTED = intersects[ 0 ].object;
            if(INTERSECTED.name != "ground"){
                INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
                INTERSECTED.material.emissive.setHex( 0xff0000 );
            }
            
        }
    } else {
        if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );
        INTERSECTED = null;
    }

    dragcontrols.update();


    stats.begin();
    renderer.render( scene, camera );
    stats.end();
};
animate();