Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
LegacyMeshData.hpp
Go to the documentation of this file.
1#pragma once
2
4
5#include <array>
6#include <cstddef>
7#include <cstdint>
8#include <expected>
9#include <optional>
10#include <span>
11#include <string>
12#include <string_view>
13#include <vector>
14
15namespace monopoly::data
16{
34
36 {
38 std::size_t offset{};
39 std::string detail;
40 std::optional<DataError> dataError;
41 };
42
43 [[nodiscard]] std::string_view meshDataErrorCodeName(
44 MeshDataErrorCode code) noexcept;
45
47 {
48 // Allocation/work budgets, not restrictions of the historical format.
49 std::size_t maximumPrimitives{ 65'536 };
50 std::size_t maximumSections{ 262'144 };
51 std::size_t maximumHeaderFields{ 262'144 };
52 };
53
55 {
56 std::uint32_t rawValue{};
58 {
59 return (rawValue & 0x8000'0000U) != 0;
60 }
61 };
62
64 {
65 std::size_t offset{};
66 std::vector<HmdHeaderField> fields;
67 };
68
70 {
71 std::size_t offset{};
72 std::uint32_t type{};
73 std::uint32_t sizeWords{};
74 std::uint16_t elementCount{};
76 };
77
79 {
80 std::size_t offset{};
81 std::optional<std::size_t> nextOffset;
82 std::size_t headerIndex{};
84 std::vector<HmdDataSection> sections;
85 };
86
88 {
89 std::int16_t x{};
90 std::int16_t y{};
91 std::int16_t z{};
92 std::int16_t padding{};
93 };
94
96 {
97 std::uint8_t u{};
98 std::uint8_t v{};
99 };
100
102 {
103 std::size_t offset{};
104 std::uint32_t startIndex{};
105 std::vector<HmdShortVector> diffs;
106 };
107
108 // One entry corresponds to legacy pose index 1 + vector index; pose 0
109 // is always the undeformed base mesh. Vertex/normal blocks pair by
110 // global ordinal, matching hmdload.cpp AddVertex/NormalDiffBlock.
112 {
113 std::optional<HmdMimeDiffBlock> vertex;
114 std::optional<HmdMimeDiffBlock> normal;
115 };
116
118 {
119 std::size_t maximumDiffBlocks{65'536};
120 std::size_t maximumVectors{1'000'000};
121 };
122
124 {
125 std::array<std::uint32_t, 3> colours{};
126 std::uint16_t texturePage{ 0xFFFF };
127 std::array<HmdTexturePoint, 3> texturePoints{};
128 std::array<std::uint16_t, 3> vertexIndices{};
129 std::array<std::uint16_t, 3> normalIndices{};
130 std::array<HmdShortVector, 3> vertices{};
131 std::array<HmdShortVector, 3> normals{};
132 };
133
135 {
136 std::uint16_t texturePage{};
137 std::uint16_t rawX{};
138 std::uint16_t rawY{};
139 std::int32_t logicalX{};
140 std::int32_t logicalY{};
141 std::uint32_t width{};
142 std::uint32_t height{};
143 // RGBA8 conversion of the source 8-bit CLUT image. NewMesh.cpp does
144 // not use the PSX transparency bit when constructing its DIB texture.
145 std::vector<std::uint8_t> rgba;
146 };
147
148 // Immutable, CPU-owned inspection of the unmapped HMD disk payload.
149 // All physical pointers are little-endian u32 DWORD offsets, never native
150 // pointers. MESHX is the runtime postload object, not another disk format
151 // (Source/artlib/L_Data.cpp:7965-8026).
153 {
154 public:
155 [[nodiscard]] static std::expected<LegacyMeshData, MeshDataError>
157
158 [[nodiscard]] std::uint32_t versionId() const noexcept;
159 [[nodiscard]] std::span<const std::optional<std::size_t>>
160 blockRoots() const noexcept;
161 [[nodiscard]] std::span<const HmdPrimitiveHeader>
162 headers() const noexcept;
163 [[nodiscard]] std::span<const HmdPrimitive> primitives() const noexcept;
164 [[nodiscard]] std::span<const std::byte> bytes() const noexcept;
165
166 [[nodiscard]] std::expected<std::span<const std::byte>, MeshDataError>
167 sectionBytes(std::size_t primitiveIndex, std::size_t sectionIndex) const;
168
169 // Decodes one category-0 triangle with normals, as consumed by
170 // NewMesh.cpp:272-361. Preserves raw coordinates/normals/UV: no GPU,
171 // texture resolution, axis conversion or interpolation is implied.
172 // Structural parse alone does not validate category-specific payloads.
173 // SVECTOR arrays have no declared length here: each referenced record
174 // is checked against the owning HMD bytes, not an invented vertex count.
175 [[nodiscard]] std::expected<HmdTriangle, MeshDataError> triangle(
176 std::size_t primitiveIndex, std::size_t sectionIndex,
177 std::size_t triangleIndex) const;
178
179 // Category-2 GsUIMG1 images as consumed by NewMesh.cpp::ProcessHMDImage.
180 // Header fields are IMAGE TOP and CLUT TOP word-offset bases; image
181 // records remain immutable disk data and are converted without GDI.
182 // Decodes only the vertex/normal MIMe types used by Monopoly
183 // (GsVtxMIMe/GsNrmMIMe). Primitive chains are consumed tail-first
184 // like HMD_MapUnit; reset/joint MIMe remain intentionally opaque.
185 [[nodiscard]] std::expected<std::vector<HmdMimePose>, MeshDataError>
186 mimePoses(HmdMimeLimits limits = {}) const;
187
188 [[nodiscard]] std::expected<std::vector<HmdTextureImage>, MeshDataError>
189 textureImages() const;
190
191 private:
192 LegacyMeshData() = default;
193 SharedDataBytes owner_;
194 std::uint32_t versionId_{};
195 std::vector<std::optional<std::size_t>> blockRoots_;
196 std::vector<HmdPrimitiveHeader> headers_;
197 std::vector<HmdPrimitive> primitives_;
198 };
199
200 // Keeps the DAT lease after unmount/clear; never treats a MeshX pointer
201 // payload as serialized HMD data.
202 [[nodiscard]] std::expected<LegacyMeshData, MeshDataError>
204 MeshParseLimits limits = {});
205}
std::shared_ptr< const data::HmdTextureImage > source
unsigned index
std::span< const HmdPrimitive > primitives() const noexcept
std::expected< std::vector< HmdTextureImage >, MeshDataError > textureImages() const
std::expected< std::span< const std::byte >, MeshDataError > sectionBytes(std::size_t primitiveIndex, std::size_t sectionIndex) const
std::span< const std::optional< std::size_t > > blockRoots() const noexcept
std::span< const HmdPrimitiveHeader > headers() const noexcept
std::expected< std::vector< HmdMimePose >, MeshDataError > mimePoses(HmdMimeLimits limits={}) const
std::uint32_t versionId() const noexcept
std::expected< HmdTriangle, MeshDataError > triangle(std::size_t primitiveIndex, std::size_t sectionIndex, std::size_t triangleIndex) const
std::span< const std::byte > bytes() const noexcept
static std::expected< LegacyMeshData, MeshDataError > parse(SharedDataBytes bytes, MeshParseLimits limits={})
std::expected< LegacyMeshData, MeshDataError > openLegacyMeshData(const DataSource &source, DataId id, MeshParseLimits limits)
std::uint32_t DataId
Definition DataBanks.hpp:10
std::shared_ptr< const DataBytes > SharedDataBytes
std::string_view meshDataErrorCodeName(MeshDataErrorCode code) noexcept
bool isOffset() const noexcept
std::vector< HmdShortVector > diffs
std::optional< HmdMimeDiffBlock > normal
std::optional< HmdMimeDiffBlock > vertex
std::vector< HmdHeaderField > fields
std::optional< std::size_t > nextOffset
std::vector< HmdDataSection > sections
std::vector< std::uint8_t > rgba
std::array< HmdTexturePoint, 3 > texturePoints
std::array< std::uint16_t, 3 > normalIndices
std::array< HmdShortVector, 3 > normals
std::array< std::uint32_t, 3 > colours
std::array< HmdShortVector, 3 > vertices
std::array< std::uint16_t, 3 > vertexIndices
std::optional< DataError > dataError