Threejs 奇幻几何体:边缘、线框、包围盒大冒险

几何体

边缘几何体

可以作为一个辅助对象来查看几何体的边缘。

js 复制代码
gltfLoader.load("./models/building.gltf", (gltf) => {
  console.log(gltf);
  //隐藏后就可以直接看到线框
  // scene.add(gltf.scene);

  //这个模型是由多个几何体组成的,所以需要遍历
  gltf.scene.traverse((child) => {
    if (child.isMesh) {
      //获取几何体
      const geometry = child.geometry;

      // //获取边缘
      const edges = new THREE.EdgesGeometry(geometry);

      //创建线条材质
      const lineMaterial = new THREE.LineBasicMaterial({ color: 0xff0000 });

      //创建线条
      const line = new THREE.LineSegments(edges, lineMaterial);
      //将线条添加到场景中
      scene.add(line);
    }
  });
});

EdgesGeometry 构造函数用于创建边缘几何体,接受一个几何体对象作为参数。

LineBasicMaterial 构造函数用于创建线条材质,接受一个对象作为参数。

LineSegments 构造函数用于创建线条,接受两个参数:

  • geometry: 线条几何体。

  • material: 线条材质。

traverse 方法用于遍历场景中的所有对象,接受一个回调函数作为参数。

线框几何体

js 复制代码
let edges = new THREE.WireframeGeometry(geometry);

WireframeGeometry 构造函数用于创建线框几何体,接受一个几何体对象作为参数。

模型解压

在 Three.js 中,模型解压是指将压缩的模型文件解压缩为 Three.js 可以直接使用的模型对象的过程。通常,模型文件在压缩后可以减小文件大小,加快加载速度,但是解压缩过程需要消耗一定的计算资源。

正如上面加载的 building.gltf 模型是压缩过的,如果正常加载会报错,所以需要解压。

DRACOLoader

DRACOLoader 是 Three.js 提供的一个用于加载和解压缩 Draco 压缩格式的模型文件的加载器。Draco 是一个开源的 3D 图形压缩库,可以有效地减少 3D 模型的文件大小,加快加载速度,并保持较高的图形质量。

使用步骤:

  1. 引入 DRACOLoader
js 复制代码
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";
  1. 创建 DRACOLoader 实例
js 复制代码
const dracoLoader = new DRACOLoader();
  1. 设置 DRACOLoader 的解析器路径
js 复制代码
dracoLoader.setDecoderPath("./draco/");

注意: 解析器路径是相对于当前 HTML 文件的路径,所以需要把 three/examples/jsm/libs/draco 文件夹拷贝到项目public中。

  1. 设置加载器 draco 解码器
js 复制代码
gltfLoader.setDRACOLoader(dracoLoader);

包围盒

包围盒(Bounding Box)是一个用于描述物体体积的几何体,用于计算物体的位置、大小和碰撞等属性。在三维图形学中,包围盒通常用于加速物体的碰撞检测和渲染。

Box3

js 复制代码
objLoader.load("./models/1.obj", (obj) => {
  scene.add(obj);
  obj.children[0].material.map = new THREE.TextureLoader().load("./models/nezha.png");

  //获取模型,可以直接根据数据找,也可以使用getObjectByName方法
  // const nezha = obj.children[0]
  const nezha = obj.getObjectByName("texture_v100");
  //获取几何体
  const nazhaGeometry = nezha.geometry;
  //计算包围盒
  nazhaGeometry.computeBoundingBox();
  //获取包围盒
  const nazhaBox = nazhaGeometry.boundingBox;
  //创建包围盒辅助线
  const nazhaBoxHelper = new THREE.Box3Helper(nazhaBox, 0xff0000);
  scene.add(nazhaBoxHelper);
});

getObjectByName 方法用于获取指定名称的对象,返回值为对象本身。

.computeBoundingBox() 方法用于计算几何体的包围盒,返回值为包围盒对象。

.boundingBox 属性用于获取几何体的包围盒,返回值为包围盒对象。

Box3Helper 构造函数用于创建包围盒辅助线,接受两个参数:

  • box: 要显示的包围盒对象。

  • color: 辅助线的颜色。

因为生成的包围盒是一个立方体,所以可以直接通过 min 和 max 属性获取立方体的最小和最大坐标。可快速生成包围盒。

Sphere

js 复制代码
objLoader.load("./models/1.obj", (obj) => {
  scene.add(obj);
  obj.children[0].material.map = new THREE.TextureLoader().load("./models/nezha.png");

  const nezha = obj.getObjectByName("texture_v100");
  //获取几何体
  const nazhaGeometry = nezha.geometry;

  //计算包围球
  nazhaGeometry.computeBoundingSphere();
  //获取包围球
  const nazhaSphere = nazhaGeometry.boundingSphere;
  //创建包围球
  const sphereGeometry = new THREE.SphereGeometry(nazhaSphere.radius, 16, 16);
  const sphereMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00, wireframe: true });
  const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
  sphere.position.copy(nazhaSphere.center);
  scene.add(sphere);
});

