Files
HelloVulkan/Engine/include/Engine/Renderer/Mesh.h
T
atdunbg 1c4b6f37ff feat: Jolt 物理系统——刚体/碰撞体/物理调试图元 + 引擎时间单源
- 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)
2026-10-02 20:08:54 +08:00

99 lines
3.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// 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