three.js 构建简单的房间

通过three.js构建一个简单的房间

知识点

  • 轨道控制器:OrbitControls

  • 使用ThreeBSP库进行Three.js网格组合

  • tweenjs动画效果就是使一个对象在一定时间内从一个状态到另外一个状态

代码

<!DOCTYPE html>

<html>

<head>
  <title>构建一个简单的房间</title>

  <style>
    body {
      /* set margin to 0 and overflow to hidden, to go fullscreen */
      margin: 0;
      overflow: hidden;
    }
  </style>
</head>

<body>

  <div id="ThreeJS" style="position: absolute; left: 0px; top: 0px"></div>
  <script type="text/javascript" src="js/three.js"></script>
  <script type="text/javascript" src="js/OrbitControls.js"></script>
  <script type="text/javascript" src="js/ThreeBSP.js"></script>
  <script type="text/javascript" src="js/Tween.js"></script>

  <!-- Javascript code that runs our Three.js examples -->
  <script type="text/javascript">
    // 设置全局变量
    var scene, camera, renderer, controls, tween, door;
    var clock = new THREE.Clock();
    var materialArrayA = [];
    var materialArrayB = [];
    var matArrayA = [];//内墙
    var matArrayB = [];//外墙
    var dummy = new THREE.Object3D();//仿制品
    /**
      * 创建场景对象Scene
      */
    scene = new THREE.Scene();
    /**
     * 相机设置
     */
    var width = window.innerWidth; //窗口宽度
    var height = window.innerHeight; //窗口高度
    var k = width / height; //窗口宽高比
    var s = 200; //三维场景显示范围控制系数,系数越大,显示的范围越大
    //创建相机对象
    camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
    camera.position.set(200, 300, 200); //设置相机位置
    camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
    controls = new THREE.OrbitControls(camera);

    init()
    // 初始化
    function init() {
      initLight() //灯光
      //墙纹理
      createWallMaterail();
      createFloor();
      createLayout();
    }
    // 创建地板
    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)
      })
    }

    //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);	
    }

    /**
     * 创建渲染器对象
     */
    renderer = new THREE.WebGLRenderer();
    renderer.setSize(width, height);//设置渲染区域尺寸
    renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
    document.body.appendChild(renderer.domElement); //body元素中插入canvas对象

    // 创建墙
    function createCubeWall(width, height, depth, angle, meterial, x, y, z) {
      var cubeGeometry = new THREE.BoxGeometry(width, height, depth)
      var cube = new THREE.Mesh(cubeGeometry, meterial)
      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, meterial, x, y, z) {
      var cubeGeometry = new THREE.BoxGeometry(width, height, depth)
      var cube = new THREE.Mesh(cubeGeometry, meterial)
      cube.position.x = x
      cube.position.y = y
      cube.position.z = z
      cube.rotation.y += angle * Math.PI
      return cube
    }
    // 创建墙纹理
    function createWallMaterail() {
      // MeshPhongMaterial 网格材质
      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 }));  //右


    }
    //墙上挖门,通过两个几何体生成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 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);
    }


    var animate = function () {
      requestAnimationFrame(animate);

      TWEEN.update();
      // renderer.render(scene, camera);
      controls.update()
      renderer.render(scene, camera);
    };


    animate();
  </script>

</body>

</html>

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值