From c8a1cd90bf67bae4eedf91c238a2f192ed7fb06d Mon Sep 17 00:00:00 2001 From: atdunbg Date: Sun, 4 Oct 2026 18:42:23 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dphysics=E7=89=A9=E7=90=86?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E8=AE=A1=E7=AE=97=E4=B8=8D=E6=AD=A3=E7=A1=AE?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=8C=E5=90=8C=E6=97=B6=E4=B8=BA?= =?UTF-8?q?=E7=89=A9=E7=90=86=E6=B7=BB=E5=8A=A0map=E7=B4=A2=E5=BC=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App/scripts/Spinner.cpp | 10 +----- Engine/include/Engine/Physics/PhysicsWorld.h | 5 +++ Engine/src/Physics/PhysicsWorld.cpp | 32 ++++++++++++-------- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/App/scripts/Spinner.cpp b/App/scripts/Spinner.cpp index ab9239c..7ba2710 100644 --- a/App/scripts/Spinner.cpp +++ b/App/scripts/Spinner.cpp @@ -25,23 +25,15 @@ namespace { void OnUpdate(float dt) override { // 四元数复合绕 Y(避免每帧欧拉↔四元数往返累积失真) - /* const glm::quat step = glm::angleAxis( glm::radians(m_Speed * dt), glm::vec3(0.0f, 1.0f, 0.0f)); Transform().SetRotationQuat(step * Transform().GetRotationQuat()); - */ } private: float m_Speed = 90.0f; // 度/秒 }; - static const bool s_Spinner_registered = [] { - ::Engine::Scripting::ScriptRegistry::Register( - "Spinner", []() -> ::Engine::Scope<::Engine::Scripting::ScriptBehavior> { - return ::Engine::CreateScope(); - }); - return true; - }(); + ENGINE_REGISTER_SCRIPT(Spinner); } // namespace diff --git a/Engine/include/Engine/Physics/PhysicsWorld.h b/Engine/include/Engine/Physics/PhysicsWorld.h index 516d25c..74eac42 100644 --- a/Engine/include/Engine/Physics/PhysicsWorld.h +++ b/Engine/include/Engine/Physics/PhysicsWorld.h @@ -183,6 +183,11 @@ namespace Engine { std::unordered_map m_Bodies; // entity 位模式 → body + // BodyID 序号 → entity 位模式(O(1) 反查;ContactListener 回调用) + // 与 m_Bodies 同生共死:CreateBody 同插,RemoveBody/孤儿清理同 erase。 + // 主线程在 SyncScene 写、Step 内 Update 阶段不写 → 回调线程只读,无需加锁 + std::unordered_map m_BodyToEntity; + // ---- 碰撞事件收集(多线程回调入队,主线程消费)---- class ContactListenerImpl; // cpp 定义(JPH::ContactListener 派生) Scope m_ContactListener; diff --git a/Engine/src/Physics/PhysicsWorld.cpp b/Engine/src/Physics/PhysicsWorld.cpp index c5f585a..47235ff 100644 --- a/Engine/src/Physics/PhysicsWorld.cpp +++ b/Engine/src/Physics/PhysicsWorld.cpp @@ -352,6 +352,7 @@ namespace Engine { !reg.all_of(e)) { bi.RemoveBody(it->second.id); bi.DestroyBody(it->second.id); + m_BodyToEntity.erase(it->second.id.GetIndexAndSequenceNumber()); invalidated.push_back(it->first); it = m_Bodies.erase(it); } else { @@ -370,6 +371,7 @@ namespace Engine { if (found != m_Bodies.end()) { bi.RemoveBody(found->second.id); bi.DestroyBody(found->second.id); + m_BodyToEntity.erase(found->second.id.GetIndexAndSequenceNumber()); m_Bodies.erase(found); invalidated.push_back(bits); } @@ -381,6 +383,7 @@ namespace Engine { if (found != m_Bodies.end()) { bi.RemoveBody(found->second.id); bi.DestroyBody(found->second.id); + m_BodyToEntity.erase(found->second.id.GetIndexAndSequenceNumber()); m_Bodies.erase(found); invalidated.push_back(bits); } @@ -402,6 +405,7 @@ namespace Engine { // 类型/碰撞体/质量变更 → 重建(简单正确,重置速度可接受) bi.RemoveBody(rec.id); bi.DestroyBody(rec.id); + m_BodyToEntity.erase(found->second.id.GetIndexAndSequenceNumber()); m_Bodies.erase(found); invalidated.push_back(bits); rb.bodyValid = false; @@ -891,6 +895,7 @@ namespace Engine { rec.lastPos = tr.GetWorldPosition(); rec.lastRot = tr.GetWorldRotationQuat(); m_Bodies[entityBits] = rec; + m_BodyToEntity[id.GetIndexAndSequenceNumber()] = entityBits; rb.bodyId = id.GetIndexAndSequenceNumber(); rb.bodyValid = true; @@ -902,6 +907,7 @@ namespace Engine { auto &bi = m_System->GetBodyInterface(); bi.RemoveBody(found->second.id); bi.DestroyBody(found->second.id); + m_BodyToEntity.erase(found->second.id.GetIndexAndSequenceNumber()); m_Bodies.erase(found); } @@ -913,12 +919,9 @@ namespace Engine { } bool PhysicsWorld::TryBitsByBodyId(const JPH::BodyID &id, u32 &outBits) const { - for (const auto &[bits, rec]: m_Bodies) { - if (rec.id == id) { - outBits = bits; - return true; - } - } + const auto& found = m_BodyToEntity.find(id.GetIndexAndSequenceNumber()); + if (found == m_BodyToEntity.end()) return false; + outBits = found->second; return false; } @@ -1059,23 +1062,28 @@ namespace Engine { const JPH::BodyID id(rb.bodyId); const JPH::RVec3 pos = bi.GetPosition(id); const JPH::Quat rot = bi.GetRotation(id); + const glm::vec3 worldPos(pos.GetX(), pos.GetY(), pos.GetZ()); + const glm::quat worldRot = ToGlm(rot); // body 姿态是世界系:写回经 world→local 换算(挂父层级实体 // 不破坏相对位姿;根实体 = 直写)。标脏 → UpdateTransforms 重算 m_Scene.SetWorldPose( e, - glm::vec3(pos.GetX(), pos.GetY(), pos.GetZ()), - ToGlm(rot), + worldPos, + worldRot, tr.GetWorldScale()); const JPH::Vec3 vel = bi.GetLinearVelocity(id); rb.velocity = glm::vec3(vel.GetX(), vel.GetY(), vel.GetZ()); - // lastPos/lastRot 同步到 body 姿态:否则下帧 SyncScene 把物理 - // 位移误判为编辑器拖动 → teleport 回旧位置死循环 + // lastPos/lastRot 同步到 body 当前姿态:否则下帧 SyncScene 会把物理 + // 位移误判为编辑器拖动 → teleport + 清零速度死循环。 + // 注意:必须用 bi.GetPosition/GetRotation 的 fresh 值,不能读 + // tr.GetWorldPosition()——SetWorldPose 只改 local+标脏,world cache + // 要等本帧末尾 Scene::UpdateTransforms 才重算,此刻仍是旧值。 const u32 bits = static_cast(entt::to_integral(e)); if (auto it = m_Bodies.find(bits); it != m_Bodies.end()) { - it->second.lastPos = tr.GetWorldPosition(); - it->second.lastRot = tr.GetWorldRotationQuat(); + it->second.lastPos = worldPos; + it->second.lastRot = worldRot; } } }