如何在React Three Fiber中获取模型尺寸以调整另一模型?
在React Three Fiber中基于模型尺寸调整另一个模型大小的实现方法
要实现这个需求,核心是利用Three.js的包围盒(Bounding Box) API获取模型尺寸,再计算缩放比例应用到目标模型上。以下是具体步骤和代码示例:
1. 获取模型尺寸的核心方法
Three.js的几何体默认不会自动计算包围盒,需要手动调用computeBoundingBox()方法生成,之后通过boundingBox.getSize()提取尺寸数据。
2. 具体实现代码
方式一:直接修改几何体顶点(永久缩放)
这种方式会修改几何体的原始顶点数据,所有使用该几何体的网格都会应用此缩放:
import { useLoader, useEffect } from '@react-three/fiber' import { STLLoader } from 'three/addons/loaders/STLLoader.js' import * as THREE from 'three' function ModelScaler() { const geomUpper = useLoader(STLLoader, upperUrl) const geomLower = useLoader(STLLoader, lowerUrl) useEffect(() => { // 确保两个模型都加载完成 if (!geomUpper || !geomLower) return // 计算upper模型的尺寸 geomUpper.computeBoundingBox() const upperSize = new THREE.Vector3() geomUpper.boundingBox.getSize(upperSize) // 计算lower模型的尺寸 geomLower.computeBoundingBox() const lowerSize = new THREE.Vector3() geomLower.boundingBox.getSize(lowerSize) // 方案1:按各轴单独缩放(不保持模型原有比例) const scaleX = upperSize.x / lowerSize.x const scaleY = upperSize.y / lowerSize.y const scaleZ = upperSize.z / lowerSize.z // 方案2:等比例缩放(保持模型原有比例,取最小比例值) // const scaleRatio = Math.min(upperSize.x/lowerSize.x, upperSize.y/lowerSize.y, upperSize.z/lowerSize.z) // 应用缩放到lower几何体 geomLower.scale(scaleX, scaleY, scaleZ) // 等比例缩放则用:geomLower.scale(scaleRatio, scaleRatio, scaleRatio) // 标记顶点数据需要更新,让Three.js重新上传到GPU geomLower.attributes.position.needsUpdate = true }, [geomUpper, geomLower]) return ( <> <mesh geometry={geomUpper} /> <mesh geometry={geomLower} /> </> ) }
方式二:在网格级别设置缩放(仅视觉变换)
这种方式不会修改几何体本身,只是在渲染时应用缩放变换,更灵活:
import { useLoader, useEffect, useState } from '@react-three/fiber' import { STLLoader } from 'three/addons/loaders/STLLoader.js' import * as THREE from 'three' function ModelScaler() { const geomUpper = useLoader(STLLoader, upperUrl) const geomLower = useLoader(STLLoader, lowerUrl) const [lowerScale, setLowerScale] = useState([1, 1, 1]) useEffect(() => { if (!geomUpper || !geomLower) return geomUpper.computeBoundingBox() const upperSize = new THREE.Vector3() geomUpper.boundingBox.getSize(upperSize) geomLower.computeBoundingBox() const lowerSize = new THREE.Vector3() geomLower.boundingBox.getSize(lowerSize) // 计算缩放比例 const scaleX = upperSize.x / lowerSize.x const scaleY = upperSize.y / lowerSize.y const scaleZ = upperSize.z / lowerSize.z setLowerScale([scaleX, scaleY, scaleZ]) }, [geomUpper, geomLower]) return ( <> <mesh geometry={geomUpper} /> <mesh geometry={geomLower} scale={lowerScale} /> </> ) }
关键注意点
computeBoundingBox()必须调用:Three.js不会自动计算包围盒,不调用的话geomUpper.boundingBox会是null- 两种缩放方式的区别:
- 修改几何体:影响碰撞检测、射线投射等依赖顶点数据的功能
- 网格级别缩放:仅视觉效果,不改变原始几何体数据
needsUpdate = true:修改几何体顶点后必须标记,否则Three.js不会更新GPU中的数据
内容的提问来源于stack exchange,提问作者Mercyfon
相关产品推荐
相关产品推荐

