小工具知识网

当前位置: 首页 > 行业知识 > WEB 3D技术 three.js 包围盒

行业知识

WEB 3D技术 three.js 包围盒

2026-11-13 23:46:00 来源:互联网转载

本文 我们来说 包围盒

如下图所示 就是一个方框 框住我们整个物体

它的作用 比较明显的就是 当用户点击某个物体 我们用包围盒套住 用户能够很直观的知道自己当前选中的物体是哪一个

还有就是 比如 我们物体做的比较复杂 是非常多顶点构建的 那么 我们判断它有没有和其他物体接触就很麻烦 但 有了包围盒 我们只需要判断包围盒有没有接触即可

然后 我们官网搜索 BufferGeometry

包围盒是所有几何体都有的属性

这里 我们有两个 一个是 包围盒 另一个是 包围圈

简单说 一个是包围成立方体 另一个是成球形包围

默认情况 例如我们自己创建的几何体 是不会有这个属性的 我们需要自己通过 computeBoundingBox 去计算

我这里 先写成这样的代码

import './style.css'import * as THREE from "three";import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";//创建相机const camera = new THREE.PerspectiveCamera(    45, //视角 视角越大  能看到的范围就越大    window.innerWidth / window.innerHeight,//相机的宽高比  一般和画布一样大最好    0.1,    1000);const scene = new THREE.Scene();const gltfLoader = new GLTFLoader();gltfLoader.load(    // 模型路径    "/gltf/scene.gltf",    // 加较完成同调    (gltf) =>{        gltf.scene.traverse((child) => {            if (child.isMesh) {                child.frustumCulled = false;                child.castShadow = true;                child.material.emissive = child.material.color;                child.material.emissiveMap = child.material.map;            }        });        scene.add(gltf.scene);    })//c创建一个canvas容器  并追加到 body上const renderer = new THREE.WebGLRenderer(0);renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);//设置相机位置   这里 我们设置Z轴  大家可以试试  S Y 和 Z  都是可以的camera.position.z = 5;//设置相机默认看向哪里   三个 0  代表 默认看向原点camera.lookAt(0, 0, 0);//将内容渲染到元素上renderer.render(scene, camera);const controls = new OrbitControls(camera, renderer.domElement);let rgbeloader = new RGBELoader();rgbeloader.load("/xhdr/Alex_Hart-Snow_Pano_2k.hdr",(texture) =>{    scene.background = texture;    texture.mapping = THREE.EquirectangularReflectionMapping;})function animate() {    controls.update();    requestAnimationFrame(animate);    /*cube.rotation.x += 0.01;    cube.rotation.y += 0.01;*/    renderer.render(scene, camera);}animate();

这里 就是简单引入了 hdr场景贴图 和一个 glb 车的3D元素

那么 现在 我们要给这台车 做一个包围盒

首先 我们需要拿到它的几何体对象 先在代码中 控制台打印gltf对象下面的 scene

然后 下面有两个比较重要的内容 它的name 和 id

getObjectById 通过id获取元素对象

getObjectByName 通过name属性获取元素对象

我们肯定是用name 会更方便一点

我们的name 叫 webvrmodel_Scene

我们改写代码如下

