physics: rigid body drive API (force/impulse/torque/velocity)
PhysicsWorld facade methods addressed by entity bits via body records: AddForce/AddImpulse/AddTorque (dynamic bodies only, auto-wake), Set/ GetLinearVelocity/SetAngularVelocity (dynamic + kinematic). Inspector RigidBody block gains impulse debug controls for manual response tests. Transient by design — nothing serialized.
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
#include "InspectorPanel.h"
|
#include "InspectorPanel.h"
|
||||||
#include "Engine/ECS/Components.h"
|
#include "Engine/ECS/Components.h"
|
||||||
#include "Engine/Renderer/Model.h"
|
#include "Engine/Renderer/Model.h"
|
||||||
|
#include "Engine/Physics/PhysicsWorld.h" // Apply Impulse 调试(GetPhysics 门面)
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
@@ -263,6 +264,16 @@ void InspectorPanel::Draw(const EditorContext& ctx, entt::entity selected)
|
|||||||
{
|
{
|
||||||
ImGui::Text("vel: %.2f, %.2f, %.2f m/s",
|
ImGui::Text("vel: %.2f, %.2f, %.2f m/s",
|
||||||
rb->velocity.x, rb->velocity.y, rb->velocity.z);
|
rb->velocity.x, rb->velocity.y, rb->velocity.z);
|
||||||
|
|
||||||
|
// 驱动调试(冲量瞬态不序列化):直接推一把看响应
|
||||||
|
static glm::vec3 s_debugImpulse{0.0f, 5.0f, 0.0f};
|
||||||
|
ImGui::DragFloat3("impulse", &s_debugImpulse.x, 0.1f);
|
||||||
|
if (ImGui::Button("Apply Impulse"))
|
||||||
|
{
|
||||||
|
ctx.app->GetPhysics().AddImpulse(
|
||||||
|
static_cast<uint32_t>(entt::to_integral(selected)),
|
||||||
|
s_debugImpulse);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,19 @@ namespace Engine {
|
|||||||
bool RayCast(const glm::vec3& origin, const glm::vec3& dir,
|
bool RayCast(const glm::vec3& origin, const glm::vec3& dir,
|
||||||
f32 maxDist, RayHit& outHit) const;
|
f32 maxDist, RayHit& outHit) const;
|
||||||
|
|
||||||
|
// ---- 刚体驱动(游戏逻辑/编辑器调试;按实体位模式寻址)----
|
||||||
|
// Jolt 力在每步模拟后清零:游戏逻辑每帧持续施加 = 正确用法;
|
||||||
|
// 冲量一次性改变动量(自动唤醒休眠体);速度直写会打断自然
|
||||||
|
// 模拟(Unity 同语义)。body 不存在或类型不符时静默忽略:
|
||||||
|
// 力/扭矩/冲量仅动态体,速度直写动态+运动学体
|
||||||
|
void AddForce(u32 entityBits, const glm::vec3& force);
|
||||||
|
void AddImpulse(u32 entityBits, const glm::vec3& impulse);
|
||||||
|
void AddTorque(u32 entityBits, const glm::vec3& torque);
|
||||||
|
void SetLinearVelocity(u32 entityBits, const glm::vec3& velocity);
|
||||||
|
void SetAngularVelocity(u32 entityBits, const glm::vec3& angularVelocity);
|
||||||
|
// 无 body / 静态体返回零向量
|
||||||
|
glm::vec3 GetLinearVelocity(u32 entityBits) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// 创建时缓存的参数(变更检测 → 重建 body)
|
// 创建时缓存的参数(变更检测 → 重建 body)
|
||||||
struct BodyRecord {
|
struct BodyRecord {
|
||||||
@@ -104,6 +117,7 @@ namespace Engine {
|
|||||||
ECS::RigidBodyComponent& rb,
|
ECS::RigidBodyComponent& rb,
|
||||||
ECS::TransformComponent& tr);
|
ECS::TransformComponent& tr);
|
||||||
void RemoveBody(u32 entityBits);
|
void RemoveBody(u32 entityBits);
|
||||||
|
const BodyRecord* FindRecord(u32 entityBits) const; // 刚体驱动寻址
|
||||||
void QueueEvent(CollisionEvent&& ev); // 回调线程 append(多线程并发,加锁)
|
void QueueEvent(CollisionEvent&& ev); // 回调线程 append(多线程并发,加锁)
|
||||||
bool TryBitsByBodyId(const JPH::BodyID& id, u32& outBits) const;
|
bool TryBitsByBodyId(const JPH::BodyID& id, u32& outBits) const;
|
||||||
|
|
||||||
|
|||||||
@@ -578,6 +578,63 @@ namespace Engine {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---- 刚体驱动(游戏逻辑/编辑器调试;见头文件语义注释)----
|
||||||
|
|
||||||
|
const PhysicsWorld::BodyRecord *PhysicsWorld::FindRecord(const u32 entityBits) const {
|
||||||
|
const auto found = m_Bodies.find(entityBits);
|
||||||
|
return found != m_Bodies.end() ? &found->second : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 力/扭矩/冲量:仅动态体(Jolt 对静态/运动学体施加力无意义)
|
||||||
|
void PhysicsWorld::AddForce(const u32 entityBits, const glm::vec3 &force) {
|
||||||
|
const auto *rec = FindRecord(entityBits);
|
||||||
|
if (!rec || rec->type != static_cast<u8>(ECS::RigidBodyComponent::BodyType::Dynamic))
|
||||||
|
return;
|
||||||
|
m_System->GetBodyInterface().AddForce(
|
||||||
|
rec->id, JPH::Vec3(force.x, force.y, force.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicsWorld::AddImpulse(const u32 entityBits, const glm::vec3 &impulse) {
|
||||||
|
const auto *rec = FindRecord(entityBits);
|
||||||
|
if (!rec || rec->type != static_cast<u8>(ECS::RigidBodyComponent::BodyType::Dynamic))
|
||||||
|
return;
|
||||||
|
m_System->GetBodyInterface().AddImpulse(
|
||||||
|
rec->id, JPH::Vec3(impulse.x, impulse.y, impulse.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicsWorld::AddTorque(const u32 entityBits, const glm::vec3 &torque) {
|
||||||
|
const auto *rec = FindRecord(entityBits);
|
||||||
|
if (!rec || rec->type != static_cast<u8>(ECS::RigidBodyComponent::BodyType::Dynamic))
|
||||||
|
return;
|
||||||
|
m_System->GetBodyInterface().AddTorque(
|
||||||
|
rec->id, JPH::Vec3(torque.x, torque.y, torque.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 速度直写:动态+运动学体都有效(运动学体速度即其运动方式)
|
||||||
|
void PhysicsWorld::SetLinearVelocity(const u32 entityBits, const glm::vec3 &velocity) {
|
||||||
|
const auto *rec = FindRecord(entityBits);
|
||||||
|
if (!rec || rec->type == static_cast<u8>(ECS::RigidBodyComponent::BodyType::Static))
|
||||||
|
return;
|
||||||
|
m_System->GetBodyInterface().SetLinearVelocity(
|
||||||
|
rec->id, JPH::Vec3(velocity.x, velocity.y, velocity.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicsWorld::SetAngularVelocity(const u32 entityBits, const glm::vec3 &angularVelocity) {
|
||||||
|
const auto *rec = FindRecord(entityBits);
|
||||||
|
if (!rec || rec->type == static_cast<u8>(ECS::RigidBodyComponent::BodyType::Static))
|
||||||
|
return;
|
||||||
|
m_System->GetBodyInterface().SetAngularVelocity(
|
||||||
|
rec->id, JPH::Vec3(angularVelocity.x, angularVelocity.y, angularVelocity.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 PhysicsWorld::GetLinearVelocity(const u32 entityBits) const {
|
||||||
|
const auto *rec = FindRecord(entityBits);
|
||||||
|
if (!rec || rec->type == static_cast<u8>(ECS::RigidBodyComponent::BodyType::Static))
|
||||||
|
return {0.0f, 0.0f, 0.0f};
|
||||||
|
const JPH::Vec3 v = m_System->GetBodyInterface().GetLinearVelocity(rec->id);
|
||||||
|
return {v.GetX(), v.GetY(), v.GetZ()};
|
||||||
|
}
|
||||||
|
|
||||||
// ---- 写回:动态体姿态 → Transform(标脏,帧循环统一 Compose)----
|
// ---- 写回:动态体姿态 → Transform(标脏,帧循环统一 Compose)----
|
||||||
|
|
||||||
void PhysicsWorld::Writeback() const {
|
void PhysicsWorld::Writeback() const {
|
||||||
|
|||||||
Reference in New Issue
Block a user