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 }