359 lines
11 KiB
Python
359 lines
11 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
|
||
"""
|
||
选择框边界测试脚本
|
||
|
||
测试保存和加载场景后选择框是否正常显示
|
||
"""
|
||
|
||
import sys
|
||
import os
|
||
import tempfile
|
||
import shutil
|
||
|
||
# 添加项目路径
|
||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||
|
||
from main import MyWorld
|
||
from PyQt5.QtWidgets import QApplication
|
||
|
||
def test_selection_bounds():
|
||
"""测试选择框边界问题"""
|
||
|
||
print("=== 选择框边界测试 ===\n")
|
||
|
||
# 创建应用程序
|
||
app = QApplication.instance()
|
||
if app is None:
|
||
app = QApplication(sys.argv)
|
||
|
||
# 创建世界
|
||
world = MyWorld()
|
||
|
||
return test_selection_bounds_with_world(world)
|
||
|
||
def test_selection_bounds_with_world(world):
|
||
"""使用提供的world实例测试选择框边界问题"""
|
||
|
||
print("=== 选择框边界测试 ===\n")
|
||
|
||
# 清理之前的测试数据
|
||
world.models.clear()
|
||
for child in world.render.getChildren():
|
||
if child.getName() in ["test_cube", "fbx_model", "selectionBox", "gizmo"]:
|
||
child.removeNode()
|
||
|
||
print("1. 创建测试模型...")
|
||
|
||
# 创建一个简单的测试立方体
|
||
from panda3d.core import CardMaker
|
||
cm = CardMaker("test_cube")
|
||
cm.setFrame(-1, 1, -1, 1)
|
||
|
||
# 创建立方体的6个面(使用ModelRoot确保保存/加载正常)
|
||
from panda3d.core import ModelRoot
|
||
model_root = ModelRoot("test_cube")
|
||
cube = world.render.attachNewNode(model_root)
|
||
|
||
# 前面
|
||
front = cube.attachNewNode(cm.generate())
|
||
front.setP(-90)
|
||
front.setZ(1)
|
||
front.setColor(1, 0, 0, 1)
|
||
|
||
# 后面
|
||
back = cube.attachNewNode(cm.generate())
|
||
back.setP(-90)
|
||
back.setZ(-1)
|
||
back.setColor(0, 1, 0, 1)
|
||
|
||
# 设置测试缩放(模拟FBX导入后的状态)
|
||
cube.setScale(0.5, 0.5, 0.5)
|
||
cube.setPos(2, 0, 1)
|
||
|
||
# 设置碰撞检测
|
||
world.scene_manager.setupCollision(cube)
|
||
|
||
# 添加到模型列表
|
||
world.models.append(cube)
|
||
cube.setTag("file", "test_cube.fbx")
|
||
cube.setTag("is_model_root", "1")
|
||
|
||
print("✓ 测试模型创建完成")
|
||
print(f" 位置: {cube.getPos()}")
|
||
print(f" 缩放: {cube.getScale()}")
|
||
print(f" 边界: {cube.getBounds().getMin()} 到 {cube.getBounds().getMax()}")
|
||
|
||
print("\n2. 测试选择功能...")
|
||
|
||
# 选择模型
|
||
world.selection.updateSelection(cube)
|
||
|
||
# 获取原始选择框信息
|
||
original_bounds = cube.getBounds()
|
||
original_pos = cube.getPos()
|
||
original_scale = cube.getScale()
|
||
|
||
print(f" 原始边界: {original_bounds.getMin()} 到 {original_bounds.getMax()}")
|
||
print(f" 原始位置: {original_pos}")
|
||
print(f" 原始缩放: {original_scale}")
|
||
|
||
print("\n3. 保存场景...")
|
||
|
||
# 创建临时文件
|
||
temp_dir = tempfile.mkdtemp(prefix="bounds_test_")
|
||
scene_file = os.path.join(temp_dir, "test_scene.bam")
|
||
|
||
try:
|
||
# 保存场景
|
||
success = world.scene_manager.saveScene(scene_file)
|
||
if success:
|
||
print("✓ 场景保存成功")
|
||
else:
|
||
print("✗ 场景保存失败")
|
||
return False
|
||
|
||
print("\n4. 重新加载场景...")
|
||
|
||
# 加载场景
|
||
success = world.scene_manager.loadScene(scene_file)
|
||
if success:
|
||
print("✓ 场景加载成功")
|
||
else:
|
||
print("✗ 场景加载失败")
|
||
return False
|
||
|
||
print("\n5. 检查加载后的模型状态...")
|
||
|
||
if not world.models:
|
||
print("✗ 加载后没有找到模型")
|
||
return False
|
||
|
||
loaded_model = world.models[0]
|
||
loaded_bounds = loaded_model.getBounds()
|
||
loaded_pos = loaded_model.getPos()
|
||
loaded_scale = loaded_model.getScale()
|
||
|
||
print(f" 加载后边界: {loaded_bounds.getMin()} 到 {loaded_bounds.getMax()}")
|
||
print(f" 加载后位置: {loaded_pos}")
|
||
print(f" 加载后缩放: {loaded_scale}")
|
||
|
||
print("\n6. 比较结果...")
|
||
|
||
# 检查位置是否一致
|
||
pos_diff = (loaded_pos - original_pos).length()
|
||
scale_diff = (loaded_scale - original_scale).length()
|
||
|
||
print(f" 位置差异: {pos_diff}")
|
||
print(f" 缩放差异: {scale_diff}")
|
||
|
||
# 检查边界大小
|
||
original_size = (original_bounds.getMax() - original_bounds.getMin()).length()
|
||
loaded_size = (loaded_bounds.getMax() - loaded_bounds.getMin()).length()
|
||
size_diff = abs(loaded_size - original_size)
|
||
|
||
print(f" 原始边界大小: {original_size:.3f}")
|
||
print(f" 加载后边界大小: {loaded_size:.3f}")
|
||
print(f" 边界大小差异: {size_diff:.3f}")
|
||
|
||
print("\n7. 测试选择框...")
|
||
|
||
# 选择加载后的模型
|
||
world.selection.updateSelection(loaded_model)
|
||
|
||
# 检查选择框是否创建成功
|
||
if world.selection.selectionBox:
|
||
print("✓ 选择框创建成功")
|
||
else:
|
||
print("✗ 选择框创建失败")
|
||
return False
|
||
|
||
print("\n=== 测试结果 ===")
|
||
|
||
success = True
|
||
|
||
if pos_diff < 0.01:
|
||
print("✓ 位置信息正确恢复")
|
||
else:
|
||
print("✗ 位置信息恢复有误")
|
||
success = False
|
||
|
||
if scale_diff < 0.01:
|
||
print("✓ 缩放信息正确恢复")
|
||
else:
|
||
print("✗ 缩放信息恢复有误")
|
||
success = False
|
||
|
||
if size_diff < 0.1:
|
||
print("✓ 边界大小正常")
|
||
else:
|
||
print("✗ 边界大小异常")
|
||
success = False
|
||
|
||
if success:
|
||
print("\n🎉 选择框边界测试通过!")
|
||
print("保存和加载后选择框显示正常。")
|
||
else:
|
||
print("\n❌ 选择框边界测试失败。")
|
||
print("需要进一步检查变换信息的保存和恢复。")
|
||
|
||
return success
|
||
|
||
except Exception as e:
|
||
print(f"测试过程中出现错误: {str(e)}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
finally:
|
||
# 清理临时文件
|
||
try:
|
||
shutil.rmtree(temp_dir)
|
||
print(f"\n清理临时文件: {temp_dir}")
|
||
except Exception as e:
|
||
print(f"清理临时文件失败: {str(e)}")
|
||
|
||
def test_fbx_simulation(world=None):
|
||
"""模拟FBX模型的缩放标准化情况"""
|
||
|
||
print("\n=== FBX缩放标准化测试 ===\n")
|
||
|
||
# 重用现有的world实例,避免ShowBase冲突
|
||
if world is None:
|
||
# 创建应用程序
|
||
app = QApplication.instance()
|
||
if app is None:
|
||
app = QApplication(sys.argv)
|
||
|
||
# 创建世界
|
||
world = MyWorld()
|
||
else:
|
||
# 清理之前的测试数据
|
||
world.models.clear()
|
||
for child in world.render.getChildren():
|
||
if child.getName() in ["test_cube", "fbx_model", "selectionBox", "gizmo"]:
|
||
child.removeNode()
|
||
|
||
print("1. 创建模拟FBX模型(大缩放值)...")
|
||
|
||
# 创建一个模拟FBX导入的模型结构
|
||
from panda3d.core import CardMaker, ModelRoot
|
||
|
||
# 创建根节点(使用ModelRoot确保保存/加载正常)
|
||
model_root_node = ModelRoot("fbx_model")
|
||
model_root = world.render.attachNewNode(model_root_node)
|
||
|
||
# 创建子节点,模拟FBX的大缩放值
|
||
child_node = model_root.attachNewNode("mesh_node")
|
||
child_node.setScale(100, 100, 100) # 模拟FBX的厘米到米转换问题
|
||
|
||
# 创建几何体
|
||
cm = CardMaker("geometry")
|
||
cm.setFrame(-0.01, 0.01, -0.01, 0.01) # 很小的几何体,配合大缩放
|
||
geom = child_node.attachNewNode(cm.generate())
|
||
geom.setColor(0, 0, 1, 1)
|
||
|
||
# 应用标准化(模拟导入时的处理)
|
||
print("2. 应用缩放标准化...")
|
||
normalize_factor = 0.01 # 1/100
|
||
child_node.setScale(child_node.getScale() * normalize_factor)
|
||
child_node.setPos(child_node.getPos() * normalize_factor)
|
||
|
||
print(f" 标准化后缩放: {child_node.getScale()}")
|
||
print(f" 标准化后位置: {child_node.getPos()}")
|
||
|
||
# 设置模型根的标准变换
|
||
model_root.setPos(0, 5, 0)
|
||
model_root.setScale(2, 2, 2)
|
||
|
||
# 设置碰撞检测
|
||
world.scene_manager.setupCollision(model_root)
|
||
|
||
# 添加到模型列表
|
||
world.models.append(model_root)
|
||
model_root.setTag("file", "test_fbx.fbx")
|
||
model_root.setTag("is_model_root", "1")
|
||
model_root.setTag("scale_normalization_applied", "true")
|
||
|
||
print(f" 模型根位置: {model_root.getPos()}")
|
||
print(f" 模型根缩放: {model_root.getScale()}")
|
||
print(f" 模型边界: {model_root.getBounds().getMin()} 到 {model_root.getBounds().getMax()}")
|
||
|
||
# 继续使用与前面测试相同的流程
|
||
print("\n3. 保存和加载测试...")
|
||
|
||
# 创建临时文件
|
||
temp_dir = tempfile.mkdtemp(prefix="fbx_bounds_test_")
|
||
scene_file = os.path.join(temp_dir, "fbx_test_scene.bam")
|
||
|
||
try:
|
||
# 保存场景
|
||
world.scene_manager.saveScene(scene_file)
|
||
|
||
# 记录原始状态
|
||
original_bounds = model_root.getBounds()
|
||
original_pos = model_root.getPos()
|
||
original_scale = model_root.getScale()
|
||
|
||
# 重新加载
|
||
world.scene_manager.loadScene(scene_file)
|
||
|
||
# 检查结果
|
||
if world.models:
|
||
loaded_model = world.models[0]
|
||
loaded_bounds = loaded_model.getBounds()
|
||
loaded_pos = loaded_model.getPos()
|
||
loaded_scale = loaded_model.getScale()
|
||
|
||
print(f" 原始边界大小: {(original_bounds.getMax() - original_bounds.getMin()).length():.3f}")
|
||
print(f" 加载后边界大小: {(loaded_bounds.getMax() - loaded_bounds.getMin()).length():.3f}")
|
||
|
||
pos_diff = (loaded_pos - original_pos).length()
|
||
scale_diff = (loaded_scale - original_scale).length()
|
||
|
||
print(f" 位置差异: {pos_diff:.6f}")
|
||
print(f" 缩放差异: {scale_diff:.6f}")
|
||
|
||
if pos_diff < 0.01 and scale_diff < 0.01:
|
||
print("✓ FBX模拟测试通过")
|
||
return True
|
||
else:
|
||
print("✗ FBX模拟测试失败")
|
||
return False
|
||
else:
|
||
print("✗ 加载后没有找到模型")
|
||
return False
|
||
|
||
finally:
|
||
# 清理临时文件
|
||
try:
|
||
shutil.rmtree(temp_dir)
|
||
except:
|
||
pass
|
||
|
||
if __name__ == "__main__":
|
||
print("选择框边界问题测试\n")
|
||
|
||
# 创建应用程序
|
||
app = QApplication.instance()
|
||
if app is None:
|
||
app = QApplication(sys.argv)
|
||
|
||
# 创建世界(只创建一次)
|
||
world = MyWorld()
|
||
|
||
# 运行基础测试
|
||
test1_result = test_selection_bounds_with_world(world)
|
||
|
||
# 运行FBX模拟测试
|
||
test2_result = test_fbx_simulation(world)
|
||
|
||
print(f"\n=== 最终测试结果 ===")
|
||
print(f"基础边界测试: {'通过' if test1_result else '失败'}")
|
||
print(f"FBX模拟测试: {'通过' if test2_result else '失败'}")
|
||
|
||
if test1_result and test2_result:
|
||
print("\n🎉 所有测试通过!选择框边界问题已修复。")
|
||
else:
|
||
print("\n❌ 部分测试失败,需要进一步调试。") |