"""
VR管理器模块

负责VR功能的初始化、渲染和交互：
- OpenVR/SteamVR集成
- VR头显跟踪和渲染
- VR控制器交互
- VR模式切换
"""

import sys
import gc
import numpy as np
from panda3d.core import (
    WindowProperties, GraphicsPipe, FrameBufferProperties,
    GraphicsOutput, Texture, Camera, PerspectiveLens, MatrixLens,
    Mat4, Vec3, TransformState, RenderState, CardMaker,
    BitMask32, PandaNode, NodePath, LMatrix4, LVector3, LVector4,
    CS_yup_right, CS_default, PythonCallbackObject
)
from direct.task import Task
from direct.showbase.DirectObject import DirectObject

try:
    import openvr
    OPENVR_AVAILABLE = True
except ImportError:
    OPENVR_AVAILABLE = False
    print("警告: OpenVR未安装，VR功能将不可用")

# 导入手柄控制器、动作系统、交互系统、摇杆系统和传送系统
from core.vr.tracking.controllers import LeftController, RightController
from core.vr.interaction.actions import VRActionManager
from core.vr.interaction.grab import VRInteractionManager
from core.vr.interaction.joystick import VRJoystickManager
from core.vr.interaction.teleport import VRTeleportSystem
from enum import Enum


class VRRenderMode(Enum):
    """VR渲染模式枚举"""
    NORMAL = "normal"  # 普通渲染模式
    RENDER_PIPELINE = "render_pipeline"  # RenderPipeline高级渲染模式


