summaryrefslogtreecommitdiff
path: root/src/rendering/gltf.zig
diff options
context:
space:
mode:
authorLorenzo Torres <torres@sideros.org>2025-03-24 19:40:35 +0100
committerLorenzo Torres <torres@sideros.org>2025-03-24 19:40:35 +0100
commit56559a93868f303bcd4c9e3d0a0891f084672386 (patch)
treed2dafc7303567685a60abefc6c92aec75c9c758e /src/rendering/gltf.zig
parent7660bc09bc3787da09e8e4e83a03575e8078d330 (diff)
implemented glTF loading
Diffstat (limited to 'src/rendering/gltf.zig')
-rw-r--r--src/rendering/gltf.zig160
1 files changed, 155 insertions, 5 deletions
diff --git a/src/rendering/gltf.zig b/src/rendering/gltf.zig
index 614ee25..888191d 100644
--- a/src/rendering/gltf.zig
+++ b/src/rendering/gltf.zig
@@ -2,15 +2,165 @@ const std = @import("std");
const mesh = @import("mesh.zig");
const Allocator = std.mem.Allocator;
-pub const Model = packed struct {
+pub const Model = struct {
+ const Asset = struct {
+ version: []u8,
+ generator: ?[]u8 = null,
+ copyright: ?[]u8 = null,
+ };
+ const Buffer = struct {
+ byteLength: usize,
+ uri: ?[]u8 = null,
+ };
+ const BufferView = struct {
+ buffer: usize,
+ byteLength: usize,
+ byteOffset: usize,
+ byteStride: ?usize = null,
+ target: ?usize = null,
+ };
+ const Node = struct {
+ name: []u8,
+ mesh: ?usize = null,
+ weights: ?[]f64 = null,
+ children: ?[]usize = null,
+ rotation: ?[4]f64 = null,
+ scale: ?[3]f64 = null,
+ translation: ?[3]f64 = null,
+ camera: ?usize = null,
+ matrix: ?[16]usize = null,
+ };
+ const Accessor = struct {
+ bufferView: usize,
+ byteOffset: ?usize = null,
+ componentType: usize,
+ count: usize,
+ type: []u8,
+ max: ?[]f64 = null,
+ min: ?[]f64 = null,
+ };
+ const Primitive = struct {
+ const Attributes = struct {
+ NORMAL: ?usize = null,
+ POSITION: ?usize = null,
+ TANGENT: ?usize = null,
+ TEXCOORD_0: ?usize = null,
+ TEXCOORD_1: ?usize = null,
+ COLOR_0: ?usize = null,
+ JOINTS_0: ?usize = null,
+ WEIGHTS_0: ?usize = null,
+ };
+
+ attributes: ?Attributes = null,
+ indices: ?usize = null,
+ material: ?usize = null,
+ mode: ?usize = null,
+ };
+ const Mesh = struct {
+ name: ?[]u8 = null,
+ primitives: ?[]Primitive = null,
+ weights: ?[]f64 = null,
+ };
+ const Skin = struct {
+ inverseBindMatrices: usize,
+ joints: []usize,
+ skeleton: usize,
+ };
+ const Texture = struct {
+ sampler: usize,
+ source: usize,
+ };
+ const Image = struct {
+ uri: ?[]u8 = null,
+ bufferView: ?usize = null,
+ mimeType: ?[]u8 = null,
+ };
+ const Material = struct {
+ const Pbr = struct {
+ baseColorFactor: ?[4]f64 = null,
+ baseColorTexture: ?struct {
+ index: usize,
+ texCoord: usize,
+ } = null,
+ metallicFactor: ?f64 = null,
+ roughnessFactor: ?f64 = null,
+ };
+ name: ?[]u8 = null,
+ pbrMetallicRoughness: Pbr,
+ doubleSided: bool,
+ };
+ const Scene = struct {
+ nodes: ?[]usize = null,
+ name: ?[]u8 = null,
+ };
+
const Chunk = packed struct {
+ const offset = Header.offset + 8;
length: u32,
- ty: u32,
+ type: u32,
+ };
- },
- header: packed struct {
+ const JsonChunk = struct {
+ asset: Asset,
+ scene: usize,
+ scenes: ?[]Scene = null,
+ nodes: ?[]Node = null,
+ materials: ?[]Material = null,
+ meshes: ?[]Mesh = null,
+ accessors: ?[]Accessor = null,
+ bufferViews: ?[]BufferView = null,
+ buffers: ?[]Buffer = null,
+ };
+
+ const Header = packed struct {
+ const offset = 12;
magic: u32,
version: u32,
length: u32,
- },
+ };
+
+ const Binary = struct {
+ data: []u8,
+ const Vec3 = [3]f32;
+
+ pub fn readU16(self: Binary, allocator: Allocator, view: BufferView, count: usize) ![]u16 {
+ const data = self.data[view.byteOffset .. view.byteOffset + view.byteLength];
+ const scalars = try allocator.alloc(u16, count);
+
+ var j: usize = 0;
+ for (0..data.len / 2) |i| {
+ scalars[i] = std.mem.bytesAsValue(u16, data[j .. j + 1]).*;
+ j += 2;
+ }
+
+ return scalars;
+ }
+
+ pub fn readVec3(self: Binary, allocator: Allocator, view: BufferView, count: usize) ![]Vec3 {
+ const data = self.data[view.byteOffset .. view.byteOffset + view.byteLength];
+ const vectors = try allocator.alloc(Vec3, count);
+
+ for (0..count) |i| {
+ vectors[i] = std.mem.bytesAsValue(Vec3, data[(@sizeOf(Vec3) * i) .. (@sizeOf(Vec3) * i) + @sizeOf(Vec3)]).*;
+ }
+
+ return vectors;
+ }
+ };
};
+
+pub fn parseFile(allocator: Allocator, name: []const u8) !struct { vertices: [][3]f32, indices: []u16 } {
+ const file = try std.fs.cwd().openFile(name, .{});
+ const all = try file.readToEndAlloc(allocator, 1_000_000);
+ const json_chunk = std.mem.bytesAsValue(Model.Chunk, all[Model.Header.offset..]);
+
+ const data = (try std.json.parseFromSlice(Model.JsonChunk, allocator, @constCast(all[Model.Chunk.offset .. Model.Chunk.offset + json_chunk.length]), .{ .ignore_unknown_fields = true })).value;
+ const binary = Model.Binary{ .data = all[Model.Chunk.offset + json_chunk.length + 8 ..] };
+
+ const vertices = try binary.readVec3(allocator, data.bufferViews.?[data.meshes.?[0].primitives.?[0].attributes.?.POSITION.?], 24);
+ const indices = try binary.readU16(allocator, data.bufferViews.?[data.meshes.?[0].primitives.?[0].indices.?], 36);
+ std.debug.print("vertices: {any}\n", .{vertices});
+ std.debug.print("indices: {any}\n", .{indices});
+
+ return .{ .vertices = vertices, .indices = indices };
+}