commit dd54785a418716cb14026d20e4089d4da1690a8a
parent 520f7e4d8ff0e3eee977a6c32d3a37e1b499338f
Author: Christian Ermann <christianermann@gmail.com>
Date: Fri, 6 Dec 2024 16:22:18 -0800
Add transforms
Diffstat:
M | src/main.zig | | | 91 | ++++++++++++++++++++++++++++++++++++++++++++++++------------------------------- |
A | src/transform.zig | | | 29 | +++++++++++++++++++++++++++++ |
2 files changed, 84 insertions(+), 36 deletions(-)
diff --git a/src/main.zig b/src/main.zig
@@ -16,6 +16,7 @@ const Mesh = @import("mesh.zig");
const Camera = @import("camera.zig");
const input = @import("input.zig");
+const Transform = @import("transform.zig");
const load_obj = @import("load_obj.zig");
@@ -383,8 +384,7 @@ pub const MeshBufferOptions = struct {
};
pub const MeshOptions = struct {
- scale: f32 = 1.0,
- offset: f32x3 = .{ 0, 0, 0 },
+ transform: *Transform,
data: *const Mesh,
};
@@ -477,6 +477,12 @@ pub const MeshBuffer = struct {
.{ .indirect = true, .copy_dst = true },
false,
),
+ .lines_instances = Buffer(MeshInstanceData).init(
+ options.n_meshes,
+ device,
+ .{ .storage = true, .copy_dst = true },
+ false,
+ ),
.meshes = std.ArrayList(RenderMesh).init(options.allocator),
.lines = std.ArrayList(RenderLines).init(options.allocator),
};
@@ -486,6 +492,7 @@ pub const MeshBuffer = struct {
self: *MeshBuffer,
positions: []const f32x4,
indices: []const u32,
+ transform: *Transform,
) !*RenderLines {
const num_vertices = positions.len;
const num_indices = indices.len;
@@ -493,7 +500,7 @@ pub const MeshBuffer = struct {
const offset_p = try self.positions.allocWrite(positions, self.queue);
const offset_i = try self.indices.allocWrite(indices, self.queue);
- const instance_id = self.indirect.count();
+ const instance_id = self.lines_indirect.count();
const indirect_args = [_][5]u32{.{
@intCast(num_indices),
1,
@@ -506,8 +513,14 @@ pub const MeshBuffer = struct {
const lines = RenderLines{
.num_vertices = num_vertices,
.num_indices = num_indices,
+ .transform = transform,
};
+ const instances = [_]MeshInstanceData{
+ lines.instanceData(),
+ };
+ _ = try self.lines_instances.allocWrite(&instances, self.queue);
+
try self.lines.append(lines);
return &self.lines.items[0];
}
@@ -536,8 +549,7 @@ pub const MeshBuffer = struct {
const mesh = RenderMesh{
.num_vertices = num_vertices,
.num_indices = num_indices,
- .scale = options.scale,
- .offset = options.offset,
+ .transform = options.transform,
};
const instances = [_]MeshInstanceData{
@@ -602,34 +614,39 @@ pub const MeshBuffer = struct {
mesh.dirty = false;
}
}
+
+ pub fn updateLines(self: *MeshBuffer) void {
+ for (self.lines.items, 0..) |*line, i| {
+ if (!line.dirty) {
+ continue;
+ }
+ const instances = [_]MeshInstanceData{line.instanceData()};
+ self.lines_instances.write(&instances, self.queue, @intCast(i));
+ line.dirty = false;
+ }
+ }
};
pub const RenderLines = struct {
num_vertices: usize,
num_indices: usize,
- scale: f32 = 1.0,
- offset: f32x3 = .{ 0.0, 0.0, 0.0 },
+ transform: *Transform,
dirty: bool = false,
- pub fn instanceData(self: *const RenderLines) InstanceData {
- return InstanceData{
- .model_matrix = .{
- .{ self.scale, 0, 0, 0 },
- .{ 0, self.scale, 0, 0 },
- .{ 0, 0, self.scale, 0 },
- .{ self.offset[0], self.offset[1], self.offset[2], 1 },
- },
+ pub fn instanceData(self: *const RenderLines) MeshInstanceData {
+ return MeshInstanceData{
+ .model_matrix = self.transform.matrix(),
.material = undefined,
};
}
pub fn setScale(self: *RenderMesh, scale: f32) void {
- self.scale = scale;
+ self.transform.scale = .{ scale, scale, scale };
self.dirty = true;
}
pub fn setOffset(self: *RenderMesh, offset: f32x3) void {
- self.offset = offset;
+ self.transform.offset = offset;
self.dirty = true;
}
};
@@ -637,30 +654,24 @@ pub const RenderLines = struct {
pub const RenderMesh = struct {
num_vertices: usize,
num_indices: usize,
- scale: f32 = 1.0,
- offset: f32x3 = .{ 0.0, 0.0, 0.0 },
+ transform: *Transform,
material: Material = undefined,
dirty: bool = false,
- pub fn instanceData(self: *const RenderMesh) InstanceData {
- return InstanceData{
- .model_matrix = .{
- .{ self.scale, 0, 0, 0 },
- .{ 0, self.scale, 0, 0 },
- .{ 0, 0, self.scale, 0 },
- .{ self.offset[0], self.offset[1], self.offset[2], 1 },
- },
+ pub fn instanceData(self: *const RenderMesh) MeshInstanceData {
+ return MeshInstanceData{
+ .model_matrix = self.transform.matrix(),
.material = self.material,
};
}
pub fn setScale(self: *RenderMesh, scale: f32) void {
- self.scale = scale;
+ self.transform.scale = .{ scale, scale, scale };
self.dirty = true;
}
pub fn setOffset(self: *RenderMesh, offset: f32x3) void {
- self.offset = offset;
+ self.transform.offset = offset;
self.dirty = true;
}
@@ -729,22 +740,23 @@ pub fn main() !void {
const cbunny_mesh = try buildClusters(allocator, &bunny_mesh, 64, 126);
std.log.info("num clusters: {}", .{cluster_mesh.descriptors.?.len});
+ var transform_1 = Transform{};
+ var transform_2 = Transform{};
+
var render_mesh = try mesh_buffer.initMesh(&.{
.data = &cluster_mesh,
- .scale = 1,
- .offset = .{ 0, 0, 0 },
+ .transform = &transform_1,
}, allocator);
_ = try mesh_buffer.initMesh(&.{
.data = &cbunny_mesh,
- .scale = 1,
- .offset = .{ 0, 0, 0 },
+ .transform = &transform_2,
}, allocator);
const corners = mesh.bboxVertices();
- const indices = Mesh.bboxIndices();
+ const bbox_indices = Mesh.bboxIndices();
- _ = try mesh_buffer.initLines(&corners, &indices);
+ var lines = try mesh_buffer.initLines(&corners, &bbox_indices, &transform_1);
var rp = try MeshRenderPipeline.init(&app, &mesh_buffer, &textures, "shaders/mesh_clusters.wgsl");
@@ -753,7 +765,7 @@ pub fn main() !void {
.{
.positions = &mesh_buffer.positions,
.indices = &mesh_buffer.indices,
- .instances = &mesh_buffer.instances,
+ .instances = &mesh_buffer.lines_instances,
.indirect = &mesh_buffer.lines_indirect,
},
"shaders/lines.wgsl",
@@ -807,6 +819,13 @@ pub fn main() !void {
camera.invProj(&skybox_uniform.inv_proj);
app.queue.writeBuffer(skybox.uniform_buffer, 0, &[1]SkyBoxRenderPipeline.UniformData{skybox_uniform});
+ transform_1.translate(.{ 0.01, 0, 0 });
+ render_mesh.dirty = true;
+ lines.dirty = true;
+
+ mesh_buffer.updateMeshes();
+ mesh_buffer.updateLines();
+
try app.frame(&passes);
}
}
diff --git a/src/transform.zig b/src/transform.zig
@@ -0,0 +1,29 @@
+const std = @import("std");
+const gpu = @import("mach_gpu");
+
+const f32x3 = @import("main.zig").f32x3;
+const mat4 = @import("main.zig").mat4;
+
+const Self = @This();
+
+scale: f32x3 = .{ 1, 1, 1 },
+offset: f32x3 = .{ 0, 0, 0 },
+dirty: bool = false,
+
+pub fn dirty(self: *const Self) bool {
+ return self.dirty;
+}
+
+pub fn matrix(self: *const Self) mat4 {
+ return .{
+ .{ self.scale[0], 0, 0, 0 },
+ .{ 0, self.scale[1], 0, 0 },
+ .{ 0, 0, self.scale[2], 0 },
+ .{ self.offset[0], self.offset[1], self.offset[2], 1 },
+ };
+}
+
+pub fn translate(self: *Self, translation: f32x3) void {
+ self.offset += translation;
+ self.dirty = true;
+}