class VRManager(DirectObject):
    """VR管理器类 - 处理所有VR相关功能"""

    def __init__(self, world):
        """初始化VR管理器

        Args:
            world: 主世界对象引用
        """
        super().__init__()

        self.world = world
        self.vr_system = None
        self.vr_enabled = False
        self.vr_initialized = False

        # VR渲染相关
        self.vr_left_eye_buffer = None
        self.vr_right_eye_buffer = None
        self.vr_left_camera = None
        self.vr_right_camera = None
        self.vr_compositor = None

        # VR纹理和ID缓存 - 修复重复准备问题
        self.vr_left_texture = None
        self.vr_right_texture = None
        self.left_texture_id = None   # 缓存左眼纹理的OpenGL ID
        self.right_texture_id = None  # 缓存右眼纹理的OpenGL ID
        self.textures_prepared = False # 标记纹理是否已准备

        # VR跟踪数据
        self.hmd_pose = Mat4.identMat()
        self.controller_poses = {}
        self.tracked_device_poses = []
        self.poses = None  # OpenVR渲染姿态数组
        self.game_poses = None  # OpenVR游戏逻辑姿态数组

        # 🚀 对象池和缓存系统 - 修复16-19帧周期性GPU峰值
        self._matrix_pool = []  # Mat4对象池
        self._matrix_pool_size = 8  # 池大小，足够处理多个控制器
        self._cached_matrices = {}  # 设备ID到矩阵的缓存
        self._controller_poses_cache = {}  # 控制器姿态缓存，避免每帧clear()

        # 🚀 OpenVR Texture对象缓存 - 避免每帧创建openvr.Texture_t()
        self._left_ovr_texture = None    # 左眼纹理对象缓存
        self._right_ovr_texture = None   # 右眼纹理对象缓存

        # Python垃圾回收控制
        self._gc_control_enabled = True  # 是否启用GC控制
        self._gc_disabled = False  # GC是否被禁用
        self._manual_gc_interval = 900  # 每900帧手动触发一次GC (15秒@60fps) - 减少GC频率
        self._last_manual_gc_frame = 0

        # 🚀 立即初始化对象池和GC控制（在其他组件之前）
        self._initialize_object_pools()

        # VR渲染参数
        self.eye_width = 1080
        self.eye_height = 1200
        self.near_clip = 0.1
        self.far_clip = 1000.0

        # VR分辨率缩放优化
        self.resolution_scale = 0.75  # 默认0.75倍分辨率，性能和质量平衡
        self.base_eye_width = 1080    # 原始推荐分辨率
        self.base_eye_height = 1200
        self.scaled_eye_width = 1080  # 实际使用的缩放后分辨率
        self.scaled_eye_height = 1200

        # VR质量预设
        self.quality_presets = {
            'performance': 0.6,   # 性能模式 - 约60%分辨率
            'balanced': 0.75,     # 平衡模式 - 约75%分辨率
            'quality': 1.0        # 质量模式 - 100%分辨率
        }
        self.current_quality_preset = 'balanced'  # 默认平衡模式

        # 🎨 VR渲染模式配置 - RenderPipeline集成
        self.vr_render_mode = VRRenderMode.NORMAL  # 默认使用普通渲染模式
        self.render_pipeline_enabled = False  # RenderPipeline是否已启用
        self.vr_pipeline_left_target = None  # 左眼RenderPipeline渲染目标
        self.vr_pipeline_right_target = None  # 右眼RenderPipeline渲染目标
        self.pipeline_resolution_scale = 0.75  # RenderPipeline模式下的分辨率缩放（性能优化）
        self.vr_pipeline_controller = None  # VR Pipeline控制器（管理完整的VR渲染管线）

        # RenderPipeline VR优化配置
        self.pipeline_vr_config = {
            'enable_shadows': True,          # 启用阴影
            'enable_ao': True,               # 启用环境光遮蔽
            'enable_bloom': False,           # 禁用泛光（VR性能考虑）
            'enable_motion_blur': False,     # 禁用运动模糊（VR中会引起不适）
            'enable_ssr': False,             # 禁用屏幕空间反射（性能密集）
            'shadow_quality': 'medium',      # 阴影质量：low/medium/high
            'ao_quality': 'low',             # AO质量：low/medium/high
        }

        # VR任务
        self.vr_task = None

        # VR锚点层级系统
        self.tracking_space = None
        self.hmd_anchor = None
        self.left_eye_anchor = None
        self.right_eye_anchor = None

        # 坐标系转换矩阵 - 使用Panda3D内置方法
        self.coord_mat = LMatrix4.convert_mat(CS_yup_right, CS_default)
        self.coord_mat_inv = LMatrix4.convert_mat(CS_default, CS_yup_right)

        # 性能监控
        self.frame_count = 0
        self.last_fps_check = 0
        self.last_fps_time = 0
        self.vr_fps = 0
        self.submit_failures = 0
        self.pose_failures = 0

        # OpenVR 帧ID跟踪（防止重复提交）
        self.openvr_frame_id = 0
        self.left_eye_last_render_frame = -1
        self.right_eye_last_render_frame = -1

        # 高级性能监控（默认关闭，手动开启）
        self.performance_monitoring = False  # 是否启用性能监控
        self.debug_output_enabled = False  # 是否启用调试输出
        self.debug_mode = 'detailed'  # 'brief' 或 'detailed'
        self.cpu_usage = 0.0
        self.memory_usage = 0.0
        self.gpu_usage = 0.0
        self.gpu_memory_usage = 0.0
        self.frame_times = []  # 存储最近帧时间
        self.max_frame_time_history = 60  # 保存60帧的历史
        self.last_performance_check = 0
        self.performance_check_interval = 0.5  # 每0.5秒更新一次性能数据

        # 渲染管线详细监控
        self.enable_pipeline_monitoring = True  # 是否启用管线监控
        self.performance_mode_enabled = False  # 性能优化模式（禁用监控以减少对象创建）
        self.performance_mode_trigger_frame = 600  # 第600帧后启用性能模式
        self.wait_poses_time = 0.0  # waitGetPoses耗时
        self.left_render_time = 0.0  # 左眼渲染耗时
        self.right_render_time = 0.0  # 右眼渲染耗时
        self.submit_time = 0.0  # 纹理提交耗时
        self.left_render_count = 0  # 左眼渲染次数计数
        self.right_render_count = 0  # 右眼渲染次数计数
        self.total_frame_time = 0.0  # 总帧时间
        self.vr_sync_wait_time = 0.0  # VR同步等待时间

        # 时间监控历史（保存最近30帧）
        self.wait_poses_times = []
        self.render_times = []
        self.submit_times = []
        self.sync_wait_times = []
        self.pipeline_history_size = 30

        # GPU渲染时间监控（OpenVR Frame Timing）
        self.enable_gpu_timing = False  # 是否启用GPU时间监控（默认关闭）
        self.gpu_scene_render_ms = 0.0  # GPU场景渲染时间
        self.gpu_pre_submit_ms = 0.0  # 提交前GPU时间
        self.gpu_post_submit_ms = 0.0  # 提交后GPU时间
        self.gpu_total_render_ms = 0.0  # GPU总渲染时间
        self.gpu_compositor_render_ms = 0.0  # GPU合成器渲染时间
        self.gpu_client_frame_interval_ms = 0.0  # 客户端帧间隔
        self.gpu_timing_history = []  # GPU时间历史记录
        self.gpu_timing_history_size = 30  # GPU时间历史记录大小
        self.gpu_timing_failure_count = 0  # GPU时间获取失败次数

        # VR系统信息
        self.current_eye_resolution = (self.eye_width, self.eye_height)
        self.recommended_eye_resolution = (0, 0)
        self.vr_display_frequency = 0.0
        self.vr_vsync_enabled = True
        self.vsync_to_photons_ms = 0.0  # VSync到光子的延迟
        self.target_frame_time_ms = 0.0  # 目标帧时间
        self.vsync_window_ms = 0.0  # VSync时间窗口
        self.async_reprojection_enabled = False  # 异步重投影状态
        self.motion_smoothing_enabled = False  # 运动平滑状态

        # 🧪 VR测试模式
        self.vr_test_mode = False  # 是否启用VR测试模式
        self.test_display_mode = 'stereo'  # 'left', 'right', 'stereo'
        self.test_display_quad = None  # 测试显示的四边形
        self.test_right_quad = None  # 右眼显示的四边形（立体模式）
        self.stereo_display_created = False  # 立体显示是否已创建
        self.test_performance_hud = None  # 性能HUD
        self.test_performance_text = None  # 性能文本节点
        self.test_mode_initialized = False  # 测试模式是否已初始化
        self.hud_update_counter = 0  # HUD更新计数器
        self.hud_update_interval = 30  # HUD更新间隔（帧数），30帧约0.5秒@60fps

        # 🔧 VR测试模式调试选项 - 逐步启用普通VR功能
        self.test_mode_submit_texture = False  # 是否在测试模式提交纹理到OpenVR
        self.test_mode_wait_poses = False      # 是否在测试模式调用waitGetPoses

        # waitGetPoses调用策略配置 - 使用高性能的update_task策略
        self.use_prediction_time = 0.011  # 11ms的预测时间 - OpenVR标准值，平衡准确性和延迟
        self.poses_updated_in_task = True  # 始终在更新任务中获取姿态（Running Start模式）

        # 🎨 初始化VR配置管理器
        try:
            from core.vr.config.vr_config import VRConfigManager
            self.config_manager = VRConfigManager()
            # 加载配置并应用
            self.config_manager.apply_config_to_vr_manager(self)
            print("✓ VR配置管理器初始化完成并已加载配置")
        except Exception as e:
            print(f"⚠️ VR配置管理器初始化失败: {e}")
            self.config_manager = None

        # 尝试导入性能监控库
        self._init_performance_monitoring()

        # VR提交策略 - 基于参考实现
        self.submit_together = True  # 是否在right_cb中同时提交左右眼


        # Running Start标记 - Valve最佳实践
        self._waitgetposes_called_this_frame = False

        # 姿态缓存 - 修复时序不匹配
        self._cached_render_poses = None  # 用于渲染的缓存姿态
        self._first_frame = True  # 首帧标记

        # ATW控制选项 - 备选方案
        self.disable_async_reprojection = False  # 是否禁用异步重投影

        # VR手柄控制器
        self.left_controller = None
        self.right_controller = None
        self.controllers = {}  # 设备索引到控制器的映射
        self.tracked_device_anchors = {}  # 跟踪设备锚点

        # VR动作系统 - 可选择禁用（用于API兼容性问题）
        self.disable_action_system = True  # 禁用动作系统，使用直接控制器输入

        if not self.disable_action_system:
            try:
                self.action_manager = VRActionManager(self)
                print("✓ VR动作管理器初始化完成")
            except Exception as e:
                print(f"⚠️ VR动作管理器初始化失败: {e}")
                self.action_manager = None
        else:
            self.action_manager = None
            print("🚫 VR动作系统已禁用，使用直接控制器输入")

        # VR交互系统 - 添加异常保护
        try:
            self.interaction_manager = VRInteractionManager(self)
            print("✓ VR交互管理器初始化完成")
        except Exception as e:
            print(f"⚠️ VR交互管理器初始化失败: {e}")
            self.interaction_manager = None

        # VR传送系统 - 添加异常保护
        try:
            self.teleport_system = VRTeleportSystem(self)
            print("✓ VR传送系统初始化完成")
        except Exception as e:
            print(f"⚠️ VR传送系统初始化失败: {e}")
            self.teleport_system = None

        # VR摇杆系统 - 添加异常保护
        try:
            self.joystick_manager = VRJoystickManager(self)
            print("✓ VR摇杆管理器初始化完成")
        except Exception as e:
            print(f"⚠️ VR摇杆管理器初始化失败: {e}")
            self.joystick_manager = None

        print("✓ VR管理器初始化完成")

    def _initialize_object_pools(self):
        """初始化对象池 - 修复16-19帧周期性GPU峰值"""
        try:
            # 预填充Mat4对象池
            for _ in range(self._matrix_pool_size):
                self._matrix_pool.append(Mat4())

            print(f"✅ Mat4对象池初始化完成 - 池大小: {self._matrix_pool_size}")

            # 🚀 预创建OpenVR Texture对象 - 消除每帧创建openvr.Texture_t()的开销
            try:
                import openvr
                self._left_ovr_texture = openvr.Texture_t()
                self._right_ovr_texture = openvr.Texture_t()

                # 设置固定属性（这些不变）
                self._left_ovr_texture.eType = openvr.TextureType_OpenGL
                self._left_ovr_texture.eColorSpace = openvr.ColorSpace_Gamma
                self._right_ovr_texture.eType = openvr.TextureType_OpenGL
                self._right_ovr_texture.eColorSpace = openvr.ColorSpace_Gamma

                print("✅ OpenVR Texture对象缓存已创建 - 避免每帧创建新对象")
            except Exception as texture_error:
                print(f"⚠️ OpenVR Texture对象创建失败: {texture_error}")
                # 不影响整体初始化，但性能可能不是最优

            # 启用GC控制
            if self._gc_control_enabled:
                # 禁用自动垃圾回收，改为手动控制
                gc.disable()
                self._gc_disabled = True
                print("✅ Python垃圾回收已禁用，改为手动控制")

        except Exception as e:
            print(f"⚠️ 对象池初始化失败: {e}")

    def _get_pooled_matrix(self):
        """从对象池获取Mat4对象"""
        if self._matrix_pool:
            return self._matrix_pool.pop()
        else:
            # 池为空时创建新对象（不应该发生，但作为备用）
            return Mat4()

    def _return_pooled_matrix(self, matrix):
        """将Mat4对象返回对象池"""
        if len(self._matrix_pool) < self._matrix_pool_size:
            # 重置矩阵到单位矩阵
            matrix.identMat()
            self._matrix_pool.append(matrix)

    def _manual_gc_control(self):
        """手动垃圾回收控制 - 避免VR渲染期间的GC峰值"""
        if not self._gc_control_enabled or not self._gc_disabled:
            return

        # 🚀 智能GC间隔：性能模式下减少GC频率
        current_interval = self._manual_gc_interval
        if self.performance_mode_enabled:
            current_interval = self._manual_gc_interval * 2  # 性能模式下间隔翻倍

        # 每N帧手动触发一次垃圾回收
        if self.frame_count - self._last_manual_gc_frame >= current_interval:
            # 在非渲染关键时刻触发GC
            collected = gc.collect()
            self._last_manual_gc_frame = self.frame_count

            # 仅在收集到对象时输出信息
            if collected > 0:
                print(f"🗑️ 手动GC: 清理了 {collected} 个对象 (帧#{self.frame_count})")

    def _update_matrix_from_openvr(self, panda_mat, ovr_matrix):
        """直接更新现有Mat4对象的数值，避免创建新对象"""
        # 复用_convert_openvr_matrix_to_panda中的转换逻辑
        # X轴行：Panda3D的X轴对应OpenVR的X轴
        panda_mat.setCell(0, 0, ovr_matrix[0][0])     # X_x → X_x
        panda_mat.setCell(0, 1, ovr_matrix[0][1])     # X_y → X_y
        panda_mat.setCell(0, 2, ovr_matrix[0][2])     # X_z → X_z
        panda_mat.setCell(0, 3, ovr_matrix[0][3])     # 位移X分量

        # Y轴行：Panda3D的Y轴对应OpenVR的-Z轴
        panda_mat.setCell(1, 0, -ovr_matrix[2][0])    # -Z_x → Y_x
        panda_mat.setCell(1, 1, -ovr_matrix[2][1])    # -Z_y → Y_y
        panda_mat.setCell(1, 2, -ovr_matrix[2][2])    # -Z_z → Y_z
        panda_mat.setCell(1, 3, -ovr_matrix[2][3])    # 位移Y分量（-Z位移）

        # Z轴行：Panda3D的Z轴对应OpenVR的Y轴
        panda_mat.setCell(2, 0, ovr_matrix[1][0])     # Y_x → Z_x
        panda_mat.setCell(2, 1, ovr_matrix[1][1])     # Y_y → Z_y
        panda_mat.setCell(2, 2, ovr_matrix[1][2])     # Y_z → Z_z
        panda_mat.setCell(2, 3, ovr_matrix[1][3])     # 位移Z分量（Y位移）

        # 齐次坐标
        panda_mat.setCell(3, 0, 0)
        panda_mat.setCell(3, 1, 0)
        panda_mat.setCell(3, 2, 0)
        panda_mat.setCell(3, 3, 1)

    def convert_mat(self, mat):
        """
        将OpenVR矩阵转换为Panda3D矩阵 - 基于参考实现
        """
        if len(mat.m) == 4:
            result = LMatrix4(
                mat.m[0][0], mat.m[1][0], mat.m[2][0], mat.m[3][0],
                mat.m[0][1], mat.m[1][1], mat.m[2][1], mat.m[3][1],
                mat.m[0][2], mat.m[1][2], mat.m[2][2], mat.m[3][2],
                mat.m[0][3], mat.m[1][3], mat.m[2][3], mat.m[3][3])
        elif len(mat.m) == 3:
            result = LMatrix4(
                mat.m[0][0], mat.m[1][0], mat.m[2][0], 0.0,
                mat.m[0][1], mat.m[1][1], mat.m[2][1], 0.0,
                mat.m[0][2], mat.m[1][2], mat.m[2][2], 0.0,
                mat.m[0][3], mat.m[1][3], mat.m[2][3], 1.0)
        return result

    def is_vr_available(self):
        """检查VR系统是否可用"""
        if not OPENVR_AVAILABLE:
            return False

        try:
            # 检查SteamVR是否运行
            return openvr.isRuntimeInstalled() and openvr.isHmdPresent()
        except Exception as e:
            print(f"VR检查失败: {e}")
            return False

    def initialize_vr(self):
        """初始化VR系统"""
        if not OPENVR_AVAILABLE:
            print("❌ OpenVR不可用，无法初始化VR")
            return False

        if self.vr_initialized:
            print("VR系统已经初始化")
            return True

        try:
            print("🔄 正在初始化VR系统...")

            # 🚀 确保对象池已正确初始化（备用检查）
            if not hasattr(self, '_matrix_pool') or len(self._matrix_pool) == 0:
                print("⚠️ 对象池未初始化，正在重新初始化...")
                self._initialize_object_pools()

            # 初始化OpenVR - 使用Scene应用类型确保正确的焦点管理
            self.vr_system = openvr.init(openvr.VRApplication_Scene)
            if not self.vr_system:
                print("❌ 无法初始化OpenVR系统")
                return False

            # 获取compositor
            self.vr_compositor = openvr.VRCompositor()
            if not self.vr_compositor:
                print("❌ 无法获取VR Compositor")
                return False

            # 获取推荐的渲染目标尺寸
            base_width, base_height = self.vr_system.getRecommendedRenderTargetSize()
            self.base_eye_width = base_width
            self.base_eye_height = base_height

            # 应用分辨率缩放
            self.scaled_eye_width = int(base_width * self.resolution_scale)
            self.scaled_eye_height = int(base_height * self.resolution_scale)

            # 使用缩放后的分辨率作为实际渲染分辨率
            self.eye_width = self.scaled_eye_width
            self.eye_height = self.scaled_eye_height

            self.current_eye_resolution = (self.eye_width, self.eye_height)
            self.recommended_eye_resolution = (base_width, base_height)

            print(f"✓ VR基础分辨率: {base_width}x{base_height}")
            print(f"✓ VR缩放系数: {self.resolution_scale}")
            print(f"✓ VR实际分辨率: {self.eye_width}x{self.eye_height}")
            print(f"📊 分辨率优化: {(1 - self.resolution_scale**2) * 100:.1f}% 像素减少")

            # 获取VR系统信息
            try:
                # 获取显示频率
                self.vr_display_frequency = self.vr_system.getFloatTrackedDeviceProperty(
                    openvr.k_unTrackedDeviceIndex_Hmd,
                    openvr.Prop_DisplayFrequency_Float
                )
                print(f"✓ VR显示频率: {self.vr_display_frequency} Hz")

                # 获取IPD（瞳距）
                ipd = self.vr_system.getFloatTrackedDeviceProperty(
                    openvr.k_unTrackedDeviceIndex_Hmd,
                    openvr.Prop_UserIpdMeters_Float
                )
                print(f"✓ IPD（瞳距）: {ipd * 1000:.1f}mm")

                # 获取设备制造商和型号
                manufacturer = self.vr_system.getStringTrackedDeviceProperty(
                    openvr.k_unTrackedDeviceIndex_Hmd,
                    openvr.Prop_ManufacturerName_String
                )
                model = self.vr_system.getStringTrackedDeviceProperty(
                    openvr.k_unTrackedDeviceIndex_Hmd,
                    openvr.Prop_ModelNumber_String
                )
                print(f"✓ VR设备: {manufacturer} {model}")

                # 获取更多系统配置信息
                try:
                    # 获取刷新率相关信息
                    seconds_since_last_vsync = self.vr_system.getFloatTrackedDeviceProperty(
                        openvr.k_unTrackedDeviceIndex_Hmd,
                        openvr.Prop_SecondsFromVsyncToPhotons_Float
                    )
                    self.vsync_to_photons_ms = seconds_since_last_vsync * 1000
                    print(f"✓ VSync到光子延迟: {self.vsync_to_photons_ms:.2f}ms")

                    # 获取显示延迟信息
                    display_refresh_rate = self.vr_display_frequency
                    if display_refresh_rate > 0:
                        self.target_frame_time_ms = 1000.0 / display_refresh_rate
                        print(f"✓ 目标帧时间: {self.target_frame_time_ms:.2f}ms")

                        # 计算VSync时间窗口
                        self.vsync_window_ms = self.target_frame_time_ms * 0.1  # 10%的窗口
                        print(f"✓ VSync时间窗口: ±{self.vsync_window_ms:.2f}ms")

                except Exception as vsync_error:
                    print(f"⚠️ 获取VSync信息失败: {vsync_error}")

                # 检查是否启用了异步重投影
                try:
                    if hasattr(openvr, 'VRSettings'):
                        settings = openvr.VRSettings()
                        if settings:
                            self.async_reprojection_enabled = settings.getBool("steamvr", "enableAsyncReprojection")
                            print(f"✓ 异步重投影: {'启用' if self.async_reprojection_enabled else '禁用'}")

                            self.motion_smoothing_enabled = settings.getBool("steamvr", "motionSmoothing")
                            print(f"✓ 运动平滑: {'启用' if self.motion_smoothing_enabled else '禁用'}")

                except Exception as settings_error:
                    print(f"⚠️ 获取VR设置失败: {settings_error}")

            except Exception as e:
                print(f"⚠️ 获取VR系统信息失败: {e}")

            # 创建OpenVR姿态数组 - 分离渲染和游戏姿态
            poses_t = openvr.TrackedDevicePose_t * openvr.k_unMaxTrackedDeviceCount
            self.poses = poses_t()  # 渲染姿态（预测的）
            self.game_poses = poses_t()  # 游戏逻辑姿态（当前的）
            print("✓ VR渲染和游戏姿态数组已创建")

            # 🔧 关键修复：统一初始化流程
            # 如果目标模式是RenderPipeline，先用普通模式初始化，然后切换
            # 这样两个场景都走相同的、已验证的代码路径
            target_render_mode = self.vr_render_mode
            use_deferred_pipeline_switch = False

            if target_render_mode == VRRenderMode.RENDER_PIPELINE:
                print("🎨 目标VR渲染模式: RenderPipeline")
                print("   策略：先用普通模式初始化，然后切换到RenderPipeline")
                self.vr_render_mode = VRRenderMode.NORMAL
                use_deferred_pipeline_switch = True
            else:
                print(f"🎨 VR渲染模式: {self.vr_render_mode.value}")

            # 创建VR渲染缓冲区 - 始终用普通模式初始化
            if not self._create_vr_buffers():
                print("❌ 创建VR渲染缓冲区失败")
                return False

            # 设置VR相机
            if not self._setup_vr_cameras():
                print("❌ 设置VR相机失败")
                return False

            # 优化VR渲染管线
            self._optimize_vr_rendering()

            # 初始化手柄控制器
            self._initialize_controllers()

            # 初始化动作系统 - 仅在启用时初始化
            if not self.disable_action_system and self.action_manager:
                try:
                    if not self.action_manager.initialize():
                        print("⚠️ VR动作系统初始化失败，但VR系统将继续运行")
                except Exception as e:
                    print(f"⚠️ VR动作系统初始化异常: {e}")
            else:
                if self.disable_action_system:
                    print("🚫 VR动作系统已禁用，跳过初始化")
                else:
                    print("⚠️ VR动作管理器未创建，跳过动作系统初始化")

            # 初始化交互系统 - 检查是否存在
            if self.interaction_manager:
                try:
                    if not self.interaction_manager.initialize():
                        print("⚠️ VR交互系统初始化失败，但VR系统将继续运行")
                except Exception as e:
                    print(f"⚠️ VR交互系统初始化异常: {e}")
            else:
                print("⚠️ VR交互管理器未创建，跳过交互系统初始化")

            # 初始化VR传送系统
            if self.teleport_system:
                try:
                    if not self.teleport_system.initialize():
                        print("⚠️ VR传送系统初始化失败，但VR系统将继续运行")
                except Exception as e:
                    print(f"⚠️ VR传送系统初始化异常: {e}")
            else:
                print("⚠️ VR传送系统未创建，跳过传送系统初始化")

            # 初始化VR摇杆系统
            if self.joystick_manager:
                try:
                    # 传入传送系统引用给摇杆管理器
                    self.joystick_manager.initialize(self.teleport_system)
                    print("✓ VR摇杆系统初始化成功")
                except Exception as e:
                    print(f"⚠️ VR摇杆系统初始化异常: {e}")
            else:
                print("⚠️ VR摇杆管理器未创建，跳过摇杆系统初始化")

            # 可选：禁用异步重投影（备选方案）
            if self.disable_async_reprojection:
                self._disable_async_reprojection()

            # 启动VR更新任务
            self._start_vr_task()

            self.vr_initialized = True
            print("✅ VR系统初始化成功（普通模式）")

            # 🔧 关键修复：如果目标是RenderPipeline模式，现在切换过去
            # 这样场景2（先设RP再进VR）会走场景1（先VR再设RP）相同的代码路径
            if use_deferred_pipeline_switch:
                print("\n🔄 现在切换到目标渲染模式: RenderPipeline")
                print("   这将触发buffer重建和visualizer刷新...")
                if self.set_vr_render_mode(target_render_mode):
                    print("✅ 已成功切换到RenderPipeline模式")
                else:
                    print("⚠️ 切换到RenderPipeline失败，保持普通模式")

            return True

        except Exception as e:
            print(f"❌ VR初始化失败: {e}")
            import traceback
            traceback.print_exc()
            return False

    def _create_vr_buffers(self):
        """创建VR渲染缓冲区 - 使用分辨率缩放优化"""
        try:
            print(f"🔧 创建VR缓冲区:")
            print(f"   推荐分辨率: {self.base_eye_width}x{self.base_eye_height}")
            print(f"   缩放系数: {self.resolution_scale}")
            print(f"   实际分辨率: {self.eye_width}x{self.eye_height}")
            print(f"   像素减少: {(1 - self.resolution_scale**2) * 100:.1f}%")

            # 创建左眼纹理和缓冲区
            self.vr_left_texture = self._create_vr_texture("VR Left Eye Texture")
            self.vr_left_eye_buffer = self._create_vr_buffer(
                "VR Left Eye",
                self.vr_left_texture,
                self.eye_width,
                self.eye_height
            )

            if not self.vr_left_eye_buffer:
                print("❌ 创建左眼缓冲区失败")
                return False

            # 设置左眼缓冲区属性
            self.vr_left_eye_buffer.setSort(-100)
            self.vr_left_eye_buffer.setClearColor((0.1, 0.2, 0.4, 1))  # 深蓝色背景便于调试
            self.vr_left_eye_buffer.setActive(True)

            # 创建右眼纹理和缓冲区
            self.vr_right_texture = self._create_vr_texture("VR Right Eye Texture")
            self.vr_right_eye_buffer = self._create_vr_buffer(
                "VR Right Eye",
                self.vr_right_texture,
                self.eye_width,
                self.eye_height
            )

            if not self.vr_right_eye_buffer:
                print("❌ 创建右眼缓冲区失败")
                return False

            # 设置右眼缓冲区属性
            self.vr_right_eye_buffer.setSort(-99)
            self.vr_right_eye_buffer.setClearColor((0.1, 0.2, 0.4, 1))  # 深蓝色背景便于调试
            self.vr_right_eye_buffer.setActive(True)

            # 🚀 关键优化：立即准备纹理并缓存OpenGL ID，避免后续重复准备
            print("🔧 准备纹理并缓存OpenGL ID...")
            if self._prepare_and_cache_textures():
                print("✅ VR渲染缓冲区和纹理缓存创建成功")
                return True
            else:
                print("❌ 纹理准备失败")
                return False

        except Exception as e:
            print(f"❌ 创建VR缓冲区失败: {e}")
            import traceback
            traceback.print_exc()
            return False

    def _create_vr_texture(self, name):
        """创建VR纹理对象 - 基于参考实现"""
        texture = Texture(name)
        texture.setWrapU(Texture.WMClamp)
        texture.setWrapV(Texture.WMClamp)
        texture.setMinfilter(Texture.FTLinear)
        texture.setMagfilter(Texture.FTLinear)
        return texture

    def _prepare_and_cache_textures(self):
        """准备纹理并缓存OpenGL ID - 解决重复准备问题"""
        try:
            # 🔧 验证纹理对象存在
            if not self.vr_left_texture or not self.vr_right_texture:
                print("❌ VR纹理对象不存在")
                print(f"   左眼纹理: {self.vr_left_texture}")
                print(f"   右眼纹理: {self.vr_right_texture}")
                return False

            # 获取graphics state guardian和prepared objects
            gsg = self.world.win.getGsg()
            if not gsg:
                print("❌ 无法获取GraphicsStateGuardian")
                return False

            prepared_objects = gsg.getPreparedObjects()
            if not prepared_objects:
                print("❌ 无法获取PreparedObjects")
                return False

            # 准备左眼纹理并缓存ID
            print(f"   准备左眼纹理: {self.vr_left_texture.getXSize()}x{self.vr_left_texture.getYSize()}")
            texture_context = self.vr_left_texture.prepareNow(0, prepared_objects, gsg)
            if texture_context and hasattr(texture_context, 'getNativeId'):
                self.left_texture_id = texture_context.getNativeId()
                if self.left_texture_id > 0:
                    print(f"   ✅ 左眼纹理准备完成 ({self.vr_render_mode.value}): ID={self.left_texture_id}")
                else:
                    print("   ❌ 左眼纹理ID无效")
                    return False
            else:
                print("   ❌ 左眼纹理准备失败")
                return False

            # 准备右眼纹理并缓存ID
            print(f"   准备右眼纹理: {self.vr_right_texture.getXSize()}x{self.vr_right_texture.getYSize()}")
            texture_context = self.vr_right_texture.prepareNow(0, prepared_objects, gsg)
            if texture_context and hasattr(texture_context, 'getNativeId'):
                self.right_texture_id = texture_context.getNativeId()
                if self.right_texture_id > 0:
                    print(f"   ✅ 右眼纹理准备完成 ({self.vr_render_mode.value}): ID={self.right_texture_id}")
                else:
                    print("   ❌ 右眼纹理ID无效")
                    return False
            else:
                print("   ❌ 右眼纹理准备失败")
                return False

            # 标记纹理已准备
            self.textures_prepared = True
            print("   ✅ 纹理准备完成，ID已缓存，后续帧将直接使用缓存ID")
            return True

        except Exception as e:
            print(f"❌ 纹理准备和缓存失败: {e}")
            import traceback
            traceback.print_exc()
            return False

    def _create_vr_buffer(self, name, texture, width, height):
        """创建VR渲染缓冲区 - 基于参考实现 + 性能诊断"""
        # 设置帧缓冲属性
        fbprops = FrameBufferProperties()
        fbprops.setRgbaBits(1, 1, 1, 1)
        # 可以在这里添加多重采样抗锯齿
        # fbprops.setMultisamples(4)

        # 创建缓冲区
        buffer = self.world.win.makeTextureBuffer(name, width, height, to_ram=False, fbp=fbprops)

        if buffer:
            # 🔍 性能诊断：检查缓冲区类型和属性
            self._diagnose_buffer_performance(buffer, name, width, height)

            # 清除默认渲染纹理
            buffer.clearRenderTextures()
            # 🚀 使用RTMBindOrCopy模式 - 已经是最优选择
            # RTMBindOrCopy会尝试直接绑定到纹理，只有硬件不支持时才回退到复制
            # 这已经是Panda3D中最高效的渲染到纹理模式
            buffer.addRenderTexture(texture, GraphicsOutput.RTMBindOrCopy, GraphicsOutput.RTPColor)

        else:
            print(f"⚠️ VR缓冲区创建失败: {name} ({width}x{height})")

        return buffer

    def _diagnose_buffer_performance(self, buffer, name, width, height):
        """诊断VR缓冲区性能特性"""
        try:
            # 检查缓冲区类型
            buffer_type = type(buffer).__name__

            # 检查是否为parasite buffer（性能较差的类型）
            is_parasite = 'Parasite' in buffer_type

            # 获取缓冲区信息
            is_valid = buffer.isValid()
            is_hardware = hasattr(buffer, 'getGsg') and buffer.getGsg() is not None

            # 输出诊断信息（仅第一次创建时）
            if not hasattr(self, '_buffer_diagnosis_shown'):
                print(f"🔍 VR缓冲区诊断 [{name}]:")
                print(f"   类型: {buffer_type}")
                print(f"   分辨率: {width}x{height} ({width*height/1000000:.1f}M像素)")
                print(f"   有效性: {'✓' if is_valid else '✗'}")
                print(f"   硬件支持: {'✓' if is_hardware else '✗'}")

                if is_parasite:
                    print(f"   ⚠️ 检测到Parasite Buffer - 性能可能受限")
                    print(f"   建议: 检查显卡是否支持真正的离屏渲染")
                else:
                    print(f"   ✓ 使用硬件FBO - 性能良好")

                # 显示帧缓冲区属性
                if hasattr(buffer, 'getFbProperties'):
                    fbp = buffer.getFbProperties()
                    if fbp:
                        print(f"   颜色位数: R{fbp.getRedBits()}G{fbp.getGreenBits()}B{fbp.getBlueBits()}A{fbp.getAlphaBits()}")
                        if hasattr(fbp, 'getMultisamples') and fbp.getMultisamples() > 0:
                            print(f"   MSAA: {fbp.getMultisamples()}x")

                self._buffer_diagnosis_shown = True

        except Exception as e:
            print(f"缓冲区诊断失败: {e}")

    def _create_vr_buffers_with_pipeline(self):
        """创建带RenderPipeline的VR渲染缓冲区 - 高级渲染模式"""
        try:
            print(f"🎨 创建RenderPipeline VR缓冲区:")
            print(f"   推荐分辨率: {self.base_eye_width}x{self.base_eye_height}")
            print(f"   Pipeline缩放: {self.pipeline_resolution_scale}")

            # 检查RenderPipeline是否可用
            if not hasattr(self.world, 'render_pipeline') or not self.world.render_pipeline:
                print("❌ RenderPipeline未初始化，无法使用高级渲染模式")
                return False

            pipeline = self.world.render_pipeline

            # 计算RenderPipeline模式下的分辨率
            pipeline_width = int(self.base_eye_width * self.pipeline_resolution_scale)
            pipeline_height = int(self.base_eye_height * self.pipeline_resolution_scale)

            print(f"   实际分辨率: {pipeline_width}x{pipeline_height}")
            print(f"   像素减少: {(1 - self.pipeline_resolution_scale**2) * 100:.1f}%")

            # 导入RenderPipeline相关模块
            try:
                from RenderPipelineFile.rpcore.render_target import RenderTarget
            except ImportError as e:
                print(f"❌ 无法导入RenderPipeline模块: {e}")
                return False

            # 导入VR stages模块
            try:
                from core.vr.rendering.stages import VRPipelineController
            except ImportError as e:
                print(f"❌ 无法导入VR stages模块: {e}")
                return False

            # 创建VR Pipeline控制器
            print("   初始化VR Pipeline控制器...")
            self.vr_pipeline_controller = VRPipelineController(pipeline)

            # 保存分辨率信息（将在_setup_vr_cameras中使用）
            self.pipeline_vr_width = pipeline_width
            self.pipeline_vr_height = pipeline_height

            # 应用RenderPipeline效果配置
            self._apply_pipeline_vr_effects()

            self.render_pipeline_enabled = True
            print("✅ VR Pipeline控制器已初始化（将在相机设置时创建完整管线）")

            # 检查天空盒状态
            self._check_skybox_status()

            return True

        except Exception as e:
            print(f"❌ 创建RenderPipeline VR缓冲区失败: {e}")
            import traceback
            traceback.print_exc()
            return False

    def _apply_pipeline_vr_effects(self):
        """为VR场景应用RenderPipeline效果配置"""
        try:
            print("🎨 应用RenderPipeline VR优化配置...")

            # 根据配置调整RenderPipeline设置
            config = self.pipeline_vr_config

            # 注意：实际的插件启用/禁用需要在pipeline.yaml中配置
            # 这里只是记录当前的VR优化意图
            print(f"   阴影: {'启用' if config['enable_shadows'] else '禁用'}")
            print(f"   环境光遮蔽: {'启用' if config['enable_ao'] else '禁用'}")
            print(f"   泛光效果: {'启用' if config['enable_bloom'] else '禁用'} (VR推荐禁用)")
            print(f"   运动模糊: {'启用' if config['enable_motion_blur'] else '禁用'} (VR推荐禁用)")
            print(f"   屏幕空间反射: {'启用' if config['enable_ssr'] else '禁用'} (VR推荐禁用)")

            print("✅ RenderPipeline VR效果配置完成")

        except Exception as e:
            print(f"⚠️ 应用RenderPipeline VR效果失败: {e}")

    def _check_skybox_status(self):
        """检查并报告天空盒状态"""
        try:
            print("\n🌌 检查天空盒状态...")

            # 方法1：在render节点下搜索所有名字包含skybox的节点
            skybox_nodes = self.world.render.findAllMatches("**/skybox*")
            if skybox_nodes and skybox_nodes.getNumPaths() > 0:
                print(f"   ✓ 找到 {skybox_nodes.getNumPaths()} 个天空盒节点（使用名称搜索）")
                for i in range(skybox_nodes.getNumPaths()):
                    skybox = skybox_nodes.getPath(i)
                    print(f"   天空盒 #{i+1}:")
                    print(f"      名称: {skybox.getName()}")
                    print(f"      位置: {skybox.getPos()}")
                    print(f"      缩放: {skybox.getScale()}")
                    print(f"      父节点: {skybox.getParent().getName()}")

                    # 检查是否有shader
                    if skybox.hasShader():
                        print(f"      ✓ 已应用shader效果")
                    else:
                        print(f"      ⚠️ 未应用shader效果")

                    # 检查bin设置
                    if skybox.hasBin():
                        print(f"      Bin: {skybox.getBinName()}")
            else:
                print("   ⚠️ 未找到天空盒（名称搜索）")

            # 方法2：搜索所有GeomNode（几何节点），天空盒通常是一个大的几何体
            print("   搜索所有几何节点...")
            all_geoms = self.world.render.findAllMatches("**/+GeomNode")
            print(f"   找到 {all_geoms.getNumPaths()} 个几何节点")

            # 查找大型几何体（缩放值很大，可能是天空盒）
            skybox_candidates = []
            for i in range(all_geoms.getNumPaths()):
                geom_node = all_geoms.getPath(i)
                scale = geom_node.getScale()
                # 天空盒通常缩放很大（如40000）
                if scale[0] > 1000 or scale[1] > 1000 or scale[2] > 1000:
                    print(f"   ✓ 找到大型几何体（可能是天空盒）:")
                    print(f"      名称: {geom_node.getName()}")
                    print(f"      缩放: {scale}")
                    print(f"      位置: {geom_node.getPos()}")
                    if geom_node.hasShader():
                        print(f"      ✓ 已应用shader")
                    skybox_candidates.append(geom_node)

            # 方法3：检查render节点的所有直接子节点（显示全部）
            print("   检查render的所有直接子节点...")
            render_children = self.world.render.getChildren()
            print(f"   render有 {render_children.getNumPaths()} 个直接子节点:")
            for i in range(render_children.getNumPaths()):
                child = render_children.getPath(i)
                scale = child.getScale()
                # 标记大型节点（可能是天空盒）
                if scale[0] > 1000 or scale[1] > 1000 or scale[2] > 1000:
                    print(f"      - {child.getName()} ⭐ (大型节点，缩放: {scale})")
                else:
                    print(f"      - {child.getName()}")

            # 报告结果但不自动创建
            if len(skybox_candidates) == 0:
                print("   ⚠️ 未找到明显的天空盒（缩放>1000的几何体）")
                print("   💡 RenderPipeline的天空盒可能在上述列表中，但缩放值不同")
                print("   💡 或者可能RenderPipeline未在VR模式下自动创建天空盒")
            else:
                print(f"   ✓ 找到 {len(skybox_candidates)} 个可能的天空盒")

            print("🌌 天空盒状态检查完成\n")

        except Exception as e:
            print(f"⚠️ 天空盒状态检查失败: {e}")
            import traceback
            traceback.print_exc()

    def _create_vr_skybox(self):
        """为VR创建天空盒"""
        try:
            print("   🎨 创建VR天空盒...")

            # 检查RenderPipeline是否可用
            if hasattr(self.world, 'render_pipeline') and self.world.render_pipeline:
                pipeline = self.world.render_pipeline

                # 使用RenderPipeline的load_default_skybox方法
                print("   使用RenderPipeline方法创建天空盒...")
                skybox = pipeline.common_resources.load_default_skybox()

                if skybox:
                    # 设置天空盒属性
                    skybox.set_scale(40000)  # 大型缩放
                    skybox.reparent_to(self.world.render)
                    skybox.set_bin("unsorted", 10000)  # 最后渲染

                    # 应用天空盒shader效果
                    pipeline.set_effect(skybox, "effects/skybox.yaml", {
                        "render_shadow": False,
                        "render_envmap": False,
                        "render_voxelize": False,
                        "alpha_testing": False,
                        "normal_mapping": False,
                        "parallax_mapping": False
                    }, 1000)

                    print(f"   ✅ VR天空盒已创建")
                    print(f"      名称: {skybox.getName()}")
                    print(f"      缩放: {skybox.getScale()}")
                    print(f"      位置: {skybox.getPos()}")
                    return skybox
                else:
                    print("   ❌ 无法加载天空盒模型")
                    return None
            else:
                print("   ❌ RenderPipeline未初始化，无法创建天空盒")
                return None

        except Exception as e:
            print(f"   ❌ 创建VR天空盒失败: {e}")
            import traceback
            traceback.print_exc()
            return None

    def _setup_vr_cameras(self):
        """设置VR相机 - 使用锚点层级系统"""
        try:
            # 创建VR追踪空间锚点层级
            self.tracking_space = self.world.render.attachNewNode('tracking-space')
            self.hmd_anchor = self.tracking_space.attachNewNode('hmd-anchor')
            self.left_eye_anchor = self.hmd_anchor.attachNewNode('left-eye')
            self.right_eye_anchor = self.hmd_anchor.attachNewNode('right-eye')

            # 获取投影矩阵
            projection_left = self.coord_mat_inv * self.convert_mat(
                self.vr_system.getProjectionMatrix(openvr.Eye_Left, self.near_clip, self.far_clip))
            projection_right = self.coord_mat_inv * self.convert_mat(
                self.vr_system.getProjectionMatrix(openvr.Eye_Right, self.near_clip, self.far_clip))

            # 创建左眼相机节点
            left_cam_node = Camera('left-cam')
            left_lens = MatrixLens()
            left_lens.setUserMat(projection_left)
            left_cam_node.setLens(left_lens)

            # 创建右眼相机节点
            right_cam_node = Camera('right-cam')
            right_lens = MatrixLens()
            right_lens.setUserMat(projection_right)
            right_cam_node.setLens(right_lens)

            # 附加相机到眼睛锚点
            self.vr_left_camera = self.left_eye_anchor.attachNewNode(left_cam_node)
            self.vr_right_camera = self.right_eye_anchor.attachNewNode(right_cam_node)

            # 设置显示区域 - 区分RenderPipeline和普通模式
            if self.vr_render_mode == VRRenderMode.RENDER_PIPELINE and self.vr_pipeline_controller:
                # RenderPipeline模式：使用VRPipelineController创建完整管线
                print("   使用VR Pipeline创建立体渲染管线...")

                # 创建立体渲染管线（GBuffer + Lighting + Final stages）
                success = self.vr_pipeline_controller.create_stereo_pipeline(
                    self.pipeline_vr_width,
                    self.pipeline_vr_height,
                    self.vr_left_camera,
                    self.vr_right_camera
                )

                if not success:
                    print("❌ VR Pipeline创建失败")
                    return False

                # 获取GBuffer的内部buffer（用于DisplayRegion）
                self.vr_left_eye_buffer = self.vr_pipeline_controller.get_left_buffer()
                self.vr_right_eye_buffer = self.vr_pipeline_controller.get_right_buffer()

                # 🔧 关键修复：验证buffer有效性
                if not self.vr_left_eye_buffer or not self.vr_right_eye_buffer:
                    print("❌ VR Pipeline buffer创建失败")
                    print(f"   左眼buffer: {self.vr_left_eye_buffer}")
                    print(f"   右眼buffer: {self.vr_right_eye_buffer}")
                    return False

                # 获取最终输出纹理（用于提交到OpenVR）
                left_textures = self.vr_pipeline_controller.get_left_textures()
                right_textures = self.vr_pipeline_controller.get_right_textures()

                if left_textures and right_textures:
                    self.vr_left_texture = left_textures["final"]
                    self.vr_right_texture = right_textures["final"]
                else:
                    print("❌ 无法获取VR Pipeline输出纹理")
                    return False

                # 设置缓冲区排序和清除颜色
                if self.vr_left_eye_buffer:
                    self.vr_left_eye_buffer.setSort(-100)
                    self.vr_left_eye_buffer.setClearColorActive(True)
                    self.vr_left_eye_buffer.setClearColor((0.1, 0.2, 0.4, 1))

                if self.vr_right_eye_buffer:
                    self.vr_right_eye_buffer.setSort(-99)
                    self.vr_right_eye_buffer.setClearColorActive(True)
                    self.vr_right_eye_buffer.setClearColor((0.1, 0.2, 0.4, 1))

                # 🔧 关键修复：为RenderPipeline的GBuffer DisplayRegion设置DrawCallback
                # 这确保纹理在渲染完成后被提交到OpenVR
                if self.vr_left_eye_buffer and self.vr_right_eye_buffer:
                    print("   设置RenderPipeline DisplayRegion回调...")
                    try:
                        # 🔧 验证DisplayRegion数量
                        left_dr_count = self.vr_left_eye_buffer.getNumDisplayRegions()
                        right_dr_count = self.vr_right_eye_buffer.getNumDisplayRegions()

                        print(f"   左眼buffer DisplayRegion数量: {left_dr_count}")
                        print(f"   右眼buffer DisplayRegion数量: {right_dr_count}")

                        if left_dr_count == 0 or right_dr_count == 0:
                            print("   ❌ DisplayRegion未创建，无法设置回调")
                            return False

                        # 获取RenderTarget创建的DisplayRegion
                        left_dr = self.vr_left_eye_buffer.get_display_region(0)
                        right_dr = self.vr_right_eye_buffer.get_display_region(0)

                        # 验证DisplayRegion有效性
                        if not left_dr or not right_dr:
                            print("   ❌ DisplayRegion无效")
                            return False

                        # 设置渲染回调（与普通模式一致）
                        left_dr.setDrawCallback(PythonCallbackObject(self.simple_left_cb))
                        right_dr.setDrawCallback(PythonCallbackObject(self.simple_right_cb))

                        # 确保DisplayRegion处于活动状态
                        left_dr.setActive(True)
                        right_dr.setActive(True)

                        print("   ✅ RenderPipeline DisplayRegion回调已设置")
                    except Exception as e:
                        print(f"   ⚠️ 设置DisplayRegion回调失败: {e}")
                        import traceback
                        traceback.print_exc()
                        return False

                # 🔧 关键修复：强制同步GraphicsEngine，确保所有buffer完全初始化
                print("   同步GraphicsEngine...")
                self.world.graphicsEngine.renderFrame()

                # 准备纹理并缓存OpenGL ID
                if not self._prepare_and_cache_textures():
                    print("❌ RenderPipeline纹理准备失败")
                    return False

                print("✅ VR Pipeline立体渲染管线已准备完成")
            else:
                # 普通模式：创建新的DisplayRegion
                print("   使用普通渲染区域...")
                left_dr = self.vr_left_eye_buffer.makeDisplayRegion()
                left_dr.setCamera(self.vr_left_camera)
                left_dr.setActive(True)
                left_dr.setDrawCallback(PythonCallbackObject(self.simple_left_cb))

                right_dr = self.vr_right_eye_buffer.makeDisplayRegion()
                right_dr.setCamera(self.vr_right_camera)
                right_dr.setActive(True)
                right_dr.setDrawCallback(PythonCallbackObject(self.simple_right_cb))

            print("✓ VR相机锚点层级系统设置完成")
            return True

        except Exception as e:
            print(f"❌ 设置VR相机失败: {e}")
            import traceback
            traceback.print_exc()
            return False

    def _get_eye_offset(self, eye):
        """获取眼睛相对于头显的偏移"""
        try:
            if not self.vr_system:
                # 使用标准IPD（瞳距）估算值
                ipd = 0.064  # 64mm，平均IPD
                if eye == openvr.Eye_Left:
                    return Vec3(-ipd/2, 0, 0)
                else:
                    return Vec3(ipd/2, 0, 0)

            # 从OpenVR获取眼睛到头显的变换矩阵
            eye_transform = self.vr_system.getEyeToHeadTransform(eye)

            # 提取位移信息
            x = eye_transform[0][3]
            y = eye_transform[1][3]
            z = eye_transform[2][3]

            return Vec3(x, y, z)

        except Exception as e:
            print(f"❌ 获取眼睛偏移失败: {e}")
            # 返回默认值
            ipd = 0.064
            if eye == openvr.Eye_Left:
                return Vec3(-ipd/2, 0, 0)
            else:
                return Vec3(ipd/2, 0, 0)

    def _optimize_vr_rendering(self):
        """优化VR模式下的渲染管线 - 减少不必要的后处理开销"""
        try:
            print("🔧 正在优化VR渲染管线...")

            # 检查是否有RenderPipeline
            if hasattr(self.world, 'render_pipeline') and self.world.render_pipeline:
                print("   检测到RenderPipeline，正在优化...")

                # 对VR缓冲区应用轻量级渲染设置
                if hasattr(self, 'vr_left_eye_buffer') and self.vr_left_eye_buffer:
                    self._apply_lightweight_rendering(self.vr_left_eye_buffer, "左眼")

                if hasattr(self, 'vr_right_eye_buffer') and self.vr_right_eye_buffer:
                    self._apply_lightweight_rendering(self.vr_right_eye_buffer, "右眼")

                print("✅ VR渲染管线优化完成")
            else:
                print("   未检测到RenderPipeline，使用默认Panda3D渲染")

            # 禁用VR缓冲区的不必要功能
            self._disable_vr_buffer_extras()

        except Exception as e:
            print(f"⚠️ VR渲染优化失败: {e}")
            import traceback
            traceback.print_exc()

    def _apply_lightweight_rendering(self, buffer, eye_name):
        """为VR缓冲区应用轻量级渲染设置"""
        try:
            # 禁用多重采样抗锯齿（MSAA）以提升性能
            if hasattr(buffer, 'setMultisample'):
                buffer.setMultisample(0)
                print(f"   {eye_name}: 禁用MSAA")

            # 设置更简单的清除颜色操作
            buffer.setClearColorActive(True)
            buffer.setClearColor((0.1, 0.2, 0.4, 1.0))  # 深蓝色，便于调试

            # 禁用深度写入到某些不需要的缓冲区
            # （保留主要深度测试，但减少不必要的写入）

            print(f"   {eye_name}: 应用轻量级渲染设置")

        except Exception as e:
            print(f"⚠️ {eye_name}缓冲区优化失败: {e}")

    def _disable_vr_buffer_extras(self):
        """禁用VR缓冲区的额外功能以提升性能"""
        try:
            # 禁用VR缓冲区的统计收集
            if hasattr(self, 'vr_left_eye_buffer') and self.vr_left_eye_buffer:
                if hasattr(self.vr_left_eye_buffer, 'setOneShot'):
                    self.vr_left_eye_buffer.setOneShot(False)

            if hasattr(self, 'vr_right_eye_buffer') and self.vr_right_eye_buffer:
                if hasattr(self.vr_right_eye_buffer, 'setOneShot'):
                    self.vr_right_eye_buffer.setOneShot(False)

            print("   VR缓冲区额外功能已优化")

        except Exception as e:
            print(f"⚠️ VR缓冲区额外功能优化失败: {e}")

    def _start_vr_task(self):
        """启动VR更新任务"""
        if self.vr_task:
            self.world.taskMgr.remove(self.vr_task)

        # 设置高优先级（sort=-1000），确保在渲染之前执行，参考 panda3d-openvr
        self.vr_task = self.world.taskMgr.add(self._update_vr, "update_vr", sort=-1000)
        print("✓ VR更新任务已启动（高优先级，sort=-1000）")

    def _update_vr(self, task):
        """VR更新任务 - 每帧调用（参考 panda3d-openvr 架构）"""
        if not self.vr_enabled or not self.vr_system:
            return task.cont

        try:
            # 📌 第一件事：waitGetPoses 阻塞等待 VSync（参考 panda3d-openvr）
            # 这会阻塞整个任务，确保每个 VSync 周期只执行一次
            should_call_waitgetposes = (
                not self.vr_test_mode or  # 普通VR模式总是需要
                self.test_mode_wait_poses  # 测试模式：仅当启用姿态等待时
            )

            if should_call_waitgetposes:
                self._wait_get_poses_immediate()
                # 立即更新手柄，使用最新姿态（避免过时数据）
                self.update_tracked_devices()

            # 性能监控
            self.frame_count += 1

            # 🚀 自动启用性能模式 - 减少计时对象创建
            if not self.performance_mode_enabled and self.frame_count >= self.performance_mode_trigger_frame:
                self.performance_mode_enabled = True
                if self.frame_count <= self.performance_mode_trigger_frame + 5:  # 只输出一次
                    print(f"🎯 性能模式已启用 (帧#{self.frame_count}) - 禁用详细监控以提升性能")

            # 记录帧时间
            self._track_frame_time()

            # 计算VR FPS
            import time
            current_time = time.time()
            if self.last_fps_time == 0:
                self.last_fps_time = current_time
            elif current_time - self.last_fps_time >= 1.0:  # 每秒更新一次FPS
                self.vr_fps = (self.frame_count - self.last_fps_check) / (current_time - self.last_fps_time)
                self.last_fps_check = self.frame_count
                self.last_fps_time = current_time

            # 📌 使用刚获取的姿态更新相机（而不是旧姿态）
            self._update_camera_poses()

            # 输出策略信息（仅第一次）
            if not hasattr(self, '_new_architecture_logged'):
                print("✅ 新架构已启用 - waitGetPoses 在任务开始阻塞，参考 panda3d-openvr")
                print("   这确保每个 VSync 周期只渲染一次，解决 AlreadySubmitted 错误")
                self._new_architecture_logged = True

            # 更新VR动作状态 - 仅在启用时更新
            if not self.disable_action_system and self.action_manager:
                self.action_manager.update_actions()

            # 更新VR交互系统
            if self.interaction_manager:
                self.interaction_manager.update()

            # 更新VR摇杆系统
            if self.joystick_manager:
                # 计算帧间隔时间
                import time
                if not hasattr(self, '_last_frame_time'):
                    self._last_frame_time = time.time()
                    dt = 0.016  # 默认60fps
                else:
                    current_time = time.time()
                    dt = current_time - self._last_frame_time
                    self._last_frame_time = current_time
                    # 限制dt范围，避免异常情况
                    dt = max(0.001, min(0.1, dt))

                self.joystick_manager.update(dt)

            # 更新系统性能指标（减少频率）
            if self.frame_count % 30 == 1:  # 每30帧更新一次，减少开销
                self._update_performance_metrics()

            # 更新GPU渲染时间统计（减少频率）
            if self.enable_gpu_timing and self.frame_count % 60 == 1:
                self._get_gpu_frame_timing()

            # 🚀 手动垃圾回收控制 - 避免16-19帧周期性峰值
            self._manual_gc_control()

            # 定期输出性能报告 - 默认10秒间隔
            report_interval = getattr(self, 'performance_report_interval', 600)
            if self.frame_count % report_interval == 1:
                self._print_performance_report()

        except Exception as e:
            print(f"VR更新错误: {e}")
            import traceback
            traceback.print_exc()

        return task.cont

    def _sync_gpu_if_needed(self):
        """可选的GPU同步 - 仅在需要时使用"""
        try:
            # 同步等待GPU完成（如果需要）
            gsg = self.world.win.getGsg()
            if gsg:
                gsg.getEngine().syncFrame()
        except Exception as e:
            print(f"❌ GPU同步异常: {e}")

    def simple_left_cb(self, cbdata):
        """简化的左眼渲染回调 - 精确控制渲染和提交"""
        try:
            # 🔍 精确测量渲染时间
            import time
            render_start = time.perf_counter()

            # 触发实际渲染
            cbdata.upcall()

            # 计算真实渲染时间
            self.left_render_time = (time.perf_counter() - render_start) * 1000  # 转换为毫秒

            # 记录渲染次数
            self.left_render_count += 1

            # 📌 OpenVR 帧边界检查：防止同一 OpenVR 帧内重复渲染
            if self.left_eye_last_render_frame == self.openvr_frame_id:
                return  # 已在当前 OpenVR 帧渲染过，跳过

            # 🔧 OpenVR最佳实践：左眼只渲染，不立即提交
            # 基于官方hellovr示例：两眼都渲染完后再批量提交
            self.left_eye_last_render_frame = self.openvr_frame_id

            # 渐进式VR功能测试：单独启用纹理提交时保留原逻辑
            should_submit = self.vr_test_mode and self.test_mode_submit_texture and not self.test_mode_wait_poses

            if should_submit:
                # 测试模式：单独启用纹理提交时的兼容模式
                if self.vr_compositor and self.vr_left_texture:
                    self.submit_texture(openvr.Eye_Left, self.vr_left_texture)

            if self.vr_test_mode:
                # 测试模式：始终触发屏幕显示更新
                self._update_test_display()

        except Exception as e:
            print(f"左眼渲染回调错误: {e}")

    def simple_right_cb(self, cbdata):
        """简化的右眼渲染回调 - 精确控制渲染和提交"""
        try:
            # 🔍 精确测量渲染时间
            import time
            render_start = time.perf_counter()

            # 触发实际渲染
            cbdata.upcall()

            # 计算真实渲染时间
            self.right_render_time = (time.perf_counter() - render_start) * 1000  # 转换为毫秒

            # 记录渲染次数
            self.right_render_count += 1

            # 📌 OpenVR 帧边界检查：防止同一 OpenVR 帧内重复渲染
            if self.right_eye_last_render_frame == self.openvr_frame_id:
                return  # 已在当前 OpenVR 帧渲染过，跳过

            # 🔧 OpenVR最佳实践：右眼渲染完成后批量提交两眼纹理
            # 基于官方hellovr示例：避免分散提交导致的VSync阻塞
            self.right_eye_last_render_frame = self.openvr_frame_id

            # 🔧 渐进式VR功能测试：根据调试标志决定启用哪些功能
            should_batch_submit = not self.vr_test_mode or self.test_mode_submit_texture
            should_wait_poses = not self.vr_test_mode or self.test_mode_wait_poses

            # 特殊处理：测试模式单独启用功能时的兼容模式
            if self.vr_test_mode:
                if self.test_mode_submit_texture and not self.test_mode_wait_poses:
                    # 单独测试纹理提交：使用原来的分散提交方式
                    if self.vr_compositor and self.vr_right_texture:
                        self.submit_texture(openvr.Eye_Right, self.vr_right_texture)

                        # 🚀 测试模式也需要PostPresentHandoff避免36FPS
                        try:
                            if hasattr(self.vr_compositor, 'postPresentHandoff'):
                                self.vr_compositor.postPresentHandoff()
                            elif hasattr(self.vr_compositor, 'PostPresentHandoff'):
                                self.vr_compositor.PostPresentHandoff()
                        except Exception as e:
                            pass  # 测试模式静默忽略错误
                    should_batch_submit = False
                elif self.test_mode_wait_poses and not self.test_mode_submit_texture:
                    # 单独测试姿态等待：不提交纹理
                    should_batch_submit = False

            if should_batch_submit:
                # 🚀 OpenVR最佳实践：批量提交两眼纹理
                # 这是解决36FPS问题的关键修复
                self._batch_submit_textures()

            # 🔧 关键修复：移除Submit后立即WaitGetPoses的错误实现
            # 根据OpenVR官方文档："Calling WaitGetPoses immediately after Submit is conspicuously wrong"
            # WaitGetPoses应该在下一帧开始时通过update_vr_task调用，不是Submit后立即调用
            #
            # if should_wait_poses:
            #     # 错误的实现：Submit后立即获取姿态导致36FPS
            #     self._wait_get_poses_immediate()  # ← 这是36FPS的根本原因！
            #
            # 正确的实现：让update_vr_task在下一帧开始时调用WaitGetPoses

            if self.vr_test_mode:
                # 测试模式：始终更新性能HUD
                self._update_test_performance_hud()

        except Exception as e:
            print(f"右眼渲染回调错误: {e}")

    def _wait_get_poses(self):
        """调用VRCompositor的waitGetPoses来获取焦点和姿态数据"""
        try:
            if not self.vr_compositor or not self.poses:
                return

            # 调用waitGetPoses获取焦点和姿态数据
            # 这个调用可能会阻塞直到下一个VR同步点
            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 self.frame_count % 600 == 1:  # 每10秒输出一次@60fps
                print(f"📊 VR姿态状态 - 有效姿态数: {valid_poses}, 总帧数: {self.frame_count}")

        except Exception as e:
            # 限制错误输出频率
            if not hasattr(self, '_last_error_frame'):
                self._last_error_frame = 0

            if self.frame_count - self._last_error_frame > 300:  # 每5秒最多输出一次错误
                print(f"waitGetPoses失败: {e}")
                self._last_error_frame = self.frame_count

            # 记录姿态失败次数
            self.pose_failures += 1

    def _wait_get_poses_immediate(self):
        """立即获取VR姿态 - 修复ATW闪烁的关键方法（双姿态版本）"""
        # 开始计时waitGetPoses操作
        timing = self._start_timing('wait_poses')

        try:
            if not self.vr_compositor or not self.poses or not self.game_poses:
                self._end_timing(timing)
                return

            # 关键修复：传递渲染姿态和游戏姿态数组
            # 渲染姿态用于绘制，游戏姿态用于逻辑，避免ATW过度补偿
            result = self.vr_compositor.waitGetPoses(self.poses, self.game_poses)

            # 📌 waitGetPoses 成功后立即递增 OpenVR 帧ID（新帧开始）
            self.openvr_frame_id += 1

            # 结束计时
            wait_time = self._end_timing(timing)

            # 检查姿态数据的有效性
            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

            # 🚀 优化控制器姿态更新：使用缓存，避免每帧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

                        # 检查是否已有此设备的缓存矩阵
                        if device_id not in self.controller_poses:
                            # 第一次检测到该控制器，创建新的缓存矩阵
                            self.controller_poses[device_id] = self._convert_openvr_matrix_to_panda(controller_matrix)
                        else:
                            # 复用现有矩阵，只更新数值，避免创建新对象
                            cached_mat = self.controller_poses[device_id]
                            self._update_matrix_from_openvr(cached_mat, controller_matrix)

                        valid_poses += 1
                else:
                    # 设备姿态无效，从字典中移除（如果存在）
                    if device_id in self.controller_poses:
                        # 将矩阵返回对象池
                        self._return_pooled_matrix(self.controller_poses[device_id])
                        del self.controller_poses[device_id]

            # 🔧 关键修复：立即更新手柄和跟踪设备
            # Running Start模式下必须在WaitGetPoses后立即更新，避免手柄消失
            self.update_tracked_devices()

            # 调试信息 - 仅在第一次成功时输出
            if not hasattr(self, '_dual_pose_mode_logged') and valid_poses > 0:
                print(f"✅ 双姿态立即获取模式启用 - 有效姿态数: {valid_poses}")
                print("   渲染姿态用于绘制，游戏姿态用于逻辑，防止ATW过度补偿")
                print("   手柄和跟踪设备在WaitGetPoses后立即更新")
                self._dual_pose_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 _wait_get_poses_with_prediction(self):
        """使用预测时间获取VR姿态 - 优化性能的新策略"""
        try:
            if not self.vr_compositor or not self.poses or not self.game_poses:
                return

            # 使用预测时间获取姿态
            # 预测时间通常为11-16ms，对应下一个VR帧的时间
            result = self.vr_compositor.waitGetPoses(self.poses, self.game_poses)

            # 检查姿态数据的有效性
            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_task'):
                    print("⚠️ HMD姿态数据无效（更新任务模式）")
                    self._hmd_invalid_warning_task = 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, '_update_task_mode_logged') and valid_poses > 0:
                print(f"✅ 更新任务姿态获取模式启用 - 有效姿态数: {valid_poses}")
                print(f"   预测时间: {self.use_prediction_time*1000:.1f}ms")
                self._update_task_mode_logged = True

        except Exception as e:
            # 限制错误输出频率
            if not hasattr(self, '_last_task_error_frame'):
                self._last_task_error_frame = 0

            if self.frame_count - self._last_task_error_frame > 300:  # 每5秒最多输出一次错误
                print(f"更新任务姿态获取失败: {e}")
                self._last_task_error_frame = self.frame_count

            # 记录姿态失败次数
            self.pose_failures += 1

    def _cache_poses_for_next_frame(self):
        """缓存当前姿态供下一帧渲染使用 - 修复时序不匹配"""
        try:
            if not self.poses or len(self.poses) == 0:
                return

            # 如果是第一帧，直接使用当前姿态
            if self._first_frame:
                self._cached_render_poses = self.poses
                self._first_frame = False
                print("✓ 首帧姿态缓存已设置")
                return

            # 复制当前渲染姿态到缓存
            # 下一帧将使用这些姿态进行渲染
            poses_t = openvr.TrackedDevicePose_t * openvr.k_unMaxTrackedDeviceCount
            cached_poses = poses_t()

            # 复制姿态数据
            for i in range(len(self.poses)):
                cached_poses[i] = self.poses[i]

            self._cached_render_poses = cached_poses

        except Exception as e:
            print(f"⚠️ 姿态缓存失败: {e}")


    def _reset_waitgetposes_flag(self, task):
        """重置WaitGetPoses标记 - 确保下一帧可以调用WaitGetPoses"""
        self._waitgetposes_called_this_frame = False
        return task.done

    def _update_tracking_data(self):
        """更新VR追踪数据"""
        try:
            # 获取设备姿态
            poses = self.vr_system.getDeviceToAbsoluteTrackingPose(
                openvr.TrackingUniverseStanding, 0.0, openvr.k_unMaxTrackedDeviceCount
            )

            # 更新HMD姿态（设备0通常是头显）
            if poses[0].bPoseIsValid:
                hmd_matrix = poses[0].mDeviceToAbsoluteTracking
                self.hmd_pose = self._convert_openvr_matrix_to_panda(hmd_matrix)

            # 更新控制器姿态
            for device_id in range(1, openvr.k_unMaxTrackedDeviceCount):
                if poses[device_id].bPoseIsValid:
                    device_class = self.vr_system.getTrackedDeviceClass(device_id)
                    if device_class == openvr.TrackedDeviceClass_Controller:
                        controller_matrix = poses[device_id].mDeviceToAbsoluteTracking
                        self.controller_poses[device_id] = self._convert_openvr_matrix_to_panda(controller_matrix)

        except Exception as e:
            print(f"更新追踪数据失败: {e}")

    def _convert_openvr_matrix_to_panda(self, ovr_matrix):
        """将OpenVR矩阵转换为Panda3D矩阵 - 使用对象池优化

        坐标系转换：
        OpenVR: X右, Y上, -Z前（右手坐标系）
        Panda3D: X右, Y前, Z上（右手坐标系）

        转换规则：
        OpenVR X → Panda3D X
        OpenVR Y → Panda3D Z
        OpenVR -Z → Panda3D Y
        """
        # 🚀 使用对象池获取预分配的Mat4对象，避免每帧创建新对象
        mat = self._get_pooled_matrix()

        # 修正的坐标转换矩阵
        # OpenVR: X右, Y上, -Z前 → Panda3D: X右, Y前, Z上
        # 转换规则: (ovr_x, ovr_y, ovr_z) → (panda_x, panda_y, panda_z)
        #          (ovr_x, ovr_y, ovr_z) → (ovr_x, -ovr_z, ovr_y)

        # X轴行：Panda3D的X轴对应OpenVR的X轴
        mat.setCell(0, 0, ovr_matrix[0][0])     # X_x → X_x
        mat.setCell(0, 1, ovr_matrix[0][1])     # X_y → X_y
        mat.setCell(0, 2, ovr_matrix[0][2])     # X_z → X_z
        mat.setCell(0, 3, ovr_matrix[0][3])     # 位移X分量

        # Y轴行：Panda3D的Y轴对应OpenVR的-Z轴
        mat.setCell(1, 0, -ovr_matrix[2][0])    # -Z_x → Y_x
        mat.setCell(1, 1, -ovr_matrix[2][1])    # -Z_y → Y_y
        mat.setCell(1, 2, -ovr_matrix[2][2])    # -Z_z → Y_z
        mat.setCell(1, 3, -ovr_matrix[2][3])    # 位移Y分量（-Z位移）

        # Z轴行：Panda3D的Z轴对应OpenVR的Y轴
        mat.setCell(2, 0, ovr_matrix[1][0])     # Y_x → Z_x
        mat.setCell(2, 1, ovr_matrix[1][1])     # Y_y → Z_y
        mat.setCell(2, 2, ovr_matrix[1][2])     # Y_z → Z_z
        mat.setCell(2, 3, ovr_matrix[1][3])     # 位移Z分量（Y位移）

        # 齐次坐标
        mat.setCell(3, 0, 0)
        mat.setCell(3, 1, 0)
        mat.setCell(3, 2, 0)
        mat.setCell(3, 3, 1)

        # 🚀 优化调试信息 - 避免创建Vec3对象，减少GC压力
        if not hasattr(self, '_coord_debug_counter'):
            self._coord_debug_counter = 0
        self._coord_debug_counter += 1

        if self._coord_debug_counter % 600 == 1:  # 每10秒输出一次@60fps
            print(f"🔄 坐标系转换调试 (第{self._coord_debug_counter}帧)")

            # 直接输出数值，避免创建Vec3对象
            ovr_x, ovr_y, ovr_z = ovr_matrix[0][3], ovr_matrix[1][3], ovr_matrix[2][3]
            print(f"   OpenVR原始位置: ({ovr_x:.3f}, {ovr_y:.3f}, {ovr_z:.3f})")

            # 直接从矩阵读取数值，避免创建Vec3对象
            panda_x = mat.getCell(0, 3)
            panda_y = mat.getCell(1, 3)
            panda_z = mat.getCell(2, 3)
            print(f"   Panda3D转换位置: ({panda_x:.3f}, {panda_y:.3f}, {panda_z:.3f})")

            # 手动验证转换：OpenVR (x,y,z) → Panda3D (x,-z,y)
            expected_x = ovr_x
            expected_y = -ovr_z
            expected_z = ovr_y
            print(f"   预期转换结果: ({expected_x:.3f}, {expected_y:.3f}, {expected_z:.3f})")

            # 计算误差，避免创建Vec3对象
            diff_x = panda_x - expected_x
            diff_y = panda_y - expected_y
            diff_z = panda_z - expected_z
            diff_magnitude = (diff_x*diff_x + diff_y*diff_y + diff_z*diff_z)**0.5

            if diff_magnitude < 0.001:
                print(f"   ✅ 坐标转换正确 (误差: {diff_magnitude:.6f})")
            else:
                print(f"   ⚠️ 坐标转换可能有误 (误差: {diff_magnitude:.6f})")
                print(f"   差异: ({diff_x:.6f}, {diff_y:.6f}, {diff_z:.6f})")

        return mat

    def update_hmd(self, pose):
        """
        更新HMD锚点 - 基于参考实现
        """
        try:
            # 将OpenVR姿态转换为Panda3D矩阵
            modelview = self.convert_mat(pose.mDeviceToAbsoluteTracking)

            # 应用坐标系转换并设置HMD锚点
            self.hmd_anchor.setMat(self.coord_mat_inv * modelview * self.coord_mat)

            # 获取眼睛到头部的变换
            view_left = self.convert_mat(self.vr_system.getEyeToHeadTransform(openvr.Eye_Left))
            view_right = self.convert_mat(self.vr_system.getEyeToHeadTransform(openvr.Eye_Right))

            # 设置眼睛锚点
            self.left_eye_anchor.setMat(self.coord_mat_inv * view_left * self.coord_mat)
            self.right_eye_anchor.setMat(self.coord_mat_inv * view_right * self.coord_mat)

        except Exception as e:
            print(f"更新HMD姿态失败: {e}")

    def _update_camera_poses(self):
        """更新相机姿态 - 使用锚点系统简化处理"""
        try:
            # 使用锚点系统后，相机位置自动跟随锚点
            # 只需要获取HMD姿态并更新锚点即可

            # 从poses数组中获取HMD姿态
            if hasattr(self, 'poses') and len(self.poses) > 0:
                hmd_pose = self.poses[openvr.k_unTrackedDeviceIndex_Hmd]
                if hmd_pose.bPoseIsValid:
                    self.update_hmd(hmd_pose)
                else:
                    print("⚠️ HMD姿态数据无效")

        except Exception as e:
            print(f"更新相机姿态失败: {e}")
            import traceback
            traceback.print_exc()

    def _update_camera_poses_with_cache(self):
        """使用缓存姿态更新相机 - 符合OpenVR时序假设"""
        try:
            # 使用缓存的姿态，符合OpenVR的时序假设
            # OpenVR假设你用上一次WaitGetPoses的姿态渲染当前提交的帧

            if not self._cached_render_poses:
                # 如果没有缓存姿态，回退到当前姿态（首帧情况）
                print("⚠️ 没有缓存姿态，使用当前姿态")
                return self._update_camera_poses()

            # 从缓存姿态数组中获取HMD姿态
            if len(self._cached_render_poses) > 0:
                hmd_pose = self._cached_render_poses[openvr.k_unTrackedDeviceIndex_Hmd]
                if hmd_pose.bPoseIsValid:
                    self.update_hmd(hmd_pose)

                    # 调试信息 - 验证缓存姿态使用
                    if not hasattr(self, '_cached_pose_logged'):
                        print("✅ 使用缓存姿态更新相机 - 符合OpenVR时序假设")
                        self._cached_pose_logged = True
                else:
                    print("⚠️ 缓存的HMD姿态数据无效")

        except Exception as e:
            print(f"使用缓存姿态更新相机失败: {e}")
            # 回退到正常更新方式
            self._update_camera_poses()
            import traceback
            traceback.print_exc()


    def enable_vr(self):
        """启用VR模式"""
        if not self.is_vr_available():
            print("❌ VR系统不可用")
            return False

        if not self.vr_initialized:
            if not self.initialize_vr():
                return False

        self.vr_enabled = True

        # 禁用主相机避免干扰VR渲染
        self._disable_main_cam()

        # VR性能优化：使用Running Start模式（Valve最佳实践）
        print("🚀 VR性能优化：Running Start模式已启用")
        print("   优势：在帧开始时获取姿态，提供VSync前3ms的渲染时间")
        print("   注意：Submit后立即调用WaitGetPoses是错误实现")
        self.set_prediction_time(11.0)  # 11ms预测时间 - OpenVR标准值，平衡准确性和延迟

        # 🚀 动态调整Qt Timer频率以支持VR
        if hasattr(self.world, 'qtWidget') and self.world.qtWidget:
            if hasattr(self.world.qtWidget, 'synchronizer'):
                # 设置为144Hz，让OpenVR控制实际渲染节奏
                self.world.qtWidget.synchronizer.setInterval(int(1000/144))
                print("✓ Qt Timer调整为144Hz，让OpenVR控制VR渲染节奏")

        # 🔧 关键修复：检测并重建缺失的手柄visualizer
        # 当渲染模式切换时，visualizer可能被清理但控制器对象仍存在
        if hasattr(self, 'left_controller') and self.left_controller:
            if not self.left_controller.visualizer and self.left_controller.anchor_node:
                print("🔧 检测到左手柄visualizer缺失，正在重建...")
                self.left_controller._create_visualizer()
                if self.left_controller.visualizer:
                    print("✅ 左手柄visualizer已重建")

        if hasattr(self, 'right_controller') and self.right_controller:
            if not self.right_controller.visualizer and self.right_controller.anchor_node:
                print("🔧 检测到右手柄visualizer缺失，正在重建...")
                self.right_controller._create_visualizer()
                if self.right_controller.visualizer:
                    print("✅ 右手柄visualizer已重建")

        print("✅ VR模式已启用")
        return True

    def disable_vr(self):
        """禁用VR模式"""
        self.vr_enabled = False

        # 清理手柄可视化（但保留控制器对象以便重新启用）
        if hasattr(self, 'left_controller') and self.left_controller:
            if hasattr(self.left_controller, 'visualizer') and self.left_controller.visualizer:
                try:
                    self.left_controller.visualizer.cleanup()
                    self.left_controller.visualizer = None
                    print("✓ 左手控制器可视化已清理")
                except Exception as e:
                    print(f"⚠️ 清理左手控制器可视化失败: {e}")

        if hasattr(self, 'right_controller') and self.right_controller:
            if hasattr(self.right_controller, 'visualizer') and self.right_controller.visualizer:
                try:
                    self.right_controller.visualizer.cleanup()
                    self.right_controller.visualizer = None
                    print("✓ 右手控制器可视化已清理")
                except Exception as e:
                    print(f"⚠️ 清理右手控制器可视化失败: {e}")

        # 隐藏手柄锚点节点
        if hasattr(self, 'left_controller') and self.left_controller and self.left_controller.anchor_node:
            self.left_controller.anchor_node.hide()

        if hasattr(self, 'right_controller') and self.right_controller and self.right_controller.anchor_node:
            self.right_controller.anchor_node.hide()

        # 恢复主相机
        self._enable_main_cam()

        # 恢复Qt Timer到60FPS
        if hasattr(self.world, 'qtWidget') and self.world.qtWidget:
            if hasattr(self.world.qtWidget, 'synchronizer'):
                self.world.qtWidget.synchronizer.setInterval(int(1000/60))
                print("✓ Qt Timer恢复为60Hz")

        print("✅ VR模式已禁用，手柄模型已隐藏")

    def set_vr_render_mode(self, mode):
        """切换VR渲染模式

        Args:
            mode: VRRenderMode枚举值或字符串 ('normal' 或 'render_pipeline')

        Returns:
            bool: 切换是否成功
        """
        try:
            # 转换输入为枚举类型
            if isinstance(mode, str):
                mode_str = mode.lower()
                if mode_str == "normal":
                    new_mode = VRRenderMode.NORMAL
                elif mode_str in ["render_pipeline", "renderpipeline", "pipeline"]:
                    new_mode = VRRenderMode.RENDER_PIPELINE
                else:
                    print(f"❌ 无效的渲染模式: {mode}")
                    print("   支持的模式: 'normal' 或 'render_pipeline'")
                    return False
            elif isinstance(mode, VRRenderMode):
                new_mode = mode
            else:
                print(f"❌ 无效的模式类型: {type(mode)}")
                return False

            # 检查是否与当前模式相同
            if new_mode == self.vr_render_mode:
                print(f"✓ VR渲染模式已经是 {new_mode.value}，无需切换")
                return True

            print(f"🔄 正在切换VR渲染模式: {self.vr_render_mode.value} → {new_mode.value}")

            # 检查VR是否已初始化
            if not self.vr_initialized:
                print("⚠️ VR未初始化，仅更新渲染模式配置")
                self.vr_render_mode = new_mode
                print(f"✓ VR渲染模式已更新为 {new_mode.value}（下次启动VR时生效）")
                return True

            # 保存当前VR启用状态
            was_enabled = self.vr_enabled

            # 如果VR已启用，先禁用
            if was_enabled:
                print("   暂时禁用VR...")
                self.disable_vr()

            # 更新渲染模式
            old_mode = self.vr_render_mode
            self.vr_render_mode = new_mode

            # 清理现有缓冲区
            print("   清理现有渲染缓冲区...")
            self._cleanup_vr_buffers()

            # 根据新模式重建缓冲区
            print(f"   创建新的渲染缓冲区（{new_mode.value}）...")
            success = False

            if new_mode == VRRenderMode.RENDER_PIPELINE:
                success = self._create_vr_buffers_with_pipeline()
                if not success:
                    print("⚠️ RenderPipeline模式创建失败，回退到普通渲染模式")
                    self.vr_render_mode = VRRenderMode.NORMAL
                    success = self._create_vr_buffers()
            else:
                success = self._create_vr_buffers()

            if not success:
                print("❌ 缓冲区创建失败，尝试恢复原模式")
                self.vr_render_mode = old_mode
                if old_mode == VRRenderMode.RENDER_PIPELINE:
                    self._create_vr_buffers_with_pipeline()
                else:
                    self._create_vr_buffers()
                return False

            # 重新设置相机
            print("   重新设置VR相机...")
            if not self._setup_vr_cameras():
                print("❌ 相机设置失败")
                return False

            # 如果之前VR是启用的，重新启用
            if was_enabled:
                print("   重新启用VR...")
                self.enable_vr()

                # 🔧 关键修复：重建所有手柄的visualizer以适配新渲染模式
                print("   刷新手柄visualizer以适配新渲染模式...")
                if hasattr(self, 'left_controller') and self.left_controller:
                    self.left_controller.recreate_visualizer()

                if hasattr(self, 'right_controller') and self.right_controller:
                    self.right_controller.recreate_visualizer()

            print(f"✅ VR渲染模式已切换为 {self.vr_render_mode.value}")

            # 保存配置
            if self.config_manager:
                self.config_manager.save_from_vr_manager(self)

            return True

        except Exception as e:
            print(f"❌ 切换VR渲染模式失败: {e}")
            import traceback
            traceback.print_exc()
            return False

    def get_vr_render_mode(self):
        """获取当前VR渲染模式

        Returns:
            VRRenderMode: 当前渲染模式
        """
        return self.vr_render_mode

    def _cleanup_vr_buffers(self):
        """清理VR渲染缓冲区"""
        try:
            # 清理VR Pipeline Controller（如果使用RenderPipeline模式）
            if self.vr_pipeline_controller:
                print("   清理VR Pipeline...")
                self.vr_pipeline_controller.cleanup_all()
                self.vr_pipeline_controller = None

            # 清理左眼缓冲区
            if self.vr_left_eye_buffer:
                # 如果是RenderPipeline模式，buffer已被VRPipelineController清理
                # 如果是普通模式，需要手动清理
                if self.vr_render_mode == VRRenderMode.NORMAL:
                    self.world.graphicsEngine.removeWindow(self.vr_left_eye_buffer)
                self.vr_left_eye_buffer = None

            # 清理右眼缓冲区
            if self.vr_right_eye_buffer:
                if self.vr_render_mode == VRRenderMode.NORMAL:
                    self.world.graphicsEngine.removeWindow(self.vr_right_eye_buffer)
                self.vr_right_eye_buffer = None

            # 清理纹理
            self.vr_left_texture = None
            self.vr_right_texture = None
            self.left_texture_id = None
            self.right_texture_id = None
            self.textures_prepared = False

            # 清理RenderPipeline渲染目标（旧版，保留兼容性）
            if self.vr_pipeline_left_target:
                self.vr_pipeline_left_target = None

            if self.vr_pipeline_right_target:
                self.vr_pipeline_right_target = None

            self.render_pipeline_enabled = False

            print("✓ VR渲染缓冲区已清理")

        except Exception as e:
            print(f"⚠️ 清理VR缓冲区时出错: {e}")

    def cleanup(self):
        """清理VR资源"""
        try:
            print("🔄 正在清理VR资源...")

            # 停止VR任务
            if self.vr_task:
                self.world.taskMgr.remove(self.vr_task)
                self.vr_task = None

            # 🚀 恢复Python垃圾回收并清理对象池
            if self._gc_disabled:
                # 最后一次手动垃圾回收
                collected = gc.collect()
                print(f"🗑️ 最终GC清理: {collected} 个对象")

                # 恢复自动垃圾回收
                gc.enable()
                self._gc_disabled = False
                print("✅ Python垃圾回收已恢复为自动模式")

            # 清理对象池
            if hasattr(self, '_matrix_pool'):
                pool_size = len(self._matrix_pool)
                self._matrix_pool.clear()
                print(f"🧹 Mat4对象池已清理: {pool_size} 个对象")

            # 清理缓存
            if hasattr(self, '_cached_matrices'):
                self._cached_matrices.clear()
            if hasattr(self, '_controller_poses_cache'):
                self._controller_poses_cache.clear()

            # 清理OpenVR Texture对象缓存
            if hasattr(self, '_left_ovr_texture'):
                self._left_ovr_texture = None
            if hasattr(self, '_right_ovr_texture'):
                self._right_ovr_texture = None
                print("🧹 OpenVR Texture对象缓存已清理")

            # 清理渲染缓冲区
            if self.vr_left_eye_buffer:
                self.vr_left_eye_buffer.removeAllDisplayRegions()
                self.world.graphicsEngine.removeWindow(self.vr_left_eye_buffer)
                self.vr_left_eye_buffer = None

            if self.vr_right_eye_buffer:
                self.vr_right_eye_buffer.removeAllDisplayRegions()
                self.world.graphicsEngine.removeWindow(self.vr_right_eye_buffer)
                self.vr_right_eye_buffer = None

            # 清理相机
            if self.vr_left_camera:
                self.vr_left_camera.removeNode()
                self.vr_left_camera = None

            if self.vr_right_camera:
                self.vr_right_camera.removeNode()
                self.vr_right_camera = None

            # 清理控制器
            if hasattr(self, 'left_controller') and self.left_controller:
                try:
                    self.left_controller.cleanup()
                    self.left_controller = None
                    print("✓ 左手控制器已清理")
                except Exception as e:
                    print(f"⚠️ 清理左手控制器失败: {e}")

            if hasattr(self, 'right_controller') and self.right_controller:
                try:
                    self.right_controller.cleanup()
                    self.right_controller = None
                    print("✓ 右手控制器已清理")
                except Exception as e:
                    print(f"⚠️ 清理右手控制器失败: {e}")

            # 清理控制器字典
            if hasattr(self, 'controllers'):
                self.controllers.clear()
                print("✓ 控制器字典已清理")

            # 清理VR子系统
            if hasattr(self, 'joystick_manager') and self.joystick_manager:
                try:
                    self.joystick_manager.cleanup()
                    self.joystick_manager = None
                    print("✓ VR摇杆系统已清理")
                except Exception as e:
                    print(f"⚠️ 清理VR摇杆系统失败: {e}")

            if hasattr(self, 'teleport_system') and self.teleport_system:
                try:
                    self.teleport_system.cleanup()
                    self.teleport_system = None
                    print("✓ VR传送系统已清理")
                except Exception as e:
                    print(f"⚠️ 清理VR传送系统失败: {e}")

            if hasattr(self, 'interaction_manager') and self.interaction_manager:
                try:
                    self.interaction_manager.cleanup()
                    self.interaction_manager = None
                    print("✓ VR交互系统已清理")
                except Exception as e:
                    print(f"⚠️ 清理VR交互系统失败: {e}")

            if hasattr(self, 'action_manager') and self.action_manager:
                try:
                    self.action_manager.cleanup()
                    self.action_manager = None
                    print("✓ VR动作系统已清理")
                except Exception as e:
                    print(f"⚠️ 清理VR动作系统失败: {e}")

            # 关闭OpenVR
            if self.vr_system and OPENVR_AVAILABLE:
                try:
                    openvr.shutdown()
                except:
                    pass
                self.vr_system = None

            self.vr_enabled = False
            self.vr_initialized = False

            print("✅ VR资源清理完成")

        except Exception as e:
            print(f"⚠️ VR清理过程中出错: {e}")

    def get_vr_status(self):
        """获取VR状态信息"""
        return {
            'available': self.is_vr_available(),
            'initialized': self.vr_initialized,
            'enabled': self.vr_enabled,
            'eye_resolution': (self.eye_width, self.eye_height),
            'device_count': len(self.controller_poses) + (1 if self.vr_enabled else 0),
            'vr_fps': self.vr_fps,
            'frame_count': self.frame_count,
            'submit_failures': self.submit_failures,
            'pose_failures': self.pose_failures
        }

    def _print_performance_report(self):
        """输出VR性能报告"""
        if not self.performance_monitoring or not self.debug_output_enabled:
            return

        stats = self.get_performance_stats()

        # 简短模式输出
        if self.debug_mode == 'brief':
            self._print_brief_performance_report(stats)
            return

        print("📊 ======= VR性能监控报告 =======")

        # 帧率和帧时间信息
        print(f"🎯 渲染性能:")
        print(f"   VR帧率: {stats['vr_fps']:.1f} FPS")
        print(f"   平均帧时间: {stats['frame_time_avg']:.2f} ms")
        print(f"   最小帧时间: {stats['frame_time_min']:.2f} ms")
        print(f"   最大帧时间: {stats['frame_time_max']:.2f} ms")
        print(f"   95%帧时间: {stats['frame_time_95th']:.2f} ms")

        # 系统性能
        print(f"💻 系统性能:")
        print(f"   CPU使用率: {stats['cpu_usage']:.1f}%")
        print(f"   内存使用率: {stats['memory_usage']:.1f}%")

        # GPU性能
        print(f"🎮 GPU性能:")
        if self.gputil_available or self.nvidia_ml_available:
            print(f"   GPU使用率: {stats['gpu_usage']:.1f}%")
            print(f"   显存使用率: {stats['gpu_memory_usage']:.1f}%")
        else:
            print(f"   GPU监控: 不可用 (需要安装 GPUtil 或 pynvml)")
            print(f"   安装命令: pip install GPUtil nvidia-ml-py")

        # GPU渲染时间（OpenVR Frame Timing）
        if self.enable_gpu_timing:
            print(f"⚡ GPU渲染时间:")
            pipeline_stats = self._get_pipeline_stats()
            gpu_stats = pipeline_stats.get('gpu_timing', {})
            gpu_current = pipeline_stats.get('current', {})

            # 检查是否有可用的GPU时间数据
            has_gpu_data = any(
                gpu_current.get(field, 0) > 0
                for field in ['gpu_scene_render', 'gpu_total_render', 'gpu_pre_submit', 'gpu_post_submit', 'gpu_compositor_render']
            )

            if has_gpu_data:
                # 显示GPU时间统计（最近30帧平均）
                scene_render = gpu_stats.get('scene_render', {'avg': 0})
                total_render = gpu_stats.get('total_render', {'avg': 0})
                pre_submit = gpu_stats.get('pre_submit', {'avg': 0})
                post_submit = gpu_stats.get('post_submit', {'avg': 0})
                compositor = gpu_stats.get('compositor_render', {'avg': 0})

                if scene_render['avg'] > 0:
                    print(f"   GPU场景渲染: {scene_render['avg']:.2f}ms (min:{scene_render['min']:.1f}, max:{scene_render['max']:.1f})")
                if total_render['avg'] > 0:
                    print(f"   GPU总渲染时间: {total_render['avg']:.2f}ms (min:{total_render['min']:.1f}, max:{total_render['max']:.1f})")
                if pre_submit['avg'] > 0:
                    print(f"   GPU提交前时间: {pre_submit['avg']:.2f}ms (min:{pre_submit['min']:.1f}, max:{pre_submit['max']:.1f})")
                if post_submit['avg'] > 0:
                    print(f"   GPU提交后时间: {post_submit['avg']:.2f}ms (min:{post_submit['min']:.1f}, max:{post_submit['max']:.1f})")
                if compositor['avg'] > 0:
                    print(f"   GPU合成器时间: {compositor['avg']:.2f}ms (min:{compositor['min']:.1f}, max:{compositor['max']:.1f})")

                # 显示当前帧GPU时间
                print(f"🔍 当前帧GPU时间:")
                if gpu_current.get('gpu_scene_render', 0) > 0:
                    print(f"   场景渲染: {gpu_current['gpu_scene_render']:.2f}ms")
                if gpu_current.get('gpu_total_render', 0) > 0:
                    print(f"   总渲染: {gpu_current['gpu_total_render']:.2f}ms")
                if gpu_current.get('gpu_compositor_render', 0) > 0:
                    print(f"   合成器: {gpu_current['gpu_compositor_render']:.2f}ms")

                # GPU时间瓶颈分析
                current_total = gpu_current.get('gpu_total_render', 0)
                current_scene = gpu_current.get('gpu_scene_render', 0)
                if current_total > 12.0:  # 假设72fps目标，留出一些余量
                    print(f"   ⚠️ GPU总渲染时间过长: {current_total:.1f}ms")
                elif current_scene > 8.0:
                    print(f"   ⚠️ GPU场景渲染时间偏高: {current_scene:.1f}ms")

            else:
                print(f"   GPU渲染时间: 暂无数据")
                if self.gpu_timing_failure_count > 0:
                    print(f"   获取失败次数: {self.gpu_timing_failure_count}")
                else:
                    print(f"   等待OpenVR Frame Timing数据...")
        else:
            print(f"⚡ GPU渲染时间: 已禁用")

        # VR特定指标
        print(f"🥽 VR指标:")
        print(f"   总帧数: {stats['frame_count']}")
        print(f"   提交失败: {stats['submit_failures']}")
        print(f"   姿态失败: {stats['pose_failures']}")

        # 计算失败率
        if stats['frame_count'] > 0:
            submit_fail_rate = (stats['submit_failures'] / stats['frame_count']) * 100
            pose_fail_rate = (stats['pose_failures'] / stats['frame_count']) * 100
            print(f"   提交失败率: {submit_fail_rate:.2f}%")
            print(f"   姿态失败率: {pose_fail_rate:.2f}%")

        # 渲染管线监控
        if self.enable_pipeline_monitoring:
            pipeline_stats = self._get_pipeline_stats()
            print(f"⚙️ 渲染管线分析:")
            print(f"   当前分辨率: {pipeline_stats['vr_info']['eye_resolution'][0]}x{pipeline_stats['vr_info']['eye_resolution'][1]}")
            print(f"   推荐分辨率: {pipeline_stats['vr_info']['recommended_resolution'][0]}x{pipeline_stats['vr_info']['recommended_resolution'][1]}")
            print(f"   显示频率: {pipeline_stats['vr_info']['display_frequency']:.1f} Hz")

            # VSync和时序信息
            if pipeline_stats['vr_info']['target_frame_time_ms'] > 0:
                print(f"🎯 VSync时序:")
                print(f"   目标帧时间: {pipeline_stats['vr_info']['target_frame_time_ms']:.2f}ms")
                print(f"   VSync到光子: {pipeline_stats['vr_info']['vsync_to_photons_ms']:.2f}ms")
                print(f"   VSync窗口: ±{pipeline_stats['vr_info']['vsync_window_ms']:.2f}ms")
                print(f"   异步重投影: {'启用' if pipeline_stats['vr_info']['async_reprojection'] else '禁用'}")
                print(f"   运动平滑: {'启用' if pipeline_stats['vr_info']['motion_smoothing'] else '禁用'}")

                # 分析帧时间是否在目标范围内
                current_frame_time = stats['frame_time_avg']
                target_frame_time = pipeline_stats['vr_info']['target_frame_time_ms']
                if current_frame_time > 0 and target_frame_time > 0:
                    frame_time_ratio = current_frame_time / target_frame_time
                    if frame_time_ratio > 1.1:
                        print(f"   ⚠️ 帧时间超标: {current_frame_time:.1f}ms (目标:{target_frame_time:.1f}ms)")
                    elif frame_time_ratio < 0.9:
                        print(f"   ✅ 帧时间充裕: {current_frame_time:.1f}ms (目标:{target_frame_time:.1f}ms)")
                    else:
                        print(f"   ✓ 帧时间正常: {current_frame_time:.1f}ms (目标:{target_frame_time:.1f}ms)")

        # 🔧 性能优化诊断
        print(f"🔧 优化诊断:")
        current = pipeline_stats.get('current', {}) if self.enable_pipeline_monitoring else {}

        # 🔍 渲染回调诊断 - 新增
        self._print_render_callback_diagnostics()

        # waitGetPoses时序分析
        wait_poses_time = current.get('wait_poses', 0)
        if wait_poses_time > 10:
            print(f"   ⚠️ waitGetPoses时间过长: {wait_poses_time:.1f}ms")
            print(f"      可能原因: 错过VSync窗口，建议调整预测时间")
        elif wait_poses_time > 5:
            print(f"   ⚠️ waitGetPoses时间偏高: {wait_poses_time:.1f}ms")
        else:
            print(f"   ✓ waitGetPoses时间正常: {wait_poses_time:.1f}ms")

        # CPU-GPU并行度分析 - 增强诊断
        gpu_total = current.get('gpu_total_render', 0)
        cpu_render_left = getattr(self, 'left_render_time', 0)
        cpu_render_right = getattr(self, 'right_render_time', 0)
        cpu_render_total = cpu_render_left + cpu_render_right

        print(f"   真实渲染时间对比:")
        print(f"     CPU左眼: {cpu_render_left:.2f}ms")
        print(f"     CPU右眼: {cpu_render_right:.2f}ms")
        print(f"     CPU总计: {cpu_render_total:.2f}ms")
        print(f"     GPU总计: {gpu_total:.2f}ms")

        if cpu_render_total < 1.0:
            print(f"   ⚠️ CPU渲染时间异常短: {cpu_render_total:.2f}ms")
            print(f"      可能原因: 渲染回调未正确执行或渲染被跳过")
        elif gpu_total > 0 and cpu_render_total > 0:
            ratio = gpu_total / cpu_render_total
            if ratio > 10:
                print(f"   ⚠️ GPU严重等待CPU: 比例{ratio:.1f}:1")
                print(f"      建议: 检查OpenGL命令提交时机和渲染状态")
            elif ratio > 3:
                print(f"   ⚠️ GPU等待CPU: 比例{ratio:.1f}:1")
                print(f"      建议: 检查OpenGL命令提交是否及时")
            else:
                print(f"   ✓ CPU-GPU时间匹配: 比例{ratio:.1f}:1")

        # 预测时间诊断
        current_prediction = self.use_prediction_time * 1000
        print(f"   预测时间设置: {current_prediction:.1f}ms")
        if current_prediction > 15:
            print(f"      建议: 预测时间较高，可能增加waitGetPoses延迟")
        elif current_prediction < 8:
            print(f"      注意: 预测时间较低，可能影响姿态准确性")
        else:
            print(f"      ✓ 预测时间在合理范围内")

        # 优化状态总结
        optimization_score = 0
        if wait_poses_time < 8:
            optimization_score += 1
        if stats['vr_fps'] > 60:
            optimization_score += 1
        if stats.get('frame_time_avg', 0) < target_frame_time * 1.1:
            optimization_score += 1

        if optimization_score >= 2:
            print(f"   ✅ 优化效果良好 ({optimization_score}/3)")
        else:
            print(f"   ⚠️ 仍有优化空间 ({optimization_score}/3)")

        print(f"🕐 各阶段耗时 (最近{self.pipeline_history_size}帧平均):")
        print(f"   waitGetPoses: {pipeline_stats['wait_poses']['avg']:.2f}ms (min:{pipeline_stats['wait_poses']['min']:.1f}, max:{pipeline_stats['wait_poses']['max']:.1f})")
        print(f"   渲染总计: {pipeline_stats['render']['avg']:.2f}ms (min:{pipeline_stats['render']['min']:.1f}, max:{pipeline_stats['render']['max']:.1f})")
        print(f"   纹理提交: {pipeline_stats['submit']['avg']:.2f}ms (min:{pipeline_stats['submit']['min']:.1f}, max:{pipeline_stats['submit']['max']:.1f})")
        if pipeline_stats['sync_wait']['avg'] > 0:
            print(f"   同步等待: {pipeline_stats['sync_wait']['avg']:.2f}ms (min:{pipeline_stats['sync_wait']['min']:.1f}, max:{pipeline_stats['sync_wait']['max']:.1f})")

        print(f"🔍 当前帧详情:")
        print(f"   左眼渲染: {pipeline_stats['current']['left_render']:.2f}ms")
        print(f"   右眼渲染: {pipeline_stats['current']['right_render']:.2f}ms")
        print(f"   姿态获取: {pipeline_stats['current']['wait_poses']:.2f}ms")

        # 显示Running Start模式信息
        print(f"🎯 Running Start模式:")
        print(f"   模式: Valve Running Start - 帧开始时获取姿态")
        print(f"   优势: VSync前3ms获取姿态，提供充足渲染时间")
        print(f"   预测时间: {self.use_prediction_time * 1000:.1f}ms")

        # 分析最大瓶颈
        current = pipeline_stats['current']
        bottleneck_analysis = []
        if current['wait_poses'] > 5.0:
            bottleneck_analysis.append(f"姿态获取耗时过长({current['wait_poses']:.1f}ms)")
        if current['total_render'] > 8.0:
            bottleneck_analysis.append(f"渲染耗时过长({current['total_render']:.1f}ms)")
        if current['submit'] > 2.0:
            bottleneck_analysis.append(f"纹理提交耗时过长({current['submit']:.1f}ms)")

        if bottleneck_analysis:
            print(f"🚨 瓶颈分析:")
            for analysis in bottleneck_analysis:
                print(f"   ⚠️ {analysis}")

        # 性能建议
        self._print_performance_recommendations(stats)

        print("===============================")

    def _print_performance_recommendations(self, stats):
        """根据性能数据输出优化建议"""
        print(f"💡 性能建议:")

        recommendations = []

        # FPS相关建议
        if stats['vr_fps'] < 60:
            recommendations.append("   ⚠️ VR帧率过低，可能影响体验")

        # 帧时间相关建议
        if stats['frame_time_avg'] > 16.7:  # 60fps = 16.7ms
            recommendations.append("   ⚠️ 平均帧时间过高，建议降低渲染质量")

        if stats['frame_time_max'] > 50:
            recommendations.append("   ⚠️ 检测到严重卡顿，检查CPU/GPU负载")

        # CPU建议
        if stats['cpu_usage'] > 80:
            recommendations.append("   🔴 CPU使用率过高，可能存在CPU瓶颈")
        elif stats['cpu_usage'] > 60:
            recommendations.append("   🟡 CPU使用率偏高，注意监控")

        # 内存建议
        if stats['memory_usage'] > 85:
            recommendations.append("   🔴 内存使用率过高，可能影响性能")

        # GPU建议
        if self.gputil_available or self.nvidia_ml_available:
            if stats['gpu_usage'] > 95:
                recommendations.append("   🔴 GPU使用率接近满载，存在GPU瓶颈")
            if stats['gpu_memory_usage'] > 90:
                recommendations.append("   🔴 显存使用率过高，可能需要降低纹理质量")

        # GPU渲染时间建议
        if self.enable_gpu_timing:
            if self.gpu_total_render_ms > 12.0:
                recommendations.append("   ⚠️ GPU总渲染时间过长，建议优化场景复杂度")
            if self.gpu_scene_render_ms > 8.0:
                recommendations.append("   ⚠️ GPU场景渲染时间偏高，考虑降低渲染质量")
            if self.gpu_compositor_render_ms > 3.0:
                recommendations.append("   ⚠️ GPU合成器时间过长，检查VR设置或叠加层")
            if self.gpu_timing_failure_count > 100:
                recommendations.append("   ⚠️ GPU时间统计频繁失败，可能需要更新OpenVR")

        # 失败率建议
        submit_fail_rate = (stats['submit_failures'] / max(stats['frame_count'], 1)) * 100
        if submit_fail_rate > 1:
            recommendations.append("   ⚠️ VR帧提交失败率较高，检查VR系统状态")

        if not recommendations:
            recommendations.append("   ✅ 性能表现良好，无明显问题")

        for rec in recommendations:
            print(rec)

    def _print_brief_performance_report(self, stats):
        """输出简短的VR性能报告"""
        # 创建一行简短摘要
        summary = f"🥽 VR性能: {stats['vr_fps']:.1f}fps"

        if stats['frame_time_avg'] > 0:
            summary += f" | 帧时间: {stats['frame_time_avg']:.1f}ms"

        if self.psutil_available:
            summary += f" | CPU: {stats['cpu_usage']:.0f}%"
            summary += f" | 内存: {stats['memory_usage']:.0f}%"

        # 显示GPU信息，如果库不可用则显示提示
        if self.gputil_available or self.nvidia_ml_available:
            summary += f" | GPU: {stats['gpu_usage']:.0f}%"
        else:
            summary += " | GPU: N/A"

        # 添加失败率指示
        if stats['frame_count'] > 0:
            submit_fail_rate = (stats['submit_failures'] / stats['frame_count']) * 100
            if submit_fail_rate > 0.1:
                summary += f" | 提交失败: {submit_fail_rate:.1f}%"

        # 添加管线关键信息
        if self.enable_pipeline_monitoring:
            pipeline_stats = self._get_pipeline_stats()
            current = pipeline_stats['current']

            # 显示关键瓶颈
            if current['wait_poses'] > 5.0:
                summary += f" | 姿态: {current['wait_poses']:.1f}ms⚠️"
            elif current['wait_poses'] > 0:
                summary += f" | 姿态: {current['wait_poses']:.1f}ms"

            if current['total_render'] > 8.0:
                summary += f" | 渲染: {current['total_render']:.1f}ms⚠️"
            elif current['total_render'] > 0:
                summary += f" | 渲染: {current['total_render']:.1f}ms"

            # 添加GPU渲染时间信息
            if self.enable_gpu_timing:
                gpu_total = current.get('gpu_total_render', 0)
                gpu_scene = current.get('gpu_scene_render', 0)
                if gpu_total > 12.0:
                    summary += f" | GPU: {gpu_total:.1f}ms⚠️"
                elif gpu_total > 0:
                    summary += f" | GPU: {gpu_total:.1f}ms"
                elif gpu_scene > 0:
                    summary += f" | GPU场景: {gpu_scene:.1f}ms"

            # 显示目标帧时间对比
            vr_info = pipeline_stats['vr_info']
            if vr_info['target_frame_time_ms'] > 0:
                target = vr_info['target_frame_time_ms']
                current_avg = stats['frame_time_avg']
                if current_avg > target * 1.1:
                    summary += f" | 目标:{target:.0f}ms⚠️"
                else:
                    summary += f" | 目标:{target:.0f}ms"

        # 性能状态指示
        if stats['vr_fps'] < 72:
            summary += " ⚠️"
        elif stats['vr_fps'] > 85:
            summary += " ✅"

        print(summary)

    # 注意：原来的left_cb和right_cb函数已被删除
    # 它们的功能已集成到_handle_vr_rendering_and_submit方法中

    # 注意：_safe_submit_texture方法已删除
    # VR纹理提交现在完全由Panda3D的renderFrame()自动处理

    def submit_texture(self, eye, texture):
        """优化的VR纹理提交 - 使用缓存的纹理ID，避免重复prepareNow"""
        try:
            if not self.vr_compositor:
                print("❌ VR compositor不可用")
                self.submit_failures += 1
                return

            # 🚀 关键修复：防止同一帧重复提交
            current_frame = getattr(self, 'frame_count', 0)
            if not hasattr(self, '_last_submit_frame'):
                self._last_submit_frame = {}

            # 检查当前帧是否已经提交过此眼睛的纹理
            if eye in self._last_submit_frame and self._last_submit_frame[eye] == current_frame:
                # 静默跳过，避免spam输出
                return

            # 记录当前帧提交
            self._last_submit_frame[eye] = current_frame

            # 🚀 关键优化：直接使用缓存的纹理ID，避免重复prepareNow
            if eye == openvr.Eye_Left:
                handle = self.left_texture_id
                eye_name = "左眼"
            elif eye == openvr.Eye_Right:
                handle = self.right_texture_id
                eye_name = "右眼"
            else:
                print(f"❌ 未知的眼睛类型: {eye}")
                self.submit_failures += 1
                return

            # 检查缓存的纹理ID是否有效
            if not handle or handle <= 0:
                print(f"❌ {eye_name}纹理ID缓存无效: {handle}")
                print("   这可能表示纹理准备失败，需要检查_prepare_and_cache_textures()")
                self.submit_failures += 1
                return

            # ❌ 移除gsg.flush()调用 - 基于OpenVR官方实践
            # gsg.flush()等同于OpenGL的glFlush()，导致强制CPU-GPU同步
            # 每帧调用2次（左右眼）是GPU周期性峰值的主要原因
            # 参考：OpenVR社区经验表明同步调用是性能杀手
            #
            # gsg = self.world.win.getGsg()
            # if gsg and hasattr(gsg, 'flush'):
            #     try:
            #         gsg.flush()
            #     except Exception as flush_error:
            #         if not hasattr(self, '_gsg_flush_error_logged'):
            #             print(f"⚠️ GSG刷新失败: {flush_error}")
            #             self._gsg_flush_error_logged = True

            # 🚀 关键优化：使用缓存的OpenVR Texture对象，避免每帧创建
            if eye == openvr.Eye_Left:
                ovr_texture = self._left_ovr_texture
            else:
                ovr_texture = self._right_ovr_texture

            # 检查缓存对象是否存在（向后兼容）
            if ovr_texture is None:
                # 备用方案：如果缓存对象不存在，创建新的（性能较差）
                ovr_texture = openvr.Texture_t()
                ovr_texture.eType = openvr.TextureType_OpenGL
                ovr_texture.eColorSpace = openvr.ColorSpace_Gamma
                if not hasattr(self, '_texture_fallback_warned'):
                    print("⚠️ 使用Texture对象备用方案（性能次优）")
                    self._texture_fallback_warned = True

            # 只更新handle，其他属性已预设置
            ovr_texture.handle = handle

            # 提交到VR系统
            error = self.vr_compositor.submit(eye, ovr_texture)

            # 检查错误
            if error and error != openvr.VRCompositorError_None:
                print(f"⚠️ VR{eye_name}纹理提交错误: {error}")
                self.submit_failures += 1
            else:
                # 只在第一次成功时输出
                if not hasattr(self, '_optimized_submit_success_logged'):
                    print(f"✅ 优化版VR纹理提交成功! 使用缓存ID，避免重复prepareNow")
                    print(f"   {eye_name}纹理ID: {handle}")
                    self._optimized_submit_success_logged = True

            # 🔧 智能GPU同步策略 - 减少不必要的flush调用
            # 只有在检测到性能问题或每N帧时才强制flush
            if eye == openvr.Eye_Right:
                self._smart_gpu_sync()

        except Exception as e:
            print(f"❌ VR纹理提交异常: {e}")
            import traceback
            traceback.print_exc()
            self.submit_failures += 1

    def _smart_gpu_sync(self):
        """智能GPU同步策略 - 只在必要时进行同步"""
        try:
            # 初始化同步控制变量
            if not hasattr(self, '_last_gpu_sync_frame'):
                self._last_gpu_sync_frame = 0
                self._gpu_sync_interval = 60  # 每60帧强制同步一次（1秒@60FPS）
                self._performance_based_sync = True

            current_frame = getattr(self, 'frame_count', 0)

            # 策略1: 性能自适应同步
            if self._performance_based_sync:
                # 如果渲染时间过长，增加同步频率
                total_render_time = getattr(self, 'left_render_time', 0) + getattr(self, 'right_render_time', 0)

                if total_render_time > 15.0:  # 如果总渲染时间超过15ms
                    # 高负载时更频繁同步
                    sync_interval = 30  # 每30帧同步
                elif total_render_time > 10.0:
                    sync_interval = 45  # 中等负载
                else:
                    sync_interval = self._gpu_sync_interval  # 正常负载

                should_sync = (current_frame - self._last_gpu_sync_frame) >= sync_interval
            else:
                # 策略2: 固定间隔同步
                should_sync = (current_frame - self._last_gpu_sync_frame) >= self._gpu_sync_interval

            # 执行同步
            if should_sync:
                gsg = self.world.win.getGsg()
                if gsg and hasattr(gsg, 'flush'):
                    try:
                        gsg.flush()
                        self._last_gpu_sync_frame = current_frame

                        # 只在首次或Debug时输出
                        if not hasattr(self, '_smart_sync_logged') or self.debug_output_enabled:
                            if not hasattr(self, '_smart_sync_logged'):
                                print(f"🔧 智能GPU同步已启用 - 间隔：{sync_interval}帧")
                                self._smart_sync_logged = True
                            elif self.debug_output_enabled and current_frame % 600 == 1:
                                print(f"🔧 智能同步触发 (帧#{current_frame}, 间隔:{sync_interval})")

                    except Exception as flush_error:
                        if not hasattr(self, '_smart_sync_error_logged'):
                            print(f"⚠️ 智能GPU同步失败: {flush_error}")
                            self._smart_sync_error_logged = True

        except Exception as e:
            print(f"⚠️ 智能GPU同步策略异常: {e}")

    def _disable_main_cam(self):
        """禁用主相机 - 基于参考实现"""
        try:
            # 保存原始相机状态
            if not hasattr(self, '_original_camera_parent'):
                self._original_camera_parent = self.world.camera.getParent()

            # 创建空节点并将主相机重新附加到它
            self._empty_world = NodePath("empty_world")
            self.world.camera.reparentTo(self._empty_world)

            print("✓ 主相机已禁用")
        except Exception as e:
            print(f"⚠️ 禁用主相机失败: {e}")

    def _enable_main_cam(self):
        """恢复主相机 - 基于参考实现"""
        try:
            # 恢复原始相机状态
            if hasattr(self, '_original_camera_parent') and self._original_camera_parent:
                self.world.camera.reparentTo(self._original_camera_parent)
            else:
                # 如果没有保存的父节点，重新附加到render
                self.world.camera.reparentTo(self.world.render)

            # 清理空世界节点
            if hasattr(self, '_empty_world'):
                self._empty_world.removeNode()
                delattr(self, '_empty_world')

            print("✓ 主相机已恢复")
        except Exception as e:
            print(f"⚠️ 恢复主相机失败: {e}")

    def _initialize_controllers(self):
        """初始化VR手柄控制器"""
        try:
            print("🎮 正在初始化VR手柄控制器...")

            # 创建左右手柄控制器实例
            self.left_controller = LeftController(self)
            self.right_controller = RightController(self)

            # 检测现有连接的控制器
            self._detect_controllers()

            print("✓ VR手柄控制器初始化完成")

        except Exception as e:
            print(f"⚠️ VR手柄初始化失败: {e}")
            import traceback
            traceback.print_exc()

    def _detect_controllers(self):
        """检测并连接VR控制器"""
        if not self.vr_system:
            return

        try:
            for device_index in range(openvr.k_unMaxTrackedDeviceCount):
                # 检查设备是否已连接
                if not self.vr_system.isTrackedDeviceConnected(device_index):
                    continue

                # 获取设备类型
                device_class = self.vr_system.getTrackedDeviceClass(device_index)

                if device_class == openvr.TrackedDeviceClass_Controller:
                    # 获取控制器角色
                    role = self.vr_system.getControllerRoleForTrackedDeviceIndex(device_index)

                    if role == openvr.TrackedControllerRole_LeftHand and self.left_controller:
                        self.left_controller.set_device_index(device_index)
                        self.controllers[device_index] = self.left_controller
                        # 为设备创建锚点
                        self._create_tracked_device_anchor(device_index, 'left_controller')

                    elif role == openvr.TrackedControllerRole_RightHand and self.right_controller:
                        self.right_controller.set_device_index(device_index)
                        self.controllers[device_index] = self.right_controller
                        # 为设备创建锚点
                        self._create_tracked_device_anchor(device_index, 'right_controller')

            print(f"🎮 检测到 {len(self.controllers)} 个控制器")

        except Exception as e:
            print(f"⚠️ 控制器检测失败: {e}")

    def _create_tracked_device_anchor(self, device_index, name):
        """为跟踪设备创建锚点节点"""
        if not self.tracking_space:
            print(f"⚠️ 无法为设备 {device_index} 创建锚点 - tracking_space未初始化")
            return

        try:
            # 获取设备模型名称
            if self.vr_system:
                model_name = self.vr_system.getStringTrackedDeviceProperty(
                    device_index,
                    openvr.Prop_RenderModelName_String
                )
                anchor_name = f"{device_index}:{model_name}:{name}"
            else:
                anchor_name = f"{device_index}:{name}"

            # 创建锚点节点
            device_anchor = self.tracking_space.attachNewNode(anchor_name)
            self.tracked_device_anchors[device_index] = device_anchor

            print(f"✓ 为设备 {device_index} 创建锚点: {anchor_name}")

        except Exception as e:
            print(f"⚠️ 创建设备锚点失败: {e}")

    def update_tracked_devices(self):
        """更新所有跟踪设备的姿态 - 基于参考实现"""
        if not self.poses or not self.vr_system:
            return

        try:
            # 更新每个已连接的控制器
            for device_index, controller in self.controllers.items():
                if device_index < len(self.poses):
                    pose_data = self.poses[device_index]

                    # 更新控制器姿态
                    controller.update_pose(pose_data)

                    # 更新控制器输入状态
                    controller.update_input_state(self.vr_system)

            # 更新其他跟踪设备的锚点
            for device_index in range(1, min(len(self.poses), openvr.k_unMaxTrackedDeviceCount)):
                if device_index in self.tracked_device_anchors:
                    pose_data = self.poses[device_index]
                    if pose_data.bPoseIsValid:
                        # 转换姿态矩阵
                        modelview = self.convert_mat(pose_data.mDeviceToAbsoluteTracking)
                        final_matrix = self.coord_mat_inv * modelview * self.coord_mat

                        # 更新锚点变换
                        anchor = self.tracked_device_anchors[device_index]
                        anchor.setMat(final_matrix)
                        anchor.show()
                    else:
                        # 姿态无效，隐藏锚点
                        self.tracked_device_anchors[device_index].hide()

        except Exception as e:
            if self.frame_count % 300 == 0:  # 每5秒输出一次错误
                print(f"⚠️ 更新跟踪设备失败: {e}")

    def get_controller_by_role(self, role):
        """根据角色获取控制器

        Args:
            role: 'left' 或 'right'

        Returns:
            VRController实例或None
        """
        if role == 'left':
            return self.left_controller
        elif role == 'right':
            return self.right_controller
        return None

    def are_controllers_connected(self):
        """检查是否有控制器连接"""
        return len(self.controllers) > 0

    def get_connected_controllers(self):
        """获取所有连接的控制器列表"""
        return list(self.controllers.values())

    def trigger_controller_haptic(self, role, duration=0.001, strength=1.0):
        """触发控制器震动反馈

        Args:
            role: 'left', 'right' 或 'both'
            duration: 震动持续时间（秒）
            strength: 震动强度 (0.0-1.0)
        """
        if role in ['left', 'both'] and self.left_controller:
            self.left_controller.trigger_haptic_feedback(duration, strength)

        if role in ['right', 'both'] and self.right_controller:
            self.right_controller.trigger_haptic_feedback(duration, strength)

    # VR动作系统便捷方法
    def is_trigger_pressed(self, hand='any'):
        """检查扳机是否被按下

        Args:
            hand: 'left', 'right', 'any'
        """
        device_path = None
        if hand == 'left':
            device_path = '/user/hand/left'
        elif hand == 'right':
            device_path = '/user/hand/right'

        pressed, _ = self.action_manager.is_digital_action_pressed('trigger', device_path)
        return pressed

    def is_trigger_just_pressed(self, hand='any'):
        """检查扳机是否刚刚被按下"""
        device_path = None
        if hand == 'left':
            device_path = '/user/hand/left'
        elif hand == 'right':
            device_path = '/user/hand/right'

        pressed, _ = self.action_manager.is_digital_action_just_pressed('trigger', device_path)
        return pressed

    def is_grip_pressed(self, hand='any'):
        """检查握把是否被按下"""
        device_path = None
        if hand == 'left':
            device_path = '/user/hand/left'
        elif hand == 'right':
            device_path = '/user/hand/right'

        pressed, _ = self.action_manager.is_digital_action_pressed('grip', device_path)
        return pressed

    def is_grip_just_pressed(self, hand='any'):
        """检查握把是否刚刚被按下"""
        device_path = None
        if hand == 'left':
            device_path = '/user/hand/left'
        elif hand == 'right':
            device_path = '/user/hand/right'

        pressed, _ = self.action_manager.is_digital_action_just_pressed('grip', device_path)
        return pressed

    def is_menu_pressed(self, hand='any'):
        """检查菜单按钮是否被按下"""
        device_path = None
        if hand == 'left':
            device_path = '/user/hand/left'
        elif hand == 'right':
            device_path = '/user/hand/right'

        pressed, _ = self.action_manager.is_digital_action_pressed('menu', device_path)
        return pressed

    def is_trackpad_touched(self, hand='any'):
        """检查触摸板是否被触摸"""
        device_path = None
        if hand == 'left':
            device_path = '/user/hand/left'
        elif hand == 'right':
            device_path = '/user/hand/right'

        touched, _ = self.action_manager.is_digital_action_pressed('trackpad_touch', device_path)
        return touched

    def get_trackpad_position(self, hand='any'):
        """获取触摸板位置

        Returns:
            Vec2或None: 触摸板位置 (-1到1的范围)
        """
        device_path = None
        if hand == 'left':
            device_path = '/user/hand/left'
        elif hand == 'right':
            device_path = '/user/hand/right'

        value, _ = self.action_manager.get_analog_action_value('trackpad', device_path)
        return value

    # VR交互系统便捷方法
    def get_selected_object(self, hand='any'):
        """获取指定手选中的对象

        Args:
            hand: 'left', 'right', 'any'

        Returns:
            选中的对象节点或None
        """
        if hand == 'any':
            # 返回任意手选中的对象
            for controller in self.get_connected_controllers():
                selected = self.interaction_manager.get_selected_object(controller.name)
                if selected:
                    return selected
            return None
        else:
            return self.interaction_manager.get_selected_object(hand)

    def get_grabbed_object(self, hand='any'):
        """获取指定手抓取的对象

        Args:
            hand: 'left', 'right', 'any'

        Returns:
            抓取的对象节点或None
        """
        if hand == 'any':
            # 返回任意手抓取的对象
            for controller in self.get_connected_controllers():
                grabbed = self.interaction_manager.get_grabbed_object(controller.name)
                if grabbed:
                    return grabbed
            return None
        else:
            return self.interaction_manager.get_grabbed_object(hand)

    def is_grabbing_object(self, hand='any'):
        """检查是否正在抓取对象

        Args:
            hand: 'left', 'right', 'any'

        Returns:
            bool: 是否正在抓取
        """
        if hand == 'any':
            # 检查任意手是否正在抓取
            for controller in self.get_connected_controllers():
                if self.interaction_manager.is_grabbing(controller.name):
                    return True
            return False
        else:
            return self.interaction_manager.is_grabbing(hand)

    def force_release_all_grabs(self):
        """强制释放所有抓取的对象"""
        self.interaction_manager.force_release_all()

    def add_interactable_object(self, object_node):
        """将对象标记为可交互

        Args:
            object_node: 要标记的对象节点
        """
        self.interaction_manager._add_collision_to_object(object_node)

    def _disable_async_reprojection(self):
        """禁用异步重投影 - 备选修复方案"""
        try:
            # 尝试通过OpenVR设置禁用异步重投影
            if hasattr(openvr, 'VRSettings'):
                settings = openvr.VRSettings()
                if settings:
                    # 禁用异步重投影
                    error = settings.setBool("steamvr", "enableAsyncReprojection", False)
                    if error == openvr.VRSettingsError_None:
                        print("✅ 异步重投影已禁用")
                    else:
                        print(f"⚠️ 禁用异步重投影失败: 设置错误 {error}")
                else:
                    print("⚠️ 无法获取VR设置接口")
            else:
                print("⚠️ OpenVR设置接口不可用")

        except Exception as e:
            print(f"⚠️ 禁用异步重投影失败: {e}")

    def enable_async_reprojection_disable(self):
        """启用异步重投影禁用选项 - 用户可调用的方法"""
        self.disable_async_reprojection = True
        print("📝 异步重投影禁用选项已启用，将在下次VR初始化时生效")

    def disable_async_reprojection_disable(self):
        """禁用异步重投影禁用选项 - 恢复默认行为"""
        self.disable_async_reprojection = False
        print("📝 异步重投影禁用选项已关闭，将使用默认ATW行为")

    def _start_timing(self, operation_name):
        """开始计时操作 - 性能优化版本"""
        if not self.enable_pipeline_monitoring or self.performance_mode_enabled:
            return None

        import time
        # 🚀 性能优化：减少字典创建，只在必要时创建
        return {
            'operation': operation_name,
            'start_time': time.perf_counter()
        }

    def _end_timing(self, timing_data):
        """结束计时并记录结果 - 性能优化版本"""
        if not self.enable_pipeline_monitoring or self.performance_mode_enabled or not timing_data:
            return 0.0

        import time
        elapsed = (time.perf_counter() - timing_data['start_time']) * 1000  # 转换为毫秒

        # 保存到相应的历史记录
        operation = timing_data['operation']
        if operation == 'wait_poses':
            self.wait_poses_time = elapsed
            self.wait_poses_times.append(elapsed)
            if len(self.wait_poses_times) > self.pipeline_history_size:
                self.wait_poses_times.pop(0)
        elif operation == 'left_render':
            self.left_render_time = elapsed
        elif operation == 'right_render':
            self.right_render_time = elapsed
        elif operation == 'submit':
            self.submit_time = elapsed
            self.submit_times.append(elapsed)
            if len(self.submit_times) > self.pipeline_history_size:
                self.submit_times.pop(0)
        elif operation == 'sync_wait':
            self.vr_sync_wait_time = elapsed
            self.sync_wait_times.append(elapsed)
            if len(self.sync_wait_times) > self.pipeline_history_size:
                self.sync_wait_times.pop(0)

        # 计算总渲染时间
        total_render = self.left_render_time + self.right_render_time
        self.render_times.append(total_render)
        if len(self.render_times) > self.pipeline_history_size:
            self.render_times.pop(0)

        return elapsed

    def _get_pipeline_stats(self):
        """获取渲染管线统计信息"""
        def get_stats(times_list):
            if not times_list:
                return {'avg': 0.0, 'min': 0.0, 'max': 0.0}
            return {
                'avg': sum(times_list) / len(times_list),
                'min': min(times_list),
                'max': max(times_list)
            }

        # 计算GPU时间统计
        def get_gpu_field_stats(field_name):
            """从GPU时间历史记录中提取特定字段的统计信息"""
            values = []
            for gpu_data in self.gpu_timing_history:
                if field_name in gpu_data:
                    values.append(gpu_data[field_name])
            return get_stats(values)

        return {
            'wait_poses': get_stats(self.wait_poses_times),
            'render': get_stats(self.render_times),
            'submit': get_stats(self.submit_times),
            'sync_wait': get_stats(self.sync_wait_times),
            'gpu_timing': {
                'scene_render': get_gpu_field_stats('scene_render'),
                'pre_submit': get_gpu_field_stats('pre_submit'),
                'post_submit': get_gpu_field_stats('post_submit'),
                'total_render': get_gpu_field_stats('total_render'),
                'compositor_render': get_gpu_field_stats('compositor_render'),
                'frame_interval': get_gpu_field_stats('frame_interval')
            },
            'current': {
                'wait_poses': self.wait_poses_time,
                'left_render': self.left_render_time,
                'right_render': self.right_render_time,
                'submit': self.submit_time,
                'sync_wait': self.vr_sync_wait_time,
                'total_render': self.left_render_time + self.right_render_time,
                'gpu_scene_render': self.gpu_scene_render_ms,
                'gpu_pre_submit': self.gpu_pre_submit_ms,
                'gpu_post_submit': self.gpu_post_submit_ms,
                'gpu_total_render': self.gpu_total_render_ms,
                'gpu_compositor_render': self.gpu_compositor_render_ms,
                'gpu_frame_interval': self.gpu_client_frame_interval_ms
            },
            'vr_info': {
                'eye_resolution': self.current_eye_resolution,
                'recommended_resolution': self.recommended_eye_resolution,
                'display_frequency': self.vr_display_frequency,
                'vsync_enabled': self.vr_vsync_enabled,
                'target_frame_time_ms': self.target_frame_time_ms,
                'vsync_to_photons_ms': self.vsync_to_photons_ms,
                'vsync_window_ms': self.vsync_window_ms,
                'async_reprojection': self.async_reprojection_enabled,
                'motion_smoothing': self.motion_smoothing_enabled,
                'gpu_timing_enabled': self.enable_gpu_timing,
                'gpu_timing_failures': self.gpu_timing_failure_count
            }
        }


    def set_prediction_time(self, prediction_time_ms):
        """设置预测时间（仅用于update_task策略）

        Args:
            prediction_time_ms: 预测时间，单位毫秒（通常8-16ms）
        """
        prediction_time_s = prediction_time_ms / 1000.0
        if prediction_time_s < 0.005 or prediction_time_s > 0.020:
            print(f"⚠️ 预测时间超出推荐范围(5-20ms): {prediction_time_ms}ms")

        old_time = self.use_prediction_time * 1000
        self.use_prediction_time = prediction_time_s
        print(f"✓ VR预测时间已设置: {old_time:.1f}ms → {prediction_time_ms:.1f}ms")


    def test_pipeline_monitoring(self):
        """测试管线监控功能 - 用于调试和验证"""
        print("🔧 正在测试VR管线监控功能...")

        try:
            # 测试基本信息获取
            print("📊 基本信息:")
            print(f"   当前分辨率: {self.current_eye_resolution}")
            print(f"   显示频率: {self.vr_display_frequency} Hz")
            print(f"   目标帧时间: {self.target_frame_time_ms:.2f}ms")

            # Running Start模式信息
            print("🎯 Running Start模式:")
            print(f"   预测时间: {self.use_prediction_time * 1000:.1f}ms")
            print(f"   模式: Valve Running Start - 帧开始时获取姿态")

            # 测试管线统计
            if self.enable_pipeline_monitoring:
                pipeline_stats = self._get_pipeline_stats()
                print("⚙️ 管线统计:")
                print(f"   waitGetPoses历史: {len(self.wait_poses_times)}帧")
                print(f"   渲染历史: {len(self.render_times)}帧")
                print(f"   提交历史: {len(self.submit_times)}帧")

                # 测试性能报告
                print("📋 生成详细性能报告:")
                self._print_performance_report()

                print("✅ 管线监控功能测试完成")
            else:
                print("⚠️ 管线监控已禁用，无法测试统计功能")

        except Exception as e:
            print(f"❌ 测试管线监控功能时发生错误: {e}")
            import traceback
            traceback.print_exc()

    def _init_performance_monitoring(self):
        """初始化性能监控库"""
        self.psutil_available = False
        self.gputil_available = False
        self.nvidia_ml_available = False

        try:
            import psutil
            self.psutil = psutil
            self.psutil_available = True
            print("✓ psutil性能监控库已加载")
        except ImportError:
            print("⚠️ psutil库未安装，CPU和内存监控将不可用")

        try:
            import GPUtil
            self.gputil = GPUtil
            self.gputil_available = True
            print("✓ GPUtil GPU监控库已加载")
        except ImportError:
            print("⚠️ GPUtil库未安装，GPU监控将不可用")

        try:
            import pynvml
            self.pynvml = pynvml
            pynvml.nvmlInit()
            self.nvidia_ml_available = True
            print("✓ NVIDIA-ML GPU监控库已加载")
        except ImportError:
            print("⚠️ pynvml库未安装，NVIDIA GPU详细监控将不可用")
        except Exception as e:
            print(f"⚠️ NVIDIA-ML初始化失败: {e}")

    def _get_gpu_frame_timing(self, frames_ago=0):
        """获取GPU渲染时间统计

        Args:
            frames_ago: 获取多少帧之前的数据，0表示当前帧

        Returns:
            dict: GPU时间数据，如果获取失败返回None
        """
        if not self.enable_gpu_timing or not self.vr_compositor:
            return None

        try:
            # 调用OpenVR的getFrameTiming API
            result, timing = self.vr_compositor.getFrameTiming(framesAgo=frames_ago)

            if not result:
                self.gpu_timing_failure_count += 1
                if self.gpu_timing_failure_count % 300 == 1:  # 每5秒输出一次错误
                    print("⚠️ OpenVR getFrameTiming调用失败")
                return None

            # 提取GPU时间数据（单位：毫秒）
            gpu_data = {}

            # 检查timing对象是否有GPU时间相关的属性
            if hasattr(timing, 'm_flSceneRenderGpuMs'):
                gpu_data['scene_render'] = timing.m_flSceneRenderGpuMs
                self.gpu_scene_render_ms = timing.m_flSceneRenderGpuMs

            if hasattr(timing, 'm_flPreSubmitGpuMs'):
                gpu_data['pre_submit'] = timing.m_flPreSubmitGpuMs
                self.gpu_pre_submit_ms = timing.m_flPreSubmitGpuMs

            if hasattr(timing, 'm_flPostSubmitGpuMs'):
                gpu_data['post_submit'] = timing.m_flPostSubmitGpuMs
                self.gpu_post_submit_ms = timing.m_flPostSubmitGpuMs

            if hasattr(timing, 'm_flTotalRenderGpuMs'):
                gpu_data['total_render'] = timing.m_flTotalRenderGpuMs
                self.gpu_total_render_ms = timing.m_flTotalRenderGpuMs

            if hasattr(timing, 'm_flCompositorRenderGpuMs'):
                gpu_data['compositor_render'] = timing.m_flCompositorRenderGpuMs
                self.gpu_compositor_render_ms = timing.m_flCompositorRenderGpuMs

            if hasattr(timing, 'm_flClientFrameIntervalMs'):
                gpu_data['frame_interval'] = timing.m_flClientFrameIntervalMs
                self.gpu_client_frame_interval_ms = timing.m_flClientFrameIntervalMs

            # 将GPU时间数据添加到历史记录
            if gpu_data:
                self.gpu_timing_history.append(gpu_data)
                if len(self.gpu_timing_history) > self.gpu_timing_history_size:
                    self.gpu_timing_history.pop(0)

                # 调试信息 - 仅在第一次成功时输出
                if not hasattr(self, '_gpu_timing_success_logged'):
                    available_fields = list(gpu_data.keys())
                    print(f"✅ GPU时间统计已启用 - 可用字段: {available_fields}")
                    self._gpu_timing_success_logged = True

            return gpu_data

        except AttributeError as e:
            # OpenVR Python绑定可能不包含某些字段
            if self.gpu_timing_failure_count == 0:
                print(f"⚠️ GPU时间统计部分功能不可用: {e}")
                print("   这可能是由于OpenVR Python绑定版本问题")
            self.gpu_timing_failure_count += 1
            return None

        except Exception as e:
            self.gpu_timing_failure_count += 1
            if self.gpu_timing_failure_count % 300 == 1:  # 每5秒输出一次错误
                print(f"⚠️ 获取GPU时间统计失败: {e}")
            return None

    def _update_performance_metrics(self):
        """更新系统性能指标"""
        if not self.performance_monitoring:
            return

        import time
        current_time = time.time()

        # 限制更新频率
        if current_time - self.last_performance_check < self.performance_check_interval:
            return

        self.last_performance_check = current_time

        try:
            # 更新CPU和内存使用率
            if self.psutil_available:
                self.cpu_usage = self.psutil.cpu_percent(interval=None)
                memory = self.psutil.virtual_memory()
                self.memory_usage = memory.percent

            # 更新GPU使用率
            self._update_gpu_metrics()

        except Exception as e:
            if self.frame_count % 600 == 0:  # 每10秒输出一次错误
                print(f"⚠️ 性能监控更新失败: {e}")

    def _update_gpu_metrics(self):
        """更新GPU相关指标"""
        try:
            # 方法1: 使用GPUtil
            if self.gputil_available:
                gpus = self.gputil.getGPUs()
                if gpus:
                    gpu = gpus[0]  # 使用第一个GPU
                    self.gpu_usage = gpu.load * 100
                    self.gpu_memory_usage = gpu.memoryUtil * 100

            # 方法2: 使用NVIDIA-ML (更精确)
            elif self.nvidia_ml_available:
                try:
                    handle = self.pynvml.nvmlDeviceGetHandleByIndex(0)

                    # GPU使用率
                    utilization = self.pynvml.nvmlDeviceGetUtilizationRates(handle)
                    self.gpu_usage = utilization.gpu

                    # GPU内存使用率
                    memory_info = self.pynvml.nvmlDeviceGetMemoryInfo(handle)
                    self.gpu_memory_usage = (memory_info.used / memory_info.total) * 100

                except Exception as e:
                    # NVIDIA-ML可能无法在某些系统上工作
                    pass

        except Exception as e:
            # GPU监控失败，但不影响VR功能
            pass

    def _track_frame_time(self):
        """记录帧时间 - 性能优化版本"""
        import time
        current_time = time.time()

        if hasattr(self, '_last_frame_time'):
            frame_time = (current_time - self._last_frame_time) * 1000  # 转换为毫秒

            # 🚀 性能优化：性能模式下跳过列表操作以减少内存分配
            if not self.performance_mode_enabled:
                # 添加到帧时间历史
                self.frame_times.append(frame_time)

                # 限制历史长度
                if len(self.frame_times) > self.max_frame_time_history:
                    self.frame_times.pop(0)

        self._last_frame_time = current_time

    def get_performance_stats(self):
        """获取详细的性能统计信息"""
        stats = {
            'vr_fps': self.vr_fps,
            'frame_count': self.frame_count,
            'submit_failures': self.submit_failures,
            'pose_failures': self.pose_failures,
            'cpu_usage': self.cpu_usage,
            'memory_usage': self.memory_usage,
            'gpu_usage': self.gpu_usage,
            'gpu_memory_usage': self.gpu_memory_usage,
        }

        # 计算帧时间统计
        if self.frame_times:
            stats['frame_time_avg'] = sum(self.frame_times) / len(self.frame_times)
            stats['frame_time_min'] = min(self.frame_times)
            stats['frame_time_max'] = max(self.frame_times)
            stats['frame_time_95th'] = sorted(self.frame_times)[int(len(self.frame_times) * 0.95)]
        else:
            stats['frame_time_avg'] = 0
            stats['frame_time_min'] = 0
            stats['frame_time_max'] = 0
            stats['frame_time_95th'] = 0

        return stats

    def enable_performance_monitoring(self):
        """启用性能监控"""
        self.performance_monitoring = True
        print("✓ VR性能监控已启用")

    def disable_performance_monitoring(self):
        """禁用性能监控"""
        self.performance_monitoring = False
        print("✓ VR性能监控已禁用")

    def enable_gpu_timing_monitoring(self):
        """启用GPU时间监控"""
        self.enable_gpu_timing = True
        print("✓ VR GPU时间监控已启用")

    def disable_gpu_timing_monitoring(self):
        """禁用GPU时间监控"""
        self.enable_gpu_timing = False
        print("✓ VR GPU时间监控已禁用")

    def set_performance_check_interval(self, interval):
        """设置性能检查间隔

        Args:
            interval: 检查间隔（秒），建议0.1-2.0之间
        """
        if 0.1 <= interval <= 5.0:
            self.performance_check_interval = interval
            print(f"✓ 性能监控间隔设置为 {interval:.1f} 秒")
        else:
            print("⚠️ 性能监控间隔应在0.1-5.0秒之间")

    def set_frame_time_history_size(self, size):
        """设置帧时间历史记录大小

        Args:
            size: 历史记录大小（帧数），建议30-300之间
        """
        if 10 <= size <= 1000:
            self.max_frame_time_history = size
            # 清理超出的历史记录
            if len(self.frame_times) > size:
                self.frame_times = self.frame_times[-size:]
            print(f"✓ 帧时间历史记录大小设置为 {size} 帧")
        else:
            print("⚠️ 帧时间历史记录大小应在10-1000帧之间")

    def set_performance_report_interval(self, frames):
        """设置性能报告输出间隔

        Args:
            frames: 帧数间隔，建议300-7200之间（5秒-2分钟@60fps）
        """
        if 300 <= frames <= 7200:
            # 修改_update_vr中的报告间隔
            print(f"✓ 性能报告间隔设置为每 {frames} 帧（约 {frames/60:.1f} 秒@60fps）")
            # 这里可以添加一个实例变量来控制
            self.performance_report_interval = frames
        else:
            print("⚠️ 性能报告间隔应在300-7200帧之间")

    def get_performance_monitoring_config(self):
        """获取当前性能监控配置"""
        return {
            'enabled': self.performance_monitoring,
            'check_interval': self.performance_check_interval,
            'frame_history_size': self.max_frame_time_history,
            'report_interval': getattr(self, 'performance_report_interval', 1800),
            'psutil_available': self.psutil_available,
            'gputil_available': self.gputil_available,
            'nvidia_ml_available': self.nvidia_ml_available
        }

    def print_performance_monitoring_status(self):
        """输出性能监控状态"""
        config = self.get_performance_monitoring_config()

        print("🔧 ===== VR性能监控配置 =====")
        print(f"   监控状态: {'✅ 启用' if config['enabled'] else '❌ 禁用'}")
        print(f"   检查间隔: {config['check_interval']:.1f} 秒")
        print(f"   帧时间历史: {config['frame_history_size']} 帧")
        print(f"   报告间隔: {config['report_interval']} 帧")

        print(f"   可用库:")
        print(f"     psutil (CPU/内存): {'✅' if config['psutil_available'] else '❌'}")
        print(f"     GPUtil (GPU): {'✅' if config['gputil_available'] else '❌'}")
        print(f"     NVIDIA-ML (GPU): {'✅' if config['nvidia_ml_available'] else '❌'}")
        print("=============================")

    def force_performance_report(self):
        """强制输出一次性能报告"""
        print("🔄 手动触发性能报告...")
        self._print_performance_report()

    def reset_performance_counters(self):
        """重置性能计数器"""
        self.frame_count = 0
        self.last_fps_check = 0
        self.last_fps_time = 0
        self.vr_fps = 0
        self.submit_failures = 0
        self.pose_failures = 0
        self.frame_times.clear()
        print("✅ 性能计数器已重置")

    def get_current_performance_summary(self):
        """获取当前性能摘要（简短版本）"""
        stats = self.get_performance_stats()

        summary = f"VR性能: {stats['vr_fps']:.1f}fps"

        if stats['frame_time_avg'] > 0:
            summary += f" | 帧时间: {stats['frame_time_avg']:.1f}ms"

        if self.psutil_available:
            summary += f" | CPU: {stats['cpu_usage']:.0f}%"
            summary += f" | 内存: {stats['memory_usage']:.0f}%"

        # 显示GPU信息，如果库不可用则显示提示
        if self.gputil_available or self.nvidia_ml_available:
            summary += f" | GPU: {stats['gpu_usage']:.0f}%"
        else:
            summary += " | GPU: N/A"

        return summary

    def _print_render_callback_diagnostics(self):
        """输出渲染回调诊断信息 - 包含优化效果分析"""
        try:
            print(f"🔍 DrawCallback渲染诊断:")

            # 回调次数统计
            left_count = self.left_render_count
            right_count = self.right_render_count
            print(f"   渲染次数: 左眼={left_count}, 右眼={right_count}")

            if left_count == 0 and right_count == 0:
                print(f"   ❌ VR缓冲区未被渲染 - 这是严重问题!")
                return

            # 渲染次数平衡性检查
            if abs(left_count - right_count) > 5:
                print(f"   ⚠️ 左右眼渲染次数不平衡: 差异={abs(left_count - right_count)}")
            else:
                print(f"   ✓ 左右眼渲染次数平衡")

            # 🔧 真实渲染时间分析 - 显示优化效果
            left_render_time = getattr(self, 'left_render_time', 0)
            right_render_time = getattr(self, 'right_render_time', 0)
            total_render_time = left_render_time + right_render_time

            print(f"   ⏱️ 精确渲染时间测量:")
            print(f"      左眼cbdata.upcall(): {left_render_time:.2f}ms")
            print(f"      右眼cbdata.upcall(): {right_render_time:.2f}ms")
            print(f"      总计: {total_render_time:.2f}ms")

            # 渲染性能评估
            if total_render_time > 16.0:  # 超过60FPS时间
                print(f"   🔴 渲染时间过长: {total_render_time:.1f}ms (目标<13.9ms@72Hz)")
                print(f"      建议: 检查RenderPipeline优化是否生效")
            elif total_render_time > 10.0:
                print(f"   🟡 渲染时间偏高: {total_render_time:.1f}ms (可接受)")
            else:
                print(f"   🟢 渲染性能良好: {total_render_time:.1f}ms")

            # 🔧 渲染管线优化状态检查
            self._check_rendering_optimizations()

            # OpenGL状态诊断
            self._diagnose_opengl_state()

        except Exception as e:
            print(f"   渲染回调诊断失败: {e}")

    def _check_rendering_optimizations(self):
        """检查渲染优化状态"""
        try:
            print(f"   🔧 渲染优化状态:")

            # 检查RenderPipeline优化
            if hasattr(self.world, 'render_pipeline') and self.world.render_pipeline:
                print(f"      RenderPipeline: 已检测并优化")
            else:
                print(f"      RenderPipeline: 未检测到（使用基础Panda3D）")

            # 检查GPU同步优化
            if hasattr(self, '_smart_sync_logged'):
                last_sync_frame = getattr(self, '_last_gpu_sync_frame', 0)
                current_frame = getattr(self, 'frame_count', 0)
                frames_since_sync = current_frame - last_sync_frame
                print(f"      智能GPU同步: 已启用 (距离上次同步: {frames_since_sync}帧)")
            else:
                print(f"      智能GPU同步: 未初始化")

            # 检查对象池状态
            matrix_pool_status = self.get_object_pool_status()
            print(f"      对象池: Mat4={matrix_pool_status['matrix_pool_size']}/{matrix_pool_status['matrix_pool_capacity']}")

            # 检查垃圾回收控制
            gc_status = self.get_debug_status()
            if gc_status['gc_disabled']:
                print(f"      GC控制: 已启用手动模式 (间隔:{gc_status['manual_gc_interval']}帧)")
            else:
                print(f"      GC控制: 自动模式")

        except Exception as e:
            print(f"      优化状态检查失败: {e}")

    def _diagnose_opengl_state(self):
        """诊断OpenGL渲染状态"""
        try:
            # 检查VR缓冲区状态
            if hasattr(self, 'vr_left_eye_buffer') and self.vr_left_eye_buffer:
                left_gsg = self.vr_left_eye_buffer.getGsg()
                left_valid = self.vr_left_eye_buffer.isValid()
                print(f"   左眼缓冲区: {'有效' if left_valid else '无效'}")

            if hasattr(self, 'vr_right_eye_buffer') and self.vr_right_eye_buffer:
                right_gsg = self.vr_right_eye_buffer.getGsg()
                right_valid = self.vr_right_eye_buffer.isValid()
                print(f"   右眼缓冲区: {'有效' if right_valid else '无效'}")

            # 检查纹理准备状态
            if hasattr(self, 'textures_prepared'):
                print(f"   纹理准备状态: {'已准备' if self.textures_prepared else '未准备'}")

                # 检查纹理ID缓存
                if hasattr(self, 'left_texture_id') and hasattr(self, 'right_texture_id'):
                    left_id = self.left_texture_id or 0
                    right_id = self.right_texture_id or 0
                    print(f"   纹理ID缓存: 左眼={left_id}, 右眼={right_id}")

                    if left_id == 0 or right_id == 0:
                        print(f"   ⚠️ 检测到无效的纹理ID，这可能导致提交失败")
                    else:
                        print(f"   ✓ 纹理ID缓存正常")

            # 检查场景渲染状态
            if hasattr(self.world, 'render') and self.world.render:
                render_children = len(self.world.render.getChildren())
                print(f"   场景节点数: {render_children}")
                if render_children == 0:
                    print(f"   ⚠️ 场景为空，可能导致渲染时间异常短")

        except Exception as e:
            print(f"   OpenGL状态诊断失败: {e}")

    def enable_debug_output(self):
        """启用调试输出"""
        self.debug_output_enabled = True
        print("✓ VR调试输出已启用")

    def disable_debug_output(self):
        """禁用调试输出"""
        self.debug_output_enabled = False
        print("✓ VR调试输出已禁用")

    def set_debug_mode(self, mode):
        """设置调试模式

        Args:
            mode: 'brief' 或 'detailed'
        """
        if mode in ['brief', 'detailed']:
            self.debug_mode = mode
            print(f"✓ VR调试模式设置为: {mode}")
        else:
            print("⚠️ 调试模式只能是 'brief' 或 'detailed'")

    def toggle_debug_output(self):
        """切换调试输出状态"""
        self.debug_output_enabled = not self.debug_output_enabled
        status = "启用" if self.debug_output_enabled else "禁用"
        print(f"✓ VR调试输出已{status}")
        return self.debug_output_enabled

    def get_debug_status(self):
        """获取调试状态"""
        return {
            'debug_enabled': self.debug_output_enabled,
            'debug_mode': self.debug_mode,
            'performance_monitoring': self.performance_monitoring,
            'report_interval_frames': getattr(self, 'performance_report_interval', 600),
            'report_interval_seconds': getattr(self, 'performance_report_interval', 600) / 60,  # 假设60fps
            'gc_control_enabled': self._gc_control_enabled,
            'gc_disabled': self._gc_disabled,
            'manual_gc_interval': self._manual_gc_interval,
        }

    # ====== Python垃圾回收控制方法 ======

    def enable_gc_control(self):
        """启用垃圾回收控制 - 减少VR渲染期间的GC峰值"""
        if not self._gc_control_enabled:
            self._gc_control_enabled = True
            if not self._gc_disabled:
                gc.disable()
                self._gc_disabled = True
            print("✅ VR垃圾回收控制已启用")
        else:
            print("ℹ️ VR垃圾回收控制已经启用")

    def disable_gc_control(self):
        """禁用垃圾回收控制 - 恢复自动垃圾回收"""
        if self._gc_control_enabled:
            self._gc_control_enabled = False
            if self._gc_disabled:
                gc.enable()
                self._gc_disabled = False
            print("✅ VR垃圾回收控制已禁用，恢复自动垃圾回收")
        else:
            print("ℹ️ VR垃圾回收控制已经禁用")

    def set_manual_gc_interval(self, frames):
        """设置手动垃圾回收间隔

        Args:
            frames: 帧数间隔 (建议100-600)
        """
        if 50 <= frames <= 1800:
            old_interval = self._manual_gc_interval
            self._manual_gc_interval = frames
            print(f"✅ 手动GC间隔: {old_interval} → {frames} 帧")
        else:
            print("⚠️ GC间隔应在50-1800帧之间")

    def force_manual_gc(self):
        """强制执行一次垃圾回收"""
        collected = gc.collect()
        print(f"🗑️ 强制GC: 清理了 {collected} 个对象")
        return collected

    def get_object_pool_status(self):
        """获取对象池状态"""
        return {
            'matrix_pool_size': len(self._matrix_pool) if hasattr(self, '_matrix_pool') else 0,
            'matrix_pool_capacity': getattr(self, '_matrix_pool_size', 0),
            'cached_controllers': len(self.controller_poses),
            'cached_matrices': len(getattr(self, '_cached_matrices', {})),
        }

    # ====== VR分辨率缩放和质量预设系统 ======

    def set_resolution_scale(self, scale):
        """设置VR分辨率缩放系数

        Args:
            scale: 缩放系数 (0.3-1.0)，0.75表示75%分辨率
        """
        if not (0.3 <= scale <= 1.0):
            print(f"⚠️ 分辨率缩放系数应在0.3-1.0之间，当前: {scale}")
            return False

        old_scale = self.resolution_scale
        self.resolution_scale = scale

        # 如果VR已初始化，重新创建缓冲区
        if self.vr_initialized:
            self._apply_resolution_scale()

        print(f"✓ VR分辨率缩放: {old_scale} → {scale}")
        pixel_reduction = (1 - scale**2) * 100
        print(f"📊 像素减少: {pixel_reduction:.1f}%")

        return True

    def set_quality_preset(self, preset_name):
        """设置VR质量预设

        Args:
            preset_name: 'performance', 'balanced', 'quality'
        """
        if preset_name not in self.quality_presets:
            print(f"⚠️ 未知的质量预设: {preset_name}")
            print(f"   可用预设: {list(self.quality_presets.keys())}")
            return False

        old_preset = self.current_quality_preset
        self.current_quality_preset = preset_name
        scale = self.quality_presets[preset_name]

        print(f"🎯 切换VR质量预设: {old_preset} → {preset_name}")

        return self.set_resolution_scale(scale)

    def cycle_quality_preset(self):
        """循环切换质量预设"""
        presets = list(self.quality_presets.keys())
        current_index = presets.index(self.current_quality_preset)
        next_index = (current_index + 1) % len(presets)
        next_preset = presets[next_index]

        return self.set_quality_preset(next_preset)

    def _apply_resolution_scale(self):
        """应用分辨率缩放，重新创建VR缓冲区"""
        try:
            # 计算新的分辨率
            self.scaled_eye_width = int(self.base_eye_width * self.resolution_scale)
            self.scaled_eye_height = int(self.base_eye_height * self.resolution_scale)

            # 更新当前分辨率
            self.eye_width = self.scaled_eye_width
            self.eye_height = self.scaled_eye_height
            self.current_eye_resolution = (self.eye_width, self.eye_height)

            print(f"🔄 重新创建VR缓冲区...")
            print(f"   新分辨率: {self.eye_width}x{self.eye_height}")

            # 清理旧的缓冲区
            self._cleanup_vr_buffers()

            # 🔧 关键修复：根据渲染模式选择创建方法
            success = False
            if self.vr_render_mode == VRRenderMode.RENDER_PIPELINE:
                print(f"   使用RenderPipeline模式重建...")
                success = self._create_vr_buffers_with_pipeline()
                if not success:
                    print("⚠️ RenderPipeline模式创建失败，回退到普通渲染模式")
                    self.vr_render_mode = VRRenderMode.NORMAL
                    success = self._create_vr_buffers()
            else:
                print(f"   使用普通模式重建...")
                success = self._create_vr_buffers()

            if success:
                # 重新设置相机
                self._setup_vr_cameras()
                print("✅ VR缓冲区重新创建成功")
                return True
            else:
                print("❌ VR缓冲区重新创建失败")
                return False

        except Exception as e:
            print(f"❌ 应用分辨率缩放失败: {e}")
            import traceback
            traceback.print_exc()
            return False


    def get_resolution_info(self):
        """获取分辨率相关信息"""
        return {
            'base_resolution': (self.base_eye_width, self.base_eye_height),
            'current_resolution': (self.eye_width, self.eye_height),
            'resolution_scale': self.resolution_scale,
            'current_preset': self.current_quality_preset,
            'available_presets': self.quality_presets,
            'pixel_reduction_percent': (1 - self.resolution_scale**2) * 100
        }

    def print_resolution_info(self):
        """输出分辨率信息"""
        info = self.get_resolution_info()
        print("🔧 ===== VR分辨率信息 =====")
        print(f"   推荐分辨率: {info['base_resolution'][0]}x{info['base_resolution'][1]}")
        print(f"   当前分辨率: {info['current_resolution'][0]}x{info['current_resolution'][1]}")
        print(f"   缩放系数: {info['resolution_scale']}")
        print(f"   当前预设: {info['current_preset']}")
        print(f"   像素减少: {info['pixel_reduction_percent']:.1f}%")
        print("   可用预设:")
        for name, scale in info['available_presets'].items():
            marker = "✓" if name == info['current_preset'] else " "
            print(f"   {marker} {name}: {scale} ({scale*100:.0f}%)")
        print("==========================")

    # ====== 性能模式控制方法 ======

    def enable_performance_mode(self):
        """手动启用性能模式 - 立即禁用详细监控以提升性能"""
        if not self.performance_mode_enabled:
            self.performance_mode_enabled = True
            print("🎯 性能模式已手动启用 - 禁用详细监控以提升性能")
            print("   现在将减少每帧对象创建，显著提升VR性能稳定性")
        else:
            print("ℹ️ 性能模式已经启用")

    def disable_performance_mode(self):
        """禁用性能模式 - 重新启用详细监控（用于调试）"""
        if self.performance_mode_enabled:
            self.performance_mode_enabled = False
            print("🔍 性能模式已禁用 - 重新启用详细监控")
            print("   注意：这将增加每帧对象创建，可能影响VR性能")
        else:
            print("ℹ️ 性能模式已经禁用")

    def set_performance_mode_trigger_frame(self, frame_count):
        """设置性能模式自动触发的帧数

        Args:
            frame_count: 触发帧数 (建议300-1200)
        """
        if 100 <= frame_count <= 3600:
            old_trigger = self.performance_mode_trigger_frame
            self.performance_mode_trigger_frame = frame_count
            print(f"✅ 性能模式触发帧数: {old_trigger} → {frame_count}")
        else:
            print("⚠️ 触发帧数应在100-3600之间")

    def get_performance_mode_status(self):
        """获取性能模式状态"""
        return {
            'performance_mode_enabled': self.performance_mode_enabled,
            'trigger_frame': self.performance_mode_trigger_frame,
            'current_frame': self.frame_count,
            'will_trigger_at_frame': self.performance_mode_trigger_frame if not self.performance_mode_enabled else None,
            'gc_interval_normal': self._manual_gc_interval,
            'gc_interval_performance': self._manual_gc_interval * 2,
        }

    # ====== VR测试模式 ======

    def enable_vr_test_mode(self, display_mode='stereo'):
        """启用VR测试模式 - 将VR渲染直接显示在屏幕上

        Args:
            display_mode: 显示模式
                - 'stereo': 左右眼并排显示
                - 'left': 只显示左眼
                - 'right': 只显示右眼
        """
        if not self.is_vr_available():
            print("❌ VR系统不可用，无法启动测试模式")
            return False

        try:
            print(f"🧪 启动VR测试模式 - 显示模式: {display_mode}")

            # 初始化VR系统（如果还没初始化）
            if not self.vr_initialized:
                if not self.initialize_vr():
                    print("❌ VR初始化失败")
                    return False

            # 🔧 关键修复：确保测试模式的纹理资源已初始化
            # 这解决了测试模式纹理提交失败导致的36FPS问题
            print("🔧 检查VR测试模式纹理资源...")
            if not self._ensure_test_mode_textures():
                print("❌ VR测试模式纹理资源初始化失败")
                return False

            # 设置测试模式
            self.vr_test_mode = True
            self.test_display_mode = display_mode

            # 启用VR渲染但不提交给OpenVR
            if not self.vr_enabled:
                # 启用VR渲染流程（但会在回调中跳过提交）
                self.vr_enabled = True
                self._disable_main_cam()

                # 设置高帧率用于测试
                if hasattr(self.world, 'qtWidget') and self.world.qtWidget:
                    if hasattr(self.world.qtWidget, 'synchronizer'):
                        self.world.qtWidget.synchronizer.setInterval(int(1000/144))
                        print("✓ 测试模式：Qt Timer设置为144Hz")

            # 初始化测试显示系统
            if not self._initialize_test_display():
                print("❌ 测试显示系统初始化失败")
                return False

            # 创建性能HUD
            if not self._initialize_test_performance_hud():
                print("❌ 性能HUD初始化失败")
                return False

            # 恢复主相机以查看测试内容
            self._enable_main_cam()

            # 重置HUD更新计数器
            self.hud_update_counter = 0

            print("✅ VR测试模式已启用")
            print("   - VR内容将显示在屏幕上")
            print("   - 不会向OpenVR提交纹理")
            print("   - 可以准确测量纯渲染性能")
            print(f"   - 当前显示模式: {display_mode}")

            return True

        except Exception as e:
            print(f"❌ 启动VR测试模式失败: {e}")
            import traceback
            traceback.print_exc()
            return False

    def _ensure_test_mode_textures(self):
        """确保VR测试模式的纹理资源已正确初始化

        这解决了测试模式启用纹理提交时的36FPS问题：
        - VR测试模式可能跳过了VR渲染缓冲区的初始化
        - submit_texture()需要有效的texture ID和OpenVR Texture对象
        - 如果未初始化会导致提交失败，造成帧率减半
        """
        try:
            print("   检查VR渲染缓冲区...")

            # 检查VR渲染缓冲区是否存在
            buffers_exist = (
                hasattr(self, 'vr_left_eye_buffer') and self.vr_left_eye_buffer and
                hasattr(self, 'vr_right_eye_buffer') and self.vr_right_eye_buffer
            )

            if not buffers_exist:
                print("   ⚠️ VR渲染缓冲区不存在，正在创建...")
                if not self._setup_vr_render_buffers():
                    print("   ❌ VR渲染缓冲区创建失败")
                    return False
                print("   ✅ VR渲染缓冲区创建成功")
            else:
                print("   ✅ VR渲染缓冲区已存在")

            # 检查纹理ID是否已缓存
            print("   检查纹理ID缓存...")
            texture_ids_cached = (
                hasattr(self, 'left_texture_id') and self.left_texture_id and self.left_texture_id > 0 and
                hasattr(self, 'right_texture_id') and self.right_texture_id and self.right_texture_id > 0
            )

            if not texture_ids_cached:
                print("   ⚠️ 纹理ID未缓存，正在准备纹理...")
                if not self._prepare_and_cache_textures():
                    print("   ❌ 纹理准备和缓存失败")
                    return False
                print(f"   ✅ 纹理ID缓存成功 - 左眼:{self.left_texture_id}, 右眼:{self.right_texture_id}")
            else:
                print(f"   ✅ 纹理ID已缓存 - 左眼:{self.left_texture_id}, 右眼:{self.right_texture_id}")

            # 检查OpenVR Texture对象是否已创建
            print("   检查OpenVR Texture对象...")
            ovr_textures_exist = (
                hasattr(self, '_left_ovr_texture') and self._left_ovr_texture and
                hasattr(self, '_right_ovr_texture') and self._right_ovr_texture
            )

            if not ovr_textures_exist:
                print("   ⚠️ OpenVR Texture对象未创建，正在创建...")
                self._create_cached_ovr_textures()
                print("   ✅ OpenVR Texture对象创建成功")
            else:
                print("   ✅ OpenVR Texture对象已存在")

            print("   ✅ VR测试模式纹理资源检查完成，可安全启用纹理提交")
            return True

        except Exception as e:
            print(f"   ❌ VR测试模式纹理资源检查失败: {e}")
            import traceback
            traceback.print_exc()
            return False

    def _create_cached_ovr_textures(self):
        """创建缓存的OpenVR Texture对象 - 避免每帧创建新对象"""
        try:
            import openvr
            self._left_ovr_texture = openvr.Texture_t()
            self._right_ovr_texture = openvr.Texture_t()

            # 设置固定属性（这些不变）
            self._left_ovr_texture.eType = openvr.TextureType_OpenGL
            self._left_ovr_texture.eColorSpace = openvr.ColorSpace_Gamma
            self._right_ovr_texture.eType = openvr.TextureType_OpenGL
            self._right_ovr_texture.eColorSpace = openvr.ColorSpace_Gamma

            print("✅ OpenVR Texture对象缓存已创建")
        except Exception as e:
            print(f"⚠️ OpenVR Texture对象创建失败: {e}")
            # 不抛出异常，使用备用方案

    def _batch_submit_textures(self):
        """批量提交两眼纹理 - OpenVR最佳实践

        基于官方hellovr示例的实现：
        - 两眼都渲染完成后，快速连续提交
        - 减少submit阻塞时间，避免错过VSync窗口
        - 这是解决36FPS问题的关键
        """
        try:
            if not self.vr_compositor:
                return False

            # 检查纹理是否准备好
            if not (self.vr_left_texture and self.vr_right_texture):
                return False

            # 🚀 关键：快速连续提交两眼，最小化阻塞时间
            # 这符合OpenVR官方示例的做法
            success_left = False
            success_right = False

            # 提交左眼纹理
            try:
                self.submit_texture(openvr.Eye_Left, self.vr_left_texture)
                success_left = True
            except Exception as e:
                print(f"❌ 批量提交左眼失败: {e}")

            # 立即提交右眼纹理（不等待）
            try:
                self.submit_texture(openvr.Eye_Right, self.vr_right_texture)
                success_right = True
            except Exception as e:
                print(f"❌ 批量提交右眼失败: {e}")

            # 🚀 关键修复：调用PostPresentHandoff解除compositor阻塞
            # 这是解决36FPS问题的核心 - 确保compositor不会等待VSync
            if success_left and success_right:
                try:
                    # PostPresentHandoff告诉compositor我们已完成帧处理
                    # 防止compositor等待下一个VSync周期
                    if hasattr(self.vr_compositor, 'postPresentHandoff'):
                        self.vr_compositor.postPresentHandoff()
                    elif hasattr(self.vr_compositor, 'PostPresentHandoff'):
                        self.vr_compositor.PostPresentHandoff()
                    else:
                        # 备用方案：如果没有PostPresentHandoff，记录警告
                        if not hasattr(self, '_post_present_warning_logged'):
                            print("⚠️ PostPresentHandoff方法未找到，可能影响时序")
                            self._post_present_warning_logged = True
                except Exception as handoff_error:
                    if not hasattr(self, '_handoff_error_logged'):
                        print(f"⚠️ PostPresentHandoff调用失败: {handoff_error}")
                        self._handoff_error_logged = True

                # 记录批量提交状态（仅首次成功时）
                if not hasattr(self, '_batch_submit_success_logged'):
                    print("✅ OpenVR批量提交模式+PostPresentHandoff已启用")
                    print("   这应该解决36FPS → 72FPS的问题")
                    self._batch_submit_success_logged = True
                return True
            else:
                return False

        except Exception as e:
            print(f"❌ 批量提交纹理失败: {e}")
            return False

    def disable_vr_test_mode(self):
        """禁用VR测试模式"""
        try:
            print("🧪 禁用VR测试模式...")

            # 清理测试显示
            self._cleanup_test_display()

            # 清理性能HUD
            self._cleanup_test_performance_hud()

            # 关闭测试模式
            self.vr_test_mode = False
            self.test_mode_initialized = False

            # 重置HUD更新计数器
            self.hud_update_counter = 0

            # 恢复正常VR模式或禁用VR
            if self.vr_enabled:
                print("   选择: [1] 恢复正常VR模式  [2] 完全禁用VR")
                # 这里可以让用户选择，现在默认禁用VR
                self.disable_vr()

            print("✅ VR测试模式已禁用")
            return True

        except Exception as e:
            print(f"❌ 禁用VR测试模式失败: {e}")
            return False

    def switch_test_display_mode(self, display_mode):
        """切换测试显示模式

        Args:
            display_mode: 'stereo', 'left', 'right'
        """
        if not self.vr_test_mode:
            print("⚠️ 请先启用VR测试模式")
            return False

        if display_mode not in ['stereo', 'left', 'right']:
            print(f"⚠️ 无效的显示模式: {display_mode}")
            return False

        print(f"🧪 切换显示模式: {self.test_display_mode} → {display_mode}")

        # 如果切换模式，需要清理旧的显示并重置标志位
        if self.test_display_mode != display_mode:
            self._cleanup_test_display()

        self.test_display_mode = display_mode

        # 更新显示
        self._update_test_display()
        return True

    def _initialize_test_display(self):
        """初始化测试显示系统"""
        try:
            print("🔧 正在初始化测试显示系统...")

            # 导入必要的Panda3D组件
            from panda3d.core import CardMaker, PandaNode

            # 创建显示四边形
            cm = CardMaker("vr_test_display")

            if self.test_display_mode == 'stereo':
                # 并排显示：左眼在左半屏，右眼在右半屏
                cm.setFrame(-1, 1, -0.5, 0.5)  # 全屏
            else:
                # 单眼显示：占据整个屏幕
                cm.setFrame(-1, 1, -1, 1)

            # 创建节点
            self.test_display_quad = self.world.render2d.attachNewNode(cm.generate())

            # 设置初始纹理
            self._update_test_display()

            # 设置渲染状态
            self.test_display_quad.setTransparency(0)  # 不透明
            self.test_display_quad.setBin("background", 0)  # 背景层

            self.test_mode_initialized = True
            print("✅ 测试显示系统初始化完成")
            return True

        except Exception as e:
            print(f"❌ 测试显示系统初始化失败: {e}")
            import traceback
            traceback.print_exc()
            return False

    def _update_test_display(self):
        """更新测试显示内容"""
        try:
            if not self.test_mode_initialized:
                return

            # 根据显示模式设置纹理
            if self.test_display_mode == 'left':
                if not self.test_display_quad:
                    return
                if self.vr_left_texture:
                    self.test_display_quad.setTexture(self.vr_left_texture)
            elif self.test_display_mode == 'right':
                if not self.test_display_quad:
                    return
                if self.vr_right_texture:
                    self.test_display_quad.setTexture(self.vr_right_texture)
            elif self.test_display_mode == 'stereo':
                # 立体显示：只在第一次创建，后续只更新纹理
                if not self.stereo_display_created:
                    self._create_stereo_display()
                else:
                    # 只更新纹理，不重新创建
                    if self.test_display_quad and self.vr_left_texture:
                        self.test_display_quad.setTexture(self.vr_left_texture)
                    if self.test_right_quad and self.vr_right_texture:
                        self.test_right_quad.setTexture(self.vr_right_texture)

        except Exception as e:
            print(f"⚠️ 更新测试显示失败: {e}")

    def _create_stereo_display(self):
        """创建左右眼并排显示"""
        try:
            # 如果已经创建，直接返回
            if self.stereo_display_created and self.test_display_quad and self.test_right_quad:
                return

            # 移除旧的显示
            if self.test_display_quad:
                self.test_display_quad.removeNode()
            if self.test_right_quad:
                self.test_right_quad.removeNode()

            from panda3d.core import CardMaker

            # 创建左眼显示
            left_cm = CardMaker("vr_test_left")
            left_cm.setFrame(-1, 0, -1, 1)  # 左半屏
            left_quad = self.world.render2d.attachNewNode(left_cm.generate())
            if self.vr_left_texture:
                left_quad.setTexture(self.vr_left_texture)

            # 创建右眼显示
            right_cm = CardMaker("vr_test_right")
            right_cm.setFrame(0, 1, -1, 1)  # 右半屏
            right_quad = self.world.render2d.attachNewNode(right_cm.generate())
            if self.vr_right_texture:
                right_quad.setTexture(self.vr_right_texture)

            # 保存引用
            self.test_display_quad = left_quad  # 保存左眼引用
            self.test_right_quad = right_quad   # 额外保存右眼引用
            self.stereo_display_created = True  # 标记已创建

            print("✓ 立体显示已创建")

        except Exception as e:
            print(f"⚠️ 创建立体显示失败: {e}")
            self.stereo_display_created = False

    def _cleanup_test_display(self):
        """清理测试显示"""
        try:
            if self.test_display_quad:
                self.test_display_quad.removeNode()
                self.test_display_quad = None

            if hasattr(self, 'test_right_quad') and self.test_right_quad:
                self.test_right_quad.removeNode()
                self.test_right_quad = None

            # 重置立体显示标志位
            self.stereo_display_created = False

            print("✓ 测试显示已清理")

        except Exception as e:
            print(f"⚠️ 清理测试显示失败: {e}")

    def _initialize_test_performance_hud(self):
        """初始化性能HUD"""
        try:
            print("🔧 正在初始化性能HUD...")

            from direct.gui.OnscreenText import OnscreenText
            from panda3d.core import TextNode

            # 创建性能文本显示
            self.test_performance_text = OnscreenText(
                text="初始化中...",
                pos=(-0.95, 0.9),  # 左上角，调整到屏幕内
                scale=0.05,
                fg=(1, 1, 0, 1),  # 黄色
                align=TextNode.ALeft,
                shadow=(0, 0, 0, 0.5),  # 黑色阴影
                parent=self.world.render2d
            )

            print("✅ 性能HUD初始化完成")
            return True

        except Exception as e:
            print(f"❌ 性能HUD初始化失败: {e}")
            return False

    def _update_test_performance_hud(self):
        """更新性能HUD显示（限制更新频率避免重影）"""
        try:
            if not self.test_performance_text or not self.vr_test_mode:
                return

            # 增加计数器
            self.hud_update_counter += 1

            # 只在指定间隔更新文本，避免重影
            if self.hud_update_counter < self.hud_update_interval:
                return

            # 重置计数器
            self.hud_update_counter = 0

            # 收集性能数据
            left_render_time = getattr(self, 'left_render_time', 0)
            right_render_time = getattr(self, 'right_render_time', 0)
            total_render_time = left_render_time + right_render_time

            # 计算FPS
            current_fps = self.vr_fps if hasattr(self, 'vr_fps') else 0

            # 获取系统性能
            cpu_usage = getattr(self, 'cpu_usage', 0)
            memory_usage = getattr(self, 'memory_usage', 0)
            gpu_usage = getattr(self, 'gpu_usage', 0)

            # 构建显示文本
            hud_text = f"""VR TEST MODE - {self.test_display_mode.upper()}

Render Performance:
  FPS: {current_fps:.1f}
  Left Eye: {left_render_time:.2f}ms
  Right Eye: {right_render_time:.2f}ms
  Total: {total_render_time:.2f}ms

System Performance:
  CPU: {cpu_usage:.1f}%
  Memory: {memory_usage:.1f}%
  GPU: {gpu_usage:.1f}%

Render Count:
  Left Eye: {getattr(self, 'left_render_count', 0)}
  Right Eye: {getattr(self, 'right_render_count', 0)}

Target: <13.9ms@72Hz
Status: {'GOOD' if total_render_time < 10 else 'HIGH' if total_render_time < 16 else 'SLOW'}

Hotkeys:
F1=Left F2=Right F3=SideBySide
ESC=Exit Test Mode"""

            # 更新文本
            self.test_performance_text.setText(hud_text)

        except Exception as e:
            print(f"⚠️ 更新性能HUD失败: {e}")

    def _cleanup_test_performance_hud(self):
        """清理性能HUD"""
        try:
            if self.test_performance_text:
                self.test_performance_text.destroy()
                self.test_performance_text = None

            print("✓ 性能HUD已清理")

        except Exception as e:
            print(f"⚠️ 清理性能HUD失败: {e}")

    def get_test_mode_status(self):
        """获取测试模式状态"""
        if not self.vr_test_mode:
            return None

        left_render_time = getattr(self, 'left_render_time', 0)
        right_render_time = getattr(self, 'right_render_time', 0)
        total_render_time = left_render_time + right_render_time

        return {
            'test_mode_enabled': self.vr_test_mode,
            'display_mode': self.test_display_mode,
            'vr_fps': getattr(self, 'vr_fps', 0),
            'left_render_time': left_render_time,
            'right_render_time': right_render_time,
            'total_render_time': total_render_time,
            'left_render_count': getattr(self, 'left_render_count', 0),
            'right_render_count': getattr(self, 'right_render_count', 0),
            'performance_rating': ('excellent' if total_render_time < 10 else
                                  'good' if total_render_time < 16 else 'poor')
        }

    def set_test_mode_features(self, submit_texture=None, wait_poses=None):
        """设置测试模式功能开关 - 用于渐进式调试

        Args:
            submit_texture: 是否在测试模式启用纹理提交（True/False/None=保持当前）
            wait_poses: 是否在测试模式启用waitGetPoses（True/False/None=保持当前）
        """
        if submit_texture is not None:
            self.test_mode_submit_texture = submit_texture
        if wait_poses is not None:
            self.test_mode_wait_poses = wait_poses

        print(f"🔧 VR测试模式功能设置:")
        print(f"   纹理提交: {'启用' if self.test_mode_submit_texture else '禁用'}")
        print(f"   姿态等待: {'启用' if self.test_mode_wait_poses else '禁用'}")

        # 如果当前在测试模式，输出预期效果
        if self.vr_test_mode:
            print(f"   当前测试模式已启用，设置将立即生效")
        else:
            print(f"   设置已保存，将在下次启用测试模式时生效")

    def get_test_mode_features(self):
        """获取当前测试模式功能设置"""
        return {
            'submit_texture': self.test_mode_submit_texture,
            'wait_poses': self.test_mode_wait_poses,
            'test_mode_active': self.vr_test_mode
        }

    def run_vr_performance_test(self, duration_seconds=30, display_mode='stereo'):
        """运行VR性能测试 - 简单的测试入口方法

        Args:
            duration_seconds: 测试持续时间（秒）
            display_mode: 显示模式 ('stereo', 'left', 'right')

        Returns:
            dict: 测试结果统计
        """
        print("🧪 ======= VR性能测试开始 =======")
        print(f"   测试模式: {display_mode}")
        print(f"   测试时长: {duration_seconds}秒")
        print("   按ESC键提前退出测试")
        print("   F1=左眼 F2=右眼 F3=并排显示")
        print("=================================")

        # 启动测试模式
        if not self.enable_vr_test_mode(display_mode):
            print("❌ VR测试模式启动失败")
            return None

        # 记录测试开始状态
        import time
        test_start_time = time.time()
        start_frame_count = getattr(self, 'frame_count', 0)

        print("✅ VR测试模式已启动")
        print("   - VR内容直接显示在屏幕上")
        print("   - 无OpenVR纹理提交开销")
        print("   - 实时性能监控已启用")
        print(f"   - 当前显示: {display_mode.upper()}模式")
        print("\n开始性能测试...")

        # 等待测试完成（用户手动停止或超时）
        print(f"\n📊 测试将运行 {duration_seconds} 秒")
        print("   实时性能数据显示在屏幕左上角")
        print("   观察帧率和渲染时间变化")

        # 这里可以添加自动停止逻辑，但现在让用户手动控制
        print(f"\n⏰ 请观察 {duration_seconds} 秒后手动调用 disable_vr_test_mode() 停止测试")
        print("   或者随时调用 get_test_mode_status() 查看当前状态")

        return {
            'status': 'running',
            'start_time': test_start_time,
            'start_frame': start_frame_count,
            'display_mode': display_mode,
            'instructions': {
                'stop_test': 'vr_manager.disable_vr_test_mode()',
                'check_status': 'vr_manager.get_test_mode_status()',
                'switch_mode': 'vr_manager.switch_test_display_mode("left/right/stereo")'
            }
        }