- PhysicsWorld:Jolt 集成,Dynamic/Kinematic/Static 刚体,姿态写回 Transform(Unity FixedUpdate 语义,吃 scaled dt,暂停自动冻结) - 碰撞体:Box(默认/手动 halfExtents)+ Mesh 碰撞体(Static→精确 MeshShape / Dynamic·Kinematic→ConvexHull,数据源 = Mesh ctor 缓存 的 CPU 位置副本,退化三角剔除,失败回退 Box 并告警) - PhysicsDebugPass:物理调试图元每帧上传绘制(debug_line shader) - Time:引擎时间单源(BeginFrame 落定 FrameTime,scaled/unscaled 分离) - JoltPhysics 以 submodule 接入(官方 url)
99 lines
3.5 KiB
C++
99 lines
3.5 KiB
C++
//
|
||
// Created by atdunbg on 2026/9/21.
|
||
//
|
||
|
||
#ifndef HELLOVULKAN_MESH_H
|
||
#define HELLOVULKAN_MESH_H
|
||
|
||
|
||
#include <Engine/Core/Types.h>
|
||
#include <Engine/Renderer/Vertex.h>
|
||
#include <Engine/Vulkan/Buffer.h>
|
||
#include <vulkan/vulkan.hpp>
|
||
#include <vector>
|
||
|
||
namespace Engine
|
||
{
|
||
class Device;
|
||
class MemoryAllocator;
|
||
class Buffer;
|
||
class Material;
|
||
|
||
// LOD 级数:LOD0 = 原始网格,越高越简(解析期 meshopt_simplify 生成,
|
||
// 共享顶点数据,只换索引区间)
|
||
inline constexpr u32 kMeshLodCount = 3;
|
||
|
||
class Mesh
|
||
{
|
||
public:
|
||
// material 非拥有指针:Model 的材质缓存拥有(同贴图共享一份)
|
||
// lods[0] 必须为原始索引(与 vertices 对应),各级简化链由解析期生成
|
||
Mesh(Device& device, MemoryAllocator& allocator,
|
||
const std::vector<Vertex>& vertices,
|
||
const std::vector<std::vector<u32>>& lods,
|
||
Material* material);
|
||
~Mesh();
|
||
|
||
Mesh(const Mesh&) = delete;
|
||
Mesh& operator=(const Mesh&) = delete;
|
||
|
||
// instanceCount/firstInstance:GPUDriven 按 mesh 分 batch 后,
|
||
// 同 mesh 的 N 个实体一次 draw 完成,模型矩阵经实例索引取。
|
||
// lod:索引区间选择(越界取最高级)
|
||
void Draw(vk::CommandBuffer cmd, u32 instanceCount = 1,
|
||
u32 firstInstance = 0, u32 lod = 0) const;
|
||
|
||
Material* GetMaterial() const { return m_Material; }
|
||
u32 GetLodIndexCount(u32 lod) const
|
||
{
|
||
return m_Lods[lod < kMeshLodCount ? lod : kMeshLodCount - 1].indexCount;
|
||
}
|
||
// 全局连续槽位(SceneRenderer 数组化 batch 查找用,避免逐实例 hash)
|
||
u32 GetSlot() const { return m_Slot; }
|
||
|
||
// ---- MDI 兼容取数(per-mesh buffer:偏移恒 0,firstIndex 即全局)----
|
||
vk::Buffer GetVertexBuffer() const { return m_VertexBuffer->Get(); }
|
||
vk::Buffer GetIndexBuffer() const { return m_IndexBuffer->Get(); }
|
||
u32 GetVertexOffset() const { return 0; }
|
||
u32 GetGlobalFirstIndex(u32 lod) const
|
||
{
|
||
return m_Lods[lod < kMeshLodCount ? lod : kMeshLodCount - 1].firstIndex;
|
||
}
|
||
|
||
// 局部空间包围球(构造时从顶点算出),视锥剔除用
|
||
struct Bounds {
|
||
glm::vec3 center{0.0f};
|
||
f32 radius = 0.0f;
|
||
};
|
||
const Bounds& GetBounds() const { return m_Bounds; }
|
||
|
||
// ---- CPU 位置副本(物理 MeshShape/ConvexHull 数据源)----
|
||
// GPU 上传后完整 Vertex 即弃,但物理碰撞仍需三角形:构造时抽
|
||
// 位置-only(12B/顶点,约为完整 Vertex 的 1/5)+ LOD0 索引。
|
||
const std::vector<glm::vec3>& GetCpuPositions() const { return m_CpuPositions; }
|
||
const std::vector<u32>& GetCpuIndices() const { return m_CpuIndices; }
|
||
|
||
private:
|
||
// 物理碰撞数据源(MeshShape 三角网格 / ConvexHull 点云)
|
||
std::vector<glm::vec3> m_CpuPositions;
|
||
std::vector<u32> m_CpuIndices; // LOD0(原始精度)
|
||
// 同一 index buffer 内连续排布的各级索引区间
|
||
struct LodRange {
|
||
u32 firstIndex = 0;
|
||
u32 indexCount = 0;
|
||
};
|
||
|
||
Scope<Buffer> m_VertexBuffer;
|
||
Scope<Buffer> m_IndexBuffer;
|
||
std::array<LodRange, kMeshLodCount> m_Lods{};
|
||
Material* m_Material;
|
||
u32 m_Slot = 0;
|
||
Bounds m_Bounds;
|
||
|
||
u64 m_VertexBytes = 0;
|
||
u64 m_IndexBytes = 0;
|
||
};
|
||
} // namespace Engine
|
||
|
||
#endif //HELLOVULKAN_MESH_H
|