vr拆分s3

This commit is contained in:
Rowland 2025-10-20 17:01:45 +08:00
parent 32b6ac2885
commit e20d2a2191
6 changed files with 780 additions and 1266 deletions

179
IFLOW.md Normal file
View File

@ -0,0 +1,179 @@
# iFlow 上下文文档
## 项目概述
这是一个基于 Panda3D 和 PyQt5 的 3D 虚拟现实 (VR) 应用程序框架。该项目旨在提供一个功能齐全、模块化的 3D 环境,支持 VR 设备(如 HTC Vive, Oculus Rift的集成包含场景管理、模型导入、GUI 系统、脚本系统、地形系统、碰撞检测以及完整的 VR 交互功能。
核心架构围绕 `MyWorld` 类构建,该类继承自 `CoreWorld`并集成了各种管理器模块如选择系统、工具管理器、脚本管理器、GUI 管理器、场景管理器、项目管理器、地形管理器、碰撞管理器和 VR 管理器。
## 核心技术栈
- **核心引擎**: Panda3D
- **图形渲染**: 可选择普通渲染或 RenderPipeline 高级渲染管线
- **VR 支持**: OpenVR/SteamVR
- **用户界面**: PyQt5
- **3D 模型格式**: 支持 glTF, FBX (需转换), BAM 等
- **脚本语言**: Python (内嵌脚本系统)
- **物理/碰撞**: Panda3D 内置碰撞系统
## 项目结构
```
.
├── core/ # 核心模块
│ ├── world.py # CoreWorld 基础世界类
│ ├── vr/ # VR 子模块 (完整模块化结构)
│ │ ├── __init__.py
│ │ ├── config/ # VR 配置管理
│ │ ├── interaction/ # VR 交互系统 (动作、抓取、摇杆、传送)
│ │ ├── performance/ # VR 性能监控
│ │ ├── rendering/ # VR 渲染相关 (RenderPipeline 集成)
│ │ ├── testing/ # VR 测试模式
│ │ ├── tracking/ # VR 设备跟踪
│ │ └── visualization/ # VR 可视化 (控制器模型)
│ ├── vr_manager.py # VR 管理器主文件 (待拆分)
│ ├── selection.py # 选择系统
│ ├── tool_manager.py # 工具管理器
│ ├── script_system.py # 脚本系统
│ ├── gui_manager.py # GUI 管理器
│ ├── terrain_manager.py # 地形管理器
│ ├── collision_manager.py # 碰撞管理器
│ ├── event_handler.py # 事件处理器
│ ├── patrol_system.py # 巡检系统
│ ├── Command_System.py # 命令系统
│ └── InfoPanelManager.py # 信息面板管理器
├── demo/ # 示例和测试文件
├── gui/ # GUI 相关模块
├── project/ # 项目管理模块
├── scene/ # 场景管理模块 (部分代码在 core/)
├── scripts/ # 脚本文件目录
├── ui/ # UI 组件和主窗口
├── QPanda3D/ # Panda3D 与 PyQt 集成库
├── Resources/ # 资源文件 (模型、纹理等)
├── config/ # 配置文件
│ └── vr_settings.json # VR 配置文件
├── main.py # 程序入口点
└── Start_Run.py # 启动脚本
```
## 核心功能模块
### 1. World (core/world.py, main.py)
- `CoreWorld`: 基础 3D 世界设置,包括相机、光照、地面、资源路径。
- `MyWorld`: 扩展的主世界类,整合所有管理器和功能模块。
- **初始化**: 设置资源路径、相机、光照、地面,加载中文字体。
- **兼容性**: 提供旧版属性访问接口。
- **功能代理**: 将大量功能委托给专门的管理器。
### 2. VR 系统 (core/vr/)
这是一个高度模块化的 VR 子系统,核心是 `VRManager` (core/vr_manager.py)。
- **VRManager**:
- **初始化与状态管理**: 检查 VR 可用性、初始化 OpenVR、管理启用/禁用状态。
- **渲染系统**:
- 支持普通渲染和 RenderPipeline 高级渲染两种模式。
- 创建和管理左右眼的渲染缓冲区和相机。
- 实现高效的纹理提交到 OpenVR Compositor。
- 支持动态分辨率缩放和质量预设。
- **跟踪系统**:
- 通过 OpenVR 获取 HMD 和控制器的姿态。
- 使用锚点层级系统 (`tracking_space`, `hmd_anchor` 等) 管理设备位置。
- 坐标系转换 (OpenVR 到 Panda3D)。
- **控制器**:
- `LeftController`, `RightController`: 管理具体的手柄输入和可视化。
- 支持动作系统 (VRActionManager) 或直接输入读取。
- **交互系统**:
- **VRInteractionManager**: 对象抓取和交互。
- **VRTeleportSystem**: 传送功能。
- **VRJoystickManager**: 摇杆移动控制。
- **性能优化**:
- 对象池 (Mat4) 减少 GC 压力。
- 纹理 ID 缓存避免重复 prepare。
- 智能 GPU 同步策略。
- 性能模式自动切换。
- **配置管理**:
- `VRConfigManager`: 从 `config/vr_settings.json` 加载/保存配置。
- **测试与调试**:
- `VRTestMode`: 提供不同的测试显示模式和功能开关。
- `VRPerformanceMonitor`: 性能监控和报告。
### 3. GUI 系统 (core/gui_manager.py, gui/)
- **GUIManager**: 管理 2D 和 3D GUI 元素的创建、编辑、删除。
- **功能**:
- 创建按钮、标签、输入框、2D/3D 图像、视频屏幕等。
- GUI 编辑模式,支持拖拽创建和属性编辑。
- 与场景树和属性面板集成。
- 独立的 GUI 预览窗口。
### 4. 场景与模型管理 (core/scene_manager.py)
- **SceneManager**: 管理 3D 场景中的所有模型。
- **功能**:
- 模型导入 (支持 glTF, FBX 转换)。
- 材质和几何体处理。
- 碰撞体设置。
- 场景保存/加载 (BAM 格式)。
- 场景树更新。
### 5. 脚本系统 (core/script_system.py)
- **ScriptManager**: 嵌入式 Python 脚本系统。
- **功能**:
- 脚本文件的创建、加载、重载。
- 为游戏对象挂载/卸载脚本。
- 热重载支持。
- 脚本信息查询。
### 6. 地形系统 (core/terrain_manager.py)
- **TerrainManager**: 管理 3D 地形。
- **功能**:
- 从高度图或创建平面地形。
- 地形 LOD 更新。
- 地形高度查询和编辑。
### 7. 碰撞系统 (core/collision_manager.py)
- **CollisionManager**: 处理场景中的碰撞检测。
- **功能**:
- 模型间碰撞检测。
- 碰撞历史和统计。
### 8. 工具与选择系统 (core/tool_manager.py, core/selection.py)
- **ToolManager**: 管理当前使用的工具 (选择、移动、旋转、缩放)。
- **SelectionSystem**: 处理对象选择逻辑和相机聚焦。
## 构建与运行
### 入口点
- `main.py`: 主程序入口,创建 `MyWorld` 实例并启动 PyQt5 主窗口。
- `Start_Run.py`: 可能的启动脚本。
### 运行方式
1. 确保已安装所有依赖项Panda3D, PyQt5, OpenVR 等)。
2. 运行 `python main.py` 启动应用程序。
3. 如果连接了 VR 设备并安装了 SteamVR可以在应用内启用 VR 模式。
### 依赖项
项目未提供 `requirements.txt` 文件,但根据代码分析,主要依赖包括:
- `panda3d`
- `PyQt5`
- `openvr` (用于 VR 功能)
- `numpy` (在 VR 模块中使用)
## 开发约定
- **模块化设计**: 功能被分解到不同的管理器类中,`MyWorld` 主要起到集成和代理的作用。
- **VR 子模块化**: VR 功能被组织在 `core/vr/` 目录下,具有清晰的子模块划分。
- **配置驱动**: VR 设置通过 `config/vr_settings.json` 文件进行管理。
- **性能意识**: VR 模块包含大量性能优化措施,如对象池、缓存、智能同步等。
- **向后兼容**: `MyWorld` 通过属性代理保持与旧代码的兼容性。
- **测试模式**: VR 系统包含专门的测试模式,便于调试和验证不同功能。

