Three.js 进阶(多物体包围盒、边缘几何体、线框几何体)

本篇主要学习内容 :

  1. 多物体包围盒
  2. 边缘几何体
  3. 线框几何体

点赞 + 关注 + 收藏 = 学会了

上一节学习了物体的包围盒与包围球,这一节在此基础上学习多个物体的包围盒,及两个新的几何体,易错api较多,学习时需仔细认真

1.多物体包围盒

1.1)创建三个球体
let sphere1 = new THREE.Mesh(
    new THREE.SphereGeometry(0.5, 32, 32),
    new THREE.MeshBasicMaterial({
    
    
        color: 'blue',
    })
)
sphere1.position.x = -3
scene.add(sphere1)
let sphere2 = new THREE.Mesh(
    new THREE.SphereGeometry(0.5, 32, 32),
    new THREE.MeshBasicMaterial({
    
    
        color: 'yellow',
    })
)
scene.add(sphere2)
let sphere3 = new THREE.Mesh(
    new THREE.SphereGeometry(0.5, 32, 32),
    new THREE.MeshBasicMaterial({
    
    
        color: 'green',
    })
)
sphere3.position.x = 3
scene.add(sphere3)
1.2)计算包围盒的两种方式
var box = new THREE.Box3()
let sphereArr = [sphere1, sphere2, sphere3]

sphereArr.forEach((child) => {
    
    
    // 计算包围盒第一种方式
    child.geometry.computeBoundingBox() // 获取当前物体包围盒
    let box3 = child.geometry.boundingBox // 获取包围盒
    child.updateWorldMatrix(true, true) // 更新世界矩阵
    box3.applyMatrix4(child.matrixWorld) // 应用世界矩阵

    // 计算包围盒第二种方式
    let box3 = new THREE.Box3().setFromObject(child)
    // 合并包围盒
    box.union(box3)
})
1.3)计算包围盒的两种方式
// 创建包围盒辅助器
let boxHelper = new THREE.Box3Helper(box, 'yellow')
// 更新世界矩阵
scene.add(boxHelper)

在这里插入图片描述

2.边缘几何体

借助EdgesGeometry可以给模型设置一个模型边界线。

请添加图片描述

 gltf.scene.traverse((chil) => {
    
    
        if (chil.isMesh) {
    
    
            let geometry = chil.geometry
            // 获取边缘geometry
            // let edgesGeometry = new THREE.EdgesGeometry(geometry)
            let edgesMaterial = new THREE.LineBasicMaterial({
    
    
                color: 'red',
            })
            let edges = new THREE.LineSegments(edgesGeometry, edgesMaterial)
            // 更新建筑世界矩阵
            chil.updateWorldMatrix(true, true)
            // 复制世界矩阵
            edges.matrix.copy(chil.matrixWorld)
            // 同步世界矩阵
            edges.matrix.decompose(edges.position, edges.quaternion, edges.scale)
            // 添加到场景
            scene.add(edges)
        }
    })

3.线框几何体

WireframeGeometry可以用作辅助对象,以线框形式查看几何体

在这里插入图片描述

gltf.scene.traverse((chil) => {
    
    
        if (chil.isMesh) {
    
    
            let geometry = chil.geometry
            let edgesMaterial = new THREE.LineBasicMaterial({
    
    
                color: 'red',
            })
            // 线框geometry
            let edgesGeometry = new THREE.WireframeGeometry(geometry)
            let edges = new THREE.LineSegments(edgesGeometry, edgesMaterial)
            // 更新建筑世界矩阵
            chil.updateWorldMatrix(true, true)
            // 复制世界矩阵
            edges.matrix.copy(chil.matrixWorld)
            // 同步世界矩阵
            edges.matrix.decompose(edges.position, edges.quaternion, edges.scale)
            // 添加到场景
            scene.add(edges)
        }
    })

完整代码,多种写法,及易错点

