EG/vr/vr_system.py
Rowland bb56813e44 feat(core): 优化 ALVR 串流功能并添加对 Pico 4 的支持
- 添加对有线连接的支持,特别是 Pico 4 的有线连接
- 改进 ALVR 服务器检测和连接逻辑
- 优化 VR 帧获取和处理流程
- 增加备用帧获取功能(主摄像机视图)
- 修复 VR 眼部纹理相关问题
- 优化 VR 任务管理,确保正确渲染和提交帧
2025-07-29 10:17:13 +08:00

380 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
VR系统核心管理模块
此模块提供VR系统的核心功能负责初始化和协调其他VR组件。
"""
import os
import json
from panda3d.core import loadPrcFileData, WindowProperties
from direct.task import Task
class VRSystem:
"""VR系统的核心管理类负责初始化和协调其他VR组件"""
def __init__(self, world):
"""
初始化VR系统
Args:
world: 游戏世界实例,提供对渲染器和场景的访问
"""
self.world = world
self.display = None
self.input = None
self.streaming = None
self.device = None
self.is_initialized = False
self.config = self._load_config()
# 状态变量
self.vr_enabled = False
self.streaming_enabled = False
print("✓ VR系统核心已创建")
def _load_config(self):
"""加载VR配置"""
config_path = os.path.join(os.path.dirname(__file__), "vr_config.json")
default_config = {
"preferred_device": "openxr",
"render_resolution": [2048, 2048],
"refresh_rate": 90,
"ipd": 0.064, # 瞳距,单位:米
"streaming": {
"enabled": True,
"encoder": "h264",
"bitrate": 30000000, # 30 Mbps
"use_hardware_encoding": True
},
"performance": {
"dynamic_resolution": True,
"fixed_foveated_rendering": True,
"motion_smoothing": True
}
}
try:
if os.path.exists(config_path):
with open(config_path, 'r') as f:
return json.load(f)
else:
# 如果配置文件不存在,创建默认配置
with open(config_path, 'w') as f:
json.dump(default_config, f, indent=4)
return default_config
except Exception as e:
print(f"加载VR配置失败: {e}")
return default_config
def save_config(self):
"""保存VR配置"""
config_path = os.path.join(os.path.dirname(__file__), "vr_config.json")
try:
with open(config_path, 'w') as f:
json.dump(self.config, f, indent=4)
print("✓ VR配置已保存")
return True
except Exception as e:
print(f"保存VR配置失败: {e}")
return False
def initialize(self):
"""初始化VR系统"""
if self.is_initialized:
print("VR系统已经初始化")
return True
print("正在初始化VR系统...")
# 1. 导入必要的模块(延迟导入以避免循环依赖)
from .vr_display import VRDisplay
from .vr_input import VRInput
from .vr_streaming import VRStreaming
# 2. 根据配置选择设备实现
device_type = self.config.get("preferred_device", "openxr")
device_created = self._create_device(device_type)
if not device_created:
print("✗ 创建VR设备失败")
return False
# 3. 创建显示、输入和串流组件
self.display = VRDisplay(self)
self.input = VRInput(self)
self.streaming = VRStreaming(self)
# 4. 初始化各组件
display_initialized = self.display.initialize()
if not display_initialized:
print("✗ 初始化VR显示失败")
return False
input_initialized = self.input.initialize()
if not input_initialized:
print("✗ 初始化VR输入失败")
return False
# 5. 设置更新任务
taskMgr = self.world.taskMgr
taskMgr.add(self.update, "vr_system_update")
self.is_initialized = True
self.vr_enabled = True
print("✓ VR系统初始化完成")
return True
def _create_device(self, device_type):
"""创建VR设备实现"""
try:
if device_type == "openxr":
from .devices.openxr_device import OpenXRDevice
self.device = OpenXRDevice()
elif device_type == "oculus":
from .devices.oculus_device import OculusDevice
self.device = OculusDevice()
elif device_type == "steamvr":
from .devices.steamvr_device import SteamVRDevice
self.device = SteamVRDevice()
else:
print(f"不支持的设备类型: {device_type}")
return False
device_initialized = self.device.initialize()
if not device_initialized:
print(f"✗ 初始化{device_type}设备失败")
return False
print(f"✓ 已创建并初始化{device_type}设备")
return True
except ImportError as e:
print(f"导入设备模块失败: {e}")
return False
except Exception as e:
print(f"创建设备实例失败: {e}")
return False
def shutdown(self):
"""关闭VR系统"""
if not self.is_initialized:
print("VR系统未初始化")
return True
print("正在关闭VR系统...")
# 1. 停止串流
if self.streaming and self.streaming_enabled:
self.stop_streaming()
# 2. 关闭各组件
if self.input:
self.input.shutdown()
if self.display:
self.display.shutdown()
if self.device:
self.device.shutdown()
# 3. 移除更新任务
taskMgr = self.world.taskMgr
taskMgr.remove("vr_system_update")
self.is_initialized = False
self.vr_enabled = False
print("✓ VR系统已关闭")
return True
def update(self, task):
"""更新VR系统状态每帧调用"""
if not self.is_initialized:
return Task.cont
# 1. 更新设备状态
if self.device:
self.device.update()
# 2. 更新输入
if self.input:
self.input.update()
# 3. 更新显示
if self.display:
self.display.update()
# 4. 更新串流
if self.streaming and self.streaming_enabled:
self.streaming.update()
return Task.cont
def start_streaming(self):
"""开始VR画面串流"""
if not self.is_initialized:
print("VR系统未初始化无法开始串流")
return False
if not self.streaming:
print("VR串流组件未创建")
return False
if self.streaming_enabled:
print("VR串流已经启动")
return True
result = self.streaming.start()
if result:
self.streaming_enabled = True
print("✓ VR串流已启动")
else:
print("✗ 启动VR串流失败")
return result
def stop_streaming(self):
"""停止VR画面串流"""
if not self.streaming or not self.streaming_enabled:
print("VR串流未启动")
return True
result = self.streaming.stop()
if result:
self.streaming_enabled = False
print("✓ VR串流已停止")
else:
print("✗ 停止VR串流失败")
return result
def get_status(self):
"""获取VR系统状态信息"""
status = {
"initialized": self.is_initialized,
"vr_enabled": self.vr_enabled,
"streaming_enabled": self.streaming_enabled,
"device_type": self.config.get("preferred_device", "unknown"),
"render_resolution": self.config.get("render_resolution", [0, 0]),
"refresh_rate": self.config.get("refresh_rate", 0)
}
# 添加设备特定信息
if self.device:
device_status = self.device.get_status()
status.update(device_status)
# 添加串流信息
if self.streaming:
streaming_status = self.streaming.get_statistics()
status["streaming"] = streaming_status
return status
def set_render_resolution(self, width, height):
"""设置VR渲染分辨率"""
if not self.is_initialized:
print("VR系统未初始化无法设置渲染分辨率")
return False
self.config["render_resolution"] = [width, height]
if self.display:
result = self.display.set_resolution(width, height)
if result:
print(f"✓ VR渲染分辨率已设置为 {width}x{height}")
self.save_config()
return result
return False
def set_refresh_rate(self, rate):
"""设置VR刷新率"""
if not self.is_initialized:
print("VR系统未初始化无法设置刷新率")
return False
self.config["refresh_rate"] = rate
if self.device:
result = self.device.set_refresh_rate(rate)
if result:
print(f"✓ VR刷新率已设置为 {rate}Hz")
self.save_config()
return result
return False
def set_ipd(self, ipd):
"""设置瞳距(单位:米)"""
if not self.is_initialized:
print("VR系统未初始化无法设置瞳距")
return False
self.config["ipd"] = ipd
if self.display:
result = self.display.set_ipd(ipd)
if result:
print(f"✓ VR瞳距已设置为 {ipd}m")
self.save_config()
return result
return False
def set_streaming_quality(self, bitrate=None, encoder=None, use_hardware=None):
"""设置串流质量参数"""
if not self.streaming:
print("VR串流组件未创建无法设置串流质量")
return False
streaming_config = self.config.get("streaming", {})
if bitrate is not None:
streaming_config["bitrate"] = bitrate
if encoder is not None:
streaming_config["encoder"] = encoder
if use_hardware is not None:
streaming_config["use_hardware_encoding"] = use_hardware
self.config["streaming"] = streaming_config
result = self.streaming.set_quality(
bitrate=streaming_config.get("bitrate"),
encoder=streaming_config.get("encoder"),
use_hardware=streaming_config.get("use_hardware_encoding")
)
if result:
print("✓ VR串流质量参数已更新")
self.save_config()
return result
def calibrate(self):
"""启动VR校准过程"""
if not self.is_initialized:
print("VR系统未初始化无法校准")
return False
print("正在启动VR校准...")
# 导入校准模块
from .vr_calibration import start_calibration
result = start_calibration(self)
if result:
print("✓ VR校准完成")
else:
print("✗ VR校准失败或被取消")
return result
def is_vr_enabled(self):
"""检查VR是否启用"""
return self.vr_enabled
def is_streaming(self):
"""检查是否正在串流"""
return self.streaming_enabled