vr画面抖动修复
This commit is contained in:
parent
ded28e0097
commit
11cbefc905
@ -92,6 +92,9 @@ class VRManager(DirectObject):
|
|||||||
# VR提交策略 - 基于参考实现
|
# VR提交策略 - 基于参考实现
|
||||||
self.submit_together = True # 是否在right_cb中同时提交左右眼
|
self.submit_together = True # 是否在right_cb中同时提交左右眼
|
||||||
|
|
||||||
|
# 帧同步标记 - 修复ATW闪烁
|
||||||
|
self._poses_updated_this_frame = False
|
||||||
|
|
||||||
# VR手柄控制器
|
# VR手柄控制器
|
||||||
self.left_controller = None
|
self.left_controller = None
|
||||||
self.right_controller = None
|
self.right_controller = None
|
||||||
@ -389,20 +392,16 @@ class VRManager(DirectObject):
|
|||||||
self.last_fps_time = current_time
|
self.last_fps_time = current_time
|
||||||
|
|
||||||
# 优化的VR更新顺序:
|
# 优化的VR更新顺序:
|
||||||
# 1. 立即调用 waitGetPoses 获取最新的姿态数据
|
# 注意:WaitGetPoses现在在渲染回调中调用,避免ATW双重预测
|
||||||
# 这确保我们使用最新数据而不是上一帧的数据
|
# 这里仅更新非关键的跟踪设备和交互系统
|
||||||
self._wait_get_poses()
|
|
||||||
|
|
||||||
# 2. 更新相机位置(使用刚获取的最新姿态数据)
|
# 1. 更新手柄和其他跟踪设备
|
||||||
self._update_camera_poses()
|
|
||||||
|
|
||||||
# 3. 更新手柄和其他跟踪设备
|
|
||||||
self.update_tracked_devices()
|
self.update_tracked_devices()
|
||||||
|
|
||||||
# 4. 更新VR动作状态
|
# 2. 更新VR动作状态
|
||||||
self.action_manager.update_actions()
|
self.action_manager.update_actions()
|
||||||
|
|
||||||
# 5. 更新VR交互系统
|
# 3. 更新VR交互系统
|
||||||
self.interaction_manager.update()
|
self.interaction_manager.update()
|
||||||
|
|
||||||
# 注意:纹理提交现在通过渲染回调自动处理
|
# 注意:纹理提交现在通过渲染回调自动处理
|
||||||
@ -466,6 +465,59 @@ class VRManager(DirectObject):
|
|||||||
# 记录姿态失败次数
|
# 记录姿态失败次数
|
||||||
self.pose_failures += 1
|
self.pose_failures += 1
|
||||||
|
|
||||||
|
def _wait_get_poses_immediate(self):
|
||||||
|
"""立即获取VR姿态 - 修复ATW闪烁的关键方法"""
|
||||||
|
try:
|
||||||
|
if not self.vr_compositor or not self.poses:
|
||||||
|
return
|
||||||
|
|
||||||
|
# 使用0预测时间来避免双重预测,立即获取当前姿态
|
||||||
|
# 这是修复ATW闪烁的关键:在渲染前立即获取,避免时序错误
|
||||||
|
result = self.vr_compositor.waitGetPoses(self.poses, None)
|
||||||
|
|
||||||
|
# 检查姿态数据的有效性
|
||||||
|
valid_poses = 0
|
||||||
|
|
||||||
|
# 更新HMD姿态(设备0通常是头显)
|
||||||
|
if len(self.poses) > 0 and self.poses[0].bPoseIsValid:
|
||||||
|
valid_poses += 1
|
||||||
|
else:
|
||||||
|
# 如果HMD姿态无效,不要频繁输出错误信息
|
||||||
|
if not hasattr(self, '_hmd_invalid_warning_shown'):
|
||||||
|
print("⚠️ HMD姿态数据无效(立即模式)")
|
||||||
|
self._hmd_invalid_warning_shown = True
|
||||||
|
|
||||||
|
# 更新控制器姿态
|
||||||
|
self.controller_poses.clear()
|
||||||
|
for device_id in range(1, min(len(self.poses), openvr.k_unMaxTrackedDeviceCount)):
|
||||||
|
if self.poses[device_id].bPoseIsValid:
|
||||||
|
device_class = self.vr_system.getTrackedDeviceClass(device_id)
|
||||||
|
if device_class == openvr.TrackedDeviceClass_Controller:
|
||||||
|
controller_matrix = self.poses[device_id].mDeviceToAbsoluteTracking
|
||||||
|
self.controller_poses[device_id] = self._convert_openvr_matrix_to_panda(controller_matrix)
|
||||||
|
valid_poses += 1
|
||||||
|
|
||||||
|
# 调试信息 - 仅在第一次成功时输出
|
||||||
|
if not hasattr(self, '_immediate_mode_logged') and valid_poses > 0:
|
||||||
|
print(f"✅ 立即姿态获取模式启用 - 有效姿态数: {valid_poses}")
|
||||||
|
self._immediate_mode_logged = True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
# 限制错误输出频率
|
||||||
|
if not hasattr(self, '_last_immediate_error_frame'):
|
||||||
|
self._last_immediate_error_frame = 0
|
||||||
|
|
||||||
|
if self.frame_count - self._last_immediate_error_frame > 300: # 每5秒最多输出一次错误
|
||||||
|
print(f"立即姿态获取失败: {e}")
|
||||||
|
self._last_immediate_error_frame = self.frame_count
|
||||||
|
|
||||||
|
self.pose_failures += 1
|
||||||
|
|
||||||
|
def _reset_frame_flag(self, task):
|
||||||
|
"""重置帧标记 - 确保下一帧可以更新姿态"""
|
||||||
|
self._poses_updated_this_frame = False
|
||||||
|
return task.done
|
||||||
|
|
||||||
def _update_tracking_data(self):
|
def _update_tracking_data(self):
|
||||||
"""更新VR追踪数据"""
|
"""更新VR追踪数据"""
|
||||||
try:
|
try:
|
||||||
@ -840,26 +892,53 @@ class VRManager(DirectObject):
|
|||||||
print("========================")
|
print("========================")
|
||||||
|
|
||||||
def left_cb(self, cbdata):
|
def left_cb(self, cbdata):
|
||||||
"""左眼渲染回调 - 基于参考实现"""
|
"""左眼渲染回调 - 修复ATW闪烁问题"""
|
||||||
# 执行实际的渲染工作
|
try:
|
||||||
cbdata.upcall()
|
# 在渲染开始前立即获取最新姿态,避免ATW双重预测
|
||||||
# 根据提交策略决定是否立即提交
|
if not hasattr(self, '_poses_updated_this_frame') or not self._poses_updated_this_frame:
|
||||||
if not self.submit_together:
|
self._wait_get_poses_immediate()
|
||||||
# 分别提交模式:左眼渲染完成后立即提交
|
self._update_camera_poses()
|
||||||
self.submit_texture(openvr.Eye_Left, self.vr_left_texture)
|
self._poses_updated_this_frame = True
|
||||||
|
# 在帧结束时重置标记
|
||||||
|
self.world.taskMgr.doMethodLater(0.001, self._reset_frame_flag, "reset_frame_flag")
|
||||||
|
|
||||||
|
# 执行实际的渲染工作
|
||||||
|
cbdata.upcall()
|
||||||
|
|
||||||
|
# 根据提交策略决定是否立即提交
|
||||||
|
if not self.submit_together:
|
||||||
|
# 分别提交模式:左眼渲染完成后立即提交
|
||||||
|
self.submit_texture(openvr.Eye_Left, self.vr_left_texture)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"左眼渲染回调错误: {e}")
|
||||||
|
|
||||||
def right_cb(self, cbdata):
|
def right_cb(self, cbdata):
|
||||||
"""右眼渲染回调 - 基于参考实现"""
|
"""右眼渲染回调 - 修复ATW闪烁问题"""
|
||||||
# 执行实际的渲染工作
|
try:
|
||||||
cbdata.upcall()
|
# 在渲染开始前立即获取最新姿态,避免ATW双重预测
|
||||||
# 根据提交策略决定提交方式
|
# 由于左右眼都会调用回调,确保每帧只调用一次WaitGetPoses
|
||||||
if self.submit_together:
|
if not hasattr(self, '_poses_updated_this_frame') or not self._poses_updated_this_frame:
|
||||||
# 同时提交模式:右眼渲染完成后同时提交左右眼
|
self._wait_get_poses_immediate()
|
||||||
self.submit_texture(openvr.Eye_Left, self.vr_left_texture)
|
self._update_camera_poses()
|
||||||
self.submit_texture(openvr.Eye_Right, self.vr_right_texture)
|
self._poses_updated_this_frame = True
|
||||||
else:
|
# 在帧结束时重置标记
|
||||||
# 分别提交模式:只提交右眼
|
self.world.taskMgr.doMethodLater(0.001, self._reset_frame_flag, "reset_frame_flag")
|
||||||
self.submit_texture(openvr.Eye_Right, self.vr_right_texture)
|
|
||||||
|
# 执行实际的渲染工作
|
||||||
|
cbdata.upcall()
|
||||||
|
|
||||||
|
# 根据提交策略决定提交方式
|
||||||
|
if self.submit_together:
|
||||||
|
# 同时提交模式:右眼渲染完成后同时提交左右眼
|
||||||
|
self.submit_texture(openvr.Eye_Left, self.vr_left_texture)
|
||||||
|
self.submit_texture(openvr.Eye_Right, self.vr_right_texture)
|
||||||
|
else:
|
||||||
|
# 分别提交模式:只提交右眼
|
||||||
|
self.submit_texture(openvr.Eye_Right, self.vr_right_texture)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"右眼渲染回调错误: {e}")
|
||||||
|
|
||||||
def submit_texture(self, eye, texture):
|
def submit_texture(self, eye, texture):
|
||||||
"""提交纹理到VR - 基于参考实现,增强调试信息"""
|
"""提交纹理到VR - 基于参考实现,增强调试信息"""
|
||||||
|
|||||||
1
参考文件/panda3d-openvr
Submodule
1
参考文件/panda3d-openvr
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 3f9567897552df6c10078bc124795101cf478f91
|
||||||
Loading…
Reference in New Issue
Block a user