const gltfLoader = new GLTFLoader();gltfLoader.load(    // 模型路径    "/gltf/scene.gltf",    // 加较完成同调    (gltf) =>{        gltf.scene.traverse((child) => {            if (child.isMesh) {                child.frustumCulled = false;                child.castShadow = true;                child.material.emissive = child.material.color;                child.material.emissiveMap = child.material.map;            }        });        scene.add(gltf.scene);        let webvrmodel = gltf.scene.getObjectByName("webvrmodel_Scene");        console.log(webvrmodel);    })

通过 getObjectByName 寻找name 为 webvrmodel_Scene的对象

然后 下面用console.log 输出在控制台上

运行结果如下

这里 虽然拿到了 但其实 我们也不需要这么麻烦

可以直接这样改

const gltfLoader = new GLTFLoader();gltfLoader.load(  "/gltf/scene.gltf",  (gltf) => {    gltf.scene.traverse((child) => {      if (child.isMesh) {        child.frustumCulled = false;        child.castShadow = true;        child.material.emissive = child.material.color;        child.material.emissiveMap = child.material.map;        const geometry = child.geometry;        geometry.computeBoundingBox()        let duckBox = geometry.boundingBox;        console.log(duckBox);      }    });    scene.add(gltf.scene);  });

拿到 geometry 几何体对象字段

然后 通过对象 调用 computeBoundingBox计算出 包围盒对象

然后 通过 geometry.boundingBox 获取他的包围盒对象 并在控制台打印

这里正常的几何体对象都可以调用computeBoundingBox 取 boundingBox

是因为 我们这是导入的gltf资源 所以还要想办法去拿这个几何体的对象

运行如下

包围盒对象 给了两个属性 max和min

两个三维向量 但是 两个形成一个包围盒 这是为什么呢?

它的两个向量 其实就是两个点的坐标

因为 他是一个很规整的立方体 包围盒 所以 它只需要如下图的两位点的位置 就可以拉出一个立方体

那么 既然已经拿到最小和最大两个值 那么 我们就可以拉出这样一个包围盒工具

我们可以将代码改成这样

const gltfLoader = new GLTFLoader();gltfLoader.load(  "/gltf/scene.gltf",  (gltf) => {    gltf.scene.traverse((child) => {      if (child.isMesh) {        child.frustumCulled = false;        child.castShadow = true;        child.material.emissive = child.material.color;        child.material.emissiveMap = child.material.map;        const geometry = child.geometry;        geometry.computeBoundingBox()        let boxHelper = new THREE.Box3Helper(geometry.boundingBox, 0xffff00);        scene.add(boxHelper);      }    });    scene.add(gltf.scene);  });

THREE.Box3Helper 需要两个参数 第一个是 需要处理的包围盒对象 就是我们从gltf几何体对象上拿到的 boundingBox属性 第二个为一个颜色属性

然后将这个包围盒对象 add到场景中

运行代码如下

我们外面这个包围盒的线就出来了

几何体 则更简单 我们编写代码如下

import './style.css'import * as THREE from "three";import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";//创建相机const camera = new THREE.PerspectiveCamera(    45, //视角 视角越大  能看到的范围就越大    window.innerWidth / window.innerHeight,//相机的宽高比  一般和画布一样大最好    0.1,    1000);const scene = new THREE.Scene();let uvTexture = new THREE.TextureLoader().load("/textUv.jpg");const geometry = new THREE.BufferGeometry();// 创建顶点数据const vertices = new Float32Array([    -1.0,-1.0 ,0.0,    1.0 ,-1.0, 0.0,    1.0 ,1.0 ,0.0,    -1.0 ,1.0, 0.0])geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));const indices = new Uint16Array([0 ,1 ,2, 0, 3, 2]);const material = new THREE.MeshBasicMaterial({    map: uvTexture,    side: THREE.DoubleSide})const uv = new Float32Array([    0, 0, 1, 0, 1, 1, 0, 1])geometry.setAttribute("uv", new THREE.BufferAttribute(uv, 2));const normals = new Float32Array([    0, 0, 1,    0, 0, 1,    0, 0, 1,    0, 0, 1])geometry.setAttribute("normal", new THREE.BufferAttribute(normals, 3));geometry.setIndex(new THREE.BufferAttribute(indices, 1));console.log(geometry);const cube = new THREE.Mesh(geometry, material);scene.add(cube)//c创建一个canvas容器  并追加到 body上const renderer = new THREE.WebGLRenderer(0);renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);//设置相机位置   这里 我们设置Z轴  大家可以试试  S Y 和 Z  都是可以的camera.position.z = 5;//设置相机默认看向哪里   三个 0  代表 默认看向原点camera.lookAt(0, 0, 0);//将内容渲染到元素上renderer.render(scene, camera);const controls = new OrbitControls(camera, renderer.domElement);let rgbeloader = new RGBELoader();rgbeloader.load("/xhdr/Alex_Hart-Snow_Pano_2k.hdr",(texture) =>{    scene.background = texture;    texture.mapping = THREE.EquirectangularReflectionMapping;    material.envMap = texture;})function animate() {    controls.update();    requestAnimationFrame(animate);    /*cube.rotation.x += 0.01;    cube.rotation.y += 0.01;*/    renderer.render(scene, camera);}animate();

然后添加代码

geometry.computeBoundingBox()let boxHelper = new THREE.Box3Helper(geometry.boundingBox, 0xffff00);scene.add(boxHelper);

我们外面的包围盒就出来了

上一篇:电脑服务器哪里添加用户?

下一篇:探索回文串的奥秘,揭秘神秘面纱!