EG/demo/FBX缩放层级修复说明.md
2025-12-12 16:16:15 +08:00

6.9 KiB
Raw Blame History

FBX模型缩放层级修复说明

🔍 问题描述

用户反馈FBX模型导入时会出现缩放层级混乱的问题

  • 根节点缩放: 0.01(强制应用的单位转换)
  • 子节点缩放: 100FBX内部的原始缩放
  • 视觉效果: 正常显示,但层级结构复杂难处理

问题原因分析

原始导入逻辑

# 旧代码 - 强制FBX单位转换
if filepath.lower().endswith('.fbx'):
    scale_factor = 0.01  # 厘米到米
    model.setScale(scale_factor)  # 根节点 = 0.01

层级结构混乱

FBX模型结构:
├─ 根节点 (setScale 0.01)          ← 强制设置
│  ├─ 子节点A (原始缩放 100)       ← FBX内部缩放
│  ├─ 子节点B (原始缩放 100)       ← FBX内部缩放
│  └─ 子节点C (原始缩放 50)        ← FBX内部缩放

结果: 0.01 × 100 = 1.0 (正常显示,但层级复杂)

🛠 解决方案

1. 新的导入逻辑

def importModel(self, filepath, apply_unit_conversion=False, normalize_scales=True):
    """新的导入方法 - 智能缩放处理"""
    
    # 可选: 单位转换
    if apply_unit_conversion and filepath.lower().endswith('.fbx'):
        self._applyUnitConversion(model, 0.01)
    
    # 智能: 缩放标准化(推荐开启)
    if normalize_scales and filepath.lower().endswith('.fbx'):
        self._normalizeModelScales(model)
    
    # 只调整位置,不强制缩放
    self._adjustModelToGround(model)

2. 智能缩放标准化

新增核心功能自动检测和处理FBX子节点的大缩放值

  • 🔍 自动检测: 扫描所有子节点,识别大缩放值(>10
  • 📊 统计分析: 找到最常见的大缩放值如100
  • ⚙️ 智能标准化: 计算合适的标准化因子如1/100 = 0.01
  • 🎯 精确应用: 只处理有问题的大缩放节点

2. 保持原有结构的优势

  • 简化层级: 避免0.01 × 100的复杂计算
  • 保持一致: 所有文件格式统一处理
  • 用户选择: 可选择是否应用单位转换
  • 易于处理: 缩放操作更直观

📊 修复对比

修复前

# 强制FBX单位转换
FBX根节点.setScale(0.01)

层级结构:
根节点(0.01) -> 子节点A(100) -> 孙子节点(1)
实际显示: 0.01 × 100 × 1 = 1.0 视觉正常
处理复杂度: 复杂需要考虑多层缩放

修复后

# 智能缩放标准化(推荐)
model.importModel(filepath, normalize_scales=True)

层级结构:
根节点(1.0) -> 子节点A(1.0) -> 孙子节点(1.0)  
实际显示: 1.0 × 1.0 × 1.0 = 1.0 完美
处理复杂度: 简单统一缩放层级

# 或者保持原始结构
model.importModel(filepath, normalize_scales=False)

层级结构:
根节点(1.0) -> 子节点A(100) -> 孙子节点(1)  
实际显示: 1.0 × 100 × 1 = 100 ⚠️可能很大
处理复杂度: 简单但需要手动调整

🎛 使用方式

方式1: 智能导入(推荐)

# 默认开启缩放标准化,自动处理子节点大缩放值
model = world.importModel("model.fbx")  # normalize_scales=True

方式2: 完全保持原始结构

# 关闭所有自动处理保持FBX原始结构
model = world.importModel("model.fbx", normalize_scales=False)

方式3: 传统单位转换

# 应用厘米到米的转换 + 缩放标准化
model = world.importModel("model.fbx", apply_unit_conversion=True, normalize_scales=True)

方式4: 交互式测试

# 使用测试脚本
python demo/fbx_import_test.py
# 按U键切换单位转换模式
# 按N键切换缩放标准化模式

🧪 测试验证

测试场景

  1. 大型建筑模型: 通常FBX使用厘米模型会很大
  2. 角色模型: 通常已经合适的比例
  3. 道具模型: 混合使用情况

验证方法

# 启动测试程序
python demo/fbx_import_test.py

# 测试步骤:
1. 导入FBX模型默认保持原有缩放
2. 按I键查看缩放信息
3. 按U键切换单位转换模式
4. 重新导入同一模型对比
5. 观察层级结构差异

🎯 智能位置调整

地面对齐算法

def _adjustModelToGround(self, model):
    """智能调整到地面,不改变缩放"""
    bounds = model.getBounds()
    min_point = bounds.getMin()
    
    # 计算地面偏移(不涉及缩放)
    ground_offset = -min_point.getZ()
    model.setPos(0, 0, ground_offset)

优势

  • 🎯 精确对齐: 无论模型大小都能准确放在地面
  • 🔄 缩放无关: 位置调整独立于缩放操作
  • 🛡 错误处理: 边界获取失败时使用默认位置

📋 最佳实践建议

推荐工作流程

  1. 首次导入: 使用默认设置(不转换单位)
  2. 检查大小: 如果模型过大,考虑单位转换
  3. 手动调整: 根据需要手动设置合适的缩放
  4. 保存设置: 记录适合项目的导入参数

针对不同模型类型

模型类型 推荐设置 说明
建筑/场景 单位转换=True 通常用厘米,需要转换
角色/动物 单位转换=False 通常已合适比例
道具/物品 按情况选择 根据实际大小决定
机械设备 单位转换=True CAD导出常用厘米

调试技巧

# 检查模型层级结构
def print_model_hierarchy(model, depth=0):
    indent = "  " * depth
    print(f"{indent}{model.getName()}: scale={model.getScale()}")
    for i in range(model.getNumChildren()):
        print_model_hierarchy(model.getChild(i), depth+1)

🚀 总结

这次修复彻底解决了FBX导入时的缩放层级问题

🎯 核心突破

  • 智能标准化: 自动检测并修复子节点大缩放值如100 → 1
  • 统一层级: 实现全模型1:1缩放避免复杂的多层计算
  • 保持结构: 维护FBX内部的相对比例关系
  • 零干扰: 只处理有问题的节点,不影响正常节点

🔧 技术优势

  • 🔍 智能检测: 自动扫描识别大缩放值
  • 📊 统计分析: 基于最常见缩放值计算标准化因子
  • ⚙️ 精确处理: 只标准化明显异常的缩放(>10
  • 🎛️ 用户控制: 提供完整的开关选项

📈 效果对比

处理方式 根节点缩放 子节点缩放 最终效果 推荐度
旧方案 0.01 100 复杂层级
关闭处理 1.0 100 模型过大 ⚠️
智能标准化 1.0 1.0 完美统一

现在用户可以简单地导入FBX模型系统会自动处理所有缩放问题实现真正的"一键导入,完美显示"