zoukankan      html  css  js  c++  java
  • Three.js构造一个简单的房间

      主要研究three.js在3D场景中基本使用:画一个简单的房子、房子上画门和玻璃、房间内放一个床、定义鼠标事件可以移动场景、动画的使用等。

    1.Three.js画的一个简单的房子,模拟地板以及四堵墙 

    准备素材:

    3.jpg模拟地板

    4.jpg模拟墙

     

    代码:

    <!DOCTYPE html>
    
    <html>
    
    <head>
        <title>myHouse</title>
        <script type="text/javascript" src="../libs/three.js"></script>
        <script type="text/javascript" src="../libs/OBJLoader.js"></script>
        <script type="text/javascript" src="../libs/stats.js"></script>
        <script type="text/javascript" src="../libs/dat.gui.js"></script>
        <style>
            body {
                /* set margin to 0 and overflow to hidden, to go fullscreen */
                margin: 0;
                overflow: hidden;
            }
        </style>
    </head>
    <body>
    
    <div id="Stats-output">
    </div>
    <!-- Div which will hold the Output -->
    <div id="WebGL-output">
    </div>
    
    <!-- Javascript code that runs our Three.js examples -->
    <script type="text/javascript">
        var scene,camera,webGLRenderer,stats;
    
        function init() {
            stats = initStats();
    
            scene = new THREE.Scene();
    
            // create a camera, which defines where we're looking at.
            camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.x = 20;
            camera.position.y = 40;
            camera.position.z = 50;
            camera.lookAt(scene.position);
            scene.add(camera);
    
            // create a render and set the size
            webGLRenderer = new THREE.WebGLRenderer({
                antialias : true,
                alpha:true
            });
            webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
            webGLRenderer.setSize(window.innerWidth, window.innerHeight);
            webGLRenderer.shadowMapEnabled = true;
    
            // add spotlight for the shadows
            var spotLight = new THREE.PointLight(0xffffff);
            spotLight.position.set(30, 40, 50);
            scene.add(spotLight);
    
            initObjects();
    
            // add the output of the renderer to the html element
            document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);
    
            render();
        }
    
        function initObjects(){
            paintFloor();
            paintWalls(40, 2, 10, 0, 0, -20, 1/2,0);//后面墙
            paintWalls(40, 2, 10, 0, 0, 20, 1/2, 0);//前面墙
            paintWalls(42, 2, 10, -20, 0, 0, 1/2, 0, 1/2);//左面墙
            paintWalls(42, 2, 10, 20, 0, 0, 1/2, 0, 1/2);//右面墙
        }
    
        var paintFloor = function (){
            var loader = new THREE.TextureLoader;
            loader.load('./img/3.jpg', function (texture) {
                //x和y超过图片像素之后重复绘制图片
                texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                //设置地板重复绘制的密度是1 * 1
                texture.repeat.set(1, 1);
    
                //设置材质是双面材质
                var material = new THREE.MeshLambertMaterial({
                    map : texture,
                    side : THREE.DoubleSide
                });
    
                //创建普通的平面几何体
                var gemotery = new THREE.PlaneGeometry(40,40);
    
                //创建网格对象
                var mesh = new THREE.Mesh(gemotery,material);
                mesh.position.y = 0;
                mesh.rotation.x = Math.PI/2;
    
                scene.add(mesh);
            });
        }
    
        var paintWalls = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ){
            var loader = new THREE.TextureLoader;
            loader.load('./img/4.jpg', function (texture) {
                //x和y超过图片像素之后重复绘制图片
                texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                //设置地板重复绘制的密度是1 * 1
                texture.repeat.set(1,1);
    
                var material = new THREE.MeshLambertMaterial({
                    map : texture,
                    side : THREE.DoubleSide
                });
    
                //创建长方体几何体
                var gemotery = new THREE.BoxGeometry(width, depth, height);
    
                //创建网格对象以及进行位置的设定
                var mesh = new THREE.Mesh(gemotery,material);
                mesh.position.set(x,y,z)
                mesh.rotation.x = Math.PI * rotationX;
                mesh.rotation.y = Math.PI * rotationY;
                if(rotationZ){
                    mesh.rotation.z = Math.PI * rotationZ;
                }
    
                scene.add(mesh);
            });
        }
    
        function render() {
            requestAnimationFrame(render);
            webGLRenderer.render(scene, camera);
    
            if(stats){
                stats.update();
            }
        }
    
        function initStats() {
            var stats = new Stats();
            stats.setMode(0); // 0: fps, 1: ms
    
            // Align top-left
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';
            document.getElementById("Stats-output").appendChild(stats.domElement);
    
            return stats;
        }
    
        window.onload = init;
    </script>
    </body>
    </html>

    结果:

     2.增加鼠标事件和键盘事件控制摄像头进而模拟在房间内行走

      控制器的使用,主要的控制器如下:

    • 轨迹球控制器的使用:(使用鼠标改变场景以及在界面实时显示相机的位置)

    可用的鼠标事件如下:

    (1)引入相关JS:

     <script type="text/javascript" src="../libs/TrackballControls.js"></script>

    (2)创建控制器并绑定到相机上

        //鼠标控制动画相关组件
        var trackballControls, clock;
        function initTrackballControls(){
            clock = new THREE.Clock();
    
            trackballControls = new THREE.TrackballControls(camera);
    
            trackballControls.rotateSpeed = 1.0;
            trackballControls.zoomSpeed = 1.0;
            trackballControls.panSpeed = 1.0;
            //        trackballControls.noZoom=false;
            //        trackballControls.noPan=false;
            trackballControls.staticMoving = true;
            //        trackballControls.dynamicDampingFactor=0.3;
        }

    (3)摄像机的位置更新在render循环中完成

        function render() {
            requestAnimationFrame(render);
            webGLRenderer.render(scene, camera);
    
            //鼠标事件
            var delta = clock.getDelta();
            trackballControls.update(delta);
            logCameraPosition();
    
            if(stats){
                stats.update();
            }
        }
    
        function logCameraPosition(){
            var logInfo = "[info]: x - " + camera.position.x + " ;y - " + camera.position.y + " ;z - " + camera.position.z;
            $("#logInfo").html(logInfo);
        }

    如果禁用鼠标缩放可以将noZoom设为true。 

    代码如下:

    <!DOCTYPE html>
    
    <html>
    
    <head>
        <title>myHouse</title>
        <script type="text/javascript" src="../libs/jquery-1.9.0.js"></script>
        <script type="text/javascript" src="../libs/three.js"></script>
        <script type="text/javascript" src="../libs/OBJLoader.js"></script>
        <script type="text/javascript" src="../libs/stats.js"></script>
        <script type="text/javascript" src="../libs/dat.gui.js"></script>
        <script type="text/javascript" src="../libs/TrackballControls.js"></script>
        <style>
            body {
                /* set margin to 0 and overflow to hidden, to go fullscreen */
                margin: 0;
                overflow: hidden;
            }
        </style>
    </head>
    <body>
    
    <div id="Stats-output">
    </div>
    <!-- Div which will hold the Output -->
    <div id="WebGL-output">
    </div>
    
    <div id="logInfo" style="position: absolute; top: 0px; left: 20%;  50%; padding: 5px;"></div>
    
    <!-- Javascript code that runs our Three.js examples -->
    <script type="text/javascript">
        //基本组件
        var scene, camera, webGLRenderer, stats;
        //鼠标控制动画相关组件
        var trackballControls, clock;
    
        function init() {
            stats = initStats();
    
            scene = new THREE.Scene();
    
            // create a camera, which defines where we're looking at.
            camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.x = 20;
            camera.position.y = 40;
            camera.position.z = 50;
            camera.lookAt(scene.position);
            scene.add(camera);
    
            // create a render and set the size
            webGLRenderer = new THREE.WebGLRenderer({
                antialias : true,
                alpha:true
            });
            webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
            webGLRenderer.setSize(window.innerWidth, window.innerHeight);
            webGLRenderer.shadowMapEnabled = true;
    
            // add spotlight for the shadows
            var spotLight = new THREE.PointLight(0xffffff);
            spotLight.position.set(30, 40, 50);
            scene.add(spotLight);
    
            initObjects();
    
            // add the output of the renderer to the html element
            document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);
    
            render();
        }
    
        function initObjects(){
            paintFloor();
    
            //画墙--一般y取高度的1/2
            paintWalls(40, 2, 10, 0, 5, -20, 1/2,0);//后面墙
            paintWalls(40, 2, 10, 0, 5, 20, 1/2, 0);//前面墙
            paintWalls(42, 2, 10, -20, 5, 0, 1/2, 0, 1/2);//左面墙
            paintWalls(42, 2, 10, 20, 5, 0, 1/2, 0, 1/2);//右面墙
    
            initTrackballControls();
        }
    
    
        function render() {
            requestAnimationFrame(render);
            webGLRenderer.render(scene, camera);
    
            //鼠标事件
            var delta = clock.getDelta();
            trackballControls.update(delta);
            logCameraPosition();
    
            if(stats){
                stats.update();
            }
        }
    
        function logCameraPosition(){
            var logInfo = "[info]: x - " + camera.position.x + " ;y - " + camera.position.y + " ;z - " + camera.position.z;
            $("#logInfo").html(logInfo);
        }
    
        function initTrackballControls(){
            clock = new THREE.Clock();
    
            trackballControls = new THREE.TrackballControls(camera);
    
            trackballControls.rotateSpeed = 1.0;
            trackballControls.zoomSpeed = 1.0;
            trackballControls.panSpeed = 1.0;
            //        trackballControls.noZoom=false;
            //        trackballControls.noPan=false;
            trackballControls.staticMoving = true;
            //        trackballControls.dynamicDampingFactor=0.3;
        }
    
        var paintFloor = function (){
            var loader = new THREE.TextureLoader;
            loader.load('./img/3.jpg', function (texture) {
                //x和y超过图片像素之后重复绘制图片
                texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                //设置地板重复绘制的密度是1 * 1
                texture.repeat.set(1, 1);
    
                //设置材质是双面材质
                var material = new THREE.MeshLambertMaterial({
                    map : texture,
                    side : THREE.DoubleSide
                });
    
                //创建普通的平面几何体
                var gemotery = new THREE.PlaneGeometry(40,40);
    
                //创建网格对象
                var mesh = new THREE.Mesh(gemotery,material);
                mesh.position.y = 0;
                mesh.rotation.x = Math.PI/2;
    
                scene.add(mesh);
            });
        }
    
        var paintWalls = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ){
            var loader = new THREE.TextureLoader;
            loader.load('./img/4.jpg', function (texture) {
                //x和y超过图片像素之后重复绘制图片
                texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                //设置地板重复绘制的密度是1 * 1
                texture.repeat.set(1,1);
    
                var material = new THREE.MeshLambertMaterial({
                    map : texture,
                    side : THREE.DoubleSide
                });
    
                //创建长方体几何体
                var gemotery = new THREE.BoxGeometry(width, depth, height);
    
                //创建网格对象以及进行位置的设定
                var mesh = new THREE.Mesh(gemotery,material);
                mesh.position.set(x,y,z)
                mesh.rotation.x = Math.PI * rotationX;
                mesh.rotation.y = Math.PI * rotationY;
                if(rotationZ){
                    mesh.rotation.z = Math.PI * rotationZ;
                }
    
                scene.add(mesh);
            });
        }
    
        function initStats() {
            var stats = new Stats();
            stats.setMode(0); // 0: fps, 1: ms
    
            // Align top-left
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';
            document.getElementById("Stats-output").appendChild(stats.domElement);
    
            return stats;
        }
    
        window.onload = init;
    </script>
    </body>
    </html>

    效果:

    • 轨道控制器(支持鼠标和键盘事件)

    其支持的事件如下:

    (1)使用的类库是:https://github.com/mrdoob/three.js/blob/dev/examples/js/controls/OrbitControls.js

    (2)初始化control即可

        function initOrbitControls(){
            controls = new THREE.OrbitControls(camera,webGLRenderer.domElement);
    
            controls.minDistance = 1;
            controls.maxDistance = 5000;
        }

    代码如下:

    <!DOCTYPE html>
    <!--房子中间加个床,采用封装过的API实现 (采用轨道控制器)-->
    <html>
    
    <head>
        <title>myHouse</title>
        <script type="text/javascript" src="../libs/jquery-1.9.0.js"></script>
        <script type="text/javascript" src="../libs2/three.js"></script>
        <script type="text/javascript" src="../libs2/OBJLoader.js"></script>
        <script type="text/javascript" src="../libs2/stats.js"></script>
        <script type="text/javascript" src="../libs2/WebGL.js"></script>
        <script type="text/javascript" src="../libs2/OrbitControls.js"></script>
        <script type="text/javascript" src="../libs2/onEvent.js"></script>
        <style>
            body {
                /* set margin to 0 and overflow to hidden, to go fullscreen */
                margin: 0;
                overflow: hidden;
            }
        </style>
    </head>
    <body>
    
    <div id="Stats-output">
    </div>
    <!-- Div which will hold the Output -->
    <div id="WebGL-output">
    </div>
    
    <div id="logInfo" style="position: absolute; top: 0px; left: 20%;  50%; padding: 5px;"></div>
    
    <!-- Javascript code that runs our Three.js examples -->
    <script type="text/javascript">
        //基本组件
        var scene, camera, webGLRenderer, stats;
        //鼠标控制动画相关组件
        var controls;
        //事件相关
        var threeOnEvent;
    
        function init() {
            stats = initStats();
    
            scene = new THREE.Scene();
    
            // create a camera, which defines where we're looking at.
            camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.x = 20;
            camera.position.y = 40;
            camera.position.z = 50;
            camera.lookAt(scene.position);
            scene.add(camera);
    
            // create a render and set the size
            webGLRenderer = new THREE.WebGLRenderer({
                antialias : true,
                alpha:true
            });
            webGLRenderer.setSize(window.innerWidth, window.innerHeight);
            webGLRenderer.setPixelRatio(window.devicePixelRatio);
            webGLRenderer.setClearColor(0xEEEEEE, 1.0);
            webGLRenderer.shadowMapEnabled = true;
    
            // add spotlight for the shadows
            var spotLight = new THREE.PointLight(0xffffff);
            spotLight.position.set(30, 40, 50);
            scene.add(spotLight);
    
            initObjects();
    
            // add the output of the renderer to the html element
            document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);
    
            render();
        }
    
        function initObjects(){
            initEvent();
    
            paintFloor();
    
            //画墙--一般y取高度的1/2
            paintWalls(40, 2, 10, 0, 5, -20, 1/2,0);//后面墙
            paintWalls(40, 2, 10, 0, 5, 20, 1/2, 0);//前面墙
            paintWalls(42, 2, 10, -20, 5, 0, 1/2, 0, 1/2);//左面墙
            paintWalls(42, 2, 10, 20, 5, 0, 1/2, 0, 1/2);//右面墙
    
            initOrbitControls();
    
            paintBed();
        }
    
        var paintBed = function(){
            var textures = [];
            loadBedTextures(textures, 0, "./img/bedplate.jpg"); //right
            loadBedTextures(textures, 1, "./img/bedplate.jpg"); //left
            loadBedTextures(textures, 2, "./img/bedplate.jpg"); //front
            loadBedTextures(textures, 3, "./img/bedplate.jpg");//back
            loadBedTextures(textures, 4, "./img/bedplate.jpg"); //bottom
            loadBedTextures(textures, 5, "./img/mattess.jpg"); //top
    
            //创建长方体几何体
            var gemotery = new THREE.BoxGeometry(10, 10, 5);
    
            //创建网格对象以及进行位置的设定
            var mesh = new THREE.Mesh(gemotery, textures);
            mesh.position.set(0, 2.5, 0)
            mesh.rotation.x = Math.PI * 1/2;
    
            //绑定一些数据
            mesh.tags = "bed";
            mesh.userData.ID = 1;
            mesh.name = "myBed";
    
            //增加事件(点击事件)
            mesh.on('click',function(m) {//m代表mesh对象
               alert('1');
            })
    
            // hover eventLisener(鼠标悬浮事件)
            mesh.on('hover',function(m) {
                // mouse enter the mesh
                alert(m.name + "  " + m.tags + " " + mesh.userData.ID);
            },function(m) {
                // mouse leave out the mesh
            });
    
            scene.add(mesh);
        }
    
        function loadBedTextures(textures, index, url){
            textures[index] = new THREE.MeshBasicMaterial({
               map : new THREE.TextureLoader().load(url)
            });
        }
    
        function initEvent(){
            threeOnEvent = new THREE.onEvent(scene,camera);
        }
    
    
        function render() {
            requestAnimationFrame(render);
            webGLRenderer.render(scene, camera);
    
            //鼠标事件
            logCameraPosition();
    
            if(stats){
                stats.update();
            }
    
            //更新事件
            threeOnEvent.update();
        }
    
        function logCameraPosition(){
            var logInfo = "[info]: x - " + camera.position.x + " ;y - " + camera.position.y + " ;z - " + camera.position.z;
            $("#logInfo").html(logInfo);
        }
    
        function initOrbitControls(){
            controls = new THREE.OrbitControls(camera,webGLRenderer.domElement);
    
            controls.minDistance = 1;
            controls.maxDistance = 5000;
        }
    
        var paintFloor = function (){
            var loader = new THREE.TextureLoader;
            loader.load('./img/3.jpg', function (texture) {
                //x和y超过图片像素之后重复绘制图片
                texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                //设置地板重复绘制的密度是1 * 1
                texture.repeat.set(1, 1);
    
                //设置材质是双面材质
                var material = new THREE.MeshLambertMaterial({
                    map : texture,
                    side : THREE.DoubleSide
                });
    
                //创建普通的平面几何体
                var gemotery = new THREE.PlaneGeometry(40,40);
    
                //创建网格对象
                var mesh = new THREE.Mesh(gemotery,material);
                mesh.position.y = 0;
                mesh.rotation.x = Math.PI/2;
    
                scene.add(mesh);
            });
        }
    
        var paintWalls = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ){
            var loader = new THREE.TextureLoader;
            loader.load('./img/4.jpg', function (texture) {
                //x和y超过图片像素之后重复绘制图片
                texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                //设置地板重复绘制的密度是1 * 1
                texture.repeat.set(1,1);
    
                var material = new THREE.MeshLambertMaterial({
                    map : texture,
                    side : THREE.DoubleSide
                });
    
                //创建长方体几何体
                var gemotery = new THREE.BoxGeometry(width, depth, height);
    
                //创建网格对象以及进行位置的设定
                var mesh = new THREE.Mesh(gemotery,material);
                mesh.position.set(x,y,z)
                mesh.rotation.x = Math.PI * rotationX;
                mesh.rotation.y = Math.PI * rotationY;
                if(rotationZ){
                    mesh.rotation.z = Math.PI * rotationZ;
                }
    
                scene.add(mesh);
            });
        }
    
        function initStats() {
            var stats = new Stats();
            stats.setMode(0); // 0: fps, 1: ms
    
            // Align top-left
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';
            document.getElementById("Stats-output").appendChild(stats.domElement);
    
            return stats;
        }
    
        window.onload = init;
    </script>
    </body>
    </html>

    3.场景中添加一个床 (六面体),并且自定义鼠标点击事件悬浮在床上的时候弹出框

       这个都采用的是git上封装过的JS库来实现的,参考git地址:https://github.com/mrdoob/three.js/

      three.js的事件机制用到的是onEvent,参考:https://github.com/YoneChen/three-onEvent

      也通过tags、userData、name进行数据的绑定。

    代码如下:

    <!DOCTYPE html>
    <!--房子中间加个床,采用封装过的API实现-->
    <html>
    
    <head>
        <title>myHouse</title>
        <script type="text/javascript" src="../libs/jquery-1.9.0.js"></script>
        <script type="text/javascript" src="../libs2/three.js"></script>
        <script type="text/javascript" src="../libs2/OBJLoader.js"></script>
        <script type="text/javascript" src="../libs2/stats.js"></script>
        <script type="text/javascript" src="../libs2/WebGL.js"></script>
        <script type="text/javascript" src="../libs2/TrackballControls.js"></script>
        <script type="text/javascript" src="../libs2/onEvent.js"></script>
        <style>
            body {
                /* set margin to 0 and overflow to hidden, to go fullscreen */
                margin: 0;
                overflow: hidden;
            }
        </style>
    </head>
    <body>
    
    <div id="Stats-output">
    </div>
    <!-- Div which will hold the Output -->
    <div id="WebGL-output">
    </div>
    
    <div id="logInfo" style="position: absolute; top: 0px; left: 20%;  50%; padding: 5px;"></div>
    
    <!-- Javascript code that runs our Three.js examples -->
    <script type="text/javascript">
        //基本组件
        var scene, camera, webGLRenderer, stats;
        //鼠标控制动画相关组件
        var trackballControls, clock;
        //事件相关
        var threeOnEvent;
    
        function init() {
            stats = initStats();
    
            scene = new THREE.Scene();
    
            // create a camera, which defines where we're looking at.
            camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.x = 20;
            camera.position.y = 40;
            camera.position.z = 50;
            camera.lookAt(scene.position);
            scene.add(camera);
    
            // create a render and set the size
            webGLRenderer = new THREE.WebGLRenderer({
                antialias : true,
                alpha:true
            });
            webGLRenderer.setSize(window.innerWidth, window.innerHeight);
            webGLRenderer.setPixelRatio(window.devicePixelRatio);
            webGLRenderer.setClearColor(0xEEEEEE, 1.0);
            webGLRenderer.shadowMapEnabled = true;
    
            // add spotlight for the shadows
            var spotLight = new THREE.PointLight(0xffffff);
            spotLight.position.set(30, 40, 50);
            scene.add(spotLight);
    
            initObjects();
    
            // add the output of the renderer to the html element
            document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);
    
            render();
        }
    
        function initObjects(){
            initEvent();
    
            paintFloor();
    
            //画墙--一般y取高度的1/2
            paintWalls(40, 2, 10, 0, 5, -20, 1/2,0);//后面墙
            paintWalls(40, 2, 10, 0, 5, 20, 1/2, 0);//前面墙
            paintWalls(42, 2, 10, -20, 5, 0, 1/2, 0, 1/2);//左面墙
            paintWalls(42, 2, 10, 20, 5, 0, 1/2, 0, 1/2);//右面墙
    
            initTrackballControls();
    
            paintBed();
        }
    
        var paintBed = function(){
            var textures = [];
            loadBedTextures(textures, 0, "./img/bedplate.jpg"); //right
            loadBedTextures(textures, 1, "./img/bedplate.jpg"); //left
            loadBedTextures(textures, 2, "./img/bedplate.jpg"); //front
            loadBedTextures(textures, 3, "./img/bedplate.jpg");//back
            loadBedTextures(textures, 4, "./img/bedplate.jpg"); //bottom
            loadBedTextures(textures, 5, "./img/mattess.jpg"); //top
    
            //创建长方体几何体
            var gemotery = new THREE.BoxGeometry(10, 10, 5);
    
            //创建网格对象以及进行位置的设定
            var mesh = new THREE.Mesh(gemotery, textures);
            mesh.position.set(0, 2.5, 0)
            mesh.rotation.x = Math.PI * 1/2;
    
            //绑定一些数据
            mesh.tags = "bed";
            mesh.userData.ID = 1;
            mesh.name = "myBed";
    
            //增加事件(点击事件)
            mesh.on('click',function(m) {//m代表mesh对象
               alert('1');
            })
    
            // hover eventLisener(鼠标悬浮事件)
            mesh.on('hover',function(m) {
                // mouse enter the mesh
                alert(m.name + "  " + m.tags + " " + mesh.userData.ID);
            },function(m) {
                // mouse leave out the mesh
            });
    
            scene.add(mesh);
        }
    
        function loadBedTextures(textures, index, url){
            textures[index] = new THREE.MeshBasicMaterial({
               map : new THREE.TextureLoader().load(url)
            });
        }
    
        function initEvent(){
            threeOnEvent = new THREE.onEvent(scene,camera);
        }
    
    
        function render() {
            requestAnimationFrame(render);
            webGLRenderer.render(scene, camera);
    
            //鼠标事件
            var delta = clock.getDelta();
            trackballControls.update(delta);
            logCameraPosition();
    
            if(stats){
                stats.update();
            }
    
            //更新事件
            threeOnEvent.update();
        }
    
        function logCameraPosition(){
            var logInfo = "[info]: x - " + camera.position.x + " ;y - " + camera.position.y + " ;z - " + camera.position.z;
            $("#logInfo").html(logInfo);
        }
    
        function initTrackballControls(){
            clock = new THREE.Clock();
    
            trackballControls = new THREE.TrackballControls(camera);
    
            trackballControls.rotateSpeed = 1.0;
            trackballControls.zoomSpeed = 1.0;
            trackballControls.panSpeed = 1.0;
            //        trackballControls.noZoom=false;
            //        trackballControls.noPan=false;
            trackballControls.staticMoving = true;
            //        trackballControls.dynamicDampingFactor=0.3;
        }
    
        var paintFloor = function (){
            var loader = new THREE.TextureLoader;
            loader.load('./img/3.jpg', function (texture) {
                //x和y超过图片像素之后重复绘制图片
                texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                //设置地板重复绘制的密度是1 * 1
                texture.repeat.set(1, 1);
    
                //设置材质是双面材质
                var material = new THREE.MeshLambertMaterial({
                    map : texture,
                    side : THREE.DoubleSide
                });
    
                //创建普通的平面几何体
                var gemotery = new THREE.PlaneGeometry(40,40);
    
                //创建网格对象
                var mesh = new THREE.Mesh(gemotery,material);
                mesh.position.y = 0;
                mesh.rotation.x = Math.PI/2;
    
                scene.add(mesh);
            });
        }
    
        var paintWalls = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ){
            var loader = new THREE.TextureLoader;
            loader.load('./img/4.jpg', function (texture) {
                //x和y超过图片像素之后重复绘制图片
                texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                //设置地板重复绘制的密度是1 * 1
                texture.repeat.set(1,1);
    
                var material = new THREE.MeshLambertMaterial({
                    map : texture,
                    side : THREE.DoubleSide
                });
    
                //创建长方体几何体
                var gemotery = new THREE.BoxGeometry(width, depth, height);
    
                //创建网格对象以及进行位置的设定
                var mesh = new THREE.Mesh(gemotery,material);
                mesh.position.set(x,y,z)
                mesh.rotation.x = Math.PI * rotationX;
                mesh.rotation.y = Math.PI * rotationY;
                if(rotationZ){
                    mesh.rotation.z = Math.PI * rotationZ;
                }
    
                scene.add(mesh);
            });
        }
    
        function initStats() {
            var stats = new Stats();
            stats.setMode(0); // 0: fps, 1: ms
    
            // Align top-left
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';
            document.getElementById("Stats-output").appendChild(stats.domElement);
    
            return stats;
        }
    
        window.onload = init;
    </script>
    </body>
    </html>

    结果:

    4.  在墙上挖一个玻璃

      在墙上挖玻璃需要用到ThreeBSP.js,实际上就是求两个物体的差集之后进行添加;如果需要挖一个门,需要做的操作是:先在墙上求墙和门的差集得到一个mesh对象添加到scene中,并将门也添加到scene即可实现。

    代码如下:

    <!DOCTYPE html>
    <!--房子中间加个床,采用封装过的API实现-->
    <html>
    
    <head>
        <title>myHouse</title>
        <script type="text/javascript" src="../libs/jquery-1.9.0.js"></script>
        <script type="text/javascript" src="../libs2/three.js"></script>
        <script type="text/javascript" src="../libs2/OBJLoader.js"></script>
        <script type="text/javascript" src="../libs2/stats.js"></script>
        <script type="text/javascript" src="../libs2/WebGL.js"></script>
        <script type="text/javascript" src="../libs2/TrackballControls.js"></script>
        <script type="text/javascript" src="../libs2/onEvent.js"></script>
        <script type="text/javascript" src="../libs2/ThreeBSP.js"></script>
        <style>
            body {
                /* set margin to 0 and overflow to hidden, to go fullscreen */
                margin: 0;
                overflow: hidden;
            }
        </style>
    </head>
    <body>
    
    <div id="Stats-output">
    </div>
    <!-- Div which will hold the Output -->
    <div id="WebGL-output">
    </div>
    
    <div id="logInfo" style="position: absolute; top: 0px; left: 20%;  50%; padding: 5px;"></div>
    
    <!-- Javascript code that runs our Three.js examples -->
    <script type="text/javascript">
        //基本组件
        var scene, camera, webGLRenderer, stats;
        //鼠标控制动画相关组件
        var trackballControls, clock;
        //事件相关
        var threeOnEvent;
    
        function init() {
            stats = initStats();
    
            scene = new THREE.Scene();
    
            // create a camera, which defines where we're looking at.
            camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.x = 20;
            camera.position.y = 40;
            camera.position.z = 50;
            camera.lookAt(scene.position);
            scene.add(camera);
    
            // create a render and set the size
            webGLRenderer = new THREE.WebGLRenderer({
                antialias : true,
                alpha:true
            });
            webGLRenderer.setSize(window.innerWidth, window.innerHeight);
            webGLRenderer.setPixelRatio(window.devicePixelRatio);
            webGLRenderer.setClearColor(0xEEEEEE, 1.0);
            webGLRenderer.shadowMapEnabled = true;
    
            // add spotlight for the shadows
            var spotLight = new THREE.PointLight(0xffffff);
            spotLight.position.set(30, 40, 50);
            scene.add(spotLight);
    
            initObjects();
    
            // add the output of the renderer to the html element
            document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);
    
            render();
        }
    
        function initObjects(){
            initEvent();
    
            paintFloor();
    
            //画墙--一般y取高度的1/2
            paintWalls(40, 2, 10, 0, 5, -20, 1/2, 0, 0,true);//后面墙
            paintWalls(40, 2, 10, 0, 5, 20, 1/2, 0, 0,true);//前面墙
            paintWalls(42, 2, 10, -20, 5, 0, 1/2, 0, 1/2, true);//左面墙
            //添加带玻璃的墙
            var wallMesh = paintWalls(42, 2, 10, 20, 5, 0, 1/2, 0, 1/2, false);//右面墙
            var windowMesh = paintGlass(10, 2, 6, 20, 3, 0, 1/2, 0, 1/2, false);
            var resultMesh = createResultMesh(wallMesh, windowMesh, true);
            scene.add(resultMesh);
    
            initTrackballControls();
    
            paintBed();
        }
    
        function createResultMesh(srcMesh, destMesh, addDest){
            var srcBSP = new ThreeBSP(srcMesh);
            var destBSP = new ThreeBSP(destMesh);
            var resultBSP = srcBSP.subtract(destBSP);
            var result = resultBSP.toMesh(srcMesh.material);
            result.geometry.computeFaceNormals();
            result.geometry.computeVertexNormals();
            if(addDest){
                scene.add(destMesh);
            }
    
            return result;
        }
    
        var paintBed = function(){
            var textures = [];
            loadBedTextures(textures, 0, "./img/bedplate.jpg"); //right
            loadBedTextures(textures, 1, "./img/bedplate.jpg"); //left
            loadBedTextures(textures, 2, "./img/bedplate.jpg"); //front
            loadBedTextures(textures, 3, "./img/bedplate.jpg");//back
            loadBedTextures(textures, 4, "./img/bedplate.jpg"); //bottom
            loadBedTextures(textures, 5, "./img/mattess.jpg"); //top
    
            //创建长方体几何体
            var gemotery = new THREE.BoxGeometry(10, 10, 5);
    
            //创建网格对象以及进行位置的设定
            var mesh = new THREE.Mesh(gemotery, textures);
            mesh.position.set(0, 2.5, 0)
            mesh.rotation.x = Math.PI * 1/2;
    
            //绑定一些数据
            mesh.tags = "bed";
            mesh.userData.ID = 1;
            mesh.name = "myBed";
    
            //增加事件(点击事件)
            mesh.on('click',function(m) {//m代表mesh对象
               alert('1');
            })
    
            // hover eventLisener(鼠标悬浮事件)
            mesh.on('hover',function(m) {
                // mouse enter the mesh
                alert(m.name + "  " + m.tags + " " + mesh.userData.ID);
            },function(m) {
                // mouse leave out the mesh
            });
    
            scene.add(mesh);
        }
    
        function loadBedTextures(textures, index, url){
            textures[index] = new THREE.MeshBasicMaterial({
               map : new THREE.TextureLoader().load(url)
            });
        }
    
        function initEvent(){
            threeOnEvent = new THREE.onEvent(scene,camera);
        }
    
    
        function render() {
            requestAnimationFrame(render);
            webGLRenderer.render(scene, camera);
    
            //鼠标事件
            var delta = clock.getDelta();
            trackballControls.update(delta);
            logCameraPosition();
    
            if(stats){
                stats.update();
            }
    
            //更新事件
            threeOnEvent.update();
        }
    
        function logCameraPosition(){
            var logInfo = "[info]: x - " + camera.position.x + " ;y - " + camera.position.y + " ;z - " + camera.position.z;
            $("#logInfo").html(logInfo);
        }
    
        function initTrackballControls(){
            clock = new THREE.Clock();
    
            trackballControls = new THREE.TrackballControls(camera);
    
            trackballControls.rotateSpeed = 1.0;
            trackballControls.zoomSpeed = 1.0;
            trackballControls.panSpeed = 1.0;
            //        trackballControls.noZoom=false;
            //        trackballControls.noPan=false;
            trackballControls.staticMoving = true;
            //        trackballControls.dynamicDampingFactor=0.3;
        }
    
        var paintFloor = function (){
            var loader = new THREE.TextureLoader;
            loader.load('./img/3.jpg', function (texture) {
                //x和y超过图片像素之后重复绘制图片
                texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                //设置地板重复绘制的密度是1 * 1
                texture.repeat.set(1, 1);
    
                //设置材质是双面材质
                var material = new THREE.MeshLambertMaterial({
                    map : texture,
                    side : THREE.DoubleSide
                });
    
                //创建普通的平面几何体
                var gemotery = new THREE.PlaneGeometry(40,40);
    
                //创建网格对象
                var mesh = new THREE.Mesh(gemotery,material);
                mesh.position.y = 0;
                mesh.rotation.x = Math.PI/2;
    
                scene.add(mesh);
            });
        }
    
        var paintWalls = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ, addMesh){
            var loader = new THREE.TextureLoader;
            var texture = new THREE.TextureLoader().load('./img/4.jpg');
            texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
            //设置地板重复绘制的密度是1 * 1
            texture.repeat.set(1,1);
    
            var material = new THREE.MeshLambertMaterial({
                map : texture,
                side : THREE.DoubleSide
            });
    
            //创建长方体几何体
            var gemotery = new THREE.BoxGeometry(width, depth, height);
    
            //创建网格对象以及进行位置的设定
            var mesh = new THREE.Mesh(gemotery,material);
            mesh.position.set(x,y,z)
            mesh.rotation.x = Math.PI * rotationX;
            mesh.rotation.y = Math.PI * rotationY;
            if(rotationZ) {
                mesh.rotation.z = Math.PI * rotationZ;
            }
    
            if(addMesh) {
                scene.add(mesh);
            }
    
            return mesh;
        }
    
        var paintGlass = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ, addMesh){
            var material = new THREE.MeshBasicMaterial({
                color : 0x58ACFA,
                transparent : true,
                opacity : 0.6
            });
    
            //创建长方体几何体
            var gemotery = new THREE.BoxGeometry(width, depth, height);
    
            //创建网格对象以及进行位置的设定
            var mesh = new THREE.Mesh(gemotery,material);
            mesh.position.set(x,y,z)
            mesh.rotation.x = Math.PI * rotationX;
            mesh.rotation.y = Math.PI * rotationY;
            if(rotationZ) {
                mesh.rotation.z = Math.PI * rotationZ;
            }
    
            if(addMesh) {
                scene.add(mesh);
            }
    
            return mesh;
        }
    
        function initStats() {
            var stats = new Stats();
            stats.setMode(0); // 0: fps, 1: ms
    
            // Align top-left
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';
            document.getElementById("Stats-output").appendChild(stats.domElement);
    
            return stats;
        }
    
        window.onload = init;
    </script>
    </body>
    </html>

    结果:

    5.Tween动画实现旋转床

      tween.js是一款可生成平滑动画效果的js动画库。你只需要告诉tween你想修改什么值,以及动画结束时它的最终值是什么,动画花费多少时间等信息,tween引擎就可以计算从开始动画点到结束动画点之间值,来产生平滑的动画效果。  其详细用法参考: https://www.cnblogs.com/jiangxiaobo/p/6207264.html

     代码:

    <!DOCTYPE html>
    <!--房子中间加个床,采用封装过的API实现,动态改变床的位置-->
    <html>
    
    <head>
        <title>myHouse</title>
        <script type="text/javascript" src="../libs/jquery-1.9.0.js"></script>
        <script type="text/javascript" src="../libs2/three.js"></script>
        <script type="text/javascript" src="../libs2/OBJLoader.js"></script>
        <script type="text/javascript" src="../libs2/stats.js"></script>
        <script type="text/javascript" src="../libs2/WebGL.js"></script>
        <script type="text/javascript" src="../libs2/TrackballControls.js"></script>
        <script type="text/javascript" src="../libs2/onEvent.js"></script>
        <script type="text/javascript" src="../libs2/ThreeBSP.js"></script>
        <script type="text/javascript" src="../libs2/tween.min.js"></script>
        <style>
            body {
                /* set margin to 0 and overflow to hidden, to go fullscreen */
                margin: 0;
                overflow: hidden;
            }
        </style>
    </head>
    <body>
    
    <div id="Stats-output">
    </div>
    <!-- Div which will hold the Output -->
    <div id="WebGL-output">
    </div>
    
    <div id="logInfo" style="position: absolute; top: 0px; left: 20%;  50%; padding: 5px;"></div>
    
    <!-- Javascript code that runs our Three.js examples -->
    <script type="text/javascript">
        //基本组件
        var scene, camera, webGLRenderer, stats;
        //鼠标控制动画相关组件
        var trackballControls, clock;
        //事件相关
        var threeOnEvent;
    
        function init() {
            stats = initStats();
    
            scene = new THREE.Scene();
    
            // create a camera, which defines where we're looking at.
            camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.x = 20;
            camera.position.y = 40;
            camera.position.z = 50;
            camera.lookAt(scene.position);
            scene.add(camera);
    
            // create a render and set the size
            webGLRenderer = new THREE.WebGLRenderer({
                antialias : true,
                alpha:true
            });
            webGLRenderer.setSize(window.innerWidth, window.innerHeight);
            webGLRenderer.setPixelRatio(window.devicePixelRatio);
            webGLRenderer.setClearColor(0xEEEEEE, 1.0);
            webGLRenderer.shadowMapEnabled = true;
    
            // add spotlight for the shadows
            var spotLight = new THREE.PointLight(0xffffff);
            spotLight.position.set(30, 40, 50);
            scene.add(spotLight);
    
            initObjects();
    
            // add the output of the renderer to the html element
            document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);
    
            render();
        }
    
        function initObjects(){
            initEvent();
    
            paintFloor();
    
            //画墙--一般y取高度的1/2
            paintWalls(40, 2, 10, 0, 5, -20, 1/2, 0, 0,true);//后面墙
            paintWalls(40, 2, 10, 0, 5, 20, 1/2, 0, 0,true);//前面墙
            paintWalls(42, 2, 10, -20, 5, 0, 1/2, 0, 1/2, true);//左面墙
            //添加带玻璃的墙
            var wallMesh = paintWalls(42, 2, 10, 20, 5, 0, 1/2, 0, 1/2, false);//右面墙
            var windowMesh = paintGlass(10, 2, 6, 20, 3, 0, 1/2, 0, 1/2, false);
            var resultMesh = createResultMesh(wallMesh, windowMesh, true);
            scene.add(resultMesh);
    
            initTrackballControls();
    
            paintBed();
        }
    
        function createResultMesh(srcMesh, destMesh, addDest) {
            var srcBSP = new ThreeBSP(srcMesh);
            var destBSP = new ThreeBSP(destMesh);
            var resultBSP = srcBSP.subtract(destBSP);
            var result = resultBSP.toMesh(srcMesh.material);
            result.geometry.computeFaceNormals();
            result.geometry.computeVertexNormals();
            if(addDest){
                scene.add(destMesh);
            }
    
            return result;
        }
    
        var paintBed = function(){
            var textures = [];
            loadBedTextures(textures, 0, "./img/bedplate.jpg"); //right
            loadBedTextures(textures, 1, "./img/bedplate.jpg"); //left
            loadBedTextures(textures, 2, "./img/bedplate.jpg"); //front
            loadBedTextures(textures, 3, "./img/bedplate.jpg");//back
            loadBedTextures(textures, 4, "./img/bedplate.jpg"); //bottom
            loadBedTextures(textures, 5, "./img/mattess.jpg"); //top
    
            //创建长方体几何体
            var gemotery = new THREE.BoxGeometry(10, 10, 5);
    
            //创建网格对象以及进行位置的设定
            var mesh = new THREE.Mesh(gemotery, textures);
            mesh.position.set(0, 2.5, 0)
            mesh.rotation.x = Math.PI * 1/2;
    
            //绑定一些数据
            mesh.tags = "bed";
            mesh.userData.ID = 1;
            mesh.name = "myBed";
    
            //增加事件(点击事件)
            mesh.on('click',function(m) {//m代表mesh对象
               alert('1');
            })
    
            // hover eventLisener(鼠标悬浮事件)
            mesh.on('hover',function(m) {
                // mouse enter the mesh
                alert(m.name + "  " + m.tags + " " + mesh.userData.ID);
            },function(m) {
                // mouse leave out the mesh
            });
    
            scene.add(mesh);
    
            startAnnotation(mesh);
        }
    
        function startAnnotation(mesh) {
            var indexNumber = {
                indexNumber : 0
            };
            var currentTween = new TWEEN.Tween(indexNumber).to({
                indexNumber : 2
            },5000);
            currentTween.easing(TWEEN.Easing.Sinusoidal.InOut);
            currentTween.repeat(60);//重复次数
            currentTween.yoyo(true);//结束之后反方向反弹
    
            currentTween.onUpdate(function(){
                var indexNumber = this.indexNumber;
                //改变床的旋转角度实现旋转床
                mesh.rotation.z = Math.PI * indexNumber;
    
                //也可以根据数字的范围进行一些其他动画(比如说实现闪烁效果等)
                if(indexNumber < 1){
                } else {
                }
            });
            currentTween.start();
        }
    
        function loadBedTextures(textures, index, url){
            textures[index] = new THREE.MeshBasicMaterial({
               map : new THREE.TextureLoader().load(url)
            });
        }
    
        function initEvent(){
            threeOnEvent = new THREE.onEvent(scene,camera);
        }
    
    
        function render() {
            requestAnimationFrame(render);
            webGLRenderer.render(scene, camera);
    
            //鼠标事件
            var delta = clock.getDelta();
            trackballControls.update(delta);
            logCameraPosition();
    
            if(stats){
                stats.update();
            }
    
            //更新事件
            threeOnEvent.update();
    
            //动画
            TWEEN.update();
        }
    
        function logCameraPosition(){
            var logInfo = "[info]: x - " + camera.position.x + " ;y - " + camera.position.y + " ;z - " + camera.position.z;
            $("#logInfo").html(logInfo);
        }
    
        function initTrackballControls(){
            clock = new THREE.Clock();
    
            trackballControls = new THREE.TrackballControls(camera);
    
            trackballControls.rotateSpeed = 1.0;
            trackballControls.zoomSpeed = 1.0;
            trackballControls.panSpeed = 1.0;
            //        trackballControls.noZoom=false;
            //        trackballControls.noPan=false;
            trackballControls.staticMoving = true;
            //        trackballControls.dynamicDampingFactor=0.3;
        }
    
        var paintFloor = function (){
            var loader = new THREE.TextureLoader;
            loader.load('./img/3.jpg', function (texture) {
                //x和y超过图片像素之后重复绘制图片
                texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                //设置地板重复绘制的密度是1 * 1
                texture.repeat.set(1, 1);
    
                //设置材质是双面材质
                var material = new THREE.MeshLambertMaterial({
                    map : texture,
                    side : THREE.DoubleSide
                });
    
                //创建普通的平面几何体
                var gemotery = new THREE.PlaneGeometry(40,40);
    
                //创建网格对象
                var mesh = new THREE.Mesh(gemotery,material);
                mesh.position.y = 0;
                mesh.rotation.x = Math.PI/2;
    
                scene.add(mesh);
            });
        }
    
        var paintWalls = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ, addMesh){
            var loader = new THREE.TextureLoader;
            var texture = new THREE.TextureLoader().load('./img/4.jpg');
            texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
            //设置地板重复绘制的密度是1 * 1
            texture.repeat.set(1,1);
    
            var material = new THREE.MeshLambertMaterial({
                map : texture,
                side : THREE.DoubleSide
            });
    
            //创建长方体几何体
            var gemotery = new THREE.BoxGeometry(width, depth, height);
    
            //创建网格对象以及进行位置的设定
            var mesh = new THREE.Mesh(gemotery,material);
            mesh.position.set(x,y,z)
            mesh.rotation.x = Math.PI * rotationX;
            mesh.rotation.y = Math.PI * rotationY;
            if(rotationZ) {
                mesh.rotation.z = Math.PI * rotationZ;
            }
    
            if(addMesh) {
                scene.add(mesh);
            }
    
            return mesh;
        }
    
        var paintGlass = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ, addMesh){
            var material = new THREE.MeshBasicMaterial({
                color : 0x58ACFA,
                transparent : true,
                opacity : 0.6
            });
    
            //创建长方体几何体
            var gemotery = new THREE.BoxGeometry(width, depth, height);
    
            //创建网格对象以及进行位置的设定
            var mesh = new THREE.Mesh(gemotery,material);
            mesh.position.set(x,y,z)
            mesh.rotation.x = Math.PI * rotationX;
            mesh.rotation.y = Math.PI * rotationY;
            if(rotationZ) {
                mesh.rotation.z = Math.PI * rotationZ;
            }
    
            if(addMesh) {
                scene.add(mesh);
            }
    
            return mesh;
        }
    
        function initStats() {
            var stats = new Stats();
            stats.setMode(0); // 0: fps, 1: ms
    
            // Align top-left
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';
            document.getElementById("Stats-output").appendChild(stats.domElement);
    
            return stats;
        }
    
        window.onload = init;
    </script>
    </body>
    </html>

    结果:

      床会一直旋转。。。

    6.   增加一个玻璃天窗,完成最终的房子 

      旋转床、鼠标和键盘对场景缩放。

    <!DOCTYPE html>
    <!--房子中间加个床,采用封装过的API实现,动态改变床的位置-->
    <html>
    
    <head>
        <title>myHouse</title>
        <script type="text/javascript" src="../libs/jquery-1.9.0.js"></script>
        <script type="text/javascript" src="../libs2/three.js"></script>
        <script type="text/javascript" src="../libs2/OBJLoader.js"></script>
        <script type="text/javascript" src="../libs2/stats.js"></script>
        <script type="text/javascript" src="../libs2/WebGL.js"></script>
        <script type="text/javascript" src="../libs2/OrbitControls.js"></script>
        <script type="text/javascript" src="../libs2/onEvent.js"></script>
        <script type="text/javascript" src="../libs2/ThreeBSP.js"></script>
        <script type="text/javascript" src="../libs2/tween.min.js"></script>
        <style>
            body {
                /* set margin to 0 and overflow to hidden, to go fullscreen */
                margin: 0;
                overflow: hidden;
            }
        </style>
    </head>
    <body>
    
    <div id="Stats-output">
    </div>
    <!-- Div which will hold the Output -->
    <div id="WebGL-output">
    </div>
    
    <div id="logInfo" style="position: absolute; top: 0px; left: 20%;  50%; padding: 5px;"></div>
    
    <!-- Javascript code that runs our Three.js examples -->
    <script type="text/javascript">
        //基本组件
        var scene, camera, webGLRenderer, stats;
        //鼠标控制动画相关组件
        var controls;
        //事件相关
        var threeOnEvent;
    
        function init() {
            stats = initStats();
    
            scene = new THREE.Scene();
    
            // create a camera, which defines where we're looking at.
            camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.x = 20;
            camera.position.y = 40;
            camera.position.z = 50;
            camera.lookAt(scene.position);
            scene.add(camera);
    
            // create a render and set the size
            webGLRenderer = new THREE.WebGLRenderer({
                antialias : true,
                alpha:true
            });
            webGLRenderer.setSize(window.innerWidth, window.innerHeight);
            webGLRenderer.setPixelRatio(window.devicePixelRatio);
            webGLRenderer.setClearColor(0xEEEEEE, 1.0);
            webGLRenderer.shadowMapEnabled = true;
    
            // add spotlight for the shadows
            var spotLight = new THREE.PointLight(0xffffff);
            spotLight.position.set(30, 40, 50);
            scene.add(spotLight);
    
            initObjects();
    
            // add the output of the renderer to the html element
            document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);
    
            render();
        }
    
        function initObjects(){
            initEvent();
    
            paintFloor();
            paintCell();
    
            //画墙--一般y取高度的1/2
            paintWalls(40, 2, 10, 0, 5, -20, 1/2, 0, 0,true);//后面墙
            paintWalls(40, 2, 10, 0, 5, 20, 1/2, 0, 0,true);//前面墙
            paintWalls(42, 2, 10, -20, 5, 0, 1/2, 0, 1/2, true);//左面墙
            //添加带玻璃的墙
            var wallMesh = paintWalls(42, 2, 10, 20, 5, 0, 1/2, 0, 1/2, false);//右面墙
            var windowMesh = paintGlass(10, 2, 6, 20, 3, 0, 1/2, 0, 1/2, false);
            var resultMesh = createResultMesh(wallMesh, windowMesh, true);
            scene.add(resultMesh);
    
            initOrbitControls();
    
            paintBed();
        }
    
        function createResultMesh(srcMesh, destMesh, addDest) {
            var srcBSP = new ThreeBSP(srcMesh);
            var destBSP = new ThreeBSP(destMesh);
            var resultBSP = srcBSP.subtract(destBSP);
            var result = resultBSP.toMesh(srcMesh.material);
            result.geometry.computeFaceNormals();
            result.geometry.computeVertexNormals();
            if(addDest){
                scene.add(destMesh);
            }
    
            return result;
        }
    
        var paintBed = function(){
            var textures = [];
            loadBedTextures(textures, 0, "./img/bedplate.jpg"); //right
            loadBedTextures(textures, 1, "./img/bedplate.jpg"); //left
            loadBedTextures(textures, 2, "./img/bedplate.jpg"); //front
            loadBedTextures(textures, 3, "./img/bedplate.jpg");//back
            loadBedTextures(textures, 4, "./img/bedplate.jpg"); //bottom
            loadBedTextures(textures, 5, "./img/mattess.jpg"); //top
    
            //创建长方体几何体
            var gemotery = new THREE.BoxGeometry(10, 10, 5);
    
            //创建网格对象以及进行位置的设定
            var mesh = new THREE.Mesh(gemotery, textures);
            mesh.position.set(0, 2.5, 0)
            mesh.rotation.x = Math.PI * 1/2;
    
            //绑定一些数据
            mesh.tags = "bed";
            mesh.userData.ID = 1;
            mesh.name = "myBed";
    
            //增加事件(点击事件)
            mesh.on('click',function(m) {//m代表mesh对象
               alert('1');
            })
    
            // hover eventLisener(鼠标悬浮事件)
            mesh.on('hover',function(m) {
                // mouse enter the mesh
                alert(m.name + "  " + m.tags + " " + mesh.userData.ID);
            },function(m) {
                // mouse leave out the mesh
            });
    
            scene.add(mesh);
    
            startAnnotation(mesh);
        }
    
        function startAnnotation(mesh) {
            var indexNumber = {
                indexNumber : 0
            };
            var currentTween = new TWEEN.Tween(indexNumber).to({
                indexNumber : 2
            },5000);
            currentTween.easing(TWEEN.Easing.Sinusoidal.InOut);
            currentTween.repeat(60);//重复次数
            currentTween.yoyo(true);//结束之后反方向反弹
    
            currentTween.onUpdate(function(){
                var indexNumber = this.indexNumber;
                //改变床的旋转角度实现旋转床
                mesh.rotation.z = Math.PI * indexNumber;
    
                //也可以根据数字的范围进行一些其他动画(比如说实现闪烁效果等)
                if(indexNumber < 1){
                } else {
                }
            });
            currentTween.start();
        }
    
        function loadBedTextures(textures, index, url){
            textures[index] = new THREE.MeshBasicMaterial({
               map : new THREE.TextureLoader().load(url)
            });
        }
    
        function initEvent(){
            threeOnEvent = new THREE.onEvent(scene,camera);
        }
    
    
        function render() {
            requestAnimationFrame(render);
            webGLRenderer.render(scene, camera);
    
            logCameraPosition();
    
            if(stats){
                stats.update();
            }
    
            //更新事件
            threeOnEvent.update();
    
            //动画
            TWEEN.update();
        }
    
        function logCameraPosition(){
            var logInfo = "[info]: x - " + camera.position.x + " ;y - " + camera.position.y + " ;z - " + camera.position.z;
            $("#logInfo").html(logInfo);
        }
    
        function initOrbitControls(){
            controls = new THREE.OrbitControls(camera,webGLRenderer.domElement);
    
            controls.minDistance = 1;
            controls.maxDistance = 5000;
        }
    
        var paintFloor = function (){
            var loader = new THREE.TextureLoader;
            loader.load('./img/3.jpg', function (texture) {
                //x和y超过图片像素之后重复绘制图片
                texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                //设置地板重复绘制的密度是1 * 1
                texture.repeat.set(1, 1);
    
                //设置材质是双面材质
                var material = new THREE.MeshLambertMaterial({
                    map : texture,
                    side : THREE.DoubleSide
                });
    
                //创建普通的平面几何体
                var gemotery = new THREE.PlaneGeometry(40,40);
    
                //创建网格对象
                var mesh = new THREE.Mesh(gemotery,material);
                mesh.position.y = 0;
                mesh.rotation.x = Math.PI/2;
    
                scene.add(mesh);
            });
        }
    
        var paintCell = function (){
            //设置材质是双面材质
            var material = new THREE.MeshBasicMaterial({
                color : 0x58ACFA,
                transparent : true,
                opacity : 0.6
            });
    
            //创建普通的平面几何体
            //创建长方体几何体
            var gemotery = new THREE.BoxGeometry(40, 40, 1);
    
            //创建网格对象
            var mesh = new THREE.Mesh(gemotery,material);
            mesh.position.y = 9;
            mesh.rotation.x = Math.PI/2;
    
            scene.add(mesh);
        }
    
        var paintWalls = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ, addMesh){
            var loader = new THREE.TextureLoader;
            var texture = new THREE.TextureLoader().load('./img/4.jpg');
            texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
            //设置地板重复绘制的密度是1 * 1
            texture.repeat.set(1,1);
    
            var material = new THREE.MeshLambertMaterial({
                map : texture,
                side : THREE.DoubleSide
            });
    
            //创建长方体几何体
            var gemotery = new THREE.BoxGeometry(width, depth, height);
    
            //创建网格对象以及进行位置的设定
            var mesh = new THREE.Mesh(gemotery,material);
            mesh.position.set(x,y,z)
            mesh.rotation.x = Math.PI * rotationX;
            mesh.rotation.y = Math.PI * rotationY;
            if(rotationZ) {
                mesh.rotation.z = Math.PI * rotationZ;
            }
    
            if(addMesh) {
                scene.add(mesh);
            }
    
            return mesh;
        }
    
        var paintGlass = function (width, depth, height, x, y, z, rotationX, rotationY, rotationZ, addMesh){
            var material = new THREE.MeshBasicMaterial({
                color : 0x58ACFA,
                transparent : true,
                opacity : 0.6
            });
    
            //创建长方体几何体
            var gemotery = new THREE.BoxGeometry(width, depth, height);
    
            //创建网格对象以及进行位置的设定
            var mesh = new THREE.Mesh(gemotery,material);
            mesh.position.set(x,y,z)
            mesh.rotation.x = Math.PI * rotationX;
            mesh.rotation.y = Math.PI * rotationY;
            if(rotationZ) {
                mesh.rotation.z = Math.PI * rotationZ;
            }
    
            if(addMesh) {
                scene.add(mesh);
            }
    
            return mesh;
        }
    
        function initStats() {
            var stats = new Stats();
            stats.setMode(0); // 0: fps, 1: ms
    
            // Align top-left
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';
            document.getElementById("Stats-output").appendChild(stats.domElement);
    
            return stats;
        }
    
        window.onload = init;
    </script>
    </body>
    </html>

    结果:

    git源码地址: https://github.com/qiao-zhi/threejsDemo

    效果演示

    总结:

      一般物体的y取的是高度是1/2;

      旋转角度的单位是Math.PI (乘以对应的角度,1就是180度,0.5就是90度)

  • 相关阅读:
    oracle sql 优化大全
    MyBatis学习笔记
    Eclipse启动项目时,删除workspaces无用的工作区间
    java 中 BigDecimal 怎么与 0 比较
    Mybatis 异常: The content of elements must consist of well-formed character data or markup
    ODS与数据仓库
    MyBatis 缓存
    管理信息系统需求调研分析指南
    Merge Into 语句代替Insert/Update在Oracle中的应用实战
    Oracle数据库常用函数使用--持续更新中
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/10969445.html
Copyright © 2011-2022 走看看