Skip to content

Commit c78e257

Browse files
committed
patterns: Add json support for glb files
This makes it possible to separate display the different buffer views, accessors and images (even visualizing them). Unfortunately the data within the JSON gets sometimes corrupted and this is the reason, why it parses the JSON multiple times at some places.
1 parent 0b75336 commit c78e257

File tree

1 file changed

+204
-5
lines changed

1 file changed

+204
-5
lines changed

patterns/gltf.hexpat

Lines changed: 204 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@
2222
* SOFTWARE.
2323
*/
2424

25-
#pragma author H. Utku Maden
25+
#pragma author H. Utku Maden, xZise
2626
#pragma description GL Transmission Format binary 3D model (.glb)
2727
#pragma MIME model/gltf-binary
28+
#pragma magic [67 6C 54 46] @ 0x00
2829

2930
import std.mem;
3031
import std.io;
3132
import type.magic;
33+
import hex.type.json;
34+
import std.core;
3235

3336
/**
3437
* @brief The glTF magic section.
@@ -53,7 +56,10 @@ enum gltf_chunk_type_t : u32 {
5356
struct gltf_chunk_t {
5457
u32 length; /**< Length of this chunk. */
5558
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. */
5763
};
5864

5965
fn gltf_format(gltf_chunk_type_t x)
@@ -64,7 +70,200 @@ fn gltf_format(gltf_chunk_type_t x)
6470
return "";
6571
};
6672

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;
6975

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

Comments
 (0)