- 创建详细的README文档,介绍项目功能、架构、使用方法等 - 新增.pyc文件和目录,用于缓存编译后的Python代码 - 添加.lingma规则文件,用于代码格式检查 - 删除ALVR串流处理器代码,准备替换为OpenXR输入处理器 - 新增OpenXR输入处理器代码,处理VR控制器输入
261 lines
8.9 KiB
Python
261 lines
8.9 KiB
Python
"""
|
||
OpenXR输入处理器
|
||
|
||
处理OpenXR控制器输入和手势识别
|
||
支持多种OpenXR控制器和输入方式
|
||
"""
|
||
|
||
from direct.showbase.DirectObject import DirectObject
|
||
from panda3d.core import Vec3, Point3, CollisionRay, CollisionNode, CollisionHandlerQueue, BitMask32
|
||
from direct.task import Task
|
||
import time
|
||
|
||
|
||
class OpenXRInputHandler(DirectObject):
|
||
"""OpenXR输入处理器"""
|
||
|
||
def __init__(self, world, openxr_manager):
|
||
super().__init__()
|
||
self.world = world
|
||
self.openxr_manager = openxr_manager
|
||
|
||
# 控制器状态
|
||
self.controllers = {}
|
||
self.controller_nodes = {}
|
||
self.controller_rays = {}
|
||
|
||
# 手势识别
|
||
self.gesture_enabled = True
|
||
self.gesture_history = []
|
||
self.gesture_threshold = 0.1
|
||
|
||
# 交互系统
|
||
self.interaction_enabled = True
|
||
self.selected_object = None
|
||
self.grab_offset = Vec3(0, 0, 0)
|
||
|
||
# 输入映射
|
||
self.input_mappings = {
|
||
'trigger': self._handle_trigger,
|
||
'grip': self._handle_grip,
|
||
'thumbstick': self._handle_thumbstick,
|
||
'touchpad': self._handle_touchpad,
|
||
'menu': self._handle_menu,
|
||
'system': self._handle_system
|
||
}
|
||
|
||
print("✓ OpenXR输入处理器初始化完成")
|
||
|
||
def start_input_handling(self):
|
||
"""启动输入处理"""
|
||
if not self.openxr_manager.is_openxr_enabled():
|
||
print("OpenXR未启用,无法启动输入处理")
|
||
return False
|
||
|
||
# 启动输入更新任务
|
||
self.world.taskMgr.add(self._update_input, "openxr_input_update")
|
||
|
||
# 设置控制器可视化
|
||
self._setup_controller_visualization()
|
||
|
||
print("✓ OpenXR输入处理已启动")
|
||
return True
|
||
|
||
def stop_input_handling(self):
|
||
"""停止输入处理"""
|
||
self.world.taskMgr.remove("openxr_input_update")
|
||
self._cleanup_controller_visualization()
|
||
print("✓ OpenXR输入处理已停止")
|
||
|
||
def _update_input(self, task):
|
||
"""更新输入处理"""
|
||
if not self.openxr_manager.is_openxr_enabled():
|
||
return Task.cont
|
||
|
||
try:
|
||
# 更新所有控制器
|
||
self._update_controllers()
|
||
|
||
# 处理手势识别
|
||
if self.gesture_enabled:
|
||
self._process_gestures()
|
||
|
||
# 处理交互
|
||
if self.interaction_enabled:
|
||
self._process_interactions()
|
||
|
||
except Exception as e:
|
||
print(f"OpenXR输入更新错误: {str(e)}")
|
||
|
||
return Task.cont
|
||
|
||
def _update_controllers(self):
|
||
"""更新控制器状态"""
|
||
if self.openxr_manager.simulation_mode:
|
||
# 在模拟模式下使用模拟数据
|
||
sim_data = self.openxr_manager.get_simulation_data('controller_poses')
|
||
for controller_id, pose_data in sim_data.items():
|
||
if pose_data['connected']:
|
||
self._update_controller_pose(controller_id, pose_data)
|
||
else:
|
||
# TODO: 实际OpenXR控制器更新
|
||
pass
|
||
|
||
def _update_controller_pose(self, controller_id, pose_data):
|
||
"""更新控制器姿态"""
|
||
# 更新控制器位置和旋转
|
||
if controller_id not in self.controller_nodes:
|
||
self._create_controller_node(controller_id)
|
||
|
||
controller_node = self.controller_nodes[controller_id]
|
||
position = pose_data['position']
|
||
rotation = pose_data['rotation']
|
||
|
||
controller_node.setPos(*position)
|
||
controller_node.setQuat(Quat(*rotation))
|
||
|
||
def _create_controller_node(self, controller_id):
|
||
"""创建控制器节点"""
|
||
# 创建一个简单的控制器可视化模型
|
||
from panda3d.core import CardMaker
|
||
cm = CardMaker(f'controller_{controller_id}')
|
||
cm.setFrame(-0.05, 0.05, -0.05, 0.05)
|
||
controller_node = self.world.render.attachNewNode(cm.generate())
|
||
controller_node.setColor(0, 1, 0, 1) # 绿色
|
||
|
||
self.controller_nodes[controller_id] = controller_node
|
||
|
||
# 创建控制器射线
|
||
self._create_controller_ray(controller_id)
|
||
|
||
def _create_controller_ray(self, controller_id):
|
||
"""创建控制器射线"""
|
||
# 创建碰撞射线用于交互检测
|
||
ray_node = CollisionNode(f'controller_ray_{controller_id}')
|
||
ray = CollisionRay()
|
||
ray.setOrigin(Point3(0, 0, 0))
|
||
ray.setDirection(Vec3(0, 1, 0)) # 默认向前
|
||
ray_node.addSolid(ray)
|
||
ray_node.setFromCollideMask(BitMask32.bit(0))
|
||
|
||
ray_np = self.controller_nodes[controller_id].attachNewNode(ray_node)
|
||
queue = CollisionHandlerQueue()
|
||
|
||
self.controller_rays[controller_id] = {
|
||
'node': ray_np,
|
||
'queue': queue
|
||
}
|
||
|
||
def _setup_controller_visualization(self):
|
||
"""设置控制器可视化"""
|
||
if self.openxr_manager.simulation_mode:
|
||
# 在模拟模式下创建控制器可视化
|
||
sim_data = self.openxr_manager.get_simulation_data('controller_poses')
|
||
for controller_id in sim_data.keys():
|
||
self._create_controller_node(controller_id)
|
||
|
||
def _cleanup_controller_visualization(self):
|
||
"""清理控制器可视化"""
|
||
# 移除所有控制器节点
|
||
for controller_node in self.controller_nodes.values():
|
||
controller_node.removeNode()
|
||
|
||
self.controller_nodes.clear()
|
||
self.controller_rays.clear()
|
||
|
||
def _process_gestures(self):
|
||
"""处理手势识别"""
|
||
# TODO: 实现手势识别逻辑
|
||
pass
|
||
|
||
def _process_interactions(self):
|
||
"""处理交互"""
|
||
# TODO: 实现交互逻辑
|
||
pass
|
||
|
||
def _handle_trigger(self, controller_id, value):
|
||
"""处理触发器输入"""
|
||
# TODO: 实现触发器处理逻辑
|
||
pass
|
||
|
||
def _handle_grip(self, controller_id, value):
|
||
"""处理抓握输入"""
|
||
# TODO: 实现抓握处理逻辑
|
||
pass
|
||
|
||
def _handle_thumbstick(self, controller_id, x, y):
|
||
"""处理摇杆输入"""
|
||
# TODO: 实现摇杆处理逻辑
|
||
pass
|
||
|
||
def _handle_touchpad(self, controller_id, x, y, pressed):
|
||
"""处理触摸板输入"""
|
||
# TODO: 实现触摸板处理逻辑
|
||
pass
|
||
|
||
def _handle_menu(self, controller_id, pressed):
|
||
"""处理菜单按钮"""
|
||
# TODO: 实现菜单按钮处理逻辑
|
||
pass
|
||
|
||
def _handle_system(self, controller_id, pressed):
|
||
"""处理系统按钮"""
|
||
# TODO: 实现系统按钮处理逻辑
|
||
pass
|
||
|
||
def get_all_controllers(self):
|
||
"""获取所有控制器"""
|
||
if self.openxr_manager.simulation_mode:
|
||
sim_data = self.openxr_manager.get_simulation_data('controller_poses')
|
||
return list(sim_data.keys())
|
||
else:
|
||
# TODO: 返回实际连接的控制器
|
||
return []
|
||
|
||
def get_controller_state(self, controller_id):
|
||
"""获取控制器状态"""
|
||
if self.openxr_manager.simulation_mode:
|
||
sim_data = self.openxr_manager.get_simulation_data('controller_poses')
|
||
if controller_id in sim_data:
|
||
# 返回模拟控制器状态
|
||
return {
|
||
'trigger': 0.0,
|
||
'grip': 0.0,
|
||
'thumbstick': {'x': 0.0, 'y': 0.0},
|
||
'touchpad': {'x': 0.0, 'y': 0.0, 'pressed': False},
|
||
'menu': False,
|
||
'system': False,
|
||
'connected': sim_data[controller_id]['connected']
|
||
}
|
||
|
||
# 默认返回空状态
|
||
return {
|
||
'trigger': 0.0,
|
||
'grip': 0.0,
|
||
'thumbstick': {'x': 0.0, 'y': 0.0},
|
||
'touchpad': {'x': 0.0, 'y': 0.0, 'pressed': False},
|
||
'menu': False,
|
||
'system': False,
|
||
'connected': False
|
||
}
|
||
|
||
def set_gesture_enabled(self, enabled):
|
||
"""设置手势识别启用状态"""
|
||
self.gesture_enabled = enabled
|
||
print(f"{'✓' if enabled else '✗'} OpenXR手势识别已{'启用' if enabled else '禁用'}")
|
||
|
||
def set_interaction_enabled(self, enabled):
|
||
"""设置交互启用状态"""
|
||
self.interaction_enabled = enabled
|
||
print(f"{'✓' if enabled else '✗'} OpenXR交互已{'启用' if enabled else '禁用'}")
|
||
|
||
def show_controller_rays(self, show=True):
|
||
"""显示/隐藏控制器射线"""
|
||
for ray_data in self.controller_rays.values():
|
||
ray_node = ray_data['node']
|
||
if show:
|
||
ray_node.show()
|
||
else:
|
||
ray_node.hide()
|
||
|
||
print(f"{'✓' if show else '✗'} 控制器射线已{'显示' if show else '隐藏'}") |