three.js导入3D模型展示城市及高亮+房型弹出

·  阅读 6044

说明: 公司需要做此项目,之前都没接触过,所以个人集合了所有能找到的资料做出了一个demo项目出来,希望对需要的各位有帮助。

1.先导入3D模型: obj+mtl文件

注意:

(1)在导入模型之前需要手动去修改mtl文件里面的路径,因为若是不改的话会导致材质加载失败的问题

(2)所有的变量最好不要在data里面定义,因为模型大一点的话会卡顿等。目前我是在外部定义的。

微信图片_20210408104643.png

模型需要放在根目录下,不然会读取不到。

2.使用three.js是由场景(网格模型(具体实物+材质)+光照(点光源(阴影)+环境光源))+相机+渲染(鼠标缩放拖动之类的)组成的。

我们先初始化

init() {
      let container = document.getElementById("container");
      /* 
        场景
      */
      scene = new THREE.Scene();
      /* 
        相机
      */
      //  scene.background = new THREE.Color( 0xa0a0a0 );
      camera = new THREE.PerspectiveCamera(
        75,
        container.clientWidth / container.clientHeight,
        1,
        1000
      );

      camera.position.set(292, 109, 268);
      camera.position.set(0, 0, 50);
    }
复制代码

如果要拿图片做背景的话(直接添进初始化里面) import BG from '../../public/xxxx.png'new THREE.TextureLoader().load(BG);

接着就是添加光源效果,如果不加的话会导致漆黑一片的效果。

// 环境光 能保持整体都是亮点
      let ambientLight = new THREE.AmbientLight(0x999999);
      // 点光源 就像灯泡一样的效果  白色灯光 亮度0.6
      let pointLight = new THREE.PointLight(0xffffff, 0.8);

      // 将灯光加入到场景中
      scene.add(ambientLight);
      // 将灯光加到摄像机中 点光源跟随摄像机移动
      // 为什么这样做  因为这样可以让后期处理时的辉光效果更漂亮
      camera.add(pointLight);

      // 我们将摄像机加入到场景中
      scene.add(camera);
复制代码

接着就是在初始化控制器(鼠标左右键的操作) new OrbitControls(camera, renderer.domElement);如果需要模型自动旋转的话autoRotate设为true就行了,他默认的是2.0, 你要是觉得快了可以调动autoRotateSpeed属性。 最大缩放效果与最小缩放效果是maxDistance/minDistance,他们的值是number。

3.加载模型

// 加载模型
    loadObj() {
      let _this = this;
      let manager = new THREE.LoadingManager();
      manager.addHandler(/\.dds$/i, new DDSLoader());

      mtlloader.load("/model/6/1.mtl", (materials) => {
        objloader.setMaterials(materials);
        materials.preload();
        objloader.load(
          "/model/6/1.obj",
          function (obj) {
            // oldChildren = _this.dealMeshMaterial(obj.children);
            obj.traverse((child) => {
              if (child instanceof THREE.Mesh) {
                child.material.transparent = true;
                child.material.reflectivity = 0.9;
              }
            });
            obj.scale.set(0.02, 0.02, 0.02);
            obj.position.set(0, -7, 0);
            scene.add(obj);
          },fn(), fn2());
      });
    },
    fn() // fn函数是成功调用
    fn2 // fn2失败时调用
复制代码

如果需要加载进度的话就在fn函数获取进度值

4.点击高亮

当我们需要高亮时需要在初始化里面注册一个事件(本人觉得单机体验不好,就用了双击) renderer.domElement.addEventListener("dblclick", this.mouseClick, false);

在加载模块时我是留住了每个模块的材质的

    /**
     * 留住每个模型的原材质
     */
    dealMeshMaterial(arrs) {
      let result = [];
      for (let i = 0; i < arrs.length; i++) {
        let obj = {
          // name: arrs[i].name,
          material: arrs[i].material,
          uuid: arrs[i].uuid,
        };
        result.push(obj);
      }
      return result;
    }
复制代码

点击事件

mouseClick(event) {
      // 还原之前的 点击状态
      this.showDetailBox = false;
      this.restore(scene.children[2].children, oldChildren);
      // 获取 raycaster 和所有模型相交的数组,其中的元素按照距离排序,越近的越靠前
      let intersects = this.getIntersects(event, event.clientX, event.clientY);
      // console.log(intersects);
      // 获取选中最近的 Mesh 对象
      if (
        intersects.length != 0 &&
        intersects[0].object instanceof THREE.Mesh
      ) {
        selectObject = intersects[0].object;
        if (this.isClick) {
          this.showObject(selectObject, event);
        } else {
          console.log(1111);
        }
      } else {
        // console.log(selectObject);
        this.colseData();
      }
    }
复制代码

项目地址

注:此demo是用vue3.0来实现的,如果需要用vue2.0的话只需要把代码复制过去就行了。 定义的变量用的多的话 例:scene camera 这些变量需要在export default 外部定义,否则游览器会崩掉或者卡死。

gitee : https://gitee.com/chen_post/vue_three#compiles-and-hot-reloads-for-development

分类:
前端
标签:
分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改