新增调试绘制体系:DebugDraw 服务 + 物理调试 pass + 脚本侧力学线
通用图元(线/箭头四翼头/球/胶囊/盒)瞬时+持久双缓冲聚合; 物理 pass 画刚体速度/重力/接触反力;角色 collider 与力学 线归位(引擎只画资产、脚本画行为);线宽按设备上限钳制
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
//
|
||||
|
||||
#include <Engine/Physics/PhysicsWorld.h>
|
||||
#include <Engine/Debug/DebugDraw.h>
|
||||
|
||||
#include <Engine/Core/Log.h>
|
||||
#include <Engine/ECS/Components.h>
|
||||
@@ -274,12 +275,14 @@ namespace Engine {
|
||||
void PhysicsWorld::CollectDebugData() {
|
||||
m_DebugDraw->BeginCollect();
|
||||
|
||||
// 1) Jolt 原生:collider 线框 + 速度箭头(软体 mDrawSoftBody* 后续加这里)
|
||||
if ((m_DebugBits & (kPhyDbgColliders | kPhyDbgVelocity)) != 0) {
|
||||
// 1) Jolt 原生:collider 线框(软体 mDrawSoftBody* 后续加这里)。
|
||||
// 速度箭头不交 Jolt 画——其 BodyManager::DrawBodies 无零速保
|
||||
// 护,静止刚体的零向量箭头退化成 +X 方向(本次修复的突兀箭
|
||||
// 头)→ 统一在下方手画并加阈值
|
||||
if ((m_DebugBits & kPhyDbgColliders) != 0) {
|
||||
JPH::BodyManager::DrawSettings ds;
|
||||
ds.mDrawShape = (m_DebugBits & kPhyDbgColliders) != 0;
|
||||
ds.mDrawShape = true;
|
||||
ds.mDrawShapeWireframe = true;
|
||||
ds.mDrawVelocity = (m_DebugBits & kPhyDbgVelocity) != 0;
|
||||
m_System->DrawBodies(ds, m_DebugDraw.get());
|
||||
}
|
||||
|
||||
@@ -289,39 +292,86 @@ namespace Engine {
|
||||
}
|
||||
|
||||
// 3) 手绘箭头(Jolt 无现成 API):重力 = 常量方向指示(长度固定),
|
||||
// 加速度 = 速度差分(方向/长度随值,静止噪声阈值截断)
|
||||
// 加速度 = 速度差分(方向/长度随值,静止噪声阈值截断)。
|
||||
// 走引擎通用 DebugDraw 服务。收集按渲染帧率跑(Step 末尾
|
||||
// 无步进帧也重画,每帧全量重建)→ duration 必须 0(当帧瞬
|
||||
// 时):此前沿用 step 率时代的 2×步长续期,高帧率下每根箭
|
||||
// 头叠 4-5 个滞后副本,物体一动副本脱锚拖尾——表现为断断
|
||||
// 续续乱跳
|
||||
auto &bi = m_System->GetBodyInterface();
|
||||
const JPH::Vec3 gravity = m_System->GetGravity();
|
||||
constexpr f32 kGravityLen = 1.0f; // 世界单位
|
||||
constexpr f32 kAccelScale = 0.05f;
|
||||
constexpr f32 kAccelMaxLen = 2.0f;
|
||||
const JPH::Color kGravityColor(220, 60, 60); // 红:重力
|
||||
const JPH::Color kAccelColor(255, 170, 40); // 橙:加速度
|
||||
constexpr f32 kVelScale = 0.2f; // 速度箭头比例(单位/速度)
|
||||
constexpr f32 kDbgDur = 0.0f; // 渲染帧率收集 → 瞬时图元
|
||||
constexpr glm::vec4 kGravityColor = Debug::Rgb(0xDC3C3C); // 红:重力
|
||||
constexpr glm::vec4 kAccelColor = Debug::Rgb(0xE0640A); // 深橙:加速度
|
||||
constexpr glm::vec4 kVelColor = Debug::Rgb(0x5ADC5A); // 绿:速度
|
||||
constexpr glm::vec4 kContactColor = Debug::Rgb(0xD9C33C); // 黄:接触反力
|
||||
auto ToG = [](const JPH::RVec3Arg v) {
|
||||
return glm::vec3{static_cast<f32>(v.GetX()),
|
||||
static_cast<f32>(v.GetY()),
|
||||
static_cast<f32>(v.GetZ())};
|
||||
};
|
||||
|
||||
for (auto &[bits, rec]: m_Bodies) {
|
||||
if (rec.type != static_cast<u8>(ECS::RigidBodyComponent::BodyType::Dynamic)) {
|
||||
continue;
|
||||
}
|
||||
const JPH::RVec3 com = bi.GetCenterOfMassPosition(rec.id);
|
||||
const glm::vec3 com = ToG(bi.GetCenterOfMassPosition(rec.id));
|
||||
|
||||
// 速度箭头(绿):零速阈值——Jolt 原生 DrawBodies 无零速保
|
||||
// 护(静止零向量箭头退化成 +X),此处阈值手画
|
||||
if ((m_DebugBits & kPhyDbgVelocity) != 0) {
|
||||
const JPH::Vec3 v = bi.GetLinearVelocity(rec.id);
|
||||
if (v.LengthSq() > 1e-4f) { // >0.01 m/s 才画
|
||||
Debug::Arrow(com, com + ToG(JPH::RVec3(v * kVelScale)),
|
||||
kVelColor,
|
||||
/*headSize*/ 0.12f, /*width*/ 2.0f,
|
||||
/*duration*/ kDbgDur, /*depthTest*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_DebugBits & kPhyDbgGravity) != 0) {
|
||||
const JPH::Vec3 g = gravity * bi.GetGravityFactor(rec.id);
|
||||
const f32 len = g.Length();
|
||||
if (len > 1e-4f) {
|
||||
const JPH::RVec3 tip = com + JPH::RVec3(g * (kGravityLen / len));
|
||||
m_DebugDraw->DrawArrow(com, tip, kGravityColor, kGravityLen * 0.12f);
|
||||
Debug::Arrow(
|
||||
com,
|
||||
com + ToG(JPH::RVec3(g * (kGravityLen / len))),
|
||||
kGravityColor,
|
||||
/*headSize*/ 0.12f, /*width*/ 2.0f,
|
||||
/*duration*/ kDbgDur, /*depthTest*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_DebugBits & kPhyDbgAccel) != 0) {
|
||||
// 接触合力(比力 F/m = a − g,从测量加速度反推):静置
|
||||
// = +g 纯法向(与重力箭头等长反向 = 力平衡);滑动出现
|
||||
// 水平分量(摩擦);自由落体 ≈ 0 不画。长度按重力箭头
|
||||
// 同一比例归一 → 静置红下黄上视觉等长
|
||||
const JPH::Vec3 gB = gravity * bi.GetGravityFactor(rec.id);
|
||||
const glm::vec3 spec = rec.lastAccel -
|
||||
glm::vec3(gB.GetX(), gB.GetY(), gB.GetZ());
|
||||
const f32 smag = glm::length(spec);
|
||||
if (smag > 0.2f && gravity.Length() > 1e-4f) {
|
||||
const f32 slen = std::min(
|
||||
smag * kGravityLen / gravity.Length(), kAccelMaxLen);
|
||||
Debug::Arrow(com, com + (spec / smag) * slen,
|
||||
kContactColor,
|
||||
/*headSize*/ 0.12f, /*width*/ 2.0f,
|
||||
/*duration*/ kDbgDur, /*depthTest*/ false);
|
||||
}
|
||||
|
||||
const f32 mag = glm::length(rec.lastAccel);
|
||||
if (mag > 0.05f) {
|
||||
const glm::vec3 dir = rec.lastAccel / mag;
|
||||
const f32 len = std::min(mag * kAccelScale, kAccelMaxLen);
|
||||
const JPH::RVec3 tip =
|
||||
com + JPH::RVec3(dir.x, dir.y, dir.z) * len;
|
||||
m_DebugDraw->DrawArrow(
|
||||
com, tip, kAccelColor, std::max(len * 0.15f, 0.05f));
|
||||
Debug::Arrow(com, com + (rec.lastAccel / mag) * len,
|
||||
kAccelColor,
|
||||
/*headSize*/ 0.12f,
|
||||
/*width*/ 2.0f,
|
||||
/*duration*/ kDbgDur, /*depthTest*/ false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -334,6 +384,10 @@ namespace Engine {
|
||||
}
|
||||
}
|
||||
|
||||
// 角色运动类线条(速度/加速度)一律归用户脚本画(Unity
|
||||
// CharacterController 同语义:引擎只画 collider,移动调试归
|
||||
// 移动逻辑的拥有者);物理侧不保留任何角色箭头
|
||||
|
||||
// 释放上一帧缓存不再引用的通用几何 batch(DebugRenderer 内部池)
|
||||
m_DebugDraw->NextFrame();
|
||||
}
|
||||
@@ -675,7 +729,12 @@ namespace Engine {
|
||||
if (tr == nullptr) {
|
||||
continue;
|
||||
}
|
||||
entry.cc->Update(dt, gravity, *m_TempAllocator);
|
||||
// 每角色重力倍率(组件直读:Inspector 调完下个物理步即生效,
|
||||
// 不触发重建——重力只是 Update 的入参,不是形状参数)
|
||||
const auto *cc = reg.try_get<ECS::CharacterControllerComponent>(
|
||||
static_cast<entt::entity>(bits));
|
||||
const f32 gscale = cc != nullptr ? cc->gravityScale : 1.0f;
|
||||
entry.cc->Update(dt, gravity * gscale, *m_TempAllocator);
|
||||
const glm::vec3 p = entry.cc->GetPosition(); // 原点 = 脚底(世界系)
|
||||
// 写回走 world→local 换算(层级实体挂父下仍正确;标脏 →
|
||||
// UpdateTransforms 重算 world)
|
||||
@@ -1047,6 +1106,12 @@ namespace Engine {
|
||||
: glm::vec3{0.0f};
|
||||
}
|
||||
|
||||
glm::vec3 PhysicsWorld::GetCharacterPosition(const u32 entityBits) const {
|
||||
const auto found = m_Characters.find(entityBits);
|
||||
return found != m_Characters.end() ? found->second.cc->GetPosition()
|
||||
: glm::vec3{0.0f};
|
||||
}
|
||||
|
||||
// ---- 写回:动态体姿态 → Transform(标脏,帧循环统一 Compose)----
|
||||
|
||||
void PhysicsWorld::Writeback() {
|
||||
|
||||
Reference in New Issue
Block a user