View File

@ -1,358 +0,0 @@
# VR Manager 模块化拆分 - 阶段1完成报告
## 📋 任务概述
**阶段**: 阶段1 - 拆分性能监控系统
**开始时间**: 2025-10-14
**完成时间**: 2025-10-14
**状态**: ✅ 已完成
---
## 🎯 完成的工作
### 1. 创建的文件
| 文件路径 | 行数 | 说明 |
|---------|------|------|
| `core/vr/performance/monitoring.py` | 1,168 | VR性能监控核心模块 |
| `core/vr/performance/__init__.py` | 已更新 | 模块导出接口 |
| `core/vr/performance/MIGRATION_REPORT.md` | - | 迁移文档 |
| `core/vr_manager.py.backup.stage1` | 4,736 | 原始文件备份 |
| `test_performance_integration.py` | - | 集成测试脚本 |
### 2. 修改的文件
| 文件路径 | 变化 | 说明 |
|---------|------|------|
| `core/vr_manager.py` | 4,736 → 3,829行 (-907行) | 删除性能监控代码,添加委托方法 |
---
## 📊 代码统计
### 代码行数变化
- **原始 vr_manager.py**: 4,736行 ❌ (超标 5.3倍)
- **重构后 vr_manager.py**: 3,829行 ⚠️ (超标 4.25倍)
- **新增 monitoring.py**: 1,168行 ✅ (符合900行标准)
- **净减少**: 907行 (-19.1%)
### 迁移的内容
- **迁移的方法**: 35个
- **迁移的属性**: 34个
- **委托方法**: 34个保持API兼容
---
## 🔧 技术实现
### 1. VRPerformanceMonitor类结构
```python
class VRPerformanceMonitor:
"""VR性能监控系统
功能模块:
- 性能报告 (3个方法)
- 性能监控核心 (4个方法)
- GPU计时 (3个方法)
- 渲染管线统计 (4个方法)
- 诊断工具 (3个方法)
- 调试控制 (5个方法)
- 配置方法 (4个方法)
- 查询方法 (4个方法)
- 控制方法 (4个方法)
"""
```
### 2. 集成方式
**在VRManager中**:
```python
# 初始化性能监控系统
self.performance_monitor = VRPerformanceMonitor(self)
# 委托方法示例
def enable_performance_monitoring(self):
if self.performance_monitor:
return self.performance_monitor.enable_performance_monitoring()
```
### 3. 设计原则
- ✅ **组合优先于继承**: 通过组合模式集成子系统
- ✅ **单一职责**: 性能监控功能独立管理
- ✅ **向后兼容**: 100%保持现有API
- ✅ **松耦合**: 最小化模块间依赖
---
## ✅ 验证测试
### 1. 编译检查
```bash
python3 -m py_compile core/vr/performance/monitoring.py ✅
python3 -m py_compile core/vr_manager.py ✅
```
### 2. 导入测试
```bash
from core.vr.performance import VRPerformanceMonitor ✅
```
### 3. 集成测试 (7项测试)
- ✅ 模块导入正常
- ✅ 类结构完整 (13个关键方法验证)
- ✅ 初始化成功
- ✅ 基本方法正常
- ✅ 计时方法正常
- ✅ 配置方法正常
- ✅ 重置和禁用正常
**测试结果**: 全部通过 ✅
---
## 📦 迁移的功能模块
### 1. 性能报告 (3个方法)
- `_print_performance_report` - 详细性能报告
- `_print_performance_recommendations` - 优化建议
- `_print_brief_performance_report` - 简短摘要
### 2. 性能监控核心 (4个方法)
- `_init_performance_monitoring` - 初始化监控库
- `_update_performance_metrics` - 更新性能指标
- `_update_gpu_metrics` - 更新GPU指标
- `_track_frame_time` - 帧时间追踪
### 3. GPU计时 (3个方法)
- `_get_gpu_frame_timing` - 获取GPU渲染时间
- `enable_gpu_timing_monitoring` - 启用GPU监控
- `disable_gpu_timing_monitoring` - 禁用GPU监控
### 4. 渲染管线统计 (4个方法)
- `_start_timing` - 开始计时
- `_end_timing` - 结束计时
- `_get_pipeline_stats` - 获取管线统计
- `test_pipeline_monitoring` - 测试监控功能
### 5. 诊断工具 (3个方法)
- `_print_render_callback_diagnostics` - 渲染回调诊断
- `_check_rendering_optimizations` - 优化状态检查
- `_diagnose_opengl_state` - OpenGL状态诊断
### 6. 调试控制 (5个方法)
- `enable_debug_output`, `disable_debug_output`
- `set_debug_mode`, `toggle_debug_output`
- `get_debug_status`
### 7. 配置方法 (4个方法)
- `set_performance_check_interval`
- `set_frame_time_history_size`
- `set_performance_report_interval`
- `set_prediction_time`
### 8. 查询方法 (4个方法)
- `get_performance_stats` - 详细统计
- `get_current_performance_summary` - 性能摘要
- `get_performance_monitoring_config` - 监控配置
- `print_performance_monitoring_status` - 监控状态
### 9. 控制方法 (4个方法)
- `enable_performance_monitoring`, `disable_performance_monitoring`
- `force_performance_report`, `reset_performance_counters`
---
## 🎯 目标达成情况
| 目标 | 计划 | 实际 | 状态 |
|-----|------|------|------|
| 迁移方法数 | 35个 | 35个 | ✅ |
| 迁移属性数 | ~30个 | 34个 | ✅ |
| 新文件行数 | ~900行 | 1,168行 | ⚠️ 超出29% |
| vr_manager.py减少 | 预期减少 | -907行 (-19.1%) | ✅ |
| API兼容性 | 100% | 100% | ✅ |
| 测试通过率 | 100% | 100% | ✅ |
**说明**: monitoring.py略超900行目标但仍是合理的模块大小功能完整且职责清晰。
---
## 📂 目录结构
```
EG/
├── core/
│ ├── vr_manager.py (3,829行) ⬇️ -19%
│ └── vr/
│ └── performance/
│ ├── __init__.py ✨
│ ├── monitoring.py (1,168行) ✨
│ └── MIGRATION_REPORT.md ✨
├── test_performance_integration.py ✨
├── STAGE1_COMPLETION_REPORT.md ✨
└── VR_Manager 模块化拆分计划.md
```
---
## 🔄 Git状态
### 待提交的文件
```
修改:
core/vr/performance/__init__.py
core/vr_manager.py
新增:
core/vr/performance/monitoring.py
core/vr/performance/MIGRATION_REPORT.md
test_performance_integration.py
STAGE1_COMPLETION_REPORT.md
备份:
core/vr_manager.py.backup.stage1
```
### 建议的提交信息
```
feat(vr): 模块化拆分阶段1 - 性能监控系统
- 创建独立的VRPerformanceMonitor类 (1,168行)
- 迁移35个性能监控方法和34个属性
- 添加34个委托方法保持API兼容性
- vr_manager.py从4,736行减少到3,829行 (-19%)
- 所有测试通过100% API兼容
相关文档:
- core/vr/performance/MIGRATION_REPORT.md
- STAGE1_COMPLETION_REPORT.md
```
---
## 🐛 修复的Bug
在集成过程中发现并修复了以下关键问题:
### Bug 1: AttributeError - 渲染计数属性缺失
**错误信息**:
```
'VRManager' object has no attribute 'left_render_count'
'VRManager' object has no attribute 'right_render_count'
```
**原因**: 属性迁移到VRPerformanceMonitor后,VRManager中的渲染回调仍通过`self.left_render_count`访问。
**解决方案**: 在VRManager中添加16组@property代理(32个属性总计),透明转发到performance_monitor:
```python
@property
def left_render_count(self):
if self.performance_monitor:
return self.performance_monitor.left_render_count
return 0
@left_render_count.setter
def left_render_count(self, value):
if self.performance_monitor:
self.performance_monitor.left_render_count = value
```
**影响范围**: vr_manager.py增加约192行代理属性代码(3648-3886行)
### Bug 2: UnboundLocalError - 变量作用域问题
**错误信息**:
```
local variable 'target_frame_time' referenced before assignment
File "monitoring.py", line 318, in _print_performance_report
```
**原因**:
1. `target_frame_time`在第249行条件块内定义,但在第318行条件块外使用
2. `pipeline_stats`仅在`enable_pipeline_monitoring=True`时定义,但在327-360行无条件使用
**解决方案**:
1. 第231行添加默认值: `target_frame_time = 13.9 # 默认目标帧时间(72Hz)`
2. 第327-360行包裹在条件检查中: `if self.enable_pipeline_monitoring:`
**修复位置**: monitoring.py 第231行, 第327-360行
### 验证结果
- ✅ 属性代理测试: 9/9 通过 (test_property_proxy.py)
- ✅ 集成测试: 7项全部通过 (test_performance_integration.py)
- ✅ 所有修复经过充分测试验证
---
## 🚀 后续工作
### 下一步: 阶段2 - 拆分测试调试系统
根据计划阶段2将拆分测试调试系统 (~800行):
**待迁移的功能**:
- 测试模式管理 (17个方法)
- 纹理管理
- 显示系统
- HUD系统
- 性能测试
**预期文件**: `core/vr/testing/test_mode.py`
**预期收益**: vr_manager.py再减少约700-800行
---
## ✨ 关键改进
1. **模块化**: 性能监控完全独立,便于维护和测试
2. **代码质量**: vr_manager.py减少907行更易阅读
3. **可测试性**: 独立模块可单独测试
4. **API稳定性**: 100%向后兼容,无需修改现有调用代码
5. **文档完善**: 提供迁移文档和测试脚本
---
## 📝 经验总结
### 成功因素
- ✅ 渐进式迁移,先分析后实施
- ✅ 完整的备份策略
- ✅ 委托模式保证API兼容性
- ✅ 充分的测试验证
- ✅ 清晰的文档记录
### 注意事项
- ⚠️ 新模块略超900行但功能完整
- ⚠️ vr_manager.py仍然较大需要继续拆分
- ⚠️ 某些属性需要通过vr_manager访问
### 优化建议
- 考虑进一步细分monitoring.py (如独立GPU计时模块)
- 继续执行阶段2-6的拆分计划
- 最终目标: vr_manager.py < 900行
---
## ✅ 阶段1完成确认
- [x] 创建备份
- [x] 创建目录结构
- [x] 分析和提取代码
- [x] 创建VRPerformanceMonitor类
- [x] 集成到VRManager
- [x] 添加委托方法
- [x] 编译检查通过
- [x] 导入测试通过
- [x] 集成测试通过
- [x] 文档完善
**阶段1状态**: ✅ **圆满完成**
---
**生成时间**: 2025-10-14
**负责人**: Claude (Ultrathink模式)
**下一阶段**: 阶段2 - 测试调试系统拆分

