I’m not too experienced in odin myself, but here’s how I wrote my simple gltf (glb to be precise) loader:
load_glb :: proc(data: []byte) -> (mesh: Mesh, err: B3DM_Error) {
JSON := [4]byte{'J', 'S', 'O', 'N'}
BIN := [4]byte{'B', 'I', 'N', 0}
GlobalHeader :: struct { magic, version, length: u32 }
gh := cast(^GlobalHeader)raw_data(data)
if gh.magic != 1179937895 { return mesh, .Bad_File }
if gh.version != 2 { return mesh, .Unsupported_Feature }
if gh.length != u32(len(data)) { return mesh, .Bad_File }
ChunkHeader :: struct { length: u32, type: [4]byte }
ch0 := cast(^ChunkHeader)raw_data(data[size_of(GlobalHeader):])
if mem.compare(ch0.type[:], JSON[:]) != 0 { return mesh, .Bad_File }
cd0 := data[size_of(GlobalHeader) + size_of(ChunkHeader):][:ch0.length]
ch1 := cast(^ChunkHeader)raw_data(data[size_of(GlobalHeader) + size_of(ChunkHeader) + ch0.length:])
if mem.compare(ch1.type[:], BIN[:]) != 0 { return mesh, .Bad_File }
cd1 := data[size_of(GlobalHeader) + size_of(ChunkHeader) + ch0.length + size_of(ChunkHeader):][:ch1.length]
glb: GLB
json.unmarshal(cd0, &glb) or_return
if len(glb.meshes) != 1 { return mesh, .Unsupported_Feature }
if len(glb.meshes[0].primitives) != 1 { return mesh, .Unsupported_Feature }
m0 := glb.meshes[0].primitives[0]
....
I’m defining a struct and then casting parts of the buffer into the struct. The reason the procedure takes a slice is because the glb is embeded into a b3dm file, parsed in a similar way
load_b3dm :: proc(path: string) -> (mesh: TileMesh, err: B3DM_Error) {
Header :: struct {
magic, version, byte_len: u32,
feature_table_json_len, feature_table_bin_len: u32,
batch_table_json_len, batch_table_bin_len: u32,
}
Feature_Table :: struct { RTC_CENTER: [3]f64 }
data := os.read_entire_file_or_err(path) or_return
if len(data) < size_of(Header) { return mesh, .File_Too_Small }
h := cast(^Header)raw_data(data)
if h.magic != 1835283298 { return mesh, .Bad_File }
if h.version != 1 { return mesh, .Unsupported_Feature }
if h.byte_len != u32(len(data)) { return mesh, .Bad_File }
if h.feature_table_json_len == 0 { return mesh, .Unsupported_Feature }
if h.feature_table_bin_len != 0 { return mesh, .Unsupported_Feature }
if h.batch_table_json_len != 0 { return mesh, .Unsupported_Feature }
if h.batch_table_bin_len != 0 { return mesh, .Unsupported_Feature }
ft: Feature_Table
json.unmarshal(data[size_of(Header):][:h.feature_table_json_len], &ft) or_return
mesh.rtc_center = ft.RTC_CENTER
mesh.mesh = load_glb(data[size_of(Header) + h.feature_table_json_len:]) or_return
delete(data)
return
}