EG/plugins/user/soft_body_cloth_physics/plugin.py
2025-12-12 16:16:15 +08:00

511 lines
18 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.

"""
软体物理和布料模拟插件主入口
提供完整的软体物理和布料模拟功能
"""
from panda3d.core import Vec3
from plugins.plugin_interface_spec import BasePlugin
from .core.cloth_manager import ClothManager
from .core.soft_body_manager import SoftBodyManager
from .core.cloth_physics import ClothPhysics
from .core.soft_body_physics import SoftBodyPhysics
from .materials.cloth_materials import ClothMaterialManager
from .utils.mesh_generator import MeshGenerator
from .debug.cloth_debug import PhysicsDebugManager
import json
import os
class Plugin(BasePlugin):
"""
软体物理和布料模拟插件
提供布料模拟和软体物理功能,支持多种材质、形状和物理效应
"""
def __init__(self, plugin_manager, name: str = "soft_body_cloth_physics"):
super().__init__(plugin_manager, name)
# 核心管理器
self.cloth_manager = None
self.soft_body_manager = None
self.cloth_physics = None
self.soft_body_physics = None
self.material_manager = None
self.mesh_generator = None
self.debug_manager = None
# 配置
self.config = {
'gravity': Vec3(0, 0, -9.81),
'time_step': 1.0/60.0,
'sub_steps': 4,
'default_cloth_density': 0.5,
'default_soft_body_density': 1.0,
'enable_debug_visualization': False,
'debug_flags': {
'show_mesh': True,
'show_anchors': True,
'show_forces': False,
'show_velocities': False,
'show_normals': False,
'show_tears': True,
'show_collisions': False,
'show_bounding_box': False
},
'performance': {
'max_cloth_objects': 50,
'max_soft_body_objects': 50,
'update_frequency': 60,
'sub_steps': 4
},
'physics': {
'air_density': 1.225,
'water_density': 1000.0,
'water_offset': 0.0,
'water_normal': Vec3(0, 0, 1)
},
'wind': {
'enabled': False,
'velocity': Vec3(0, 0, 0),
'turbulence': 0.0,
'frequency': 1.0
}
}
# 状态
self.initialized = False
self.performance_stats = {
'total_cloth_objects': 0,
'total_soft_body_objects': 0,
'simulation_time': 0.0,
'update_count': 0
}
def initialize(self) -> bool:
"""
初始化插件
Returns:
是否初始化成功
"""
try:
print(f"正在初始化 {self.name} 插件...")
# 获取世界对象
world = self.plugin_manager.world
# 初始化所有管理器
self.cloth_manager = ClothManager(world)
self.soft_body_manager = SoftBodyManager(world)
self.cloth_physics = ClothPhysics(world)
self.soft_body_physics = SoftBodyPhysics(world)
self.material_manager = ClothMaterialManager()
self.mesh_generator = MeshGenerator()
self.debug_manager = PhysicsDebugManager(world.render)
# 加载配置
self._load_config()
# 应用配置
self._apply_config()
# 启用调试可视化(如果配置中启用)
if self.config['enable_debug_visualization']:
self.debug_manager.enable()
# 设置调试标志
for flag, value in self.config['debug_flags'].items():
if flag == 'show_mesh':
self.debug_manager.set_cloth_visibility(mesh=value)
self.debug_manager.set_soft_body_visibility(mesh=value)
elif flag == 'show_anchors':
self.debug_manager.set_cloth_visibility(anchors=value)
elif flag == 'show_forces':
self.debug_manager.set_cloth_visibility(forces=value)
self.debug_manager.set_soft_body_visibility(forces=value)
elif flag == 'show_velocities':
self.debug_manager.set_cloth_visibility(velocities=value)
self.debug_manager.set_soft_body_visibility(velocities=value)
elif flag == 'show_normals':
self.debug_manager.set_cloth_visibility(normals=value)
elif flag == 'show_tears':
self.debug_manager.set_cloth_visibility(tears=value)
elif flag == 'show_collisions':
self.debug_manager.set_cloth_visibility(collisions=value)
self.debug_manager.set_soft_body_visibility(collisions=value)
elif flag == 'show_bounding_box':
self.debug_manager.set_cloth_visibility(bounding_box=value)
# 设置性能参数
self.cloth_manager.max_cloth_objects = self.config['performance']['max_cloth_objects']
self.cloth_manager.cloth_update_frequency = self.config['performance']['update_frequency']
self.soft_body_manager.max_soft_body_objects = self.config['performance']['max_soft_body_objects']
self.soft_body_manager.soft_body_update_frequency = self.config['performance']['update_frequency']
# 设置风力参数
self._apply_wind_config()
self.initialized = True
print(f"{self.name} 插件初始化成功")
return True
except Exception as e:
print(f"{self.name} 插件初始化失败: {e}")
import traceback
traceback.print_exc()
return False
def enable(self) -> bool:
"""
启用插件
Returns:
是否启用成功
"""
try:
if not self.initialized:
print("⚠ 插件未初始化,无法启用")
return False
# 启用所有管理器
if self.cloth_manager:
self.cloth_manager.enable()
if self.soft_body_manager:
self.soft_body_manager.enable()
if self.cloth_physics:
# 无需特殊启用
pass
if self.soft_body_physics:
# 无需特殊启用
pass
if self.debug_manager:
self.debug_manager.enable()
self.enabled = True
print(f"{self.name} 插件已启用")
return True
except Exception as e:
print(f"{self.name} 插件启用失败: {e}")
import traceback
traceback.print_exc()
return False
def disable(self) -> bool:
"""
禁用插件
Returns:
是否禁用成功
"""
try:
# 禁用所有管理器
if self.cloth_manager:
self.cloth_manager.disable()
if self.soft_body_manager:
self.soft_body_manager.disable()
if self.debug_manager:
self.debug_manager.disable()
self.enabled = False
print(f"{self.name} 插件已禁用")
return True
except Exception as e:
print(f"{self.name} 插件禁用失败: {e}")
import traceback
traceback.print_exc()
return False
def finalize(self):
"""
清理插件资源
"""
try:
# 清理所有管理器
if self.cloth_manager:
self.cloth_manager.cleanup()
self.cloth_manager = None
if self.soft_body_manager:
self.soft_body_manager.cleanup()
self.soft_body_manager = None
if self.cloth_physics:
self.cloth_physics = None
if self.soft_body_physics:
self.soft_body_physics = None
if self.material_manager:
self.material_manager = None
if self.mesh_generator:
self.mesh_generator = None
if self.debug_manager:
self.debug_manager.cleanup()
self.debug_manager = None
print(f"{self.name} 插件资源已清理")
except Exception as e:
print(f"{self.name} 插件清理失败: {e}")
import traceback
traceback.print_exc()
def get_info(self):
"""
获取插件信息
Returns:
插件信息字典
"""
info = super().get_info()
info.update({
"name": "SoftBodyClothPhysics",
"version": "1.0.0",
"author": "iFlow Team",
"description": "提供软体物理和布料模拟功能的插件",
"features": [
"布料物理模拟",
"软体物理模拟",
"多种布料材质类型",
"参数实时调节",
"调试可视化",
"风力模拟",
"撕裂和碰撞检测",
"高级网格生成"
],
"dependencies": [
"panda3d",
"panda3d.bullet"
],
"capabilities": {
"cloth_types": self.material_manager.get_all_material_types() if self.material_manager else [],
"mesh_generation": [
"cloth_patch",
"sphere",
"box",
"capsule",
"cylinder",
"rope",
"torus",
"custom"
],
"debug_visualization": [
"mesh",
"anchors",
"forces",
"velocities",
"normals",
"tears",
"collisions",
"bounding_box"
]
}
})
return info
def update(self, dt: float):
"""
更新插件(每帧调用)
Args:
dt: 时间增量
"""
if not self.enabled or not self.initialized:
return
# 更新所有管理器
if self.cloth_manager:
self.cloth_manager.update_all_cloths(dt)
if self.soft_body_manager:
self.soft_body_manager.update_all_soft_bodies(dt)
if self.cloth_physics:
self.cloth_physics.update_wind(dt)
if self.debug_manager:
# 更新可视化
if self.cloth_manager:
self.debug_manager.update_all_visualizations(
self.cloth_manager.cloth_objects,
self.soft_body_manager.soft_body_objects if self.soft_body_manager else []
)
# 更新性能统计
self.performance_stats['update_count'] += 1
if self.cloth_manager:
self.performance_stats['total_cloth_objects'] = len(self.cloth_manager.cloth_objects)
if self.soft_body_manager:
self.performance_stats['total_soft_body_objects'] = len(self.soft_body_manager.soft_body_objects)
def get_performance_stats(self) -> dict:
"""
获取性能统计信息
Returns:
性能统计信息字典
"""
stats = self.performance_stats.copy()
# 添加管理器统计
if self.cloth_manager:
cloth_stats = self.cloth_manager.get_cloth_stats()
stats.update(cloth_stats)
if self.soft_body_manager:
soft_stats = self.soft_body_manager.get_soft_body_stats()
stats.update(soft_stats)
if self.debug_manager:
debug_stats = self.debug_manager.get_debug_stats()
stats['debug_stats'] = debug_stats
return stats
def create_cloth(self, parent_node, cloth_type: str,
width: float, height: float,
resolution_x: int, resolution_y: int,
params: dict = None,
behavior_mode: str = None) -> dict:
"""
创建布料对象
Args:
parent_node: 父节点
cloth_type: 布料类型
width: 宽度
height: 高度
resolution_x: X分辨率
resolution_y: Y分辨率
params: 参数
behavior_mode: 行为模式
Returns:
布料对象信息
"""
if not self.initialized or not self.cloth_manager:
return None
return self.cloth_manager.create_cloth_patch(
parent_node, width, height, resolution_x, resolution_y, params
)
def create_soft_body(self, parent_node, soft_type: str,
shape_type: str = "sphere",
**kwargs) -> dict:
"""
创建软体对象
Args:
parent_node: 父节点
soft_type: 软体类型
shape_type: 形状类型
**kwargs: 形状参数
Returns:
软体对象信息
"""
if not self.initialized or not self.soft_body_manager:
return None
return self.soft_body_manager.create_soft_body_from_mesh(
parent_node, soft_type, shape_type, **kwargs
)
def set_config(self, key: str, value):
"""
设置配置参数
Args:
key: 配置键
value: 配置值
"""
if key in self.config:
self.config[key] = value
if key == 'gravity':
self._apply_config()
elif key == 'enable_debug_visualization':
if value and self.debug_manager:
self.debug_manager.enable()
elif not value and self.debug_manager:
self.debug_manager.disable()
def get_config(self, key: str = None):
"""
获取配置参数
Args:
key: 配置键如果为None则返回整个配置
Returns:
配置值或整个配置字典
"""
if key:
return self.config.get(key)
return self.config.copy()
def _load_config(self):
"""
从配置文件加载配置
"""
try:
config_path = os.path.join(
os.path.dirname(__file__),
"config",
"cloth_settings.json"
)
if os.path.exists(config_path):
with open(config_path, 'r', encoding='utf-8') as f:
file_config = json.load(f)
# 合并配置
self._merge_config(self.config, file_config.get('plugin', {}))
except Exception as e:
print(f"⚠ 加载配置文件失败: {e}")
def _merge_config(self, target: dict, source: dict):
"""
合并配置字典
Args:
target: 目标字典
source: 源字典
"""
for key, value in source.items():
if isinstance(value, dict) and key in target and isinstance(target[key], dict):
self._merge_config(target[key], value)
else:
target[key] = value
def _apply_config(self):
"""
应用配置设置
"""
if self.cloth_manager:
self.cloth_manager.set_gravity(self.config['gravity'])
if self.soft_body_manager:
self.soft_body_manager.set_gravity(self.config['gravity'])
if self.cloth_physics:
self.cloth_physics.update_soft_body_world_info(
air_density=self.config['physics']['air_density'],
water_density=self.config['physics']['water_density'],
water_offset=self.config['physics']['water_offset'],
water_normal=self.config['physics']['water_normal'],
gravity=self.config['gravity']
)
if self.soft_body_physics:
self.soft_body_physics.update_soft_body_world_info(
air_density=self.config['physics']['air_density'],
water_density=self.config['physics']['water_density'],
water_offset=self.config['physics']['water_offset'],
water_normal=self.config['physics']['water_normal'],
gravity=self.config['gravity']
)
def _apply_wind_config(self):
"""
应用风力配置
"""
if self.cloth_physics and self.config['wind']['enabled']:
self.cloth_physics.set_wind_parameters(
enabled=self.config['wind']['enabled'],
velocity=self.config['wind']['velocity'],
turbulence=self.config['wind']['turbulence'],
frequency=self.config['wind']['frequency']
)