Merge remote-tracking branch 'origin/main_ch_eg' into addRender
# Conflicts: # ui/property_panel.py
This commit is contained in:
commit
e62ae89289
@ -309,51 +309,81 @@ class CollisionManager:
|
|||||||
CollisionPlane, CollisionPolygon, Plane, Vec3
|
CollisionPlane, CollisionPolygon, Plane, Vec3
|
||||||
)
|
)
|
||||||
|
|
||||||
bounds = model.getBounds()
|
# 获取考虑变换后的实际尺寸和中心
|
||||||
if bounds.isEmpty():
|
transformed_info = self._getTransformedModelInfo(model)
|
||||||
|
if not transformed_info:
|
||||||
# 默认小球体
|
# 默认小球体
|
||||||
return CollisionSphere(Point3(0, 0, 0), 1.0)
|
return CollisionSphere(Point3(0, 0, 0), 1.0)
|
||||||
|
|
||||||
center = bounds.getCenter()
|
center = transformed_info['center']
|
||||||
radius = bounds.getRadius()
|
radius = transformed_info['radius']
|
||||||
|
actual_size = transformed_info['size']
|
||||||
|
scale_factor = transformed_info['scale_factor']
|
||||||
|
|
||||||
# 自动选择最适合的形状
|
# 自动选择最适合的形状
|
||||||
if shape_type == 'auto':
|
if shape_type == 'auto':
|
||||||
shape_type = self._determineOptimalShape(model, bounds)
|
shape_type = self._determineOptimalShape(model, transformed_info)
|
||||||
|
|
||||||
if shape_type == 'sphere':
|
if shape_type == 'sphere':
|
||||||
return CollisionSphere(center, kwargs.get('radius', radius))
|
# 优化球形碰撞体
|
||||||
|
sphere_radius = kwargs.get('radius', radius)
|
||||||
|
|
||||||
|
# 支持位置偏移
|
||||||
|
pos_offset = kwargs.get('position_offset', Vec3(0, 0, 0))
|
||||||
|
sphere_center = Point3(center.x + pos_offset.x, center.y + pos_offset.y, center.z + pos_offset.z)
|
||||||
|
|
||||||
|
return CollisionSphere(sphere_center, sphere_radius)
|
||||||
|
|
||||||
elif shape_type == 'box':
|
elif shape_type == 'box':
|
||||||
# 创建自定义尺寸的包围盒
|
# 优化盒型碰撞体 - 更精确的尺寸和位置控制(考虑缩放)
|
||||||
width = kwargs.get('width', bounds.getMax().x - bounds.getMin().x)
|
# 获取自定义尺寸,如果没有提供则使用变换后的实际尺寸
|
||||||
length = kwargs.get('length', bounds.getMax().y - bounds.getMin().y)
|
width = kwargs.get('width', actual_size.x)
|
||||||
height = kwargs.get('height', bounds.getMax().z - bounds.getMin().z)
|
length = kwargs.get('length', actual_size.y)
|
||||||
|
height = kwargs.get('height', actual_size.z)
|
||||||
|
|
||||||
# 计算盒子的最小和最大点
|
# 支持位置偏移
|
||||||
|
pos_offset = kwargs.get('position_offset', Vec3(0, 0, 0))
|
||||||
|
box_center = Point3(center.x + pos_offset.x, center.y + pos_offset.y, center.z + pos_offset.z)
|
||||||
|
|
||||||
|
# 计算盒子的最小和最大点(基于偏移后的中心)
|
||||||
half_width = width / 2
|
half_width = width / 2
|
||||||
half_length = length / 2
|
half_length = length / 2
|
||||||
half_height = height / 2
|
half_height = height / 2
|
||||||
|
|
||||||
min_point = Point3(center.x - half_width, center.y - half_length, center.z - half_height)
|
min_point = Point3(box_center.x - half_width, box_center.y - half_length, box_center.z - half_height)
|
||||||
max_point = Point3(center.x + half_width, center.y + half_length, center.z + half_height)
|
max_point = Point3(box_center.x + half_width, box_center.y + half_length, box_center.z + half_height)
|
||||||
return CollisionBox(min_point, max_point)
|
return CollisionBox(min_point, max_point)
|
||||||
|
|
||||||
elif shape_type == 'capsule':
|
elif shape_type == 'capsule':
|
||||||
# 创建自定义参数的胶囊体
|
# 优化胶囊体碰撞 - 更合理的比例和位置控制(考虑缩放)
|
||||||
custom_height = kwargs.get('height', (bounds.getMax().z - bounds.getMin().z))
|
# 使用变换后的实际高度,或自定义高度
|
||||||
custom_radius = kwargs.get('radius', min(bounds.getRadius() * 0.5, custom_height * 0.3))
|
custom_height = kwargs.get('height', actual_size.z)
|
||||||
|
|
||||||
# 计算胶囊体的两个端点
|
# 更合理的半径计算:基于变换后模型宽度的平均值
|
||||||
point_a = Point3(center.x, center.y, center.z - custom_height/2 + custom_radius)
|
default_radius = min(actual_size.x, actual_size.y) / 2.5 # 稍微小于模型的宽度
|
||||||
point_b = Point3(center.x, center.y, center.z + custom_height/2 - custom_radius)
|
custom_radius = kwargs.get('radius', min(default_radius, custom_height * 0.4))
|
||||||
|
|
||||||
|
# 支持位置偏移
|
||||||
|
pos_offset = kwargs.get('position_offset', Vec3(0, 0, 0))
|
||||||
|
capsule_center = Point3(center.x + pos_offset.x, center.y + pos_offset.y, center.z + pos_offset.z)
|
||||||
|
|
||||||
|
# 计算胶囊体的两个端点(确保半径不会超出高度)
|
||||||
|
effective_height = max(custom_height, custom_radius * 2.1) # 确保高度至少是半径的2倍多一点
|
||||||
|
point_a = Point3(capsule_center.x, capsule_center.y, capsule_center.z - effective_height/2 + custom_radius)
|
||||||
|
point_b = Point3(capsule_center.x, capsule_center.y, capsule_center.z + effective_height/2 - custom_radius)
|
||||||
return CollisionCapsule(point_a, point_b, custom_radius)
|
return CollisionCapsule(point_a, point_b, custom_radius)
|
||||||
|
|
||||||
elif shape_type == 'plane':
|
elif shape_type == 'plane':
|
||||||
# 创建平面(适合地面、墙面)
|
# 优化平面碰撞 - 支持位置偏移和更灵活的法向量
|
||||||
normal = kwargs.get('normal', Vec3(0, 0, 1))
|
normal = kwargs.get('normal', Vec3(0, 0, 1))
|
||||||
point = kwargs.get('point', center)
|
|
||||||
plane = Plane(normal, point)
|
# 支持位置偏移
|
||||||
|
pos_offset = kwargs.get('position_offset', Vec3(0, 0, 0))
|
||||||
|
plane_point = kwargs.get('point', Point3(center.x + pos_offset.x, center.y + pos_offset.y, center.z + pos_offset.z))
|
||||||
|
|
||||||
|
# 标准化法向量
|
||||||
|
normal.normalize()
|
||||||
|
plane = Plane(normal, plane_point)
|
||||||
return CollisionPlane(plane)
|
return CollisionPlane(plane)
|
||||||
|
|
||||||
elif shape_type == 'polygon':
|
elif shape_type == 'polygon':
|
||||||
@ -378,10 +408,10 @@ class CollisionManager:
|
|||||||
#print("⚠️ 多边形至少需要3个顶点,回退到球体")
|
#print("⚠️ 多边形至少需要3个顶点,回退到球体")
|
||||||
return CollisionSphere(center, radius)
|
return CollisionSphere(center, radius)
|
||||||
|
|
||||||
def _determineOptimalShape(self, model, bounds):
|
def _determineOptimalShape(self, model, transformed_info):
|
||||||
"""根据模型特征自动确定最适合的碰撞体形状"""
|
"""根据模型特征自动确定最适合的碰撞体形状"""
|
||||||
# 获取模型尺寸比例
|
# 获取变换后的模型尺寸比例
|
||||||
size = bounds.getMax() - bounds.getMin()
|
size = transformed_info['size']
|
||||||
max_dim = max(size.x, size.y, size.z)
|
max_dim = max(size.x, size.y, size.z)
|
||||||
min_dim = min(size.x, size.y, size.z)
|
min_dim = min(size.x, size.y, size.z)
|
||||||
|
|
||||||
@ -410,6 +440,87 @@ class CollisionManager:
|
|||||||
else: # 其他用包围盒
|
else: # 其他用包围盒
|
||||||
return 'box'
|
return 'box'
|
||||||
|
|
||||||
|
def _getTransformedModelInfo(self, model):
|
||||||
|
"""获取考虑变换后的模型信息
|
||||||
|
|
||||||
|
Args:
|
||||||
|
model: 模型节点
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 包含变换后的尺寸、中心、半径等信息
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 获取原始包围盒
|
||||||
|
bounds = model.getBounds()
|
||||||
|
if bounds.isEmpty():
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 获取模型的变换矩阵
|
||||||
|
transform = model.getTransform()
|
||||||
|
scale = model.getScale()
|
||||||
|
|
||||||
|
# 计算缩放因子(取三轴缩放的平均值)
|
||||||
|
scale_factor = (abs(scale.x) + abs(scale.y) + abs(scale.z)) / 3.0
|
||||||
|
|
||||||
|
# 获取原始尺寸
|
||||||
|
original_size = bounds.getMax() - bounds.getMin()
|
||||||
|
|
||||||
|
# 应用缩放到尺寸
|
||||||
|
actual_size = Vec3(
|
||||||
|
original_size.x * abs(scale.x),
|
||||||
|
original_size.y * abs(scale.y),
|
||||||
|
original_size.z * abs(scale.z)
|
||||||
|
)
|
||||||
|
|
||||||
|
# 获取变换后的中心点(在世界坐标系中)
|
||||||
|
original_center = bounds.getCenter()
|
||||||
|
if hasattr(model, 'getPos'):
|
||||||
|
# 模型在世界坐标系中的位置
|
||||||
|
world_center = model.getPos(model.getParent() if model.getParent() else model)
|
||||||
|
center = Point3(world_center.x, world_center.y, world_center.z)
|
||||||
|
else:
|
||||||
|
# 如果无法获取世界位置,使用原始中心
|
||||||
|
center = original_center
|
||||||
|
|
||||||
|
# 计算变换后的半径(考虑缩放)
|
||||||
|
original_radius = bounds.getRadius()
|
||||||
|
transformed_radius = original_radius * scale_factor
|
||||||
|
|
||||||
|
# 调试信息
|
||||||
|
print(f"🔍 模型 {model.getName()} 变换信息:")
|
||||||
|
print(f" 原始尺寸: {original_size}")
|
||||||
|
print(f" 缩放因子: {scale}")
|
||||||
|
print(f" 变换后尺寸: {actual_size}")
|
||||||
|
print(f" 变换后半径: {transformed_radius:.2f}")
|
||||||
|
|
||||||
|
return {
|
||||||
|
'center': center,
|
||||||
|
'radius': transformed_radius,
|
||||||
|
'size': actual_size,
|
||||||
|
'scale_factor': scale_factor,
|
||||||
|
'original_size': original_size,
|
||||||
|
'scale': scale,
|
||||||
|
'transform': transform
|
||||||
|
}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ 获取模型变换信息失败: {e}")
|
||||||
|
# 回退到原始包围盒
|
||||||
|
bounds = model.getBounds()
|
||||||
|
if bounds.isEmpty():
|
||||||
|
return None
|
||||||
|
|
||||||
|
original_size = bounds.getMax() - bounds.getMin()
|
||||||
|
return {
|
||||||
|
'center': bounds.getCenter(),
|
||||||
|
'radius': bounds.getRadius(),
|
||||||
|
'size': original_size,
|
||||||
|
'scale_factor': 1.0,
|
||||||
|
'original_size': original_size,
|
||||||
|
'scale': Vec3(1, 1, 1),
|
||||||
|
'transform': None
|
||||||
|
}
|
||||||
|
|
||||||
def createMouseRay(self, screen_x, screen_y, mask_types=['SELECTABLE']):
|
def createMouseRay(self, screen_x, screen_y, mask_types=['SELECTABLE']):
|
||||||
"""创建鼠标射线"""
|
"""创建鼠标射线"""
|
||||||
# 组合掩码
|
# 组合掩码
|
||||||
|
|||||||
1307
ui/property_panel.py
1307
ui/property_panel.py
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user