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

如何在Three.js中避免父物体缩放时子物体变形?

解决Three.js父物体缩放时子物体变形的问题

问题描述

我开发的Three.js程序包含父物体和若干子物体,对父物体进行单维度或多维度缩放时,子物体会随之变形:

  • 缩放前效果:
    缩放前效果
  • 子物体变形示例:
    子物体变形示例

需求是父物体缩放时抵消子物体的缩放效果,但保留子物体跟随父物体移动的特性,因此无法解除父子关系。

之前尝试将子物体按1/父物体缩放比例反向缩放,但子物体尺寸过大且不准确,推测原因有两点:

  1. 父物体(6×9×1.75任意单位)与子物体原始尺寸比例不同,反向缩放公式需要额外参数调整
    • 按1/父缩放比例调整后的效果:
      按1/父缩放比例调整后的效果
  2. 可通过Blender(制作.glb模型的工具)或Three.js本身锁定子物体尺寸,但Blender中操作未成功。

解决方案

一、Three.js代码层面精确抵消缩放

要准确抵消父物体缩放对子物体的影响,需要结合父物体的当前缩放值和子物体的初始缩放/尺寸计算反向缩放比例,步骤如下:

  1. 模型加载完成后,记录子物体和父物体的初始缩放:
// 遍历所有子物体,存储初始缩放
parent.children.forEach(child => {
  child.userData.initialScale = child.scale.clone();
});
// 存储父物体初始缩放
parent.userData.initialScale = parent.scale.clone();
  1. 在父物体缩放变化时(比如渲染循环或缩放控制的回调中),实时更新子物体缩放:
function syncChildScale() {
  const parentScale = parent.scale;
  const parentInitial = parent.userData.initialScale;

  // 计算父物体各轴的缩放变化比例
  const scaleXRatio = parentScale.x / parentInitial.x;
  const scaleYRatio = parentScale.y / parentInitial.y;
  const scaleZRatio = parentScale.z / parentInitial.z;

  parent.children.forEach(child => {
    const initial = child.userData.initialScale;
    // 子物体反向缩放,抵消父物体缩放影响
    child.scale.set(
      initial.x / scaleXRatio,
      initial.y / scaleYRatio,
      initial.z / scaleZRatio
    );
  });
}

// 在渲染循环中调用,实时同步
function animate() {
  requestAnimationFrame(animate);
  syncChildScale();
  renderer.render(scene, camera);
}

这样处理后,子物体将始终保持原始尺寸,同时正常跟随父物体移动和旋转。

二、Blender模型层面设置

如果希望从模型源头上解决,在Blender中按以下步骤操作:

  • 选中子物体,进入物体模式,按Ctrl+A选择应用缩放,将子物体的缩放值重置为(1,1,1)
  • 打开右侧属性面板(N键),找到物体关系选项卡
  • 在继承变换区域,取消勾选缩放选项
  • 重复上述步骤处理所有子物体后,导出为.glb格式

导入Three.js后,父物体缩放时子物体不会继承缩放属性,但仍会跟随父物体移动,完美满足需求。如果之前操作失败,大概率是没先应用子物体的缩放就取消继承,导致缩放数据残留。

内容的提问来源于stack exchange,提问作者joo0k

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 21:36:26