forked from Rowland/EG
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
|
||||
)
|
||||
|
||||
bounds = model.getBounds()
|
||||
if bounds.isEmpty():
|
||||
# 获取考虑变换后的实际尺寸和中心
|
||||
transformed_info = self._getTransformedModelInfo(model)
|
||||
if not transformed_info:
|
||||
# 默认小球体
|
||||
return CollisionSphere(Point3(0, 0, 0), 1.0)
|
||||
|
||||
center = bounds.getCenter()
|
||||
radius = bounds.getRadius()
|
||||
center = transformed_info['center']
|
||||
radius = transformed_info['radius']
|
||||
actual_size = transformed_info['size']
|
||||
scale_factor = transformed_info['scale_factor']
|
||||
|
||||
# 自动选择最适合的形状
|
||||
if shape_type == 'auto':
|
||||
shape_type = self._determineOptimalShape(model, bounds)
|
||||
shape_type = self._determineOptimalShape(model, transformed_info)
|
||||
|
||||
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':
|
||||
# 创建自定义尺寸的包围盒
|
||||
width = kwargs.get('width', bounds.getMax().x - bounds.getMin().x)
|
||||
length = kwargs.get('length', bounds.getMax().y - bounds.getMin().y)
|
||||
height = kwargs.get('height', bounds.getMax().z - bounds.getMin().z)
|
||||
# 优化盒型碰撞体 - 更精确的尺寸和位置控制(考虑缩放)
|
||||
# 获取自定义尺寸,如果没有提供则使用变换后的实际尺寸
|
||||
width = kwargs.get('width', actual_size.x)
|
||||
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_length = length / 2
|
||||
half_height = height / 2
|
||||
|
||||
min_point = Point3(center.x - half_width, center.y - half_length, center.z - half_height)
|
||||
max_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(box_center.x + half_width, box_center.y + half_length, box_center.z + half_height)
|
||||
return CollisionBox(min_point, max_point)
|
||||
|
||||
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)
|
||||
point_b = Point3(center.x, center.y, center.z + custom_height/2 - custom_radius)
|
||||
# 更合理的半径计算:基于变换后模型宽度的平均值
|
||||
default_radius = min(actual_size.x, actual_size.y) / 2.5 # 稍微小于模型的宽度
|
||||
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)
|
||||
|
||||
elif shape_type == 'plane':
|
||||
# 创建平面(适合地面、墙面)
|
||||
# 优化平面碰撞 - 支持位置偏移和更灵活的法向量
|
||||
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)
|
||||
|
||||
elif shape_type == 'polygon':
|
||||
@ -378,10 +408,10 @@ class CollisionManager:
|
||||
#print("⚠️ 多边形至少需要3个顶点,回退到球体")
|
||||
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)
|
||||
min_dim = min(size.x, size.y, size.z)
|
||||
|
||||
@ -410,6 +440,87 @@ class CollisionManager:
|
||||
else: # 其他用包围盒
|
||||
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']):
|
||||
"""创建鼠标射线"""
|
||||
# 组合掩码
|
||||
|
||||
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