22
22
* SOFTWARE.
23
23
*/
24
24
25
- #pragma author H. Utku Maden
25
+ #pragma author H. Utku Maden, xZise
26
26
#pragma description GL Transmission Format binary 3D model (.glb)
27
27
#pragma MIME model/gltf-binary
28
+ #pragma magic [67 6C 54 46] @ 0x00
28
29
29
30
import std.mem;
30
31
import std.io;
31
32
import type.magic;
33
+ import hex.type.json;
34
+ import std.core;
32
35
33
36
/**
34
37
* @brief The glTF magic section.
@@ -53,7 +56,10 @@ enum gltf_chunk_type_t : u32 {
53
56
struct gltf_chunk_t {
54
57
u32 length; /**< Length of this chunk. */
55
58
gltf_chunk_type_t type [[format("gltf_format")]]; /**< Type of the chunk. JSON or BIN expected. */
56
- u8 string[length]; /**< The chunk data. */
59
+ match (type) {
60
+ (gltf_chunk_type_t::JSON): hex::type::Json<length> json;
61
+ (gltf_chunk_type_t::BIN): u8 data[length];
62
+ } /**< The chunk data. */
57
63
};
58
64
59
65
fn gltf_format(gltf_chunk_type_t x)
@@ -64,7 +70,200 @@ fn gltf_format(gltf_chunk_type_t x)
64
70
return "";
65
71
};
66
72
67
- gltf_magic_t magic @ 0x00 ;
68
- gltf_chunk_t chunks[while(!std::mem::eof())] @ $ ;
73
+ u64 json_offset = 0 ;
74
+ u64 json_length = 0 ;
69
75
70
- std::assert_warn(std::mem::size() == magic.length, "file size mismatch");
76
+ struct StrideType<InnerType, auto Stride> {
77
+ InnerType value [[inline]];
78
+ if (Stride > 0) {
79
+ padding[Stride - sizeof(value)];
80
+ }
81
+ };
82
+
83
+ struct Scalar<ComponentType> {
84
+ ComponentType scalar;
85
+ } [[static, sealed]];
86
+
87
+ struct Vec2<ComponentType> {
88
+ ComponentType x;
89
+ ComponentType y;
90
+ } [[static]];
91
+
92
+ struct Vec3<ComponentType> {
93
+ ComponentType x;
94
+ ComponentType y;
95
+ ComponentType z;
96
+ } [[static]];
97
+
98
+ struct Vec4<ComponentType> {
99
+ ComponentType x;
100
+ ComponentType y;
101
+ ComponentType z;
102
+ ComponentType w;
103
+ } [[static]];
104
+
105
+ struct Mat2<ComponentType> {
106
+ ComponentType a11;
107
+ ComponentType a21;
108
+ ComponentType a12;
109
+ ComponentType a22;
110
+ } [[static]];
111
+
112
+ struct Mat3<ComponentType> {
113
+ ComponentType a11;
114
+ ComponentType a21;
115
+ ComponentType a31;
116
+ ComponentType a12;
117
+ ComponentType a22;
118
+ ComponentType a32;
119
+ ComponentType a13;
120
+ ComponentType a23;
121
+ ComponentType a33;
122
+ } [[static]];
123
+
124
+ struct Mat4<ComponentType> {
125
+ ComponentType a11;
126
+ ComponentType a21;
127
+ ComponentType a31;
128
+ ComponentType a41;
129
+ ComponentType a12;
130
+ ComponentType a22;
131
+ ComponentType a32;
132
+ ComponentType a42;
133
+ ComponentType a13;
134
+ ComponentType a23;
135
+ ComponentType a33;
136
+ ComponentType a43;
137
+ ComponentType a14;
138
+ ComponentType a24;
139
+ ComponentType a34;
140
+ ComponentType a44;
141
+ } [[static]];
142
+
143
+ enum ComponentType : u64 {
144
+ BYTE = 5120,
145
+ UNSIGNED_BYTE = 5121,
146
+ SHORT = 5122,
147
+ UNSIGNED_SHORT = 5123,
148
+ UNSIGNED_INT = 5125,
149
+ FLOAT = 5126,
150
+ };
151
+
152
+ fn get_byte_stride(auto bufferView) {
153
+ if (std::core::has_member(bufferView, "byteStride")) {
154
+ return bufferView.byteStride;
155
+ } else {
156
+ return 0;
157
+ }
158
+ };
159
+
160
+ struct Accessor<auto Offset> {
161
+ hex::type::Json<json_length> Json @ json_offset;
162
+ hex::type::Json<json_length> Json2 @ json_offset;
163
+ hex::type::Json<json_length> Json3 @ json_offset;
164
+ u64 accessor_index = std::core::array_index();
165
+ u64 view_index = Json.accessors[accessor_index].bufferView [[export]];
166
+ u64 view_offset = Json.bufferViews[view_index].byteOffset [[export]];
167
+ if (std::core::has_member(Json2.bufferViews[view_index], "byteStride")) {
168
+ u64 byteStride = Json.bufferViews[view_index].byteStride [[export]];
169
+ } else {
170
+ u64 byteStride = 0 [[export]];
171
+ }
172
+ if (std::core::has_member(Json3.accessors[accessor_index], "byteOffset")) {
173
+ u64 accessor_offset = Json.accessors[accessor_index].byteOffset [[export]];
174
+ } else {
175
+ u64 accessor_offset = 0 [[export]];
176
+ }
177
+ view_offset = view_offset + accessor_offset;
178
+ u64 count_elements = Json.accessors[accessor_index].count;
179
+ ComponentType component_type = Json.accessors[accessor_index].componentType [[export]];
180
+
181
+ match (Json.accessors[accessor_index].type, component_type) {
182
+ ("SCALAR", ComponentType::BYTE): StrideType<Scalar<s8>, byteStride> content[count_elements] @ view_offset + Offset;
183
+ ("SCALAR", ComponentType::UNSIGNED_BYTE): StrideType<Scalar<u8>, byteStride> content[count_elements] @ view_offset + Offset;
184
+ ("SCALAR", ComponentType::SHORT): StrideType<Scalar<s16>, byteStride> content[count_elements] @ view_offset + Offset;
185
+ ("SCALAR", ComponentType::UNSIGNED_SHORT): StrideType<Scalar<u16>, byteStride> content[count_elements] @ view_offset + Offset;
186
+ ("SCALAR", ComponentType::UNSIGNED_INT): StrideType<Scalar<u32>, byteStride> content[count_elements] @ view_offset + Offset;
187
+ ("SCALAR", ComponentType::FLOAT): StrideType<Scalar<float>, byteStride> content[count_elements] @ view_offset + Offset;
188
+ ("VEC2", ComponentType::FLOAT): StrideType<Vec2<s8>, byteStride> content[count_elements] @ view_offset + Offset;
189
+ ("VEC2", ComponentType::UNSIGNED_INT): StrideType<Vec2<u8>, byteStride> content[count_elements] @ view_offset + Offset;
190
+ ("VEC2", ComponentType::UNSIGNED_SHORT): StrideType<Vec2<s16>, byteStride> content[count_elements] @ view_offset + Offset;
191
+ ("VEC2", ComponentType::SHORT): StrideType<Vec2<u16>, byteStride> content[count_elements] @ view_offset + Offset;
192
+ ("VEC2", ComponentType::UNSIGNED_BYTE): StrideType<Vec2<u32>, byteStride> content[count_elements] @ view_offset + Offset;
193
+ ("VEC2", ComponentType::BYTE): StrideType<Vec2<float>, byteStride> content[count_elements] @ view_offset + Offset;
194
+ ("VEC3", ComponentType::FLOAT): StrideType<Vec3<float>, byteStride> content[count_elements] @ view_offset + Offset;
195
+ ("VEC3", ComponentType::UNSIGNED_INT): StrideType<Vec3<u32>, byteStride> content[count_elements] @ view_offset + Offset;
196
+ ("VEC3", ComponentType::UNSIGNED_SHORT): StrideType<Vec3<u16>, byteStride> content[count_elements] @ view_offset + Offset;
197
+ ("VEC3", ComponentType::SHORT): StrideType<Vec3<s16>, byteStride> content[count_elements] @ view_offset + Offset;
198
+ ("VEC3", ComponentType::UNSIGNED_BYTE): StrideType<Vec3<u8>, byteStride> content[count_elements] @ view_offset + Offset;
199
+ ("VEC3", ComponentType::BYTE): StrideType<Vec3<s8>, byteStride> content[count_elements] @ view_offset + Offset;
200
+ ("VEC4", ComponentType::FLOAT): StrideType<Vec4<float>, byteStride> content[count_elements] @ view_offset + Offset;
201
+ ("VEC4", ComponentType::UNSIGNED_INT): StrideType<Vec4<u32>, byteStride> content[count_elements] @ view_offset + Offset;
202
+ ("VEC4", ComponentType::UNSIGNED_SHORT): StrideType<Vec4<u16>, byteStride> content[count_elements] @ view_offset + Offset;
203
+ ("VEC4", ComponentType::SHORT): StrideType<Vec4<s16>, byteStride> content[count_elements] @ view_offset + Offset;
204
+ ("VEC4", ComponentType::UNSIGNED_BYTE): StrideType<Vec4<u8>, byteStride> content[count_elements] @ view_offset + Offset;
205
+ ("VEC4", ComponentType::BYTE): StrideType<Vec4<s8>, byteStride> content[count_elements] @ view_offset + Offset;
206
+ ("MAT2", ComponentType::FLOAT): StrideType<Mat2<float>, byteStride> content[count_elements] @ view_offset + Offset;
207
+ ("MAT2", ComponentType::UNSIGNED_INT): StrideType<Mat2<u32>, byteStride> content[count_elements] @ view_offset + Offset;
208
+ ("MAT2", ComponentType::UNSIGNED_SHORT): StrideType<Mat2<u16>, byteStride> content[count_elements] @ view_offset + Offset;
209
+ ("MAT2", ComponentType::SHORT): StrideType<Mat2<s16>, byteStride> content[count_elements] @ view_offset + Offset;
210
+ ("MAT2", ComponentType::UNSIGNED_BYTE): StrideType<Mat2<u8>, byteStride> content[count_elements] @ view_offset + Offset;
211
+ ("MAT2", ComponentType::BYTE): StrideType<Mat2<s8>, byteStride> content[count_elements] @ view_offset + Offset;
212
+ ("MAT3", ComponentType::FLOAT): StrideType<Mat3<float>, byteStride> content[count_elements] @ view_offset + Offset;
213
+ ("MAT3", ComponentType::UNSIGNED_INT): StrideType<Mat3<u32>, byteStride> content[count_elements] @ view_offset + Offset;
214
+ ("MAT3", ComponentType::UNSIGNED_SHORT): StrideType<Mat3<u16>, byteStride> content[count_elements] @ view_offset + Offset;
215
+ ("MAT3", ComponentType::SHORT): StrideType<Mat3<s16>, byteStride> content[count_elements] @ view_offset + Offset;
216
+ ("MAT3", ComponentType::UNSIGNED_BYTE): StrideType<Mat3<u8>, byteStride> content[count_elements] @ view_offset + Offset;
217
+ ("MAT3", ComponentType::BYTE): StrideType<Mat3<s8>, byteStride> content[count_elements] @ view_offset + Offset;
218
+ ("MAT4", ComponentType::FLOAT): StrideType<Mat4<float>, byteStride> content[count_elements] @ view_offset + Offset;
219
+ ("MAT4", ComponentType::UNSIGNED_INT): StrideType<Mat4<u32>, byteStride> content[count_elements] @ view_offset + Offset;
220
+ ("MAT4", ComponentType::UNSIGNED_SHORT): StrideType<Mat4<u16>, byteStride> content[count_elements] @ view_offset + Offset;
221
+ ("MAT4", ComponentType::SHORT): StrideType<Mat4<s16>, byteStride> content[count_elements] @ view_offset + Offset;
222
+ ("MAT4", ComponentType::UNSIGNED_BYTE): StrideType<Mat4<u8>, byteStride> content[count_elements] @ view_offset + Offset;
223
+ ("MAT4", ComponentType::BYTE): StrideType<Mat4<s8>, byteStride> content[count_elements] @ view_offset + Offset;
224
+ }
225
+ };
226
+
227
+ fn mem_cnt(auto value) {
228
+ return std::core::member_count(value);
229
+ };
230
+
231
+ struct ImageBuffer<auto Offset> {
232
+ hex::type::Json<json_length> Json @ json_offset;
233
+ u64 image_index = std::core::array_index();
234
+ u64 buffer_view_index = Json.images[image_index].bufferView;
235
+ u64 byte_offset = Json.bufferViews[buffer_view_index].byteOffset;
236
+ u64 byte_length = Json.bufferViews[buffer_view_index].byteLength;
237
+ u8 image[byte_length] @ Offset + byte_offset;
238
+ } [[hex::visualize("image", image)]];
239
+
240
+ struct BufferView<auto Offset> {
241
+ hex::type::Json<json_length> Json @ json_offset;
242
+ u64 buffer_view_index = std::core::array_index();
243
+ u64 byte_offset = Json.bufferViews[buffer_view_index].byteOffset;
244
+ u64 byte_length = Json.bufferViews[buffer_view_index].byteLength;
245
+ u8 data[byte_length] @ Offset + byte_offset;
246
+ };
247
+
248
+ struct Glb {
249
+ gltf_magic_t magic;
250
+ gltf_chunk_t jsonChunk;
251
+ gltf_chunk_t chunks[while(!std::mem::eof())];
252
+
253
+ json_offset = addressof(jsonChunk.json);
254
+ json_length = jsonChunk.length;
255
+
256
+ std::assert_warn(std::mem::size() == magic.length, "file size mismatch");
257
+
258
+ if (std::core::member_count(chunks) == 1) {
259
+ u128 binChunk = addressof(chunks[0].data);
260
+ hex::type::Json<json_length> Json @ json_offset;
261
+ if (std::core::has_member(Json, "images")) {
262
+ ImageBuffer<binChunk> images[mem_cnt(jsonChunk.json.images)];
263
+ }
264
+ BufferView<binChunk> buffer_views[mem_cnt(jsonChunk.json.bufferViews)];
265
+ Accessor<binChunk> accessors[mem_cnt(jsonChunk.json.accessors)];
266
+ }
267
+ };
268
+
269
+ Glb glb @ 0x00;
0 commit comments