阶段性合并:动画重定向、碎裂共享库、第三人称玩法、编辑器面板与 vendored ufbx

- 动画:HumanoidRig 三层架构(standard 标准槽 / dialects 方言映射 / mapper 配对),
  指/趾统一走世界增量两遍式烘焙;AnimationAttach 拆为纯算法 + facade;修正 HumanoidBasis
  行走基朝向与跨骨架去重、根运动通道
- 物理:CharacterController 角色互碰撞 / shapeOffset / 接触事件;PhysicsWorld 接触合成与
  字符冲量判定
- 渲染与材质:Model 多材质按材质拆子 mesh 与贴图路径解析、DDS 直传、GLB 内嵌纹理落盘、
  不透明通道 alpha 固定 1.0、glTF FlipUVs 对齐;SceneSerializer 支持 meshIndex 与材质覆盖
- 脚本:FractureLib 抽为共享库(HostView 桥接)、WallFracture 参数直绑、新增
  ThirdPersonCamera / Follower / WASDMove 玩法;移除 GameDirector / PlayerController / Target
- 编辑器:新增 GamepadPanel、LogPanel(LogRing),改进 Inspector / 材质 / 统计 / 视口面板
- 依赖:vendored ufbx(FBX 5.x/6.x/7.x 全版本解析,替代 assimp 对 FBX 6.1 的拒读)
This commit is contained in:
2026-10-11 22:22:19 +08:00
parent 334819bf97
commit beba491bcb
57 changed files with 43200 additions and 1378 deletions
+25 -19
View File
@@ -1,15 +1,19 @@
//
// WallFracture.cpp:可碎墙脚本——碎裂逻辑已提取至 FractureLib.h
//(打靶场 Target 复用同一条路径),本文件只剩宿主职责:
// DeclareParams 直绑 Fracture::Params(参数名/默认值与历史档位
// DeclareParams 直绑 Burst::p 各字段(参数名/默认值与历史档位
// 逐一同名同值,旧场景不受影响)
// OnCollisionEnter → Burst::TryFire(一次性保护 + 对方 Dynamic
// 速度校验 + 藏墙 + Voronoi 切分 + spawn 碎片群,库内完成)
// OnCollisionEnter → Burst::TryFire(一次性保护 + 对方撞击来源
// 与速度校验 + 藏墙 + Voronoi 切分 + spawn 碎片群,库内完成)。
// 撞击来源 = 动态刚体(子弹/抛体)或角色(玩家撞墙)——角色是
// CharacterVirtual,其碰撞事件由 PhysicsWorld 从角色接触合成
// (Jolt 的 ContactListener 只回调刚体,不覆盖角色)
// OnUpdate → Burst::Tick(施速待办 / 寿命清理 / 模型回收)
// OnDestroy → Burst::Shutdown(独占碎片模型批量停飞卸载)
//
// 外观默认 = 砖色不透明(原观感);玻璃/发光碎片换 Target.cpp 的
// 用法(Fire 前改 Burst::look)。
// 外观默认继承墙的生效材质(底色/贴图/透明),碎块与墙面观感一致;
// 要独立外观(玻璃/发光碎片)置 Burst::look.inheritFromHost = false
// 再用 baseColor/emissive 显式指定。
//
// 验收步骤:编辑器摆一堵墙(MeshRenderer = procedural://cube +
// RigidBody Static Box + 挂 WallFracture,缩放即墙尺寸)→ 场景里
@@ -35,25 +39,27 @@ namespace {
void DeclareParams(Engine::Scripting::ParamBuilder& pb) override {
// Voronoi 种子数 = 碎片数(40% 在命中点半径内加密 → 孔洞
// 周边碎块小、边缘大块的玻璃碎分布;最小间距防碎片退化)
pb.Field("Count", &m_P.count, 30);
pb.Field("SeedRadius", &m_P.seedRadius, 0.9f); // 加密半径 m
pb.Field("MinSeedDist", &m_P.minSeedDist, 0.12f); // 种子最小间距 m
// 直绑 Burst::p:碎裂逻辑只读 Burst::p,绑到别处(曾经的
// 独立 m_P)会让计数器/寿命等全部失效
pb.Field("Count", &m_Burst.p.count, 30);
pb.Field("SeedRadius", &m_Burst.p.seedRadius, 0.9f); // 加密半径 m
pb.Field("MinSeedDist", &m_Burst.p.minSeedDist, 0.12f); // 种子最小间距 m
// 玻璃/陶瓷式碎裂(裂纹分离 + 重力塌落),非爆炸飞散:
// 初速 = 命中点径向 × 距离指数衰减(近动远不动)+ 法线
// 轻微外推(剥落)+ 微弱上抛;重力是塌落的主导
pb.Field("BurstSpeed", &m_P.burstSpeed, 1.2f); // 近点径向初速 m/s
pb.Field("Falloff", &m_P.falloff, 1.0f); // 距离衰减率 1/m
pb.Field("NormalPop", &m_P.normalPop, 0.4f); // 法线外推 m/s
pb.Field("UpBias", &m_P.upBias, 0.3f); // 上抛偏置 m/s
pb.Field("Lifetime", &m_P.lifetime, 6.0f); // 碎片寿命(秒)
pb.Field("MaxFragments", &m_P.maxFragments, 128); // 活碎片上限
pb.Field("MinImpactSpeed", &m_P.minImpactSpeed, 2.0f); // 触发阈值
pb.Field("BurstSpeed", &m_Burst.p.burstSpeed, 1.2f); // 近点径向初速 m/s
pb.Field("Falloff", &m_Burst.p.falloff, 1.0f); // 距离衰减率 1/m
pb.Field("NormalPop", &m_Burst.p.normalPop, 0.4f); // 法线外推 m/s
pb.Field("UpBias", &m_Burst.p.upBias, 0.3f); // 上抛偏置 m/s
pb.Field("Lifetime", &m_Burst.p.lifetime, 6.0f); // 碎片寿命(秒)
pb.Field("MaxFragments", &m_Burst.p.maxFragments, 128); // 活碎片上限
pb.Field("MinImpactSpeed", &m_Burst.p.minImpactSpeed, 2.0f); // 触发阈值
}
void OnCollisionEnter(u32 other, const glm::vec3& point,
const glm::vec3& normal) override {
// 触发条件在库内:对方须是活的 Dynamic 刚体且速度够快
//(过滤静止贴靠/角色轻碰——子弹/抛体必中)
// 触发条件在库内:对方须是够快的撞击来源——动态刚体
//(子弹/抛体)或角色(玩家撞墙);速度阈值过滤静止贴靠
m_Burst.TryFire(HV(), other, point, normal);
}
@@ -72,8 +78,8 @@ namespace {
[this](Engine::ECS::Entity e) { Destroy(e); }};
}
Engine::Fracture::Params m_P; // 参数(DeclareParams 直绑)
Engine::Fracture::Burst m_Burst; // 碎片簿记 + 生命周期(look 默认砖色)
// 碎片簿记 + 生命周期;参数即 m_Burst.p(DeclareParams 直绑其字段)
Engine::Fracture::Burst m_Burst;
};
} // namespace