用Three.js实现简单布局的3D房间

https://blog.csdn.net/mxdmojingqing/article/details/78044520

废话不说了,直接上成果图。

 代码如下

<!doctype html>
<html lang="en">
<head>
<title>房间布局</title>
<meta charset="utf-8">
<meta name="viewport"
    content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
</head>
<body>
 
 
    <script src="js/jquery-1.9.1.js"></script>
    <script src="js/Three.min.js"></script>
    <script src="js/OrbitControls.js"></script>
    <script src="js/ThreeBSP.js"></script>
    <script src="js/Detector.js"></script>
    <script src="js/Stats.js"></script>
 
 
    <script src="js/THREEx.KeyboardState.js"></script>
    <script src="js/THREEx.FullScreen.js"></script>
    <script src="js/THREEx.WindowResize.js"></script>
 
 
    <!-- people -->
    <script src="people/js/three.js"></script>
    <script src="people/js/DDSLoader.js"></script>
    <script src="people/js/MTLLoader.js"></script>
    <script src="people/js/OBJLoader.js"></script>
    <script src="people/js/Detector.js"></script>
    <script src="people/js/stats.min.js"></script>
    <script src="people/js/PathControls.js"></script>
    <script src="people/js/Tween.js"></script>
    <script src="people/js/RequestAnimationFrame.js"></script>
 
 
    <div id="ThreeJS" style="position: absolute; left: 0px; top: 0px"></div>
 
 
    <script>
        // 设置全局变量
        var scene, camera, renderer, controls, tween, door;
        var keyboard = new THREEx.KeyboardState();//保持键盘的当前状态,可以随时查询
        var clock = new THREE.Clock();
        var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
        //var VIEW_ANGLE = 45, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 20000;
        var VIEW_ANGLE = 75, ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = 10000;
        var materialArrayA = [];
        var materialArrayB = [];
        var matArrayA = [];//内墙
        var matArrayB = [];//外墙
        var dummy = new THREE.Object3D();//仿制品
        init();
        animate();
 
        //1.场景         
        function initScene() {
            scene = new THREE.Scene();
        }
 
        //2.相机
        function initCamera() {
            camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
            camera.position.set(0, 1000, 1800);
            camera.lookAt(scene.position);
            camera.lookAt(0, 0, 0);
            scene.add(camera);
        }
 
        //3.渲染器
        function initRender() {
            if (Detector.webgl)
                renderer = new THREE.WebGLRenderer({
                    antialias : true
                });
            else
                renderer = new THREE.CanvasRenderer();
            //设置渲染器的大小为窗口的内宽度,也就是内容区的宽度。
            renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
            container = document.getElementById('ThreeJS');
            container.appendChild(renderer.domElement);
            renderer.setClearColor(0x4682B4, 1.0);
        }
 
        //4.事件
        function initEvent() {
            THREEx.WindowResize(renderer, camera);
            THREEx.FullScreen.bindKey({
                charCode : 'm'.charCodeAt(0)
            });
        }
 
        //5.控制
        function initControls() {
            controls = new THREE.OrbitControls(camera, renderer.domElement);
        }
 
        //6.光源
        function initLight() {
            // 位置不同,方向光作用于物体的面也不同,看到的物体各个面的颜色也不同 
            // A start, 第二个参数是光源强度
            var directionalLight = new THREE.DirectionalLight(0xffffff, 1);//模拟远处类似太阳的光源
            directionalLight.position.set(0, 100, 0).normalize();
            scene.add(directionalLight);
            //A end
            var ambient = new THREE.AmbientLight(0xffffff, 1); //AmbientLight,影响整个场景的光源
            ambient.position.set(0, 0, 0);
            scene.add(ambient);
            //var pointlight = new THREE.PointLight(0x000000,1.5,2000);
            //scene.add(pointlight); 
        }
 
        //创建地板  
        function createFloor() {
            var loader = new THREE.TextureLoader();
            loader.load("images/floor.jpg", function(texture) {
                texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
                texture.repeat.set(10, 10);
                var floorGeometry = new THREE.BoxGeometry(1600, 1100, 1);
                var floorMaterial = new THREE.MeshBasicMaterial({
                    map : texture,
                    side : THREE.DoubleSide
                });
                var floor = new THREE.Mesh(floorGeometry, floorMaterial);
                floor.position.y = -0.5;
                floor.rotation.x = Math.PI / 2;
                scene.add(floor);
            });
 
            //茶色:0x58ACFA   透明玻璃色:0XECF1F3
            var glass_material = new THREE.MeshBasicMaterial({
                color : 0XECF1F3
            });
            glass_material.opacity = 0.4;
            glass_material.transparent = true;
 
            var left_wall = returnWallObject(20, 200, 1100, 0, matArrayB, -801,
                    100, 0);
            var left_cube = returnWallObject(20, 110, 1100, 0, matArrayB, -801,
                    100, 0);
            createResultBsp(left_wall, left_cube, 1);
            createCubeWall(1, 110, 1100, 0, glass_material, -801, 100, 0);
 
            var right_wall = returnWallObject(20, 200, 1100, 1, matArrayB, 801,
                    100, 0);
            var right_cube = returnWallObject(20, 110, 1100, 0, matArrayB, 801,
                    100, 0);
            createResultBsp(right_wall, right_cube, 1);
            createCubeWall(1, 110, 1100, 0, glass_material, 801, 100, 0);
        }
 
        //墙上挖门,通过两个几何体生成BSP对象
        function createResultBsp(bsp, less_bsp, mat) {
            switch (mat) {
            case 1:
                var material = new THREE.MeshPhongMaterial({
                    color : 0x9cb2d1,
                    specular : 0x9cb2d1,
                    shininess : 30,
                    transparent : true,
                    opacity : 1
                });
                break;
            case 2:
                var material = new THREE.MeshPhongMaterial({
                    color : 0xafc0ca,
                    specular : 0xafc0ca,
                    shininess : 30,
                    transparent : true,
                    opacity : 1
                });
                break;
            default:
            }
 
            var sphere1BSP = new ThreeBSP(bsp);
            var cube2BSP = new ThreeBSP(less_bsp);//0x9cb2d1 淡紫,0xC3C3C3 白灰 , 0xafc0ca灰
            var resultBSP = sphere1BSP.subtract(cube2BSP);
            var result = resultBSP.toMesh(material);
            result.material.flatshading = THREE.FlatShading;
            result.geometry.computeFaceNormals(); //重新计算几何体侧面法向量
            result.geometry.computeVertexNormals();
            result.material.needsUpdate = true; //更新纹理
            result.geometry.buffersNeedUpdate = true;
            result.geometry.uvsNeedUpdate = true;
            scene.add(result);
        }
 
        //创建墙
        function createCubeWall(width, height, depth, angle, material, x, y, z) {
            var cubeGeometry = new THREE.BoxGeometry(width, height, depth);
            var cube = new THREE.Mesh(cubeGeometry, material);
            cube.position.x = x;
            cube.position.y = y;
            cube.position.z = z;
            cube.rotation.y += angle * Math.PI; //-逆时针旋转,+顺时针
            scene.add(cube);
        }
 
        //返回墙对象
        function returnWallObject(width, height, depth, angle, material, x, y,
                z) {
            var cubeGeometry = new THREE.BoxGeometry(width, height, depth);
            var cube = new THREE.Mesh(cubeGeometry, material);
            cube.position.x = x;
            cube.position.y = y;
            cube.position.z = z;
            cube.rotation.y += angle * Math.PI;
            return cube;
        }
 
        //创建墙纹理
        function createWallMaterail() {
            matArrayA.push(new THREE.MeshPhongMaterial({
                color : 0xafc0ca
            })); //前  0xafc0ca :灰色
            matArrayA.push(new THREE.MeshPhongMaterial({
                color : 0xafc0ca
            })); //后  
            matArrayA.push(new THREE.MeshPhongMaterial({
                color : 0xd6e4ec
            })); //上  0xd6e4ec: 偏白色
            matArrayA.push(new THREE.MeshPhongMaterial({
                color : 0xd6e4ec
            })); //下  
            matArrayA.push(new THREE.MeshPhongMaterial({
                color : 0xafc0ca
            })); //左    0xafc0ca :灰色
            matArrayA.push(new THREE.MeshPhongMaterial({
                color : 0xafc0ca
            })); //右
 
            matArrayB.push(new THREE.MeshPhongMaterial({
                color : 0xafc0ca
            })); //前  0xafc0ca :灰色
            matArrayB.push(new THREE.MeshPhongMaterial({
                color : 0x9cb2d1
            })); //后  0x9cb2d1:淡紫
            matArrayB.push(new THREE.MeshPhongMaterial({
                color : 0xd6e4ec
            })); //上  0xd6e4ec: 偏白色
            matArrayB.push(new THREE.MeshPhongMaterial({
                color : 0xd6e4ec
            })); //下  
            matArrayB.push(new THREE.MeshPhongMaterial({
                color : 0xafc0ca
            })); //左   0xafc0ca :灰色
            matArrayB.push(new THREE.MeshPhongMaterial({
                color : 0xafc0ca
            })); //右
 
        }
 
        //创建房间布局
        function createLayout() {
 
            // 墙面1 立方体比较长的面  左一
            createCubeWall(10, 200, 900, 0, matArrayB, -651, 100, 0);
            // 墙面2  立方体比较长的面   右一
            createCubeWall(10, 200, 900, 1, matArrayB, 651, 100, 0);
            // 墙面3 门对面的墙 立方体比较短的面  
            createCubeWall(10, 200, 1310, 1.5, matArrayB, 0, 100, -451);
 
            // 墙面4   带门的面  
            var wall = returnWallObject(1310, 200, 10, 0, matArrayB, 0, 100,
                    455);
            // 门框 
            var door_cube = returnWallObject(100, 180, 10, 0, matArrayB, 0, 90,
                    455);
            createResultBsp(wall, door_cube, 1);
 
            //为墙面安装门,右门
            var loader = new THREE.TextureLoader();
            loader.load("images/door_right.png", function(texture) {
                var doorgeometry = new THREE.BoxGeometry(100, 180, 2);
                var doormaterial = new THREE.MeshBasicMaterial({
                    map : texture,
                    color : 0xffffff
                });
                doormaterial.opacity = 1.0;
                doormaterial.transparent = true;
                door = new THREE.Mesh(doorgeometry, doormaterial);
                door.position.set(-50, 0, 0);
                var door1 = door.clone();
                door1.position.set(50, 0, 0);
                door1.visible = false;
                dummy.add(door);
                dummy.add(door1);
                dummy.position.set(50, 90, 451)
                scene.add(dummy);
            });
 
            // 房间A:隔墙1 
            createCubeWall(10, 200, 250, 0, matArrayA, -151, 100, 325);
            //房间A:隔墙2  无门
            createCubeWall(10, 200, 220, 0.5, matArrayA, -256, 100, 201);
            // 厨房:隔墙3 
            createCubeWall(350, 200, 10, 0, matArrayA, 481, 100, 131);
            // 厨房:隔墙4 无门
            createCubeWall(10, 200, 200, 0, matArrayA, 301, 100, 225);
            // 房间B 
            createCubeWall(350, 200, 10, 0, matArrayA, -471, 100, -50);
            //房间B  无门
            createCubeWall(200, 200, 10, 0.5, matArrayA, 0, 100, -350);
            // 房间C
            createCubeWall(220, 200, 10, 0, matArrayA, 540, 100, -50);
            //房间C 无门
            createCubeWall(200, 200, 10, 0.5, matArrayA, 250, 100, -350);
            //厕所
            var cube = returnWallObject(10, 200, 260, 0.5, matArrayA, 125, 100,
                    -250);
            //厕所门框
            var door_cube1 = returnWallObject(10, 160, 80, 0.5, matArrayA, 155,
                    90, -250);
            createResultBsp(cube, door_cube1, 2);
 
            //茶色:0x58ACFA   透明玻璃色:0XECF1F3
            var glass_material = new THREE.MeshBasicMaterial({
                color : 0x58ACFA
            });
            glass_material.opacity = 0.6;
            glass_material.transparent = true;
            createCubeWall(1, 180, 80, 0.5, glass_material, 155, 90, -250);
        }
 
        //7.初始化OBJ对象
        function initObject() {
            //墙纹理
            createWallMaterail();
            createFloor();
            createLayout();
        }
 
        //初始化函数
        function init() {
            initScene();
            initCamera();
            initRender();
            initEvent();
            initControls();
            initLight();
            initObject();
            //监听键盘按键
            document.addEventListener("keydown", onkeyDown, false);
        }
 
        var door_state = true;//默认是门是关闭的
        //Enter=13,Space=32;
        function onkeyDown(event) {
            switch (event.keyCode) {
            case 13:
                console.log(event.keyCode);
                if (door_state) {
                    dummy.rotation.y += 0.5 * Math.PI;
                    door_state = false;
                } else {
                    dummy.rotation.y -= 0.5 * Math.PI;
                    door_state = true;
                }
                break;
            default:
                console.log(event.keyCode);
                break;
            }
        }
 
        function animate() {
            requestAnimationFrame(animate);
            renderer.render(scene, camera);
            TWEEN.update();
            update();
        }
 
        function update() {
            var delta = clock.getDelta();
            var moveDistance = 200 * delta;
            var rotateAngle = Math.PI / 2 * delta;
            controls.update();
        }
    </script>
</body>
</html>

 

 

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值