forked from Rowland/EG
vr画面抖动修复
This commit is contained in:
parent
ded28e0097
commit
11cbefc905
@ -92,6 +92,9 @@ class VRManager(DirectObject):
|
||||
# VR提交策略 - 基于参考实现
|
||||
self.submit_together = True # 是否在right_cb中同时提交左右眼
|
||||
|
||||
# 帧同步标记 - 修复ATW闪烁
|
||||
self._poses_updated_this_frame = False
|
||||
|
||||
# VR手柄控制器
|
||||
self.left_controller = None
|
||||
self.right_controller = None
|
||||
@ -389,20 +392,16 @@ class VRManager(DirectObject):
|
||||
self.last_fps_time = current_time
|
||||
|
||||
# 优化的VR更新顺序:
|
||||
# 1. 立即调用 waitGetPoses 获取最新的姿态数据
|
||||
# 这确保我们使用最新数据而不是上一帧的数据
|
||||
self._wait_get_poses()
|
||||
# 注意:WaitGetPoses现在在渲染回调中调用,避免ATW双重预测
|
||||
# 这里仅更新非关键的跟踪设备和交互系统
|
||||
|
||||
# 2. 更新相机位置(使用刚获取的最新姿态数据)
|
||||
self._update_camera_poses()
|
||||
|
||||
# 3. 更新手柄和其他跟踪设备
|
||||
# 1. 更新手柄和其他跟踪设备
|
||||
self.update_tracked_devices()
|
||||
|
||||
# 4. 更新VR动作状态
|
||||
# 2. 更新VR动作状态
|
||||
self.action_manager.update_actions()
|
||||
|
||||
# 5. 更新VR交互系统
|
||||
# 3. 更新VR交互系统
|
||||
self.interaction_manager.update()
|
||||
|
||||
# 注意:纹理提交现在通过渲染回调自动处理
|
||||
@ -466,6 +465,59 @@ class VRManager(DirectObject):
|
||||
# 记录姿态失败次数
|
||||
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):
|
||||
"""更新VR追踪数据"""
|
||||
try:
|
||||
@ -840,18 +892,42 @@ class VRManager(DirectObject):
|
||||
print("========================")
|
||||
|
||||
def left_cb(self, cbdata):
|
||||
"""左眼渲染回调 - 基于参考实现"""
|
||||
"""左眼渲染回调 - 修复ATW闪烁问题"""
|
||||
try:
|
||||
# 在渲染开始前立即获取最新姿态,避免ATW双重预测
|
||||
if not hasattr(self, '_poses_updated_this_frame') or not self._poses_updated_this_frame:
|
||||
self._wait_get_poses_immediate()
|
||||
self._update_camera_poses()
|
||||
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):
|
||||
"""右眼渲染回调 - 基于参考实现"""
|
||||
"""右眼渲染回调 - 修复ATW闪烁问题"""
|
||||
try:
|
||||
# 在渲染开始前立即获取最新姿态,避免ATW双重预测
|
||||
# 由于左右眼都会调用回调,确保每帧只调用一次WaitGetPoses
|
||||
if not hasattr(self, '_poses_updated_this_frame') or not self._poses_updated_this_frame:
|
||||
self._wait_get_poses_immediate()
|
||||
self._update_camera_poses()
|
||||
self._poses_updated_this_frame = True
|
||||
# 在帧结束时重置标记
|
||||
self.world.taskMgr.doMethodLater(0.001, self._reset_frame_flag, "reset_frame_flag")
|
||||
|
||||
# 执行实际的渲染工作
|
||||
cbdata.upcall()
|
||||
|
||||
# 根据提交策略决定提交方式
|
||||
if self.submit_together:
|
||||
# 同时提交模式:右眼渲染完成后同时提交左右眼
|
||||
@ -861,6 +937,9 @@ class VRManager(DirectObject):
|
||||
# 分别提交模式:只提交右眼
|
||||
self.submit_texture(openvr.Eye_Right, self.vr_right_texture)
|
||||
|
||||
except Exception as e:
|
||||
print(f"右眼渲染回调错误: {e}")
|
||||
|
||||
def submit_texture(self, eye, texture):
|
||||
"""提交纹理到VR - 基于参考实现,增强调试信息"""
|
||||
try:
|
||||
|
||||
1
参考文件/panda3d-openvr
Submodule
1
参考文件/panda3d-openvr
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 3f9567897552df6c10078bc124795101cf478f91
|
||||
Loading…
Reference in New Issue
Block a user