<!-- App边缘几何体线框几何体(易错) -->
<script setup>
// 导入threejs
import * as THREE from 'three'
//
import {
    
     OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
// 导入lil.gui
import {
    
     GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js'
// RGBE hdr加载器
import {
    
     RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js'
//GLTF加载器
import {
    
     GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
//DRACO解压器
import {
    
     DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'

// 创建场景
const scene = new THREE.Scene()
// 创建相机
const camera = new THREE.PerspectiveCamera(
    45, //视角
    window.innerWidth / window.innerHeight, //宽高比
    0.1, //近平面
    1000 //远平面
)
// 创建渲染器
const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)

// 设置相机位置
camera.position.x = 15
camera.position.y = 2
camera.position.z = 5
camera.lookAt(3, 0, 0) //原点
// 坐标辅助器 (xyz轴绘制)
const axesHelper = new THREE.AxesHelper(5)

scene.add(axesHelper)
// 轨道控制器  (旋转缩放)
const controls = new OrbitControls(camera, renderer.domElement)
// const controls = new OrbitControls(camera, document.body)
// 设置带阻尼(惯性缓动效果)
controls.enableDamping = true
// 阻尼系数
controls.dampingFactor = 0.05
// 旋转速度
// controls.autoRotate = true
// 渲染函数
;(function animate() {
    
    
    controls.update()
    requestAnimationFrame(animate)
    renderer.render(scene, camera)
})()
// 渲染
// 监听窗口变化
window.addEventListener('resize', () => {
    
    
    // 重置渲染器宽高比
    renderer.setSize(window.innerWidth, window.innerHeight)
    // 重置相机宽高比
    camera.aspect = window.innerWidth / window.innerHeight
    // 更新相机投影矩阵
    camera.updateProjectionMatrix()
})

const gui = new GUI()
// 实例化加载器
const gltfLoader = new GLTFLoader()
// 实例化解压器
const dracoLoader = new DRACOLoader()
// 设置draco路径
dracoLoader.setDecoderPath('./draco/')
// 设置gltf加载器解码
gltfLoader.setDRACOLoader(dracoLoader)
// 加载模型
gltfLoader.load('./model/city.glb', (gltf) => {
    
    
    scene.add(gltf.scene)
    gltf.scene.visible = false //需要线框就要隐藏掉原模型!!!!

    // let building = gltf.scene.children[0]
    // //必须是mesh对象!!!!!!!!
    // // console.log(gltf.scene.children instanceof THREE.Mesh)
    // let geometry = building.geometry
    // // 获取边缘geometry
    // let edgesGeometry = new THREE.WireframeGeometry(geometry)
    // // 创建线段材质
    // let edgesMaterial = new THREE.LineBasicMaterial({
    
    
    //     color: 'red',
    // })
    // //创建线段
    // let edges = new THREE.LineSegments(edgesGeometry, edgesMaterial)
    // // 更新建筑世界矩阵
    // building.updateWorldMatrix(true, true)
    // // 复制世界矩阵
    // edges.matrix.copy(building.matrixWorld)
    // // 同步世界矩阵
    // edges.matrix.decompose(edges.position, edges.quaternion, edges.scale)
    // // 添加到场景
    // scene.add(edges)

    gltf.scene.traverse((chil) => {
    
    
        if (chil.isMesh) {
    
    
            let geometry = chil.geometry
            // 获取边缘geometry
            // let edgesGeometry = new THREE.EdgesGeometry(geometry)
            let edgesMaterial = new THREE.LineBasicMaterial({
    
    
                color: 'red',
            })
            // 线框geometry
            let edgesGeometry = new THREE.WireframeGeometry(geometry)
            let edges = new THREE.LineSegments(edgesGeometry, edgesMaterial)
            // 更新建筑世界矩阵
            chil.updateWorldMatrix(true, true)
            // 复制世界矩阵
            edges.matrix.copy(chil.matrixWorld)
            // 同步世界矩阵
            edges.matrix.decompose(edges.position, edges.quaternion, edges.scale)
            // 添加到场景
            scene.add(edges)
        }
    })
})
</script>

到此进阶(四)学习告一段落,道阻且长,行则将至。与诸君共勉。 ⭐️