.computeBoundingSphere() 方法用于计算几何体的包围球,返回值为包围球对象。

.boundingSphere 属性用于获取几何体的包围球,返回值为包围球对象。

多物体包围

js 复制代码
//创建球
const sphere1 = new THREE.Mesh(
  new THREE.SphereGeometry(0.5, 32, 32),
  new THREE.MeshBasicMaterial({ color: 0xff0000 })
);
sphere1.position.set(2, 0, 0);
scene.add(sphere1);
const sphere2 = new THREE.Mesh(
  new THREE.SphereGeometry(0.5, 32, 32),
  new THREE.MeshBasicMaterial({ color: 0x00ff00 })
);
scene.add(sphere2);
const sphere3 = new THREE.Mesh(
  new THREE.SphereGeometry(0.5, 32, 32),
  new THREE.MeshBasicMaterial({ color: 0x0000ff })
);
sphere3.position.set(-2, 0, 0);
scene.add(sphere3);

let box = new THREE.Box3();
let sphereArr = [sphere1, sphere2, sphere3];
for (let i = 0; i < sphereArr.length; i++) {
  //计算包围盒
  sphereArr[i].geometry.computeBoundingBox();
  let box3 = sphereArr[i].geometry.boundingBox;
  //更新世界矩阵
  sphereArr[i].updateMatrixWorld(true, true);
  //应用矩阵
  box3.applyMatrix4(sphereArr[i].matrixWorld);
  //获取包围盒
  box.union(box3);
}
const boxHelper = new THREE.Box3Helper(box, 0xff0000);
scene.add(boxHelper);

.union() 方法用于合并两个包围盒,返回值为合并后的包围盒对象。

注意: 这里涉及到物体的合并,那么需要先更新世界矩阵,再应用矩阵。

js 复制代码
//简易方法
for (let i = 0; i < sphereArr.length; i++) {
  //第一种
  sphereArr[i].geometry.computeBoundingBox();
  let box3 = sphereArr[i].geometry.boundingBox;
  sphereArr[i].updateMatrixWorld(true, true);
  box3.applyMatrix4(sphereArr[i].matrixWorld);

  //第二种简易方法
  let box3 = new THREE.Box3().setFromObject(sphereArr[i]);

  box.union(box3);
}

.setFromObject() 方法用于从物体中获取包围盒,返回值为包围盒对象。

扩展

.getCenter() 方法用于获取包围盒或包围球的中心点,返回值为向量对象。

Geometry.center() 几何体居中,返回值为几何体对象。

.updateWorldMatrix() 方法用于更新几何体的世界矩阵,返回值为几何体对象。

.applyMatrix4(matrix) 方法用于将指定的矩阵应用于几何体的顶点,返回值为几何体对象。

如果存在物体和包围盒的变换,那么需要先更新世界矩阵,再应用矩阵。

js 复制代码
//更新世界矩阵
nazhaGeometry.updateWorldMatrix(true, true);
//应用矩阵
nazhaGeometry.applyMatrix4(nazha.matrixWorld);

书洞笔记\]([mp.weixin.qq.com/s/8cyl1tzrx...](https://link.juejin.cn?target=https%3A%2F%2Fmp.weixin.qq.com%2Fs%2F8cyl1tzrxga4J0LCT56GpA "https://mp.weixin.qq.com/s/8cyl1tzrxga4J0LCT56GpA")

相关推荐
—Qeyser22 分钟前
用 Deepseek 写的uniapp血型遗传查询工具
前端·javascript·ai·chatgpt·uni-app·deepseek
codingandsleeping24 分钟前
HTTP1.0、1.1、2.0 的区别
前端·网络协议·http
小满blue25 分钟前
uniapp实现目录树效果,异步加载数据
前端·uni-app
天天扭码2 小时前
零基础 | 入门前端必备技巧——使用 DOM 操作插入 HTML 元素
前端·javascript·dom
咖啡虫3 小时前
css中的3d使用:深入理解 CSS Perspective 与 Transform-Style
前端·css·3d
拉不动的猪3 小时前
设计模式之------策略模式
前端·javascript·面试
旭久3 小时前
react+Tesseract.js实现前端拍照获取/选择文件等文字识别OCR
前端·javascript·react.js
独行soc3 小时前
2025年常见渗透测试面试题-红队面试宝典下(题目+回答)
linux·运维·服务器·前端·面试·职场和发展·csrf
uhakadotcom3 小时前
Google Earth Engine 机器学习入门:基础知识与实用示例详解
前端·javascript·面试
麓殇⊙4 小时前
Vue--组件练习案例
前端·javascript·vue.js