forked from Rowland/EG
150 lines
4.7 KiB
Markdown
150 lines
4.7 KiB
Markdown
# 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) ✓ 距离合理
|
||
```
|
||
|
||
## 技术实现
|
||
|
||
### 修复前的代码
|
||
```python
|
||
def _applyScaleNormalization(self, node, normalize_factor, depth=0):
|
||
# 只调整缩放
|
||
if max_scale_component > 10:
|
||
new_scale = current_scale * normalize_factor
|
||
node.setScale(new_scale)
|
||
# 位置保持不变 - 这是问题所在!
|
||
```
|
||
|
||
### 修复后的代码
|
||
```python
|
||
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. 位置测试脚本
|
||
```bash
|
||
cd demo
|
||
python scale_position_test.py
|
||
```
|
||
|
||
按T键运行完整的位置测试,检查:
|
||
- 缩放因子是否正确(100 → 1.0)
|
||
- 位置缩放是否正确(位置 × 0.01)
|
||
- 相对位置关系是否保持
|
||
|
||
### 2. FBX导入测试
|
||
```bash
|
||
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
|
||
|
||
### 同步调整规则
|
||
```python
|
||
# 对于每个需要标准化的节点
|
||
if max_scale_component > 10:
|
||
new_scale = current_scale * normalize_factor # 缩放调整
|
||
new_pos = current_pos * normalize_factor # 位置同步调整
|
||
```
|
||
|
||
## 配置选项
|
||
|
||
在`importModel`方法中提供灵活配置:
|
||
|
||
```python
|
||
# 推荐配置(默认)
|
||
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模型导入中的核心痛点。 |