EG/demo/缩放位置修复说明.md
2025-07-10 09:19:51 +08:00

4.7 KiB
Raw Permalink Blame History

FBX模型缩放标准化位置修复说明

问题描述

在FBX模型导入时经常遇到子节点有大缩放值如100的问题。我们的缩放标准化功能可以将这些大缩放值调整为1但最初的实现存在一个重要问题只调整了缩放,没有相应调整位置,导致子节点之间的距离变得过大

问题分析

原始FBX结构示例

根节点 (缩放: 1.0, 位置: 0,0,0)
├── 子节点A (缩放: 100, 位置: 0,0,0)
├── 子节点B (缩放: 100, 位置: 60,5,320)  
└── 子节点C (缩放: 100, 位置: -16,-3,-347)

问题:仅缩放标准化

根节点 (缩放: 1.0, 位置: 0,0,0)
├── 子节点A (缩放: 1.0, 位置: 0,0,0)        ✓ 正常
├── 子节点B (缩放: 1.0, 位置: 60,5,320)     ✗ 距离过大!
└── 子节点C (缩放: 1.0, 位置: -16,-3,-347)  ✗ 距离过大!

问题根源原来在100倍缩放下(60,5,320)这样的位置是合理的因为视觉上的有效距离会被缩放影响。但当缩放变成1时这个位置就显得过大了。

解决方案

核心思路

当我们将子节点的缩放按比例缩小时,也要将它们的位置按相同比例缩小,以保持视觉上的相对关系。

修复后的标准化

根节点 (缩放: 1.0, 位置: 0,0,0)
├── 子节点A (缩放: 1.0, 位置: 0,0,0)      ✓ 正常
├── 子节点B (缩放: 1.0, 位置: 0.6,0.05,3.2)  ✓ 距离合理
└── 子节点C (缩放: 1.0, 位置: -0.16,-0.03,-3.47) ✓ 距离合理

技术实现

修复前的代码

def _applyScaleNormalization(self, node, normalize_factor, depth=0):
    # 只调整缩放
    if max_scale_component > 10:
        new_scale = current_scale * normalize_factor
        node.setScale(new_scale)
        # 位置保持不变 - 这是问题所在!

修复后的代码

def _applyScaleNormalization(self, node, normalize_factor, depth=0):
    # 同时调整缩放和位置
    if max_scale_component > 10:
        # 应用新的缩放
        new_scale = current_scale * normalize_factor
        node.setScale(new_scale)
        
        # 同时调整位置:保持视觉相对位置一致
        new_pos = current_pos * normalize_factor
        node.setPos(new_pos)

效果对比

修复前

  • 缩放值正确100 → 1.0
  • 子节点距离过大(几百个单位)
  • 视觉布局异常

修复后

  • 缩放值正确100 → 1.0
  • 子节点距离合理(几个单位)
  • 视觉布局保持原有比例关系

测试验证

使用测试脚本验证修复效果:

1. 位置测试脚本

cd demo
python scale_position_test.py

按T键运行完整的位置测试检查

  • 缩放因子是否正确100 → 1.0
  • 位置缩放是否正确(位置 × 0.01
  • 相对位置关系是否保持

2. FBX导入测试

cd demo
python fbx_import_test.py

导入实际的FBX文件使用I键查看模型信息确认

  • 子节点缩放标准化为1.0
  • 子节点位置为合理数值
  • 整体视觉效果正常

算法详解

标准化因子计算

  1. 收集缩放信息:递归扫描所有节点的缩放值
  2. 识别大缩放:找出缩放值 > 10 的节点
  3. 统计最常见值使用Counter找到最频繁的大缩放值如100
  4. 计算标准化因子normalize_factor = 1.0 / common_large_scale

同步调整规则

# 对于每个需要标准化的节点
if max_scale_component > 10:
    new_scale = current_scale * normalize_factor  # 缩放调整
    new_pos = current_pos * normalize_factor      # 位置同步调整

配置选项

importModel方法中提供灵活配置:

# 推荐配置(默认)
world.importModel("model.fbx", 
                 apply_unit_conversion=False,    # 不使用传统单位转换
                 normalize_scales=True)         # 使用智能缩放标准化

# 传统配置
world.importModel("model.fbx",
                 apply_unit_conversion=True,     # 使用传统0.01根缩放
                 normalize_scales=False)        # 不使用智能标准化

# 完全保持原始
world.importModel("model.fbx",
                 apply_unit_conversion=False,    # 不转换
                 normalize_scales=False)        # 不标准化

总结

这个修复解决了FBX模型缩放标准化时的关键问题

  1. 保持视觉一致性:子节点之间的相对位置关系不变
  2. 简化层级结构:避免复杂的缩放层级组合
  3. 提高易用性:导入后的模型结构直观易懂
  4. 兼容性好:不影响现有功能,提供可选配置

这确保了"一键导入,完美显示"的用户体验解决了FBX模型导入中的核心痛点。