render-zig

A 3D rendering engine written in Zig
git clone git://git.christianermann.dev/render-zig
Log | Files | Refs

commit 04d09de0b45d9d57e623811aa525fd7ad9f0aca2
parent e8c54fdd890cb1cd5da91b2de598de228d03a766
Author: Christian Ermann <christianermann@gmail.com>
Date:   Sun,  8 Dec 2024 17:33:28 -0800

Add cube

Diffstat:
Asrc/cube.zig | 139+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/main.zig | 10++++++++++
2 files changed, 149 insertions(+), 0 deletions(-)

diff --git a/src/cube.zig b/src/cube.zig @@ -0,0 +1,139 @@ +const std = @import("std"); + +const Mesh = @import("mesh.zig"); + +const f32x3 = @Vector(3, f32); +const f32x4 = @Vector(4, f32); + +pub fn generateCube(n_subdivisions: u32, allocator: std.mem.Allocator) !Mesh { + var positions = std.ArrayList(f32x4).init(allocator); + var normals = std.ArrayList(f32x3).init(allocator); + var tex_coords = std.ArrayList(f32x3).init(allocator); + defer positions.deinit(); + defer normals.deinit(); + defer tex_coords.deinit(); + + try generateFace(&positions, &normals, &tex_coords, n_subdivisions, .{ + .u_axis = 0, + .v_axis = 1, + .w_axis = 2, + .u_dir = 1, + .v_dir = 1, + .w_dir = 1, + }); + try generateFace(&positions, &normals, &tex_coords, n_subdivisions, .{ + .u_axis = 0, + .v_axis = 1, + .w_axis = 2, + .u_dir = -1, + .v_dir = 1, + .w_dir = -1, + }); + try generateFace(&positions, &normals, &tex_coords, n_subdivisions, .{ + .u_axis = 2, + .v_axis = 1, + .w_axis = 0, + .u_dir = -1, + .v_dir = 1, + .w_dir = 1, + }); + try generateFace(&positions, &normals, &tex_coords, n_subdivisions, .{ + .u_axis = 2, + .v_axis = 1, + .w_axis = 0, + .u_dir = 1, + .v_dir = 1, + .w_dir = -1, + }); + try generateFace(&positions, &normals, &tex_coords, n_subdivisions, .{ + .u_axis = 0, + .v_axis = 2, + .w_axis = 1, + .u_dir = 1, + .v_dir = 1, + .w_dir = -1, + }); + try generateFace(&positions, &normals, &tex_coords, n_subdivisions, .{ + .u_axis = 0, + .v_axis = 2, + .w_axis = 1, + .u_dir = 1, + .v_dir = -1, + .w_dir = 1, + }); + + var indices = std.ArrayList(u32).init(allocator); + defer indices.deinit(); + var offset: u32 = 0; + for (0..6) |_| { + offset += try generateFaceIndices(&indices, n_subdivisions, offset); + } + + const n_vertices: u32 = @intCast(positions.items.len); + var mesh = Mesh{ + .positions = try positions.toOwnedSlice(), + .normals = try normals.toOwnedSlice(), + .tex_coords = try tex_coords.toOwnedSlice(), + .indices = try indices.toOwnedSlice(), + .tangents = try allocator.alloc(f32x3, n_vertices), + .bitangents = try allocator.alloc(f32x3, n_vertices), + }; + + try mesh.tangentsAndBitangents(allocator); + return mesh; +} + +const FaceOptions = struct { + u_axis: u32, + v_axis: u32, + w_axis: u32, + u_dir: f32, + v_dir: f32, + w_dir: f32, +}; + +fn generateFace( + positions: *std.ArrayList(f32x4), + normals: *std.ArrayList(f32x3), + tex_coords: *std.ArrayList(f32x3), + n_subdivisions: u32, + face_options: FaceOptions, +) !void { + for (0..n_subdivisions + 2) |i| { + const v = @as(f32, @floatFromInt(i)) / @as(f32, @floatFromInt(n_subdivisions + 1)); + for (0..n_subdivisions + 2) |j| { + const u = @as(f32, @floatFromInt(j)) / @as(f32, @floatFromInt(n_subdivisions + 1)); + var position = f32x4{ 0, 0, 0, 1 }; + position[face_options.u_axis] = (u - 0.5) * face_options.u_dir; + position[face_options.v_axis] = (v - 0.5) * face_options.v_dir; + position[face_options.w_axis] = 0.5 * face_options.w_dir; + var normal = f32x3{ 0, 0, 0 }; + normal[face_options.w_axis] = face_options.w_dir; + const tex_coord = f32x3{ u, v, 0.0 }; + + try positions.append(position); + try normals.append(normal); + try tex_coords.append(tex_coord); + } + } +} + +fn generateFaceIndices( + indices: *std.ArrayList(u32), + n_subdivisions: u32, + offset: u32, +) !u32 { + for (0..n_subdivisions + 1) |i| { + for (0..n_subdivisions + 1) |j| { + const a: u32 = @intCast(i * (n_subdivisions + 2) + j + offset); + const b: u32 = @intCast((i + 1) * (n_subdivisions + 2) + j + offset); + try indices.append(a); + try indices.append(a + 1); + try indices.append(b + 1); + try indices.append(a); + try indices.append(b + 1); + try indices.append(b); + } + } + return (n_subdivisions + 2) * (n_subdivisions + 2); +} diff --git a/src/main.zig b/src/main.zig @@ -431,6 +431,9 @@ pub fn main() !void { const generateUVSphere = @import("uvsphere.zig").generateUVSphere; const sphere_mesh = try generateUVSphere(16, 16, allocator); + const generateCube = @import("cube.zig").generateCube; + const cube_mesh = try generateCube(1, allocator); + var rp = try MeshRenderPipeline.init( &app, .{ @@ -462,6 +465,7 @@ pub fn main() !void { var transform_1 = Transform{}; var transform_2 = Transform{}; var transform_3 = Transform{ .offset = .{ 3, 3, 3 } }; + var transform_4 = Transform{ .offset = .{ -3, -3, 0 } }; var render_mesh = try render_data.addMesh( &transform_1, @@ -481,6 +485,12 @@ pub fn main() !void { allocator, ); + _ = try render_data.addMesh( + &transform_4, + &cube_mesh, + allocator, + ); + const corners = mesh.bboxVertices(); const bbox_indices = Mesh.bboxIndices();