Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
World3DGPUScene.cpp
Go to the documentation of this file.
1#include "World3DGPUScene.hpp"
2
3#include "LegacyShadow.hpp"
4
5#include <limits>
6
7namespace monopoly::engine
8{
10 {
11 std::vector<const data::MeshRuntimeAsset*> activeMeshes;
12 const auto activeNodes = slot.order();
13 // Visibility only controls drawing, not the lifetime of a live mesh.
14 for (const auto node : activeNodes)
15 if (const auto* object = slot.find(node); object && object->asset)
16 activeMeshes.push_back(object->asset.get());
17 // Per-node animation buffers can outlive their node even when another
18 // live instance still owns the same static DataId. Retire both layers.
19 cache.pruneDynamicVertices(activeNodes);
20 cache.pruneAssets(activeMeshes);
21 }
22
23 std::expected<std::vector<World3DGPUIndexedBatch>, MeshGPUError>
25 {
26 std::vector<World3DGPUIndexedBatch> result;
27 std::vector<std::uint64_t> activeDynamicVertices;
28 for (const auto node : slot.visibleOrder())
29 {
30 const auto* object = slot.find(node);
31 if (object == nullptr || !object->screenBounds || !object->asset ||
32 !object->asset->renderData)
33 continue;
34
35 const auto renderData = object->renderData ?
36 object->renderData : object->asset->renderData;
37 if (!renderData) continue;
38 auto gpu = cache.resolveForScene(object->asset);
39 if (!gpu) return std::unexpected(gpu.error());
40 SDL_GPUBuffer* vertexBuffer = (*gpu)->vertexBuffer;
41 if (renderData != object->asset->renderData)
42 {
43 auto dynamic = cache.resolveDynamicVertices(object->node,
44 object->asset, renderData);
45 if (!dynamic) return std::unexpected(dynamic.error());
46 vertexBuffer = (*dynamic)->vertexBuffer;
47 activeDynamicVertices.push_back(object->node);
48 }
49 result.reserve(result.size() + renderData->batches.size());
50
51 for (const auto& batch : renderData->batches)
52 {
53 if (batch.firstIndex > std::numeric_limits<std::uint32_t>::max() ||
54 batch.indexCount > std::numeric_limits<std::uint32_t>::max())
55 return std::unexpected(MeshGPUError{
57 "GPU draw batch exceeds 32-bit indexed draw range"});
58
59 SDL_GPUTexture* gpuTexture = nullptr;
60 if (batch.texture)
61 {
62 gpuTexture = (*gpu)->texture(batch.texture->key);
63 if (gpuTexture == nullptr)
64 return std::unexpected(MeshGPUError{
66 "textured HMD batch has no uploaded SDL_GPU texture"});
67 }
68
69 std::array<SDL_GPUTextureSamplerBinding, 5> modernTextures{};
70 const std::array<const std::optional<data::ModernTextureBinding>*, 5> maps{
71 &batch.material.baseColorTexture, &batch.material.metallicRoughnessTexture,
72 &batch.material.normalTexture, &batch.material.emissiveTexture,
73 &batch.material.occlusionTexture};
74 for (std::size_t index = 0; index < maps.size(); ++index)
75 {
76 if (!*maps[index]) continue;
77 const auto* resource = (*gpu)->modernTexture(**maps[index]);
78 if (!resource)
79 return std::unexpected(MeshGPUError{
81 "modern map has no uploaded immutable GPU texture"});
82 modernTextures[index] = {resource->texture, resource->sampler};
83 }
84 result.push_back({
85 object->node,
86 object->contentsDataId,
87 object->priority,
88 object->clock,
89 object->worldTransform,
90 *object->screenBounds,
91 vertexBuffer,
92 (*gpu)->indexBuffer,
93 gpuTexture,
94 static_cast<std::uint32_t>(batch.firstIndex),
95 static_cast<std::uint32_t>(batch.indexCount),
96 data::isLegacyShadowMesh(object->contentsDataId),
97 batch.material,
98 batch.texture, modernTextures});
99 }
100 }
101 cache.pruneDynamicVertices(activeDynamicVertices);
103 return result;
104 }
105}
PlayerNumber slot
unsigned index
constexpr bool isLegacyShadowMesh(DataId id) noexcept
std::expected< std::vector< World3DGPUIndexedBatch >, MeshGPUError > buildWorld3DGPUScene(const SequenceWorld3DSlot &slot, MeshGPUCache &cache)
void pruneWorld3DGPUScene(const SequenceWorld3DSlot &slot, MeshGPUCache &cache)