physics: joint constraints (fixed/hinge/ball)
- JointComponent: type, target UUID, per-body local anchors, hinge axis + angle limits (data only, zero Jolt deps) - PhysicsWorld::SyncConstraints: create/remove/rebuild on snapshot change; body rebuild contagion via invalidated-bits list; target resolved lazily by UUID each sync (no two-pass load needed) - Jolt FixedConstraint/HingeConstraint/PointConstraint in LocalToBodyCOM space (anchors minus shape COM); fixed frames lock creation-time relative pose; hinge axis aligned across bodies - Inspector: Joint section with target entity name dropdown - Serialization: Joint map with UUID target, as<T> fallbacks
This commit is contained in:
@@ -236,6 +236,29 @@ namespace Engine::ECS {
|
||||
glm::vec3 velocity{0.0f}; // 只读调试视图:线速度(m/s)
|
||||
};
|
||||
|
||||
// 约束/关节(Jolt TwoBodyConstraint 家族)。纯数据 POD 零 Jolt 依赖;
|
||||
// 创建/对账在 PhysicsWorld::SyncConstraints(kPhyDbgConstraints 出图元)。
|
||||
// target 存 UUID(跨存档稳定),惰性解析——SyncScene 每帧按 UUID 反查
|
||||
// 实体:序列化无需两遍解析,UUID 再生后自然失联,加载顺序无关
|
||||
struct JointComponent {
|
||||
enum class Type : u8 { Fixed = 0, Hinge = 1, Ball = 2 };
|
||||
Type type = Type::Fixed;
|
||||
UUID target{}; // 目标实体(0 = 未设置,不建约束)
|
||||
|
||||
// 锚点:各体 Transform 局部系(Unity connectedAnchor 语义,
|
||||
// × 本体缩放烘焙)。Fixed/Hinge/Ball 都连这两点
|
||||
glm::vec3 anchorA{0.0f}; // 本体(挂组件的实体)
|
||||
glm::vec3 anchorB{0.0f}; // 目标体
|
||||
|
||||
// Hinge 专用:转轴(本体局部系,方向量不吃缩放)+ 角度限位(度)
|
||||
glm::vec3 hingeAxis{1.0f, 0.0f, 0.0f};
|
||||
bool enableLimit = false;
|
||||
f32 limitMin = -90.0f; // Jolt 语义 min∈[-180,0] max∈[0,180]
|
||||
f32 limitMax = 90.0f;
|
||||
|
||||
bool operator==(const JointComponent&) const = default;
|
||||
};
|
||||
|
||||
} // namespace Engine::ECS
|
||||
|
||||
#endif //HELLOVULKAN_COMPONENTS_H
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <Jolt/Jolt.h>
|
||||
#include <Jolt/Physics/PhysicsSystem.h>
|
||||
#include <Jolt/Physics/Body/BodyID.h>
|
||||
#include <Jolt/Physics/Constraints/Constraint.h> // JPH::Ref<Constraint>
|
||||
#include <Jolt/Core/JobSystemThreadPool.h>
|
||||
#include <Jolt/Core/TempAllocator.h>
|
||||
|
||||
@@ -114,6 +115,12 @@ namespace Engine {
|
||||
void CollectDebugData(); // 按 m_DebugBits 收集调试图元(渲染帧率)
|
||||
void CreateBody(u32 entityBits, ECS::RigidBodyComponent& rb,
|
||||
ECS::TransformComponent& tr);
|
||||
// 约束对账:owner 孤儿清理 / body 重建传染失效 / 建缺失与变更重建
|
||||
// invalidated = 本帧 SyncScene 中被销毁或重建 body 的实体位模式
|
||||
void SyncConstraints(const std::vector<u32>& invalidated);
|
||||
void CreateConstraint(u32 ownerBits, u32 targetBits,
|
||||
const ECS::JointComponent& jc);
|
||||
void RemoveConstraint(u32 ownerBits);
|
||||
// Mesh 碰撞体:实体视觉网格 → Jolt 形状(Static=MeshShape /
|
||||
// Dynamic=ConvexHull)。无 MeshRenderer 或构建失败返回 null(回退 Box)
|
||||
JPH::RefConst<JPH::Shape> BuildMeshShape(u32 entityBits,
|
||||
@@ -128,6 +135,15 @@ namespace Engine {
|
||||
void QueueEvent(CollisionEvent&& ev); // 回调线程 append(多线程并发,加锁)
|
||||
bool TryBitsByBodyId(const JPH::BodyID& id, u32& outBits) const;
|
||||
|
||||
// ---- 约束(JointComponent → Jolt TwoBodyConstraint;owner 实体寻址)----
|
||||
// target 惰性解析 UUID;body 重建/销毁 → 引用它的约束失效重建
|
||||
struct ConstraintRecord {
|
||||
JPH::Ref<JPH::Constraint> constraint;
|
||||
ECS::JointComponent snapshot; // 变更检测 → 移除重建
|
||||
u32 targetBits = 0;
|
||||
};
|
||||
std::unordered_map<u32, ConstraintRecord> m_Constraints;
|
||||
|
||||
ECS::Scene& m_Scene;
|
||||
Assets::AssetManager* m_Assets = nullptr; // Mesh 碰撞体解析 modelRef
|
||||
bool m_Enabled = true;
|
||||
|
||||
Reference in New Issue
Block a user