- 添加对有线连接的支持,特别是 Pico 4 的有线连接 - 改进 ALVR 服务器检测和连接逻辑 - 优化 VR 帧获取和处理流程 - 增加备用帧获取功能(主摄像机视图) - 修复 VR 眼部纹理相关问题 - 优化 VR 任务管理,确保正确渲染和提交帧
380 lines
12 KiB
Python
380 lines
12 KiB
Python
"""
|
||
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 |