View File

@ -1,349 +0,0 @@
# VR Manager 模块化拆分 - 阶段2完成报告
## 📋 任务概述
**阶段**: 阶段2 - 拆分测试调试系统
**开始时间**: 2025-10-14
**完成时间**: 2025-10-14
**状态**: ✅ 已完成
---
## 🎯 完成的工作
### 1. 创建的文件
| 文件路径 | 行数 | 说明 |
|---------|------|------|
| `core/vr/testing/test_mode.py` | 621 | VR测试模式核心模块 |
| `core/vr/testing/__init__.py` | 已更新 | 模块导出接口 |
| `core/vr_manager.py.backup.stage2` | 3,829 | 阶段2开始前备份 |
| `test_test_mode_integration.py` | - | 集成测试脚本 |
### 2. 修改的文件
| 文件路径 | 变化 | 说明 |
|---------|------|------|
| `core/vr/manager.py` | 3,829 → 3,630行 (-199行, 含新增代码) | 删除测试模式代码,添加委托方法和核心方法 |
**注**: 实际删除634行测试代码,新增177行(108行委托+69行_batch_submit_textures),净减少457行
---
## 📊 代码统计
### 代码行数变化
- **阶段1后 vr_manager.py**: 3,829行 ⚠️ (超标 4.25倍)
- **阶段2后 vr_manager.py**: 3,630行 ⚠️ (超标 4.03倍)
- **新增 test_mode.py**: 621行 ✅ (远低于800行目标,节省22.4%)
- **净减少**: 199行 (-5.2%)
- **累计减少** (阶段1+2): 1,106行 (-23.4%)
### 迁移的内容
- **迁移的方法**: 16个 (原计划17个,_batch_submit_textures保留在VRManager)
- **迁移的属性**: 15个
- **委托方法**: 7个(保持API兼容)
- **属性代理**: 5个(保持API兼容)
- **保留的核心方法**: 1个 (_batch_submit_textures)
---
## 🔧 技术实现
### 1. VRTestMode类结构
```python
class VRTestMode:
"""VR测试模式系统
功能模块:
- 测试模式控制 (3个方法)
- 纹理管理 (3个方法)
- 显示系统 (5个方法)
- HUD系统 (3个方法)
- 状态查询 (3个方法)
"""
```
### 2. 集成方式
**在VRManager中**:
```python
# 初始化测试调试系统
self.test_mode = VRTestMode(self)
# 委托方法示例
def enable_vr_test_mode(self, display_mode='stereo'):
if self.test_mode:
return self.test_mode.enable_vr_test_mode(display_mode)
```
### 3. 属性代理
```python
@property
def vr_test_mode(self):
if self.test_mode:
return self.test_mode.vr_test_mode
return False
@vr_test_mode.setter
def vr_test_mode(self, value):
if self.test_mode:
self.test_mode.vr_test_mode = value
```
### 4. 设计原则
- ✅ **组合优先于继承**: 通过组合模式集成子系统
- ✅ **单一职责**: 测试调试功能独立管理
- ✅ **向后兼容**: 100%保持现有API
- ✅ **松耦合**: 最小化模块间依赖
---
## ✅ 验证测试
### 1. 编译检查
```bash
python3 -m py_compile core/vr/testing/test_mode.py ✅
python3 -m py_compile core/vr_manager.py ✅
```
### 2. 导入测试
```bash
from core.vr.testing import VRTestMode ✅
from core.vr_manager import VRManager ✅
```
### 3. 集成测试 (7项测试)
- ✅ 模块导入正常
- ✅ 类结构完整 (12个关键方法验证)
- ✅ 初始化成功
- ✅ 状态查询方法正常
- ✅ 配置方法正常
- ✅ VRManager委托正常
- ✅ HUD更新逻辑正常
**测试结果**: 全部通过 ✅
---
## 📦 迁移的功能模块
### 1. 测试模式控制 (3个方法)
- `enable_vr_test_mode` - 启用测试模式
- `disable_vr_test_mode` - 禁用测试模式
- `switch_test_display_mode` - 切换显示模式
### 2. 纹理管理 (2个方法)
- `_ensure_test_mode_textures` - 确保测试纹理
- `_create_cached_ovr_textures` - 创建缓存的OVR纹理
- **注**: `_batch_submit_textures`保留在VRManager作为核心渲染功能
### 3. 显示系统 (5个方法)
- `_initialize_test_display` - 初始化测试显示
- `_update_test_display` - 更新测试显示
- `_create_stereo_display` - 创建立体显示
- `_cleanup_test_display` - 清理测试显示
### 4. HUD系统 (3个方法)
- `_initialize_test_performance_hud` - 初始化HUD
- `_update_test_performance_hud` - 更新HUD
- `_cleanup_test_performance_hud` - 清理HUD
### 5. 状态查询 (3个方法)
- `get_test_mode_status` - 获取测试模式状态
- `get_test_mode_features` - 获取测试模式特性
- `set_test_mode_features` - 设置测试模式特性
### 6. 性能测试 (1个方法)
- `run_vr_performance_test` - 运行性能测试
---
## 🎯 目标达成情况
| 目标 | 计划 | 实际 | 状态 |
|-----|------|------|------|
| 迁移方法数 | 17个 | 16个 | ✅ (_batch_submit_textures保留) |
| 迁移属性数 | ~15个 | 15个 | ✅ |
| 新文件行数 | ~800行 | 621行 | ✅ 节省22.4% |
| vr_manager.py减少 | 预期减少 | -199行 (-5.2%) | ✅ |
| API兼容性 | 100% | 100% | ✅ |
| 测试通过率 | 100% | 100% | ✅ |
**说明**:
- test_mode.py为621行,远低于800行目标,代码精简高效
- vr_manager.py净减少199行(_batch_submit_textures保留导致减少量较少)
---
## 📂 目录结构
```
EG/
├── core/
│ ├── vr_manager.py (3,555行) ⬇️ -13.7%
│ └── vr/
│ ├── performance/
│ │ ├── __init__.py
│ │ └── monitoring.py (1,168行) ✨
│ └── testing/
│ ├── __init__.py ✨
│ └── test_mode.py (688行) ✨
├── test_test_mode_integration.py ✨
├── STAGE2_COMPLETION_REPORT.md ✨
└── VR_Manager 模块化拆分计划.md
```
---
## 🐛 修复的Bug
在集成过程中发现并修复了以下问题:
### Bug 1: _setup_vr_render_buffers() 方法不存在
**错误**: `_ensure_test_mode_textures()` 调用了不存在的方法 `_setup_vr_render_buffers()`
**解决方案**: 替换为正确的方法调用:
```python
if hasattr(self.vr_manager.world, 'render_pipeline') and self.vr_manager.world.render_pipeline:
success = self.vr_manager._create_vr_buffers_with_pipeline()
else:
success = self.vr_manager._create_vr_buffers()
```
**修复位置**: test_mode.py 第209-212行
### Bug 2: _batch_submit_textures() 方法丢失 (运行时错误)
**错误信息**:
```
'VRManager' object has no attribute '_batch_submit_textures'
```
**根本原因**:
- `_batch_submit_textures`是VR渲染的核心方法,不仅用于测试模式
- 错误地将它迁移到了VRTestMode类中
- 导致正常VR渲染流程无法调用该方法
**解决方案**:
1. 将`_batch_submit_textures`方法重新添加到VRManager (vr_manager.py 3453-3521行)
2. 从VRTestMode中删除该方法,添加说明注释
3. 修复渲染回调中的测试模式方法调用:
- `self._update_test_display()``self.test_mode._update_test_display()`
- `self._update_test_performance_hud()``self.test_mode._update_test_performance_hud()`
**修复位置**:
- vr_manager.py 第1405行, 1475行, 3453-3521行
- test_mode.py 第277-279行
**影响**: 这是关键修复,确保正常VR渲染和测试模式都能正常工作
---
## 🔄 Git状态
### 待提交的文件
```
修改:
core/vr_manager.py
core/vr/testing/__init__.py
新增:
core/vr/testing/test_mode.py
test_test_mode_integration.py
STAGE2_COMPLETION_REPORT.md
备份:
core/vr_manager.py.backup.stage2
```
### 建议的提交信息
```
feat(vr): 模块化拆分阶段2 - 测试调试系统
- 创建独立的VRTestMode类 (688行)
- 迁移17个测试模式方法和15个属性
- 添加7个委托方法和5个属性代理保持API兼容性
- 修复_setup_vr_render_buffers()方法不存在的bug
- vr_manager.py从3,829行减少到3,555行 (-13.7%)
- 所有测试通过,100% API兼容
相关文档:
- STAGE2_COMPLETION_REPORT.md
```
---
## 🚀 后续工作
### 下一步: 阶段3 - 拆分对象池和优化系统
根据计划,阶段3将拆分对象池和优化系统 (~300行):
**待迁移的功能**:
- 对象池管理 (19个方法)
- GC控制
- 分辨率管理
- 性能模式
**预期文件**: `core/vr/performance/optimization.py`
**预期收益**: vr_manager.py再减少约250-300行
---
## ✨ 关键改进
1. **模块化**: 测试调试功能完全独立,便于维护和测试
2. **代码质量**: vr_manager.py减少526行,更易阅读
3. **可测试性**: 独立模块可单独测试
4. **API稳定性**: 100%向后兼容,无需修改现有调用代码
5. **Bug修复**: 发现并修复了方法不存在的bug
---
## 📝 经验总结
### 成功因素
- ✅ Agent工具高效提取代码
- ✅ 完整的备份策略
- ✅ 委托模式+属性代理保证API兼容性
- ✅ 充分的测试验证
- ✅ 清晰的文档记录
### 注意事项
- ⚠️ 发现并修复了原代码中的bug (_setup_vr_render_buffers不存在)
- ⚠️ vr_manager.py仍然较大,需要继续拆分
- ⚠️ 测试模式涉及渲染循环,集成时需要小心处理
### 优化建议
- 继续执行阶段3-6的拆分计划
- 最终目标: vr_manager.py < 900行
- 考虑为test_mode添加更多单元测试
---
## ✅ 阶段2完成确认
- [x] 创建备份
- [x] 创建目录结构
- [x] 分析和提取代码
- [x] 创建VRTestMode类
- [x] 集成到VRManager
- [x] 添加委托方法和属性代理
- [x] 编译检查通过
- [x] 导入测试通过
- [x] 集成测试通过
- [x] 文档完善
**阶段2状态**: ✅ **圆满完成**
---
**生成时间**: 2025-10-14
**负责人**: Claude (Ultrathink模式)
**下一阶段**: 阶段3 - 对象池和优化系统拆分

