优化导入模型设置碰撞体的位置及大小与模型相对应
This commit is contained in:
parent
85f61bd78a
commit
e1b4731443
@ -14,7 +14,7 @@ from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QTreeWidgetItem
|
||||
from panda3d.core import (
|
||||
ModelPool, ModelRoot, Filename, NodePath, GeomNode, Material, Vec4, Vec3,
|
||||
MaterialAttrib, ColorAttrib, Point3, CollisionNode, CollisionSphere,
|
||||
MaterialAttrib, ColorAttrib, Point3, CollisionNode, CollisionSphere, CollisionBox,
|
||||
BitMask32, TransparencyAttrib, LColor, TransformState, RenderModeAttrib
|
||||
)
|
||||
import json
|
||||
@ -164,7 +164,7 @@ class SceneManager:
|
||||
#self._adjustModelToGround(model)
|
||||
|
||||
# 创建并设置基础材质
|
||||
print("\n=== 开始设置材质 ===")
|
||||
#print("\n=== 开始设置材质 ===")
|
||||
#self._applyMaterialsToModel(model)
|
||||
|
||||
# 设置碰撞检测(重要!用于选择功能)
|
||||
@ -718,7 +718,6 @@ class SceneManager:
|
||||
def setupCollision(self, model):
|
||||
"""为模型设置碰撞检测(增强版本)"""
|
||||
try:
|
||||
|
||||
# 创建碰撞节点
|
||||
cNode = CollisionNode(f'modelCollision_{model.getName()}')
|
||||
|
||||
@ -734,39 +733,61 @@ class SceneManager:
|
||||
cNode.setIntoCollideMask(current_mask | model_collision_mask)
|
||||
print(f"为 {model.getName()} 启用模型间碰撞检测")
|
||||
|
||||
# 获取模型的边界
|
||||
bounds = model.getBounds()
|
||||
if bounds.isEmpty():
|
||||
print(f"⚠️ 模型 {model.getName()} 边界为空,使用默认碰撞体")
|
||||
# 使用默认的小球体
|
||||
cSphere = CollisionSphere(Point3(0, 0, 0), 1.0)
|
||||
else:
|
||||
center = bounds.getCenter()
|
||||
radius = bounds.getRadius()
|
||||
|
||||
# 确保半径不为零
|
||||
if radius <= 0:
|
||||
# 获取模型的边界信息,使用与选择框相同的计算方法
|
||||
minPoint = Point3()
|
||||
maxPoint = Point3()
|
||||
|
||||
# 使用与选择框相同的calcTightBounds方法获取边界
|
||||
if model.calcTightBounds(minPoint, maxPoint, self.world.render):
|
||||
# 检查边界框的有效性
|
||||
if (abs(minPoint.x) < 1e10 and abs(minPoint.y) < 1e10 and abs(minPoint.z) < 1e10 and
|
||||
abs(maxPoint.x) < 1e10 and abs(maxPoint.y) < 1e10 and abs(maxPoint.z) < 1e10):
|
||||
# 特殊处理FBX模型的碰撞体
|
||||
if model.hasTag("model_path") and model.getTag("model_path").lower().endswith('.fbx'):
|
||||
print("检测到FBX模型,调整碰撞体...")
|
||||
# 反向应用FBX的变换以匹配视觉表现
|
||||
# 缩放调整: 乘以100(因为模型被缩小了0.01倍)
|
||||
minPoint *= 100
|
||||
maxPoint *= 100
|
||||
|
||||
# 旋转调整: 绕P轴旋转-90度
|
||||
# 创建旋转矩阵
|
||||
from panda3d.core import Mat4, LRotation
|
||||
rotation = LRotation(0, -90, 0) # 绕P轴旋转-90度
|
||||
rot_matrix = Mat4()
|
||||
rotation.extractToMatrix(rot_matrix)
|
||||
|
||||
# 应用旋转变换到边界点
|
||||
minPoint = rot_matrix.xformPoint(minPoint)
|
||||
maxPoint = rot_matrix.xformPoint(maxPoint)
|
||||
|
||||
# 创建与选择框完全一致的碰撞体
|
||||
cBox = CollisionBox(minPoint, maxPoint)
|
||||
cNode.addSolid(cBox)
|
||||
radius = max(maxPoint.x - minPoint.x, maxPoint.y - minPoint.y, maxPoint.z - minPoint.z) / 2
|
||||
else:
|
||||
# 使用默认球体
|
||||
radius = 1.0
|
||||
print(f"⚠️ 模型 {model.getName()} 半径为零,使用默认半径 1.0")
|
||||
#
|
||||
# # 添加碰撞球体
|
||||
# cSphere = CollisionSphere(center, radius)
|
||||
cSphere = self.world.collision_manager.createCollisionShape(model, 'polygon')
|
||||
|
||||
cNode.addSolid(cSphere)
|
||||
cSphere = CollisionSphere(Point3(0, 0, 0), radius)
|
||||
cNode.addSolid(cSphere)
|
||||
else:
|
||||
# 使用默认球体
|
||||
radius = 1.0
|
||||
cSphere = CollisionSphere(Point3(0, 0, 0), radius)
|
||||
cNode.addSolid(cSphere)
|
||||
|
||||
# 将碰撞节点附加到模型上
|
||||
cNodePath = model.attachNewNode(cNode)
|
||||
|
||||
# 根据调试设置决定是否显示碰撞体
|
||||
if hasattr(self.world, 'debug_collision') and self.world.debug_collision:
|
||||
cNodePath.hide()
|
||||
else:
|
||||
cNodePath.hide()
|
||||
# if hasattr(self.world, 'debug_collision') and self.world.debug_collision:
|
||||
# cNodePath.show()
|
||||
# else:
|
||||
# cNodePath.hide()
|
||||
|
||||
# 为模型添加碰撞相关标签
|
||||
model.setTag("has_collision", "true")
|
||||
model.setTag("collision_radius", str(radius if 'radius' in locals() else 1.0))
|
||||
model.setTag("collision_radius", str(radius))
|
||||
|
||||
print(f"✅ 为模型 {model.getName()} 设置碰撞检测完成")
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user