Merge remote-tracking branch 'origin/main' into main_ch_eg
This commit is contained in:
commit
eb3ce79c17
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1187,44 +1187,32 @@ class SelectionSystem:
|
||||
# 检查目标节点是否有父节点
|
||||
parent_node = self.gizmoTarget.getParent()
|
||||
|
||||
# 确定轴向量的变换上下文
|
||||
if parent_node and parent_node != self.world.render:
|
||||
# 子节点:使用父节点的局部坐标系
|
||||
print(f"子节点拖拽 - 父节点: {parent_node.getName()}, 父节点旋转: {parent_node.getHpr()}")
|
||||
transform_context = parent_node
|
||||
else:
|
||||
# 顶级模型:使用世界坐标系
|
||||
print(f"顶级模型拖拽 - 使用世界坐标系")
|
||||
transform_context = self.world.render
|
||||
|
||||
# 计算轴向量在正确坐标系中的方向
|
||||
if self.dragGizmoAxis == "x":
|
||||
# 在变换上下文中的X轴方向
|
||||
# 在局部坐标系中的X轴方向
|
||||
local_axis_vector = Vec3(1, 0, 0)
|
||||
elif self.dragGizmoAxis == "y":
|
||||
# 在变换上下文中的Y轴方向
|
||||
# 在局部坐标系中的Y轴方向
|
||||
local_axis_vector = Vec3(0, 1, 0)
|
||||
elif self.dragGizmoAxis == "z":
|
||||
# 在变换上下文中的Z轴方向
|
||||
# 在局部坐标系中的Z轴方向
|
||||
local_axis_vector = Vec3(0, 0, 1)
|
||||
else:
|
||||
print(f"拖拽更新失败: 未知轴类型 {self.dragGizmoAxis}")
|
||||
return
|
||||
|
||||
# 将局部轴向量转换到世界坐标系(用于屏幕投影)
|
||||
if transform_context != self.world.render:
|
||||
# 获取变换矩阵并应用到轴向量上
|
||||
transform_mat = transform_context.getMat(self.world.render)
|
||||
# 只旋转向量,不平移
|
||||
# 确定轴向量的变换上下文
|
||||
if parent_node and parent_node != self.world.render:
|
||||
# 子节点:使用父节点的局部坐标系
|
||||
# print(f"子节点拖拽 - 父节点: {parent_node.getName()}, 父节点旋转: {parent_node.getHpr()}")
|
||||
# transform_context = parent_node
|
||||
transform_mat = parent_node.getMat(self.world.render)
|
||||
world_axis_vector = transform_mat.xformVec(local_axis_vector)
|
||||
world_axis_vector.normalize() # 归一化
|
||||
print(f"转换后的轴向量: {local_axis_vector} -> {world_axis_vector}")
|
||||
else:
|
||||
# 顶级节点,直接使用世界轴向量
|
||||
world_axis_vector = local_axis_vector
|
||||
print(f"世界轴向量: {world_axis_vector}")
|
||||
|
||||
# 计算轴的端点位置(用于屏幕投影)
|
||||
# 顶级模型:使用世界坐标系
|
||||
# print(f"顶级模型拖拽 - 使用世界坐标系")
|
||||
# transform_context = self.world.render
|
||||
axis_end = gizmo_world_pos + world_axis_vector
|
||||
|
||||
# 投影到屏幕空间
|
||||
@ -1279,83 +1267,62 @@ class SelectionSystem:
|
||||
projected_distance = (mouseDeltaX * screen_axis_dir[0] +
|
||||
mouseDeltaY * screen_axis_dir[1])
|
||||
|
||||
# 计算动态比例因子,基于相机距离和视野角度
|
||||
cam_pos = self.world.cam.getPos()
|
||||
distance_to_object = (cam_pos - gizmo_world_pos).length()
|
||||
scale_adjustment = 1.0
|
||||
if parent_node and parent_node!= self.world.render:
|
||||
current_node = parent_node
|
||||
total_scale = 1.0
|
||||
while current_node and current_node != self.world.render:
|
||||
node_scale = current_node.getScale()
|
||||
avg_scale = (node_scale.x+node_scale.y + node_scale.z)/3.0
|
||||
total_scale *= avg_scale
|
||||
current_node = current_node.getParent()
|
||||
if total_scale>0:
|
||||
scale_adjustment = 1.0 / total_scale
|
||||
# parent_scale = parent_node.getScale()
|
||||
# avg_scale = (parent_scale.x+parent_scale.y+parent_scale.z)/3.0
|
||||
# if avg_scale>0:
|
||||
# scale_adjustment = 1.0 / avg_scale
|
||||
|
||||
# 获取相机的视野角度
|
||||
fov = self.world.cam.node().getLens().getFov()[0] # 水平视野角度
|
||||
fov_radians = math.radians(fov)
|
||||
|
||||
# 获取窗口尺寸
|
||||
winWidth, winHeight = self.world.getWindowSize()
|
||||
fixed_pixel_to_world_ratio = 0.01 # 1像素 = 0.01世界单位
|
||||
scale_factor = fixed_pixel_to_world_ratio * scale_adjustment
|
||||
|
||||
# 计算一个像素在世界坐标系中的大小(在目标物体的距离处)
|
||||
# 使用透视投影公式:world_size = screen_size * distance * tan(fov/2) / (screen_width/2)
|
||||
pixel_to_world_ratio = distance_to_object * math.tan(fov_radians / 2) / (winWidth / 2)
|
||||
|
||||
# 【改进修复】:智能缩放补偿,区分继承缩放和本体缩放
|
||||
# 计算父节点链的累积缩放(不包括目标节点本身)
|
||||
parent_cumulative_scale = 1.0
|
||||
current_node = self.gizmoTarget.getParent()
|
||||
while current_node and current_node != self.world.render:
|
||||
node_scale = current_node.getScale()
|
||||
# 使用缩放的几何平均值作为累积因子
|
||||
scale_magnitude = (abs(node_scale.x) * abs(node_scale.y) * abs(node_scale.z)) ** (1.0/3.0)
|
||||
parent_cumulative_scale *= scale_magnitude
|
||||
current_node = current_node.getParent()
|
||||
|
||||
# 获取目标节点自身的缩放
|
||||
target_scale = self.gizmoTarget.getScale()
|
||||
target_scale_magnitude = (abs(target_scale.x) * abs(target_scale.y) * abs(target_scale.z)) ** (1.0/3.0)
|
||||
|
||||
# 智能补偿策略:
|
||||
# 1. 只对父节点链的小缩放进行完全补偿(这通常是单位转换导致的)
|
||||
# 2. 对目标节点自身的缩放进行部分补偿(避免大模型缩小后移动过快)
|
||||
parent_compensation = 1.0 / parent_cumulative_scale if parent_cumulative_scale > 0 else 1.0
|
||||
|
||||
# 对目标节点自身的缩放使用平方根补偿,减少过度补偿
|
||||
target_compensation = 1.0 / math.sqrt(target_scale_magnitude) if target_scale_magnitude > 0 else 1.0
|
||||
|
||||
# 限制目标补偿的最大值,避免移动过快
|
||||
target_compensation = min(target_compensation, 10.0) # 最大10倍补偿
|
||||
|
||||
# 综合补偿因子
|
||||
total_compensation = parent_compensation * target_compensation
|
||||
scale_factor = pixel_to_world_ratio * 0.5*total_compensation
|
||||
|
||||
# 【关键修复】:在正确的坐标系中计算移动向量
|
||||
# 计算移动距离(标量)
|
||||
movement_distance = projected_distance * scale_factor
|
||||
|
||||
# 在正确的坐标系中计算移动向量
|
||||
if transform_context != self.world.render:
|
||||
# 子节点:在父节点的局部坐标系中移动
|
||||
if self.dragGizmoAxis == "x":
|
||||
movement_local = Vec3(movement_distance, 0, 0)
|
||||
elif self.dragGizmoAxis == "y":
|
||||
movement_local = Vec3(0, movement_distance, 0)
|
||||
elif self.dragGizmoAxis == "z":
|
||||
movement_local = Vec3(0, 0, movement_distance)
|
||||
|
||||
# 将局部移动向量转换到父节点的坐标系中
|
||||
# 由于我们要应用到目标节点上,而目标节点相对于父节点,我们直接使用局部移动
|
||||
movement = movement_local
|
||||
print(f"子节点移动向量(局部): {movement}")
|
||||
# 获取当前位置并只修改选中轴的坐标
|
||||
currentPos = self.gizmoTargetStartPos
|
||||
|
||||
# 根据拖拽的轴,只修改对应的坐标分量
|
||||
if self.dragGizmoAxis == "x":
|
||||
newPos = Vec3(currentPos.x + movement_distance, currentPos.y, currentPos.z)
|
||||
print(f"X轴移动:{currentPos.x} -> {newPos.x}")
|
||||
elif self.dragGizmoAxis == "y":
|
||||
newPos = Vec3(currentPos.x, currentPos.y + movement_distance, currentPos.z)
|
||||
print(f"Y轴移动:{currentPos.y} -> {newPos.y}")
|
||||
elif self.dragGizmoAxis == "z":
|
||||
newPos = Vec3(currentPos.x, currentPos.y, currentPos.z + movement_distance)
|
||||
print(f"Z轴移动:{currentPos.z} -> {newPos.z}")
|
||||
else:
|
||||
# 顶级模型:在世界坐标系中移动
|
||||
if self.dragGizmoAxis == "x":
|
||||
movement = Vec3(movement_distance, 0, 0)
|
||||
elif self.dragGizmoAxis == "y":
|
||||
movement = Vec3(0, movement_distance, 0)
|
||||
elif self.dragGizmoAxis == "z":
|
||||
movement = Vec3(0, 0, movement_distance)
|
||||
print(f"顶级模型移动向量(世界): {movement}")
|
||||
|
||||
# 应用移动到目标节点
|
||||
newPos = self.gizmoTargetStartPos + movement
|
||||
self.gizmoTarget.setPos(newPos)
|
||||
print(f"未知轴: {self.dragGizmoAxis}")
|
||||
return
|
||||
|
||||
# 应用新位置到目标节点
|
||||
light_object = self.gizmoTarget.getPythonTag("rp_light_object")
|
||||
if light_object:
|
||||
light_object.pos = newPos
|
||||
self.gizmoTarget.setPos(newPos)
|
||||
else:
|
||||
self.gizmoTarget.setPos(newPos)
|
||||
|
||||
# 更新坐标轴位置 - 计算新的中心位置
|
||||
minPoint = Point3()
|
||||
maxPoint = Point3()
|
||||
if self.gizmoTarget.calcTightBounds(minPoint, maxPoint, self.world.render):
|
||||
center = Point3((minPoint.x + maxPoint.x) * 0.5,
|
||||
(minPoint.y + maxPoint.y) * 0.5,
|
||||
(minPoint.z + maxPoint.z) * 0.5)
|
||||
self.gizmo.setPos(center)
|
||||
|
||||
# 实时更新属性面板
|
||||
self.world.property_panel.refreshModelValues(self.gizmoTarget)
|
||||
|
||||
# 每次拖拽都输出调试信息(但限制频率)
|
||||
@ -1365,18 +1332,9 @@ class SelectionSystem:
|
||||
import time
|
||||
current_time = time.time()
|
||||
if current_time - self._last_drag_debug_time > 0.1: # 每0.1秒最多输出一次
|
||||
print(f"拖拽更新成功 - 轴:{self.dragGizmoAxis}, 距离:{distance_to_object:.2f}, 比例:{scale_factor:.6f}, 投影:{projected_distance:.2f}")
|
||||
print(f"拖拽更新成功 - 轴:{self.dragGizmoAxis}, 比例:{scale_factor:.6f}, 投影:{projected_distance:.2f}")
|
||||
self._last_drag_debug_time = current_time
|
||||
|
||||
newPos = self.gizmoTargetStartPos + movement
|
||||
light_object = self.gizmoTarget.getPythonTag("rp_light_object")
|
||||
if light_object:
|
||||
light_object.pos = newPos
|
||||
self.gizmoTarget.setPos(newPos)
|
||||
else:
|
||||
self.gizmoTarget.setPos(newPos)
|
||||
self.gizmo.setPos(newPos)
|
||||
|
||||
except Exception as e:
|
||||
print(f"更新坐标轴拖拽失败: {str(e)}")
|
||||
import traceback
|
||||
|
||||
Binary file not shown.
@ -405,7 +405,8 @@ class MainWindow(QMainWindow):
|
||||
self.createPointLight.clicked.connect(lambda :self.world.createPointLight())
|
||||
|
||||
# 连接树节点点击信号
|
||||
self.treeWidget.itemClicked.connect(self.world.onTreeItemClicked)
|
||||
# self.treeWidget.itemClicked.connect(self.world.onTreeItemClicked)
|
||||
self.treeWidget.itemSelectionChanged.connect(lambda :self.world.onTreeItemClicked(self.treeWidget.currentItem(), 0))
|
||||
print("已连接点击信号")
|
||||
|
||||
# 连接工具切换信号
|
||||
|
||||
@ -877,7 +877,7 @@ class PropertyPanelManager:
|
||||
print(f"材质基础颜色: {base_color}")
|
||||
|
||||
# 基础颜色标题
|
||||
color_row = 2 if material_status != "标准PBR材质" else 0
|
||||
color_row = 2 if material_status != "标准PBR材质" else 1
|
||||
material_layout.addWidget(QLabel("基础颜色"), color_row, 0)
|
||||
|
||||
# R, G, B 标签
|
||||
@ -3870,20 +3870,15 @@ class PropertyPanelManager:
|
||||
azimuth, altitude = presets[preset_name]
|
||||
|
||||
# 更新滑块和数值框
|
||||
self.sun_azimuth_slider.blockSignals(True)
|
||||
self.sun_azimuth_spinbox.blockSignals(True)
|
||||
self.sun_altitude_slider.blockSignals(True)
|
||||
self.sun_altitude_spinbox.blockSignals(True)
|
||||
# 更新滑块和数值框
|
||||
self.azimuthSpinBox.blockSignals(True)
|
||||
self.altitudeSpinBox.blockSignals(True)
|
||||
|
||||
self.sun_azimuth_slider.setValue(azimuth)
|
||||
self.sun_azimuth_spinbox.setValue(azimuth)
|
||||
self.sun_altitude_slider.setValue(altitude)
|
||||
self.sun_altitude_spinbox.setValue(altitude)
|
||||
self.azimuthSpinBox.setValue(azimuth)
|
||||
self.altitudeSpinBox.setValue(altitude)
|
||||
|
||||
self.sun_azimuth_slider.blockSignals(False)
|
||||
self.sun_azimuth_spinbox.blockSignals(False)
|
||||
self.sun_altitude_slider.blockSignals(False)
|
||||
self.sun_altitude_spinbox.blockSignals(False)
|
||||
self.azimuthSpinBox.blockSignals(False)
|
||||
self.altitudeSpinBox.blockSignals(False)
|
||||
|
||||
# 应用设置 - 优先使用Day Time Editor
|
||||
azimuth_success = self._updateDayTimeEditorSetting("scattering", "sun_azimuth", azimuth)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user