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:
@@ -307,6 +307,27 @@ namespace Engine::Serialization {
|
||||
out << YAML::EndMap;
|
||||
}
|
||||
|
||||
if (const auto* jc = reg.try_get<ECS::JointComponent>(e)) {
|
||||
out << YAML::Key << "Joint" << YAML::Value
|
||||
<< YAML::BeginMap;
|
||||
out << YAML::Key << "Type" << YAML::Value
|
||||
<< static_cast<int>(jc->type);
|
||||
// 实体引用存 UUID(跨存档稳定;target=0 未设置)
|
||||
out << YAML::Key << "Target" << YAML::Value
|
||||
<< jc->target.Value();
|
||||
out << YAML::Key << "AnchorA" << YAML::Value;
|
||||
EmitVec3(out, jc->anchorA);
|
||||
out << YAML::Key << "AnchorB" << YAML::Value;
|
||||
EmitVec3(out, jc->anchorB);
|
||||
out << YAML::Key << "HingeAxis" << YAML::Value;
|
||||
EmitVec3(out, jc->hingeAxis);
|
||||
out << YAML::Key << "EnableLimit" << YAML::Value
|
||||
<< jc->enableLimit;
|
||||
out << YAML::Key << "LimitMin" << YAML::Value << jc->limitMin;
|
||||
out << YAML::Key << "LimitMax" << YAML::Value << jc->limitMax;
|
||||
out << YAML::EndMap;
|
||||
}
|
||||
|
||||
out << YAML::EndMap; // Components
|
||||
out << YAML::EndMap; // Entity
|
||||
}
|
||||
@@ -562,6 +583,24 @@ namespace Engine::Serialization {
|
||||
rb.isSensor = n["IsSensor"].as<bool>(rb.isSensor);
|
||||
// bodyId/bodyValid/velocity 保持默认(对账重建)
|
||||
}
|
||||
|
||||
// Joint:target 只存 UUID,加载后由 PhysicsWorld 惰性反查
|
||||
//(两遍解析不需要——UUID 再生/加载顺序均由逐帧解析消化)
|
||||
if (const YAML::Node n = comps["Joint"]) {
|
||||
auto& jc = handle.AddComponent<ECS::JointComponent>();
|
||||
if (const int type = n["Type"].as<int>(0);
|
||||
type >= 0 && type <= 2) {
|
||||
jc.type =
|
||||
static_cast<ECS::JointComponent::Type>(type);
|
||||
}
|
||||
jc.target = UUID{n["Target"].as<u64>(0)};
|
||||
jc.anchorA = ReadVec3(n["AnchorA"], jc.anchorA);
|
||||
jc.anchorB = ReadVec3(n["AnchorB"], jc.anchorB);
|
||||
jc.hingeAxis = ReadVec3(n["HingeAxis"], jc.hingeAxis);
|
||||
jc.enableLimit = n["EnableLimit"].as<bool>(jc.enableLimit);
|
||||
jc.limitMin = n["LimitMin"].as<f32>(jc.limitMin);
|
||||
jc.limitMax = n["LimitMax"].as<f32>(jc.limitMax);
|
||||
}
|
||||
}
|
||||
|
||||
// 加载在 OnImGuiRender 段,错过本帧 UpdateTransforms:
|
||||
|
||||
Reference in New Issue
Block a user