修复physics物理数据计算不正确的问题,同时为物理添加map索引
This commit is contained in:
@@ -25,23 +25,15 @@ namespace {
|
|||||||
void OnUpdate(float dt) override {
|
void OnUpdate(float dt) override {
|
||||||
// 四元数复合绕 Y(避免每帧欧拉↔四元数往返累积失真)
|
// 四元数复合绕 Y(避免每帧欧拉↔四元数往返累积失真)
|
||||||
|
|
||||||
/*
|
|
||||||
const glm::quat step = glm::angleAxis(
|
const glm::quat step = glm::angleAxis(
|
||||||
glm::radians(m_Speed * dt), glm::vec3(0.0f, 1.0f, 0.0f));
|
glm::radians(m_Speed * dt), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
Transform().SetRotationQuat(step * Transform().GetRotationQuat());
|
Transform().SetRotationQuat(step * Transform().GetRotationQuat());
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float m_Speed = 90.0f; // 度/秒
|
float m_Speed = 90.0f; // 度/秒
|
||||||
};
|
};
|
||||||
|
|
||||||
static const bool s_Spinner_registered = [] {
|
ENGINE_REGISTER_SCRIPT(Spinner);
|
||||||
::Engine::Scripting::ScriptRegistry::Register(
|
|
||||||
"Spinner", []() -> ::Engine::Scope<::Engine::Scripting::ScriptBehavior> {
|
|
||||||
return ::Engine::CreateScope<Spinner>();
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}();
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -183,6 +183,11 @@ namespace Engine {
|
|||||||
|
|
||||||
std::unordered_map<u32, BodyRecord> m_Bodies; // entity 位模式 → body
|
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 派生)
|
class ContactListenerImpl; // cpp 定义(JPH::ContactListener 派生)
|
||||||
Scope<ContactListenerImpl> m_ContactListener;
|
Scope<ContactListenerImpl> m_ContactListener;
|
||||||
|
|||||||
@@ -352,6 +352,7 @@ namespace Engine {
|
|||||||
!reg.all_of<ECS::RigidBodyComponent, ECS::TransformComponent>(e)) {
|
!reg.all_of<ECS::RigidBodyComponent, ECS::TransformComponent>(e)) {
|
||||||
bi.RemoveBody(it->second.id);
|
bi.RemoveBody(it->second.id);
|
||||||
bi.DestroyBody(it->second.id);
|
bi.DestroyBody(it->second.id);
|
||||||
|
m_BodyToEntity.erase(it->second.id.GetIndexAndSequenceNumber());
|
||||||
invalidated.push_back(it->first);
|
invalidated.push_back(it->first);
|
||||||
it = m_Bodies.erase(it);
|
it = m_Bodies.erase(it);
|
||||||
} else {
|
} else {
|
||||||
@@ -370,6 +371,7 @@ namespace Engine {
|
|||||||
if (found != m_Bodies.end()) {
|
if (found != m_Bodies.end()) {
|
||||||
bi.RemoveBody(found->second.id);
|
bi.RemoveBody(found->second.id);
|
||||||
bi.DestroyBody(found->second.id);
|
bi.DestroyBody(found->second.id);
|
||||||
|
m_BodyToEntity.erase(found->second.id.GetIndexAndSequenceNumber());
|
||||||
m_Bodies.erase(found);
|
m_Bodies.erase(found);
|
||||||
invalidated.push_back(bits);
|
invalidated.push_back(bits);
|
||||||
}
|
}
|
||||||
@@ -381,6 +383,7 @@ namespace Engine {
|
|||||||
if (found != m_Bodies.end()) {
|
if (found != m_Bodies.end()) {
|
||||||
bi.RemoveBody(found->second.id);
|
bi.RemoveBody(found->second.id);
|
||||||
bi.DestroyBody(found->second.id);
|
bi.DestroyBody(found->second.id);
|
||||||
|
m_BodyToEntity.erase(found->second.id.GetIndexAndSequenceNumber());
|
||||||
m_Bodies.erase(found);
|
m_Bodies.erase(found);
|
||||||
invalidated.push_back(bits);
|
invalidated.push_back(bits);
|
||||||
}
|
}
|
||||||
@@ -402,6 +405,7 @@ namespace Engine {
|
|||||||
// 类型/碰撞体/质量变更 → 重建(简单正确,重置速度可接受)
|
// 类型/碰撞体/质量变更 → 重建(简单正确,重置速度可接受)
|
||||||
bi.RemoveBody(rec.id);
|
bi.RemoveBody(rec.id);
|
||||||
bi.DestroyBody(rec.id);
|
bi.DestroyBody(rec.id);
|
||||||
|
m_BodyToEntity.erase(found->second.id.GetIndexAndSequenceNumber());
|
||||||
m_Bodies.erase(found);
|
m_Bodies.erase(found);
|
||||||
invalidated.push_back(bits);
|
invalidated.push_back(bits);
|
||||||
rb.bodyValid = false;
|
rb.bodyValid = false;
|
||||||
@@ -891,6 +895,7 @@ namespace Engine {
|
|||||||
rec.lastPos = tr.GetWorldPosition();
|
rec.lastPos = tr.GetWorldPosition();
|
||||||
rec.lastRot = tr.GetWorldRotationQuat();
|
rec.lastRot = tr.GetWorldRotationQuat();
|
||||||
m_Bodies[entityBits] = rec;
|
m_Bodies[entityBits] = rec;
|
||||||
|
m_BodyToEntity[id.GetIndexAndSequenceNumber()] = entityBits;
|
||||||
|
|
||||||
rb.bodyId = id.GetIndexAndSequenceNumber();
|
rb.bodyId = id.GetIndexAndSequenceNumber();
|
||||||
rb.bodyValid = true;
|
rb.bodyValid = true;
|
||||||
@@ -902,6 +907,7 @@ namespace Engine {
|
|||||||
auto &bi = m_System->GetBodyInterface();
|
auto &bi = m_System->GetBodyInterface();
|
||||||
bi.RemoveBody(found->second.id);
|
bi.RemoveBody(found->second.id);
|
||||||
bi.DestroyBody(found->second.id);
|
bi.DestroyBody(found->second.id);
|
||||||
|
m_BodyToEntity.erase(found->second.id.GetIndexAndSequenceNumber());
|
||||||
m_Bodies.erase(found);
|
m_Bodies.erase(found);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -913,12 +919,9 @@ namespace Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PhysicsWorld::TryBitsByBodyId(const JPH::BodyID &id, u32 &outBits) const {
|
bool PhysicsWorld::TryBitsByBodyId(const JPH::BodyID &id, u32 &outBits) const {
|
||||||
for (const auto &[bits, rec]: m_Bodies) {
|
const auto& found = m_BodyToEntity.find(id.GetIndexAndSequenceNumber());
|
||||||
if (rec.id == id) {
|
if (found == m_BodyToEntity.end()) return false;
|
||||||
outBits = bits;
|
outBits = found->second;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1059,23 +1062,28 @@ namespace Engine {
|
|||||||
const JPH::BodyID id(rb.bodyId);
|
const JPH::BodyID id(rb.bodyId);
|
||||||
const JPH::RVec3 pos = bi.GetPosition(id);
|
const JPH::RVec3 pos = bi.GetPosition(id);
|
||||||
const JPH::Quat rot = bi.GetRotation(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 换算(挂父层级实体
|
// body 姿态是世界系:写回经 world→local 换算(挂父层级实体
|
||||||
// 不破坏相对位姿;根实体 = 直写)。标脏 → UpdateTransforms 重算
|
// 不破坏相对位姿;根实体 = 直写)。标脏 → UpdateTransforms 重算
|
||||||
m_Scene.SetWorldPose(
|
m_Scene.SetWorldPose(
|
||||||
e,
|
e,
|
||||||
glm::vec3(pos.GetX(), pos.GetY(), pos.GetZ()),
|
worldPos,
|
||||||
ToGlm(rot),
|
worldRot,
|
||||||
tr.GetWorldScale());
|
tr.GetWorldScale());
|
||||||
|
|
||||||
const JPH::Vec3 vel = bi.GetLinearVelocity(id);
|
const JPH::Vec3 vel = bi.GetLinearVelocity(id);
|
||||||
rb.velocity = glm::vec3(vel.GetX(), vel.GetY(), vel.GetZ());
|
rb.velocity = glm::vec3(vel.GetX(), vel.GetY(), vel.GetZ());
|
||||||
|
|
||||||
// lastPos/lastRot 同步到 body 姿态:否则下帧 SyncScene 把物理
|
// lastPos/lastRot 同步到 body 当前姿态:否则下帧 SyncScene 会把物理
|
||||||
// 位移误判为编辑器拖动 → teleport 回旧位置死循环
|
// 位移误判为编辑器拖动 → teleport + 清零速度死循环。
|
||||||
|
// 注意:必须用 bi.GetPosition/GetRotation 的 fresh 值,不能读
|
||||||
|
// tr.GetWorldPosition()——SetWorldPose 只改 local+标脏,world cache
|
||||||
|
// 要等本帧末尾 Scene::UpdateTransforms 才重算,此刻仍是旧值。
|
||||||
const u32 bits = static_cast<u32>(entt::to_integral(e));
|
const u32 bits = static_cast<u32>(entt::to_integral(e));
|
||||||
if (auto it = m_Bodies.find(bits); it != m_Bodies.end()) {
|
if (auto it = m_Bodies.find(bits); it != m_Bodies.end()) {
|
||||||
it->second.lastPos = tr.GetWorldPosition();
|
it->second.lastPos = worldPos;
|
||||||
it->second.lastRot = tr.GetWorldRotationQuat();
|
it->second.lastRot = worldRot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user