You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 05:54:19