""" 物理引擎集成模块 负责将物理引擎中的碰撞和力反馈转换为触觉效果 """ import time from typing import Dict, Any, List, Optional import math class PhysicsIntegration: """ 物理引擎集成 负责将物理引擎中的碰撞和力反馈转换为触觉效果 """ def __init__(self, plugin): """ 初始化物理引擎集成 Args: plugin: 触觉反馈系统插件实例 """ self.plugin = plugin self.enabled = False self.initialized = False # 物理事件监听器 self.physics_listeners = {} # 碰撞效果配置 self.collision_config = { 'enable_collision_feedback': True, 'min_impulse_threshold': 0.1, 'max_impulse_threshold': 100.0, 'intensity_scale': 1.0, 'frequency_scale': 1.0, 'duration_scale': 1.0, 'effect_type': 'impulse' } # 力反馈配置 self.force_config = { 'enable_force_feedback': True, 'min_force_threshold': 0.01, 'max_force_threshold': 10.0, 'intensity_scale': 1.0, 'frequency_scale': 1.0, 'smoothing_factor': 0.1 } # 摩擦效果配置 self.friction_config = { 'enable_friction_feedback': True, 'min_velocity_threshold': 0.1, 'texture_sensitivity': 1.0, 'vibration_frequency': 20.0 } # 材质反馈配置 self.material_config = { 'enable_material_feedback': True, 'material_effects': { 'metal': {'intensity': 0.8, 'frequency': 60.0, 'type': 'buzz'}, 'wood': {'intensity': 0.6, 'frequency': 30.0, 'type': 'rumble'}, 'stone': {'intensity': 0.9, 'frequency': 80.0, 'type': 'click'}, 'fabric': {'intensity': 0.3, 'frequency': 15.0, 'type': 'soft_rumble'}, 'rubber': {'intensity': 0.5, 'frequency': 25.0, 'type': 'bounce'} } } # 状态跟踪 self.contact_points = {} self.force_feedback_state = {} self.friction_state = {} # 统计信息 self.stats = { 'collisions_detected': 0, 'forces_processed': 0, 'friction_effects': 0, 'material_effects': 0, 'haptic_effects_generated': 0 } # 回调函数 self.physics_callbacks = { 'collision_detected': [], 'force_applied': [], 'friction_updated': [], 'haptic_effect_generated': [] } print("✓ 物理引擎集成已创建") def initialize(self) -> bool: """ 初始化物理引擎集成 Returns: 是否初始化成功 """ try: self.initialized = True print("✓ 物理引擎集成初始化完成") return True except Exception as e: print(f"✗ 物理引擎集成初始化失败: {e}") import traceback traceback.print_exc() return False def enable(self) -> bool: """ 启用物理引擎集成 Returns: 是否启用成功 """ try: if not self.initialized: print("✗ 物理引擎集成未初始化") return False self.enabled = True print("✓ 物理引擎集成已启用") return True except Exception as e: print(f"✗ 物理引擎集成启用失败: {e}") import traceback traceback.print_exc() return False def disable(self): """禁用物理引擎集成""" try: self.enabled = False print("✓ 物理引擎集成已禁用") except Exception as e: print(f"✗ 物理引擎集成禁用失败: {e}") import traceback traceback.print_exc() def finalize(self): """清理物理引擎集成资源""" try: self.disable() self.physics_listeners.clear() self.contact_points.clear() self.force_feedback_state.clear() self.friction_state.clear() self.physics_callbacks.clear() self.initialized = False print("✓ 物理引擎集成资源已清理") except Exception as e: print(f"✗ 物理引擎集成资源清理失败: {e}") import traceback traceback.print_exc() def update(self, dt: float): """ 更新物理引擎集成状态 Args: dt: 时间增量 """ try: if not self.enabled: return # 更新摩擦状态 self._update_friction_state(dt) # 更新力反馈状态 self._update_force_feedback_state(dt) except Exception as e: print(f"✗ 物理引擎集成更新失败: {e}") import traceback traceback.print_exc() def _update_friction_state(self, dt: float): """更新摩擦状态""" try: # 减少摩擦状态值(衰减) decay_rate = 0.95 keys_to_remove = [] for key, state in self.friction_state.items(): state['intensity'] *= decay_rate if state['intensity'] < 0.01: keys_to_remove.append(key) # 移除已衰减完毕的状态 for key in keys_to_remove: del self.friction_state[key] except Exception as e: print(f"✗ 摩擦状态更新失败: {e}") def _update_force_feedback_state(self, dt: float): """更新力反馈状态""" try: # 减少力反馈状态值(平滑) smoothing = self.force_config['smoothing_factor'] keys_to_remove = [] for key, state in self.force_feedback_state.items(): state['current_force'] = ( state['current_force'] * (1 - smoothing) + state['target_force'] * smoothing ) if abs(state['current_force']) < 0.001: keys_to_remove.append(key) # 移除已平滑完毕的状态 for key in keys_to_remove: del self.force_feedback_state[key] except Exception as e: print(f"✗ 力反馈状态更新失败: {e}") def process_collision(self, collision_data: Dict[str, Any]) -> bool: """ 处理碰撞事件并生成触觉效果 Args: collision_data: 碰撞数据 Returns: 是否处理成功 """ try: if not self.enabled or not self.collision_config['enable_collision_feedback']: return False # 提取碰撞信息 impulse = collision_data.get('impulse', 0.0) contact_point = collision_data.get('contact_point', (0, 0, 0)) object_a = collision_data.get('object_a', 'unknown') object_b = collision_data.get('object_b', 'unknown') material_a = collision_data.get('material_a', 'default') material_b = collision_data.get('material_b', 'default') device_id = collision_data.get('device_id') # 检查冲量阈值 if impulse < self.collision_config['min_impulse_threshold']: return False if impulse > self.collision_config['max_impulse_threshold']: impulse = self.collision_config['max_impulse_threshold'] # 计算触觉效果强度 intensity = ( impulse / self.collision_config['max_impulse_threshold'] * self.collision_config['intensity_scale'] ) intensity = max(0.0, min(1.0, intensity)) # 计算频率 frequency = 20.0 + (impulse * self.collision_config['frequency_scale']) frequency = max(1.0, min(100.0, frequency)) # 计算持续时间 duration = 0.05 + (impulse * 0.01 * self.collision_config['duration_scale']) duration = max(0.01, min(1.0, duration)) # 获取材质效果 material_effect = self._get_material_effect(material_a, material_b) # 生成触觉效果 effect_type = self.collision_config['effect_type'] if material_effect: effect_type = material_effect.get('type', effect_type) intensity *= material_effect.get('intensity', 1.0) frequency = material_effect.get('frequency', frequency) # 播放触觉效果 if self.plugin.haptic_manager: effect_id = self.plugin.haptic_manager.play_effect( effect_type=effect_type, device_id=device_id, intensity=intensity, duration=duration, frequency=frequency, parameters={ 'collision_impulse': impulse, 'contact_point': contact_point, 'objects': [object_a, object_b], 'materials': [material_a, material_b] } ) if effect_id >= 0: # 触发效果生成回调 self._trigger_physics_callback('haptic_effect_generated', { 'effect_id': effect_id, 'effect_type': effect_type, 'source': 'collision', 'intensity': intensity, 'frequency': frequency, 'duration': duration }) self.stats['haptic_effects_generated'] += 1 self.stats['collisions_detected'] += 1 print(f"✓ 碰撞触觉效果已生成: {effect_type}") return True return False except Exception as e: print(f"✗ 碰撞处理失败: {e}") return False def process_force_feedback(self, force_data: Dict[str, Any]) -> bool: """ 处理力反馈并生成连续触觉效果 Args: force_data: 力反馈数据 Returns: 是否处理成功 """ try: if not self.enabled or not self.force_config['enable_force_feedback']: return False # 提取力反馈信息 force = force_data.get('force', 0.0) force_direction = force_data.get('direction', (0, 0, 0)) object_id = force_data.get('object_id', 'unknown') device_id = force_data.get('device_id') # 检查力阈值 if abs(force) < self.force_config['min_force_threshold']: return False if abs(force) > self.force_config['max_force_threshold']: force = math.copysign(self.force_config['max_force_threshold'], force) # 计算触觉效果强度 intensity = ( abs(force) / self.force_config['max_force_threshold'] * self.force_config['intensity_scale'] ) intensity = max(0.0, min(1.0, intensity)) # 计算频率 frequency = 10.0 + (abs(force) * self.force_config['frequency_scale']) frequency = max(1.0, min(100.0, frequency)) # 更新力反馈状态 state_key = f"force_{object_id}" if state_key not in self.force_feedback_state: self.force_feedback_state[state_key] = { 'current_force': 0.0, 'target_force': force } else: self.force_feedback_state[state_key]['target_force'] = force # 生成连续触觉效果 if self.plugin.haptic_manager: # 播放连续效果 effect_id = self.plugin.haptic_manager.play_effect( effect_type='periodic', device_id=device_id, intensity=intensity, duration=0.1, # 短持续时间,循环播放 frequency=frequency, parameters={ 'force': force, 'direction': force_direction, 'object_id': object_id } ) if effect_id >= 0: # 触发效果生成回调 self._trigger_physics_callback('haptic_effect_generated', { 'effect_id': effect_id, 'effect_type': 'periodic', 'source': 'force', 'intensity': intensity, 'frequency': frequency }) self.stats['haptic_effects_generated'] += 1 self.stats['forces_processed'] += 1 print(f"✓ 力反馈触觉效果已生成: 强度 {intensity:.2f}") return True return False except Exception as e: print(f"✗ 力反馈处理失败: {e}") return False def process_friction(self, friction_data: Dict[str, Any]) -> bool: """ 处理摩擦并生成纹理触觉效果 Args: friction_data: 摩擦数据 Returns: 是否处理成功 """ try: if not self.enabled or not self.friction_config['enable_friction_feedback']: return False # 提取摩擦信息 velocity = friction_data.get('velocity', 0.0) surface_normal = friction_data.get('normal', (0, 0, 1)) object_id = friction_data.get('object_id', 'unknown') material = friction_data.get('material', 'default') device_id = friction_data.get('device_id') # 检查速度阈值 if abs(velocity) < self.friction_config['min_velocity_threshold']: return False # 计算触觉效果强度 intensity = min(1.0, abs(velocity) * 0.1 * self.friction_config['texture_sensitivity']) # 获取材质效果 material_effect = self._get_material_effect(material) # 计算频率 frequency = self.friction_config['vibration_frequency'] if material_effect: frequency = material_effect.get('frequency', frequency) # 更新摩擦状态 state_key = f"friction_{object_id}" if state_key not in self.friction_state: self.friction_state[state_key] = { 'intensity': intensity, 'velocity': velocity } else: self.friction_state[state_key]['intensity'] = max( self.friction_state[state_key]['intensity'], intensity ) # 生成摩擦触觉效果 if self.plugin.haptic_manager: effect_id = self.plugin.haptic_manager.play_effect( effect_type='noise', device_id=device_id, intensity=intensity, duration=0.05, frequency=frequency, parameters={ 'velocity': velocity, 'material': material, 'object_id': object_id } ) if effect_id >= 0: # 触发效果生成回调 self._trigger_physics_callback('haptic_effect_generated', { 'effect_id': effect_id, 'effect_type': 'noise', 'source': 'friction', 'intensity': intensity, 'frequency': frequency }) self.stats['haptic_effects_generated'] += 1 self.stats['friction_effects'] += 1 print(f"✓ 摩擦触觉效果已生成: 强度 {intensity:.2f}") return True return False except Exception as e: print(f"✗ 摩擦处理失败: {e}") return False def _get_material_effect(self, *materials) -> Optional[Dict[str, Any]]: """ 获取材质效果配置 Args: *materials: 材质名称 Returns: 材质效果配置或None """ try: if not self.material_config['enable_material_feedback']: return None material_effects = self.material_config['material_effects'] # 尝试匹配每个材质 for material in materials: if material in material_effects: return material_effects[material] return None except Exception as e: print(f"✗ 材质效果获取失败: {e}") return None def register_physics_listener(self, event_type: str, callback: callable): """ 注册物理事件监听器 Args: event_type: 事件类型 callback: 回调函数 """ try: if event_type in self.physics_listeners: self.physics_listeners[event_type].append(callback) else: self.physics_listeners[event_type] = [callback] print(f"✓ 物理事件监听器已注册: {event_type}") except Exception as e: print(f"✗ 物理事件监听器注册失败: {e}") def unregister_physics_listener(self, event_type: str, callback: callable): """ 注销物理事件监听器 Args: event_type: 事件类型 callback: 回调函数 """ try: if event_type in self.physics_listeners: if callback in self.physics_listeners[event_type]: self.physics_listeners[event_type].remove(callback) print(f"✓ 物理事件监听器已注销: {event_type}") except Exception as e: print(f"✗ 物理事件监听器注销失败: {e}") def _trigger_physics_callback(self, callback_type: str, data: Dict[str, Any]): """ 触发物理回调 Args: callback_type: 回调类型 data: 回调数据 """ try: if callback_type in self.physics_callbacks: for callback in self.physics_callbacks[callback_type]: try: callback(data) except Exception as e: print(f"✗ 物理回调执行失败: {e}") except Exception as e: print(f"✗ 物理回调触发失败: {e}") def register_physics_callback(self, callback_type: str, callback: callable): """ 注册物理回调 Args: callback_type: 回调类型 callback: 回调函数 """ try: if callback_type in self.physics_callbacks: self.physics_callbacks[callback_type].append(callback) print(f"✓ 物理回调已注册: {callback_type}") else: print(f"✗ 无效的回调类型: {callback_type}") except Exception as e: print(f"✗ 物理回调注册失败: {e}") def unregister_physics_callback(self, callback_type: str, callback: callable): """ 注销物理回调 Args: callback_type: 回调类型 callback: 回调函数 """ try: if callback_type in self.physics_callbacks: if callback in self.physics_callbacks[callback_type]: self.physics_callbacks[callback_type].remove(callback) print(f"✓ 物理回调已注销: {callback_type}") except Exception as e: print(f"✗ 物理回调注销失败: {e}") def set_collision_config(self, config: Dict[str, Any]) -> bool: """ 设置碰撞配置 Args: config: 配置字典 Returns: 是否设置成功 """ try: self.collision_config.update(config) print(f"✓ 碰撞配置已更新: {self.collision_config}") return True except Exception as e: print(f"✗ 碰撞配置设置失败: {e}") return False def set_force_config(self, config: Dict[str, Any]) -> bool: """ 设置力反馈配置 Args: config: 配置字典 Returns: 是否设置成功 """ try: self.force_config.update(config) print(f"✓ 力反馈配置已更新: {self.force_config}") return True except Exception as e: print(f"✗ 力反馈配置设置失败: {e}") return False def set_friction_config(self, config: Dict[str, Any]) -> bool: """ 设置摩擦配置 Args: config: 配置字典 Returns: 是否设置成功 """ try: self.friction_config.update(config) print(f"✓ 摩擦配置已更新: {self.friction_config}") return True except Exception as e: print(f"✗ 摩擦配置设置失败: {e}") return False def set_material_config(self, config: Dict[str, Any]) -> bool: """ 设置材质配置 Args: config: 配置字典 Returns: 是否设置成功 """ try: self.material_config.update(config) print(f"✓ 材质配置已更新: {self.material_config}") return True except Exception as e: print(f"✗ 材质配置设置失败: {e}") return False def get_collision_config(self) -> Dict[str, Any]: """ 获取碰撞配置 Returns: 配置字典 """ return self.collision_config.copy() def get_force_config(self) -> Dict[str, Any]: """ 获取力反馈配置 Returns: 配置字典 """ return self.force_config.copy() def get_friction_config(self) -> Dict[str, Any]: """ 获取摩擦配置 Returns: 配置字典 """ return self.friction_config.copy() def get_material_config(self) -> Dict[str, Any]: """ 获取材质配置 Returns: 配置字典 """ return self.material_config.copy() def get_stats(self) -> Dict[str, int]: """ 获取统计信息 Returns: 统计信息字典 """ return self.stats.copy() def reset_stats(self): """重置统计信息""" try: self.stats = { 'collisions_detected': 0, 'forces_processed': 0, 'friction_effects': 0, 'material_effects': 0, 'haptic_effects_generated': 0 } print("✓ 物理引擎集成统计信息已重置") except Exception as e: print(f"✗ 物理引擎集成统计信息重置失败: {e}")