修复physics物理数据计算不正确的问题,同时为物理添加map索引

This commit is contained in:
2026-10-04 18:42:23 +08:00
parent ee5ab8e94e
commit c8a1cd90bf
3 changed files with 26 additions and 21 deletions
+1 -9
View File
@@ -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<Spinner>();
});
return true;
}();
ENGINE_REGISTER_SCRIPT(Spinner);
} // namespace
@@ -183,6 +183,11 @@ namespace Engine {
std::unordered_map<u32, BodyRecord> m_Bodies; // entity 位模式 → body
// BodyID 序号 → entity 位模式(O(1) 反查;ContactListener 回调用)
// 与 m_Bodies 同生共死:CreateBody 同插,RemoveBody/孤儿清理同 erase。
// 主线程在 SyncScene 写、Step 内 Update 阶段不写 → 回调线程只读,无需加锁
std::unordered_map<u32, u32> m_BodyToEntity;
// ---- 碰撞事件收集(多线程回调入队,主线程消费)----
class ContactListenerImpl; // cpp 定义(JPH::ContactListener 派生)
Scope<ContactListenerImpl> m_ContactListener;
+20 -12
View File
@@ -352,6 +352,7 @@ namespace Engine {
!reg.all_of<ECS::RigidBodyComponent, ECS::TransformComponent>(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<u32>(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;
}
}
}