View File

@ -0,0 +1,346 @@
"""
VR对象池和优化系统
负责VR系统中的对象池管理垃圾回收控制分辨率缩放和性能模式控制
"""
import gc
from panda3d.core import Mat4
class VROptimization:
"""VR优化系统 - 管理对象池、GC控制、分辨率缩放和性能模式"""
def __init__(self, vr_manager):
"""初始化VR优化系统
Args:
vr_manager: VR管理器实例引用
"""
self.vr_manager = vr_manager
# 对象池属性
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
# 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' # 默认平衡模式
# 性能模式控制
self.performance_mode_enabled = False # 是否启用性能模式
self.performance_mode_trigger_frame = 600 # 600帧后自动启用性能模式
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.vr_manager.frame_count - self._last_manual_gc_frame >= current_interval:
# 在非渲染关键时刻触发GC
collected = gc.collect()
self._last_manual_gc_frame = self.vr_manager.frame_count
# 仅在收集到对象时输出信息
if collected > 0:
print(f"🗑️ 手动GC: 清理了 {collected} 个对象 (帧#{self.vr_manager.frame_count})")
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),
'matrix_pool_capacity': self._matrix_pool_size,
'cached_controllers': len(self.vr_manager.controller_poses),
'cached_matrices': len(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_manager.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.vr_manager.eye_width = self.scaled_eye_width
self.vr_manager.eye_height = self.scaled_eye_height
if hasattr(self.vr_manager, 'current_eye_resolution'):
self.vr_manager.current_eye_resolution = (self.vr_manager.eye_width, self.vr_manager.eye_height)
print(f"🔄 重新创建VR缓冲区...")
print(f" 新分辨率: {self.vr_manager.eye_width}x{self.vr_manager.eye_height}")
# 清理旧的缓冲区
self.vr_manager._cleanup_vr_buffers()
# 🔧 关键修复:根据渲染模式选择创建方法
success = False
if self.vr_manager.vr_render_mode.name == "RENDER_PIPELINE":
print(f" 使用RenderPipeline模式重建...")
success = self.vr_manager._create_vr_buffers_with_pipeline()
if not success:
print("⚠️ RenderPipeline模式创建失败回退到普通渲染模式")
self.vr_manager.vr_render_mode = self.vr_manager.VRRenderMode.NORMAL
success = self.vr_manager._create_vr_buffers()
else:
print(f" 使用普通模式重建...")
success = self.vr_manager._create_vr_buffers()
if success:
# 重新设置相机
self.vr_manager._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.vr_manager.eye_width, self.vr_manager.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.vr_manager.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,
}

