WEB 3D技术 three.js 多元素包围盒

本文 我们说多个物体的包围盒

我们先编写如下代码

import './style.css'
import * as THREE from "three";
import {
    
     OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";

const scene = new THREE.Scene();
const sphere1 =new THREE .Mesh(
    new THREE.SphereGeometry(0.7, 32, 32),
    new THREE.MeshBasicMaterial({
    
    
        color: 0x00FF00
    })
)
sphere1.position.x = -3;
scene.add(sphere1);

const sphere2 = new THREE .Mesh(
    new THREE.SphereGeometry(0.7, 32, 32),
    new THREE.MeshBasicMaterial({
    
    
        color: 0x0000FF
    })
)
scene.add(sphere2);

const sphere3 = new THREE .Mesh(
    new THREE.SphereGeometry(0.7, 32, 32),
    new THREE.MeshBasicMaterial({
    
    
        color:  0xFFE0FF
    })
)
sphere3.position.x = 3;
scene.add(sphere3);

//创建相机
const camera = new THREE.PerspectiveCamera(
    45, //视角 视角越大  能看到的范围就越大
    window.innerWidth / window.innerHeight,//相机的宽高比  一般和画布一样大最好
    0.1,  //近平面  相机能看到最近的距离
    1000  //远平面  相机能看到最远的距离
);

//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);

function animate() {
    
    
    controls.update();
    requestAnimationFrame(animate);
    /*cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;*/
    renderer.render(scene, camera);
}
animate();

先写出三个物体
在这里插入图片描述
觉得阐述为 我们要遍历 拿到每一个元素的包围盒 然后将他们合并为一个大的包围盒

我们先官网搜索 box3
如下图所示 有一个 union
在这里插入图片描述
它可以将多个盒子合并计算 最后得到一个合并后的大盒子

目前 代码的话 我们是三个小球 都添加到了场景中
在这里插入图片描述
我们可以遍历场景中的子元素

for(let i = 0;i < scene.children.length;i++) {
    
    
    console.log(scene.children[i]);
}

在这里插入图片描述
运行之后 我们查看控制台
在这里插入图片描述
我们可以这样写

//创建一个盒子
var box = new THREE.Box3();
for(let i = 0;i < scene.children.length;i++) {
    
    
    //确保元素具有几何体属性
    if(scene.children[i].geometry) {
    
    
        //通过 computeBoundingBox 计算当前元素的包围盒
        scene.children[i].geometry.computeBoundingBox();
        //获取当前元素的包围盒
        let box3 = scene.children[i].geometry.boundingBox;
        scene.children[i].updateMatrixWorld(true,true)
        // 将包围盘转换到世界坐标系
        box3.applyMatrix4(scene.children[i].matrixWorld);
        //通过外面的盒子 合并包围盒
        box.union(box3);
    }
}
//创建包围盒辅助器
let boxHelper = new THREE.Box3Helper(box, 0xffff00);
//将包围盒添加到场景中
scene.add(boxHelper);

先创建一个 盒子 叫box 后面的包围盒 用它来创建
遍历 scene.children 我们只要里面的盒子元素 所以 判断 要有geometry字段才继续
然后computeBoundingBox计算出包围盒属性 然后通过boundingBox字段拿到包围盒属性
updateMatrixWorld applyMatrix4套餐 做一个更新世界举证 元素移动时需要这个处理
然后 通过 union 将每一次算出的结果 都合并到 我们最开始创建的 box 盒子中
Box3Helper 通过 box 盒子创建包围盒辅助器 然后加入世界坐标
运行结果如下
在这里插入图片描述
我们转过来 看清楚一点
在这里插入图片描述
其实还有另一种方式
而且只需要一行代码

//创建一个盒子
var box = new THREE.Box3();
for(let i = 0;i < scene.children.length;i++) {
    
    
    //确保元素具有几何体属性
    if(scene.children[i].geometry) {
    
    
        let box3 = new THREE.Box3().setFromObject(scene.children[i]);
        box.union(box3);
    }
}
//创建包围盒辅助器
let boxHelper = new THREE.Box3Helper(box, 0xffff00);
//将包围盒添加到场景中
scene.add(boxHelper);

setFromObject 能够直接帮你算好并返回包围盒 且有更新矫正的功能
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45966674/article/details/135448854