本篇主要学习内容 :
- 多物体包围盒
- 边缘几何体
- 线框几何体
点赞 + 关注 + 收藏 = 学会了
上一节学习了物体的包围盒与包围球,这一节在此基础上学习多个物体的包围盒,及两个新的几何体,易错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>
到此进阶(四)学习告一段落,道阻且长,行则将至。与诸君共勉。 ⭐️