EG/core/openxr_input_handler.py
Rowland 72819341ef docs(README): 添加项目README文档
- 创建详细的README文档,介绍项目功能、架构、使用方法等
- 新增.pyc文件和目录,用于缓存编译后的Python代码
- 添加.lingma规则文件,用于代码格式检查
- 删除ALVR串流处理器代码,准备替换为OpenXR输入处理器
- 新增OpenXR输入处理器代码,处理VR控制器输入
2025-07-29 17:46:08 +08:00

261 lines
8.9 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.

"""
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 '隐藏'}")