View File

@ -35,6 +35,7 @@ from core.vr.interaction.grab import VRInteractionManager
from core.vr.interaction.joystick import VRJoystickManager from core.vr.interaction.joystick import VRJoystickManager
from core.vr.interaction.teleport import VRTeleportSystem from core.vr.interaction.teleport import VRTeleportSystem
from core.vr.performance.monitoring import VRPerformanceMonitor from core.vr.performance.monitoring import VRPerformanceMonitor
from core.vr.performance.optimization import VROptimization
from core.vr.testing import VRTestMode from core.vr.testing import VRTestMode
from enum import Enum from enum import Enum
@ -82,24 +83,15 @@ class VRManager(DirectObject):
self.poses = None # OpenVR渲染姿态数组 self.poses = None # OpenVR渲染姿态数组
self.game_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控制在其他组件之前 # 🚀 立即初始化对象池和GC控制在其他组件之前
self._initialize_object_pools() # 对象池和优化系统 - 模块化重构
try:
self.optimization = VROptimization(self)
self.optimization._initialize_object_pools()
print("✓ VR对象池和优化系统初始化完成")
except Exception as e:
print(f"⚠️ VR对象池和优化系统初始化失败: {e}")
self.optimization = None
# VR渲染参数 # VR渲染参数
self.eye_width = 1080 self.eye_width = 1080
@ -107,7 +99,7 @@ class VRManager(DirectObject):
self.near_clip = 0.1 self.near_clip = 0.1
self.far_clip = 1000.0 self.far_clip = 1000.0
# VR分辨率缩放优化 # VR分辨率缩放优化 - 现在由优化模块管理
self.resolution_scale = 0.75 # 默认0.75倍分辨率,性能和质量平衡 self.resolution_scale = 0.75 # 默认0.75倍分辨率,性能和质量平衡
self.base_eye_width = 1080 # 原始推荐分辨率 self.base_eye_width = 1080 # 原始推荐分辨率
self.base_eye_height = 1200 self.base_eye_height = 1200
@ -250,103 +242,107 @@ class VRManager(DirectObject):
print("✓ VR管理器初始化完成") 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}") def enable_gc_control(self):
"""启用垃圾回收控制 - 减少VR渲染期间的GC峰值"""
if self.optimization:
return self.optimization.enable_gc_control()
return False
# 🚀 预创建OpenVR Texture对象 - 消除每帧创建openvr.Texture_t()的开销 def disable_gc_control(self):
try: """禁用垃圾回收控制 - 恢复自动垃圾回收"""
import openvr if self.optimization:
self._left_ovr_texture = openvr.Texture_t() return self.optimization.disable_gc_control()
self._right_ovr_texture = openvr.Texture_t() return False
# 设置固定属性(这些不变) def set_manual_gc_interval(self, frames):
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对象缓存已创建 - 避免每帧创建新对象") Args:
except Exception as texture_error: frames: 帧数间隔 (建议100-600)
print(f"⚠️ OpenVR Texture对象创建失败: {texture_error}") """
# 不影响整体初始化,但性能可能不是最优 if self.optimization:
return self.optimization.set_manual_gc_interval(frames)
return False
# 启用GC控制 def force_manual_gc(self):
if self._gc_control_enabled: """强制执行一次垃圾回收"""
# 禁用自动垃圾回收,改为手动控制 if self.optimization:
gc.disable() return self.optimization.force_manual_gc()
self._gc_disabled = True return 0
print("✅ Python垃圾回收已禁用改为手动控制")
except Exception as e: def get_object_pool_status(self):
print(f"⚠️ 对象池初始化失败: {e}") """获取对象池状态"""
if self.optimization:
return self.optimization.get_object_pool_status()
return {}
def _get_pooled_matrix(self): def set_resolution_scale(self, scale):
"""从对象池获取Mat4对象""" """设置VR分辨率缩放系数
if self._matrix_pool:
return self._matrix_pool.pop()
else:
# 池为空时创建新对象(不应该发生,但作为备用)
return Mat4()
def _return_pooled_matrix(self, matrix): Args:
"""将Mat4对象返回对象池""" scale: 缩放系数 (0.3-1.0)0.75表示75%分辨率
if len(self._matrix_pool) < self._matrix_pool_size: """
# 重置矩阵到单位矩阵 if self.optimization:
matrix.identMat() return self.optimization.set_resolution_scale(scale)
self._matrix_pool.append(matrix) return False
def _manual_gc_control(self): def set_quality_preset(self, preset_name):
"""手动垃圾回收控制 - 避免VR渲染期间的GC峰值""" """设置VR质量预设
if not self._gc_control_enabled or not self._gc_disabled:
return
# 🚀 智能GC间隔性能模式下减少GC频率 Args:
current_interval = self._manual_gc_interval preset_name: 'performance', 'balanced', 'quality'
if self.performance_mode_enabled: """
current_interval = self._manual_gc_interval * 2 # 性能模式下间隔翻倍 if self.optimization:
return self.optimization.set_quality_preset(preset_name)
return False
# 每N帧手动触发一次垃圾回收 def cycle_quality_preset(self):
if self.frame_count - self._last_manual_gc_frame >= current_interval: """循环切换质量预设"""
# 在非渲染关键时刻触发GC if self.optimization:
collected = gc.collect() return self.optimization.cycle_quality_preset()
self._last_manual_gc_frame = self.frame_count return False
# 仅在收集到对象时输出信息 def get_resolution_info(self):
if collected > 0: """获取分辨率相关信息"""
print(f"🗑️ 手动GC: 清理了 {collected} 个对象 (帧#{self.frame_count})") if self.optimization:
return self.optimization.get_resolution_info()
return {}
def print_resolution_info(self):
"""输出分辨率信息"""
if self.optimization:
return self.optimization.print_resolution_info()
def enable_performance_mode(self):
"""手动启用性能模式 - 立即禁用详细监控以提升性能"""
if self.optimization:
return self.optimization.enable_performance_mode()
def disable_performance_mode(self):
"""禁用性能模式 - 重新启用详细监控(用于调试)"""
if self.optimization:
return self.optimization.disable_performance_mode()
def set_performance_mode_trigger_frame(self, frame_count):
"""设置性能模式自动触发的帧数
Args:
frame_count: 触发帧数 (建议300-1200)
"""
if self.optimization:
return self.optimization.set_performance_mode_trigger_frame(frame_count)
def get_performance_mode_status(self):
"""获取性能模式状态"""
if self.optimization:
return self.optimization.get_performance_mode_status()
return {}
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): def convert_mat(self, mat):
""" """
@ -392,9 +388,11 @@ class VRManager(DirectObject):
print("🔄 正在初始化VR系统...") print("🔄 正在初始化VR系统...")
# 🚀 确保对象池已正确初始化(备用检查) # 🚀 确保对象池已正确初始化(备用检查)
if not hasattr(self, '_matrix_pool') or len(self._matrix_pool) == 0: if self.optimization is None:
print("⚠️ 对象池未初始化,正在重新初始化...") print("⚠️ 优化系统未初始化,正在重新初始化...")
self._initialize_object_pools() from core.vr.performance.optimization import VROptimization
self.optimization = VROptimization(self)
self.optimization._initialize_object_pools()
# 初始化OpenVR - 使用Scene应用类型确保正确的焦点管理 # 初始化OpenVR - 使用Scene应用类型确保正确的焦点管理
self.vr_system = openvr.init(openvr.VRApplication_Scene) self.vr_system = openvr.init(openvr.VRApplication_Scene)
@ -1284,9 +1282,11 @@ class VRManager(DirectObject):
self.frame_count += 1 self.frame_count += 1
# 🚀 自动启用性能模式 - 减少计时对象创建 # 🚀 自动启用性能模式 - 减少计时对象创建
if not self.performance_mode_enabled and self.frame_count >= self.performance_mode_trigger_frame: if (self.optimization and
self.performance_mode_enabled = True not self.optimization.performance_mode_enabled and
if self.frame_count <= self.performance_mode_trigger_frame + 5: # 只输出一次 self.frame_count >= self.optimization.performance_mode_trigger_frame):
self.optimization.performance_mode_enabled = True
if self.frame_count <= self.optimization.performance_mode_trigger_frame + 5: # 只输出一次
print(f"🎯 性能模式已启用 (帧#{self.frame_count}) - 禁用详细监控以提升性能") print(f"🎯 性能模式已启用 (帧#{self.frame_count}) - 禁用详细监控以提升性能")
# 记录帧时间 # 记录帧时间
@ -1344,7 +1344,8 @@ class VRManager(DirectObject):
self._get_gpu_frame_timing() self._get_gpu_frame_timing()
# 🚀 手动垃圾回收控制 - 避免16-19帧周期性峰值 # 🚀 手动垃圾回收控制 - 避免16-19帧周期性峰值
self._manual_gc_control() if self.optimization:
self.optimization._manual_gc_control()
# 定期输出性能报告 - 默认10秒间隔 # 定期输出性能报告 - 默认10秒间隔
report_interval = getattr(self, 'performance_report_interval', 600) report_interval = getattr(self, 'performance_report_interval', 600)
@ -1580,7 +1581,8 @@ class VRManager(DirectObject):
# 设备姿态无效,从字典中移除(如果存在) # 设备姿态无效,从字典中移除(如果存在)
if device_id in self.controller_poses: if device_id in self.controller_poses:
# 将矩阵返回对象池 # 将矩阵返回对象池
self._return_pooled_matrix(self.controller_poses[device_id]) if self.optimization:
self.optimization._return_pooled_matrix(self.controller_poses[device_id])
del self.controller_poses[device_id] del self.controller_poses[device_id]
# 🔧 关键修复:立即更新手柄和跟踪设备 # 🔧 关键修复:立即更新手柄和跟踪设备
@ -1725,7 +1727,10 @@ class VRManager(DirectObject):
OpenVR -Z Panda3D Y OpenVR -Z Panda3D Y
""" """
# 🚀 使用对象池获取预分配的Mat4对象避免每帧创建新对象 # 🚀 使用对象池获取预分配的Mat4对象避免每帧创建新对象
mat = self._get_pooled_matrix() if self.optimization:
mat = self.optimization._get_pooled_matrix()
else:
mat = Mat4()
# 修正的坐标转换矩阵 # 修正的坐标转换矩阵
# OpenVR: X右, Y上, -Z前 → Panda3D: X右, Y前, Z上 # OpenVR: X右, Y上, -Z前 → Panda3D: X右, Y前, Z上
@ -2130,33 +2135,33 @@ class VRManager(DirectObject):
self.vr_task = None self.vr_task = None
# 🚀 恢复Python垃圾回收并清理对象池 # 🚀 恢复Python垃圾回收并清理对象池
if self._gc_disabled: if self.optimization and self.optimization._gc_disabled:
# 最后一次手动垃圾回收 # 最后一次手动垃圾回收
collected = gc.collect() collected = gc.collect()
print(f"🗑️ 最终GC清理: {collected} 个对象") print(f"🗑️ 最终GC清理: {collected} 个对象")
# 恢复自动垃圾回收 # 恢复自动垃圾回收
gc.enable() gc.enable()
self._gc_disabled = False self.optimization._gc_disabled = False
print("✅ Python垃圾回收已恢复为自动模式") print("✅ Python垃圾回收已恢复为自动模式")
# 清理对象池 # 清理对象池
if hasattr(self, '_matrix_pool'): if self.optimization and hasattr(self.optimization, '_matrix_pool'):
pool_size = len(self._matrix_pool) pool_size = len(self.optimization._matrix_pool)
self._matrix_pool.clear() self.optimization._matrix_pool.clear()
print(f"🧹 Mat4对象池已清理: {pool_size} 个对象") print(f"🧹 Mat4对象池已清理: {pool_size} 个对象")
# 清理缓存 # 清理缓存
if hasattr(self, '_cached_matrices'): if self.optimization and hasattr(self.optimization, '_cached_matrices'):
self._cached_matrices.clear() self.optimization._cached_matrices.clear()
if hasattr(self, '_controller_poses_cache'): if self.optimization and hasattr(self.optimization, '_controller_poses_cache'):
self._controller_poses_cache.clear() self.optimization._controller_poses_cache.clear()
# 清理OpenVR Texture对象缓存 # 清理OpenVR Texture对象缓存
if hasattr(self, '_left_ovr_texture'): # 清理OpenVR Texture对象缓存
self._left_ovr_texture = None if self.optimization:
if hasattr(self, '_right_ovr_texture'): self.optimization._left_ovr_texture = None
self._right_ovr_texture = None self.optimization._right_ovr_texture = None
print("🧹 OpenVR Texture对象缓存已清理") print("🧹 OpenVR Texture对象缓存已清理")
# 清理渲染缓冲区 # 清理渲染缓冲区
@ -2328,9 +2333,9 @@ class VRManager(DirectObject):
# 🚀 关键优化使用缓存的OpenVR Texture对象避免每帧创建 # 🚀 关键优化使用缓存的OpenVR Texture对象避免每帧创建
if eye == openvr.Eye_Left: if eye == openvr.Eye_Left:
ovr_texture = self._left_ovr_texture ovr_texture = self.optimization._left_ovr_texture if self.optimization else None
else: else:
ovr_texture = self._right_ovr_texture ovr_texture = self.optimization._right_ovr_texture if self.optimization else None
# 检查缓存对象是否存在(向后兼容) # 检查缓存对象是否存在(向后兼容)
if ovr_texture is None: if ovr_texture is None:
@ -2798,225 +2803,18 @@ class VRManager(DirectObject):
self.disable_async_reprojection = False self.disable_async_reprojection = False
print("📝 异步重投影禁用选项已关闭将使用默认ATW行为") print("📝 异步重投影禁用选项已关闭将使用默认ATW行为")
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分辨率缩放和质量预设系统 ====== # ====== 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,
}
# ======================================================================== # ========================================================================
# 性能监控属性代理 - 属性级别的API向后兼容 # 性能监控属性代理 - 属性级别的API向后兼容
@ -3181,31 +2979,7 @@ class VRManager(DirectObject):
if self.performance_monitor: if self.performance_monitor:
self.performance_monitor.debug_output_enabled = value self.performance_monitor.debug_output_enabled = value
@property
def performance_mode_enabled(self):
"""性能模式开关 - 代理到性能监控系统"""
if self.performance_monitor:
return self.performance_monitor.performance_mode_enabled
return False
@performance_mode_enabled.setter
def performance_mode_enabled(self, value):
"""性能模式开关设置 - 代理到性能监控系统"""
if self.performance_monitor:
self.performance_monitor.performance_mode_enabled = value
@property
def performance_mode_trigger_frame(self):
"""性能模式触发帧 - 代理到性能监控系统"""
if self.performance_monitor:
return self.performance_monitor.performance_mode_trigger_frame
return 600
@performance_mode_trigger_frame.setter
def performance_mode_trigger_frame(self, value):
"""性能模式触发帧设置 - 代理到性能监控系统"""
if self.performance_monitor:
self.performance_monitor.performance_mode_trigger_frame = value
# 时间监控属性 # 时间监控属性
@property @property
@ -3261,6 +3035,128 @@ class VRManager(DirectObject):
if self.performance_monitor: if self.performance_monitor:
self.performance_monitor.enable_pipeline_monitoring = value self.performance_monitor.enable_pipeline_monitoring = value
@property
def performance_mode_enabled(self):
"""性能模式开关 - 代理到优化模块"""
if self.optimization:
return self.optimization.performance_mode_enabled
return False
@performance_mode_enabled.setter
def performance_mode_enabled(self, value):
"""性能模式开关设置 - 代理到优化模块"""
if self.optimization:
self.optimization.performance_mode_enabled = value
@property
def performance_mode_trigger_frame(self):
"""性能模式触发帧 - 代理到优化模块"""
if self.optimization:
return self.optimization.performance_mode_trigger_frame
return 600
@performance_mode_trigger_frame.setter
def performance_mode_trigger_frame(self, value):
"""性能模式触发帧设置 - 代理到优化模块"""
if self.optimization:
self.optimization.performance_mode_trigger_frame = value
# 分辨率缩放属性代理
@property
def resolution_scale(self):
"""分辨率缩放系数 - 代理到优化模块"""
if self.optimization:
return self.optimization.resolution_scale
return 0.75
@resolution_scale.setter
def resolution_scale(self, value):
"""分辨率缩放系数设置 - 代理到优化模块"""
if self.optimization:
self.optimization.resolution_scale = value
@property
def base_eye_width(self):
"""基础眼宽 - 代理到优化模块"""
if self.optimization:
return self.optimization.base_eye_width
return 1080
@base_eye_width.setter
def base_eye_width(self, value):
"""基础眼宽设置 - 代理到优化模块"""
if self.optimization:
self.optimization.base_eye_width = value
@property
def base_eye_height(self):
"""基础眼高 - 代理到优化模块"""
if self.optimization:
return self.optimization.base_eye_height
return 1200
@base_eye_height.setter
def base_eye_height(self, value):
"""基础眼高设置 - 代理到优化模块"""
if self.optimization:
self.optimization.base_eye_height = value
@property
def scaled_eye_width(self):
"""缩放后眼宽 - 代理到优化模块"""
if self.optimization:
return self.optimization.scaled_eye_width
return 1080
@scaled_eye_width.setter
def scaled_eye_width(self, value):
"""缩放后眼宽设置 - 代理到优化模块"""
if self.optimization:
self.optimization.scaled_eye_width = value
@property
def scaled_eye_height(self):
"""缩放后眼高 - 代理到优化模块"""
if self.optimization:
return self.optimization.scaled_eye_height
return 1200
@scaled_eye_height.setter
def scaled_eye_height(self, value):
"""缩放后眼高设置 - 代理到优化模块"""
if self.optimization:
self.optimization.scaled_eye_height = value
@property
def current_quality_preset(self):
"""当前质量预设 - 代理到优化模块"""
if self.optimization:
return self.optimization.current_quality_preset
return "balanced"
@current_quality_preset.setter
def current_quality_preset(self, value):
"""当前质量预设设置 - 代理到优化模块"""
if self.optimization:
self.optimization.current_quality_preset = value
@property
def quality_presets(self):
"""质量预设 - 代理到优化模块"""
if self.optimization:
return self.optimization.quality_presets
return {
"performance": 0.6,
"balanced": 0.75,
"quality": 1.0
}
@quality_presets.setter
def quality_presets(self, value):
"""质量预设设置 - 代理到优化模块"""
if self.optimization:
self.optimization.quality_presets = value
# ======================================================================== # ========================================================================
# 性能监控委托方法 - API向后兼容层 # 性能监控委托方法 - API向后兼容层
# ======================================================================== # ========================================================================

View File

@ -1,200 +0,0 @@
"""
测试VRTestMode集成测试
验证测试模式系统是否正确集成到VRManager
"""
print("=" * 60)
print("VR测试模式系统集成测试")
print("=" * 60)
# 测试1: 导入VRTestMode
print("\n测试1: 导入VRTestMode...")
try:
from core.vr.testing import VRTestMode
print("✓ VRTestMode导入成功")
except Exception as e:
print(f"✗ VRTestMode导入失败: {e}")
exit(1)
# 测试2: 检查VRTestMode类结构
print("\n测试2: 检查VRTestMode类结构...")
try:
# 检查关键方法是否存在
required_methods = [
'enable_vr_test_mode',
'disable_vr_test_mode',
'switch_test_display_mode',
'get_test_mode_status',
'set_test_mode_features',
'get_test_mode_features',
'run_vr_performance_test',
'_ensure_test_mode_textures',
'_initialize_test_display',
'_update_test_display',
'_initialize_test_performance_hud',
'_update_test_performance_hud'
]
missing_methods = []
for method in required_methods:
if not hasattr(VRTestMode, method):
missing_methods.append(method)
if missing_methods:
print(f"✗ 缺少方法: {missing_methods}")
exit(1)
print(f"✓ 所有{len(required_methods)}个关键方法都存在")
except Exception as e:
print(f"✗ 类结构检查失败: {e}")
exit(1)
# 测试3: 初始化VRTestMode
print("\n测试3: 初始化VRTestMode...")
try:
from unittest.mock import Mock
# 创建模拟的VRManager
mock_vr_manager = Mock()
mock_vr_manager.world = Mock()
mock_vr_manager.world.render2d = Mock()
mock_vr_manager.vr_initialized = False
mock_vr_manager.vr_enabled = False
# 创建VRTestMode实例
test_mode = VRTestMode(mock_vr_manager)
# 检查核心属性是否正确初始化
assert test_mode.vr_test_mode == False, "vr_test_mode应该初始化为False"
assert test_mode.test_display_mode == 'stereo', "test_display_mode应该初始化为stereo"
assert test_mode.test_mode_initialized == False, "test_mode_initialized应该初始化为False"
assert test_mode.test_mode_submit_texture == False, "test_mode_submit_texture应该初始化为False"
assert test_mode.test_mode_wait_poses == False, "test_mode_wait_poses应该初始化为False"
print("✓ VRTestMode初始化成功")
print("✓ 核心属性初始化正确")
except Exception as e:
print(f"✗ VRTestMode初始化失败: {e}")
import traceback
traceback.print_exc()
exit(1)
# 测试4: 测试状态查询方法
print("\n测试4: 测试状态查询方法...")
try:
# get_test_mode_status() - 未启用时应返回None
status = test_mode.get_test_mode_status()
assert status is None, "未启用测试模式时应返回None"
print("✓ get_test_mode_status() 返回正确")
# get_test_mode_features()
features = test_mode.get_test_mode_features()
assert isinstance(features, dict), "应返回字典"
assert 'submit_texture' in features, "应包含submit_texture"
assert 'wait_poses' in features, "应包含wait_poses"
assert 'test_mode_active' in features, "应包含test_mode_active"
print("✓ get_test_mode_features() 返回正确格式")
except Exception as e:
print(f"✗ 状态查询测试失败: {e}")
import traceback
traceback.print_exc()
exit(1)
# 测试5: 测试配置方法
print("\n测试5: 测试配置方法...")
try:
# set_test_mode_features()
test_mode.set_test_mode_features(submit_texture=True, wait_poses=True)
assert test_mode.test_mode_submit_texture == True
assert test_mode.test_mode_wait_poses == True
print("✓ set_test_mode_features() 正常工作")
# 恢复默认值
test_mode.set_test_mode_features(submit_texture=False, wait_poses=False)
assert test_mode.test_mode_submit_texture == False
assert test_mode.test_mode_wait_poses == False
print("✓ 配置状态正确更新")
except Exception as e:
print(f"✗ 配置方法测试失败: {e}")
import traceback
traceback.print_exc()
exit(1)
# 测试6: 测试与VRManager的委托
print("\n测试6: 测试VRManager委托...")
try:
# 尝试导入VRManager并检查委托方法
# 注意: 这里不实际启动VRManager,只检查方法存在性
print(" 检查VRManager导入...")
from core.vr_manager import VRManager
print(" ✓ VRManager导入成功")
# 检查委托方法是否存在
delegate_methods = [
'enable_vr_test_mode',
'disable_vr_test_mode',
'switch_test_display_mode',
'get_test_mode_status',
'get_test_mode_features',
'set_test_mode_features',
'run_vr_performance_test'
]
for method in delegate_methods:
if not hasattr(VRManager, method):
print(f" ✗ VRManager缺少委托方法: {method}")
exit(1)
print(f" ✓ 所有{len(delegate_methods)}个委托方法都存在")
# 检查属性代理
delegate_properties = [
'vr_test_mode',
'test_display_mode',
'test_mode_submit_texture',
'test_mode_wait_poses',
'test_mode_initialized'
]
# 注意: 这里只能检查类定义,不能检查实例属性
print(f" ✓ 属性代理定义已检查")
except Exception as e:
print(f"✗ VRManager委托测试失败: {e}")
import traceback
traceback.print_exc()
exit(1)
# 测试7: 测试HUD更新计数器
print("\n测试7: 测试HUD更新逻辑...")
try:
# 测试HUD更新计数器
initial_counter = test_mode.hud_update_counter
assert initial_counter == 0, "初始计数器应该为0"
# 测试HUD更新间隔
assert test_mode.hud_update_interval == 30, "HUD更新间隔应该为30帧"
print("✓ HUD更新逻辑初始化正确")
except Exception as e:
print(f"✗ HUD更新测试失败: {e}")
import traceback
traceback.print_exc()
exit(1)
print("\n" + "=" * 60)
print("✅ 所有测试通过!")
print("=" * 60)
print("\n测试总结:")
print(" ✓ 模块导入正常")
print(" ✓ 类结构完整")
print(" ✓ 初始化成功")
print(" ✓ 状态查询方法正常")
print(" ✓ 配置方法正常")
print(" ✓ VRManager委托正常")
print(" ✓ HUD更新逻辑正常")
print("\nVRTestMode集成完成,准备投入使用!")