render-zig

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

cube.zig (4213B)


      1 const std = @import("std");
      2 
      3 const Mesh = @import("mesh.zig");
      4 
      5 const f32x3 = @Vector(3, f32);
      6 const f32x4 = @Vector(4, f32);
      7 
      8 pub fn generateCube(n_subdivisions: u32, allocator: std.mem.Allocator) !Mesh {
      9     var positions = std.ArrayList(f32x4).init(allocator);
     10     var normals = std.ArrayList(f32x3).init(allocator);
     11     var tex_coords = std.ArrayList(f32x3).init(allocator);
     12     defer positions.deinit();
     13     defer normals.deinit();
     14     defer tex_coords.deinit();
     15 
     16     try generateFace(&positions, &normals, &tex_coords, n_subdivisions, .{
     17         .u_axis = 0,
     18         .v_axis = 1,
     19         .w_axis = 2,
     20         .u_dir = 1,
     21         .v_dir = 1,
     22         .w_dir = 1,
     23     });
     24     try generateFace(&positions, &normals, &tex_coords, n_subdivisions, .{
     25         .u_axis = 0,
     26         .v_axis = 1,
     27         .w_axis = 2,
     28         .u_dir = -1,
     29         .v_dir = 1,
     30         .w_dir = -1,
     31     });
     32     try generateFace(&positions, &normals, &tex_coords, n_subdivisions, .{
     33         .u_axis = 2,
     34         .v_axis = 1,
     35         .w_axis = 0,
     36         .u_dir = -1,
     37         .v_dir = 1,
     38         .w_dir = 1,
     39     });
     40     try generateFace(&positions, &normals, &tex_coords, n_subdivisions, .{
     41         .u_axis = 2,
     42         .v_axis = 1,
     43         .w_axis = 0,
     44         .u_dir = 1,
     45         .v_dir = 1,
     46         .w_dir = -1,
     47     });
     48     try generateFace(&positions, &normals, &tex_coords, n_subdivisions, .{
     49         .u_axis = 0,
     50         .v_axis = 2,
     51         .w_axis = 1,
     52         .u_dir = 1,
     53         .v_dir = 1,
     54         .w_dir = -1,
     55     });
     56     try generateFace(&positions, &normals, &tex_coords, n_subdivisions, .{
     57         .u_axis = 0,
     58         .v_axis = 2,
     59         .w_axis = 1,
     60         .u_dir = 1,
     61         .v_dir = -1,
     62         .w_dir = 1,
     63     });
     64 
     65     var indices = std.ArrayList(u32).init(allocator);
     66     defer indices.deinit();
     67     var offset: u32 = 0;
     68     for (0..6) |_| {
     69         offset += try generateFaceIndices(&indices, n_subdivisions, offset);
     70     }
     71 
     72     const n_vertices: u32 = @intCast(positions.items.len);
     73     var mesh = Mesh{
     74         .positions = try positions.toOwnedSlice(),
     75         .normals = try normals.toOwnedSlice(),
     76         .tex_coords = try tex_coords.toOwnedSlice(),
     77         .indices = try indices.toOwnedSlice(),
     78         .tangents = try allocator.alloc(f32x3, n_vertices),
     79         .bitangents = try allocator.alloc(f32x3, n_vertices),
     80     };
     81 
     82     try mesh.tangentsAndBitangents(allocator);
     83     return mesh;
     84 }
     85 
     86 const FaceOptions = struct {
     87     u_axis: u32,
     88     v_axis: u32,
     89     w_axis: u32,
     90     u_dir: f32,
     91     v_dir: f32,
     92     w_dir: f32,
     93 };
     94 
     95 fn generateFace(
     96     positions: *std.ArrayList(f32x4),
     97     normals: *std.ArrayList(f32x3),
     98     tex_coords: *std.ArrayList(f32x3),
     99     n_subdivisions: u32,
    100     face_options: FaceOptions,
    101 ) !void {
    102     for (0..n_subdivisions + 2) |i| {
    103         const v = @as(f32, @floatFromInt(i)) / @as(f32, @floatFromInt(n_subdivisions + 1));
    104         for (0..n_subdivisions + 2) |j| {
    105             const u = @as(f32, @floatFromInt(j)) / @as(f32, @floatFromInt(n_subdivisions + 1));
    106             var position = f32x4{ 0, 0, 0, 1 };
    107             position[face_options.u_axis] = (u - 0.5) * face_options.u_dir;
    108             position[face_options.v_axis] = (v - 0.5) * face_options.v_dir;
    109             position[face_options.w_axis] = 0.5 * face_options.w_dir;
    110             var normal = f32x3{ 0, 0, 0 };
    111             normal[face_options.w_axis] = face_options.w_dir;
    112             const tex_coord = f32x3{ u, v, 0.0 };
    113 
    114             try positions.append(position);
    115             try normals.append(normal);
    116             try tex_coords.append(tex_coord);
    117         }
    118     }
    119 }
    120 
    121 fn generateFaceIndices(
    122     indices: *std.ArrayList(u32),
    123     n_subdivisions: u32,
    124     offset: u32,
    125 ) !u32 {
    126     for (0..n_subdivisions + 1) |i| {
    127         for (0..n_subdivisions + 1) |j| {
    128             const a: u32 = @intCast(i * (n_subdivisions + 2) + j + offset);
    129             const b: u32 = @intCast((i + 1) * (n_subdivisions + 2) + j + offset);
    130             try indices.append(a);
    131             try indices.append(a + 1);
    132             try indices.append(b + 1);
    133             try indices.append(a);
    134             try indices.append(b + 1);
    135             try indices.append(b);
    136         }
    137     }
    138     return (n_subdivisions + 2) * (n_subdivisions + 2);
    139 }