summaryrefslogtreecommitdiff
path: root/src/renderer/gltf.zig
diff options
context:
space:
mode:
authorLorenzo Torres <torres@sideros.org>2025-03-27 21:42:46 +0100
committerLorenzo Torres <torres@sideros.org>2025-03-27 21:42:46 +0100
commit1730f1e2980bfa2819c541d9b8a3bc0301b8334e (patch)
treeb4acfaf7fbd7d6f3344155c251c1d1b1d6f7a431 /src/renderer/gltf.zig
parent09691ec4d93cda6ab31d28d6e478257209fe625e (diff)
Made Renderer a separate module
Diffstat (limited to 'src/renderer/gltf.zig')
-rw-r--r--src/renderer/gltf.zig164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/renderer/gltf.zig b/src/renderer/gltf.zig
new file mode 100644
index 0000000..e65ec85
--- /dev/null
+++ b/src/renderer/gltf.zig
@@ -0,0 +1,164 @@
+const std = @import("std");
+const Mesh = @import("Mesh.zig");
+const Allocator = std.mem.Allocator;
+
+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,
+ type: u32,
+ };
+
+ const JsonChunk = struct {
+ asset: Asset,
+ scene: usize,
+ scenes: ?[]Scene = null,
+ nodes: ?[]Node = null,
+ materials: ?[]Material = null,
+ meshes: ?[]Model.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.?], data.accessors.?[data.meshes.?[0].primitives.?[0].attributes.?.POSITION.?].count);
+ const indices = try binary.readU16(allocator, data.bufferViews.?[data.meshes.?[0].primitives.?[0].indices.?], data.accessors.?[data.meshes.?[0].primitives.?[0].indices.?].count);
+
+ return .{ .vertices = vertices, .indices = indices };
+}