three.js的一些问题总结

2,582 阅读2分钟

image.png

1,加载gltf,glb模型变黑

1,加载方法

1,导入所需的包,以angular为例:

import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; //加载压缩模型需要 import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';

2,使用时核心代码:

const loader = new GLTFLoader();
    //Load a glTF resource
    //设置解压库文件路径
    var dracoLoader = new DRACOLoader();
    dracoLoader.setDecoderPath('assets/libs/draco/gltf/');
    loader.setDRACOLoader(dracoLoader);
   // this.pivot5 = new THREE.Object3D();
    loader.load(
      url,
      //called when the resource is loader
      function (gltf) {
        gltf.scene.traverse(function (child: any) {
        // console.log(9998, child);
          if (child.isMesh) {
            if(child.userData.name&&child.userData.name.indexOf('desk')>-1){
              const label = createLabel(child.userData.name);
              label.position.set( 0, 0, 0 );
              child.add( label );
            }
            child.material.emissive = child.material.color;
            child.material.emissiveMap = child.material.map;
            // child.vertices.forEach(function (e, i, arr) {
            //   var length = glist[index].vertices.length;

      }
    })
    scene.add(gltf.scene);
    
    //  this.pivot5.add(gltf);
  let res = [];
   let toArr = function (arr) {
    // console.log(6, arr);
    arr.forEach(function (item) {
      item.children.length > 0 ? toArr(item.children) : res.push(item);
    });
  }
  toArr(gltf.scene.children);
  callback(res, camera, controls, gltf.scene, scene, renderer, labelRenderer);
 
  },
  //called while loading is progressing
  function (xhr) {
    this.loadProgress = (xhr.loaded / xhr.total * 100) + '% loaded';
    console.log((xhr.loaded / xhr.total * 100) + '% loaded');
  },
  //called when loading gas errors
  function (error) {
    console.log('An error happened');
  }
);

注意事项:assets/libs/draco/gltf/存放这些文件,如下图所示:

image.png

2,模型加载中会变黑的问题解决

添加如下代码

    if (child.isMesh) {     
        child.material.emissive = child.material.color;
        child.material.emissiveMap = child.material.map;
    }

image.png

3,添加环境贴图

scene = new THREE.Scene();
var textureCube = new THREE.CubeTextureLoader().setPath('assets/img/model/entv/').load(['px.png', 'nx.png',  'py.png', 'ny.png', 'pz.png', 'nz.png',  ]);
// //六张图片分别是朝前的(preview_f.jpg)、朝后的(preview_b.jpg)、朝上的(preview_u.jpg)、朝下的(preview_d.jpg)、朝右的(preview_r.jpg)和朝左的(preview_l.jpg)
scene.background =  textureCube; //new THREE.Color(0x727272);

4,给模型添加标注

1,所用的包

import { CSS2DObject, CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer';

2,使用

image.png

核心函数:样式可以自由修改

function createLabel(name){
      const div = document.createElement( 'div' );
      div.className = 'label';
      div.textContent = name;
      div.style.padding = '4px 10px';
      div.style.color = '#fff';
      div.style.fontSize = '16px';
      div.style.position = 'absolute';
      div.style.backgroundColor = 'rgba(25,25,25,0.5)';
      div.style.borderRadius = '5px';
     // earthDiv.style.marginTop = '-1em';
      const Label = new CSS2DObject( div );
      return Label;
    }

最后别忘记渲染哦

image.png

5,模型交互

onDocumentMouseDown(e) {
    e.preventDefault();
    var raycaster = new THREE.Raycaster();
    var mouse = new THREE.Vector2();
    //将鼠标点击位置的屏幕坐标转成threejs中的标准坐标,具体解释见代码释义
    mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
    //新建一个三维单位向量 假设z方向就是0.5
    //根据照相机,把这个向量转换到视点坐标系

    raycaster.setFromCamera(mouse, this.camera);
    let INTERSECTED;
    // calculate objects intersecting the picking ray
    var intersects = raycaster.intersectObjects(this.scene.children, true);
    // if (!intersects[0]) return
    // console.log(9899, intersects);
    if (intersects.length > 0) {
      // console.log(9899, intersects);
      if (INTERSECTED != intersects[0].object && intersects[0].object instanceof THREE.Mesh) {
        if (INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
        INTERSECTED = intersects[0].object;
        INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
        INTERSECTED.material.emissive.setHex(0xffffff * Math.random());
        // console.log(6, INTERSECTED);
      }
    } else {
      if (INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
      INTERSECTED = null;

    }
  }

今日分享就到这里了,欢迎点赞指正,奥利给