从零开始搭建开源智慧城市项目(二)模型线框和物理材质

2,268 阅读2分钟

前言

上一章已经通过GLTFLoader把模型数据加载到场景,接下来我们对这些数据进行进一步处理。首先是把模型分类,整个模型可以分为三类,建筑(CITY_UNTRIANGULATED),道路(ROADS),地面(other),对不同的数据分别添加不同的材质。

模型的线框添加

模型材质分为两个部分,第一部分是模型的线框材质,第二部分是模型的面材质,首先来说线框材质

  1. 线框材质:通过ThreeEdgesGeometry可以把生成模型的线框数据,用LineBasicMaterial生成线框的模型材质,然后用LineSegments把这两个数据组合到一起,即可生产线框模型对象。
              // 拿到模型线框的Geometry,其中child.geometry是模型子对象的节点数据
              const edges = new THREE.EdgesGeometry(child.geometry, 1);
              //设置模型的材质
              const lineMaterial = new THREE.LineBasicMaterial({
                // 线的颜色
                color: "rgba(38,133,254)",
              });
              //把数据组合起来
              const lineS = new THREE.LineSegments(edges, lineMaterial);
              //设置数据的位置
              lineS.position.set(
                child.position.x,
                child.position.y,
                child.position.z
              );
              //添加到场景
              scene.add(lineS);

效果图: image.png 2. 模型面材质:这里模型面材质选择的是Three的物理材质MeshPhysicalMaterial类,这个类可以模拟玻璃的质感.

              // 模型面材质
             const material = new THREE.MeshPhysicalMaterial({
                //颜色为
                color: "rgb(50,170,255)",
                //金属度
                metalness: 0.5,
                //粗糙度
                roughness: 0.1,
                //透明度
                transmission: 0.9,
                //模型是否透明
                transparent: true,
              });
              //生成模型对象
              const mesh = new THREE.Mesh(child.geometry, material);
              //添加到场景
              scene.add(mesh);

效果图:

image.png

地面和道路材质设置

道路和地面选择的是基本材质类MeshBasicMaterial

             //道路
              const material = new THREE.MeshBasicMaterial({
                color: "rgb(41,46,76)",
              });
              const mesh = new THREE.Mesh(child.geometry, material);
              scene.add(mesh);
              //地面
              const material = new THREE.MeshBasicMaterial({
                color: "#040912",
              });
              const mesh = new THREE.Mesh(child.geometry, material);
              scene.add(mesh);

效果图: GIF 2021-12-18 18-10-30.gif

完整代码

 addGLTF() {
      const loader = new GLTFLoader();
      loader.load("shanghai.gltf", (gltf) => {
        gltf.scene.traverse((child) => {
          // 设置线框材质

          if (child.isMesh) {
            //这个判断模型是楼房还是其他  加载不同的材质
            if (["CITY_UNTRIANGULATED"].includes(child.name)) {
              // 拿到模型线框的Geometry
              const edges = new THREE.EdgesGeometry(child.geometry, 1);
              //设置模型的材质
              const lineMaterial = new THREE.LineBasicMaterial({
                // 线的颜色
                color: "rgba(38,133,254)",
              });
              //把数据组合起来
              const lineS = new THREE.LineSegments(edges, lineMaterial);
              //设置数据的位置
              lineS.position.set(
                child.position.x,
                child.position.y,
                child.position.z
              );
              //添加到场景
              scene.add(lineS);
              lineS.rotateX(-Math.PI / 2);
              // 模型面材质
              const material = new THREE.MeshPhysicalMaterial({
                //颜色为
                color: "rgb(50,170,255)",
                //金属度
                metalness: 0.5,
                //粗糙度
                roughness: 0.1,
                //透明度
                transmission: 0.9,
                //模型是否透明
                transparent: true,
              });
              //生成模型对象
              const mesh = new THREE.Mesh(child.geometry, material);
              //添加到场景
              scene.add(mesh);
              mesh.position.set(
                child.position.x,
                child.position.y,
                child.position.z
              );

              mesh.rotateX(-Math.PI / 2);
            } else if (["ROADS"].includes(child.name)) {
              //道路
              const material = new THREE.MeshBasicMaterial({
                color: "rgb(41,46,76)",
           
              });
              const mesh = new THREE.Mesh(child.geometry, material);
              mesh.rotateX(-Math.PI / 2);
              mesh.position.set(
                child.position.x,
                child.position.y,
                child.position.z
              );
              scene.add(mesh);
            } else {
              //地面
              const material = new THREE.MeshBasicMaterial({
                color: "#040912",
              });
              const mesh = new THREE.Mesh(child.geometry, material);
              scene.add(mesh);
              mesh.rotateX(-Math.PI / 2);
              mesh.position.set(
                child.position.x,
                child.position.y,
                child.position.z
              );
          
            }
          }
          // 设置线框材质
        });
      });
    },

项目地址: github.com/lixiaochjaj…