新增程序化立方体与可碎墙验收:Model::CreateCube 五层链路 + WallFracture 碎片刚体群(命中碎裂/径向飞散/寿命清理)

This commit is contained in:
2026-10-08 22:28:49 +08:00
parent ed7cb417bd
commit d2701a3d9b
9 changed files with 415 additions and 0 deletions
+83
View File
@@ -161,6 +161,89 @@ Scope<Model> Model::CreateTransparentPlane(
true));
}
Scope<Model> Model::CreateCube(Device& device, MemoryAllocator& allocator,
DescriptorManager& descriptorManager,
vk::DescriptorSetLayout textureLayout,
f32 halfSize, u8 r, u8 g, u8 b)
{
return Scope<Model>(new Model(device, allocator, descriptorManager,
textureLayout, CubeTag{},
halfSize, std::array<u8, 4>{r, g, b, 255}));
}
// 程序化立方体:6 面 24 顶点(面法线朝外,CCW 从外看),36 索引。
// 结构镜像平面 ctor:默认纹理 → 纯色 albedo 覆盖 → 单 mesh
Model::Model(Device& device, MemoryAllocator& allocator,
DescriptorManager& descriptorManager,
vk::DescriptorSetLayout textureLayout,
CubeTag, f32 halfSize, const std::array<u8, 4>& rgba)
: m_Device(device)
, m_Allocator(allocator)
, m_DescriptorManager(descriptorManager)
, m_TextureLayout(textureLayout)
{
// 纯色贴图直供 albedo 槽;生命周期挂进纹理缓存(键含 rgba 值,
// 同色共享、异色互不冲突)——与平面 ctor 同一套
InitDefaultTextures();
Scope<Texture> tex = Texture::CreateSolidColor(device, allocator,
rgba[0], rgba[1], rgba[2]);
Texture* albedoOverride = tex.get();
const std::string texKey = "proc-cube:" + std::to_string(rgba[0]) + ',' +
std::to_string(rgba[1]) + ',' + std::to_string(rgba[2]) + ',' +
std::to_string(rgba[3]);
m_TextureCache.emplace(texKey, std::move(tex));
const f32 h = halfSize;
// 逐面 4 顶点(底左/底右/顶右/顶左,从面外看)+ 单位 UV
const glm::vec3 P[24] = {
// +Z(前)
{-h,-h, h}, { h,-h, h}, { h, h, h}, {-h, h, h},
// -Z(后)
{ h,-h,-h}, {-h,-h,-h}, {-h, h,-h}, { h, h,-h},
// +Y(上)
{-h, h, h}, { h, h, h}, { h, h,-h}, {-h, h,-h},
// -Y(下)
{-h,-h,-h}, { h,-h,-h}, { h,-h, h}, {-h,-h, h},
// +X(右)
{ h,-h, h}, { h,-h,-h}, { h, h,-h}, { h, h, h},
// -X(左)
{-h,-h,-h}, {-h,-h, h}, {-h, h, h}, {-h, h,-h},
};
const glm::vec3 N[6] = {
{0, 0, 1}, {0, 0, -1}, {0, 1, 0}, {0, -1, 0}, {1, 0, 0}, {-1, 0, 0},
};
const glm::vec2 UV[4] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
std::vector<Vertex> vertices;
vertices.reserve(24);
for (u32 f = 0; f < 6; ++f) {
for (u32 i = 0; i < 4; ++i) {
vertices.push_back({P[f * 4 + i], N[f], UV[i]});
}
}
std::vector<u32> indices;
indices.reserve(36);
for (u32 f = 0; f < 6; ++f) {
const u32 b = f * 4;
const std::vector<u32> quad = {b, b + 1, b + 2, b, b + 2, b + 3};
indices.insert(indices.end(), quad.begin(), quad.end());
}
const std::vector<std::vector<u32>> lodIndices = {indices};
std::string paths[Material::kSlotCount] = {"", "", "", ""};
std::array<Texture*, Material::kSlotCount> overrides{};
overrides[Material::Albedo] = albedoOverride;
Material* mat = GetOrCreateMaterial(paths, MaterialParams{}, false,
overrides);
m_Meshes.push_back(CreateScope<Mesh>(
m_Device, m_Allocator, vertices, lodIndices, mat));
// 内建材质快照(与 m_Meshes 下标对齐,编辑器材质槽 UI 不越界)
m_MeshMaterialInfos.push_back(
{"Cube", {}, MaterialParams{}, false});
RebuildUnionBounds();
}
ParsedModel Model::ParseFromDisk(const std::string& path)
{
ParsedModel out;