Basic scene graph with inherited transforms

This commit is contained in:
sergeypdev 2024-02-23 22:04:46 +04:00
parent 756f4fa6f9
commit 59ccd86a5d
4 changed files with 55 additions and 9 deletions

View File

@ -142,7 +142,7 @@ export fn game_init(global_allocator: *std.mem.Allocator) void {
gl.viewport(0, 0, globals.g_init.width, globals.g_init.height);
_ = globals.g_mem.world.addEntity(.{
const light1 = globals.g_mem.world.addEntity(.{
.transform = .{ .pos = Vec3.new(1.8, 1, 0) },
.flags = .{ .point_light = true, .rotate = true },
.point_light = .{ .color_intensity = Vec4.new(1.0, 0.3, 0.1, 100.0), .radius = 0.1 },
@ -150,7 +150,8 @@ export fn game_init(global_allocator: *std.mem.Allocator) void {
});
_ = globals.g_mem.world.addEntity(.{
.transform = .{ .pos = Vec3.new(-2, 1, 0) },
.transform = .{ .pos = Vec3.new(-2, 0, 0) },
.parent = light1,
.flags = .{ .point_light = true, .rotate = true },
.point_light = .{
.color_intensity = Vec4.new(0.2, 0.5, 1.0, 100.0),
@ -371,11 +372,11 @@ export fn game_update() bool {
ent.rotate.rate * gmem.delta_time,
ent.rotate.axis,
).mulByVec4(Vec4.new(old_pos.x(), old_pos.y(), old_pos.z(), 1));
ent.transform.pos = Vec3.new(new_pos.x(), new_pos.y(), new_pos.z());
ent.transform.setPos(Vec3.new(new_pos.x(), new_pos.y(), new_pos.z()));
}
if (ent.flags.point_light) {
const pos = ent.transform.pos;
const pos = ent.globalMatrix(&gmem.world).extractTranslation();
var pos4 = Vec4.new(pos.x(), pos.y(), pos.z(), 1.0);
pos4 = gmem.render.camera.view_mat.mulByVec4(pos4);
@ -400,13 +401,13 @@ export fn game_update() bool {
gmem.render.draw(.{
.mesh = ent.mesh.handle,
.material = ent.mesh.material,
.transform = ent.transform.matrix(),
.transform = ent.globalMatrix(&gmem.world).*,
});
} else if (ent.flags.point_light) {
gmem.render.draw(.{
.mesh = a.Meshes.sphere,
.material = .{ .albedo = ent.point_light.color() },
.transform = ent.transform.matrix(),
.transform = ent.globalMatrix(&gmem.world).*,
});
}
}

View File

@ -44,9 +44,25 @@ pub const Entity = struct {
rot: Quat = Quat.identity(),
scale: Vec3 = Vec3.one(),
pub fn matrix(self: *Transform) Mat4 {
// TODO: cache
return Mat4.recompose(self.pos, self.rot, self.scale);
_local_dirty: bool = true,
_local: Mat4 = Mat4.identity(),
_global_dirty: bool = true,
_global: Mat4 = Mat4.identity(),
pub fn dirty(self: *Transform) void {
self._local_dirty = true;
self._global_dirty = true;
}
pub fn setPos(self: *Transform, new_pos: Vec3) void {
self.pos = new_pos;
self.dirty();
}
pub fn translate(self: *Transform, by: Vec3) void {
self.pos = self.pos.add(by);
self.dirty();
}
};
@ -75,10 +91,35 @@ pub const Entity = struct {
next: ?*Entity = null,
flags: Flags = .{},
parent: ?EntityHandle = null,
transform: Transform = .{},
mesh: Mesh = .{},
point_light: PointLight = .{},
rotate: Rotate = .{},
pub fn localMatrix(self: *Entity) *const Mat4 {
if (self.transform._local_dirty) {
self.transform._local = Mat4.recompose(self.transform.pos, self.transform.rot, self.transform.scale);
self.transform._local_dirty = false;
}
return &self.transform._local;
}
pub fn globalMatrix(self: *Entity, world: *World) *const Mat4 {
// TODO: think how to reduce pointer chasing
if (self.parent) |parent_ent| {
if (world.getEntity(parent_ent)) |parent| {
if (parent.transform._global_dirty or self.transform._global_dirty) {
self.transform._global = parent.globalMatrix(world).mul(self.localMatrix().*);
self.transform._global_dirty = false;
}
return &self.transform._global;
}
}
return self.localMatrix();
}
};
pub const EntityHandle = packed struct {

View File

@ -69,6 +69,7 @@ pub fn main() !void {
.Shader => try std.fs.Dir.copyFile(std.fs.cwd(), abs_input, output_dir, std.fs.path.basename(rel_input), .{}),
.ShaderProgram => try processShaderProgram(allocator, abs_input, output_dir),
.Texture => try processTexture(allocator, abs_input, output_dir, false),
.Scene => return error.NotImplemented,
}
const out_writer = std.io.getStdOut().writer();

View File

@ -1,6 +1,7 @@
const std = @import("std");
pub const AssetType = enum {
Scene,
Mesh,
Shader,
ShaderProgram,
@ -8,6 +9,7 @@ pub const AssetType = enum {
pub fn pluralName(self: AssetType) []const u8 {
return switch (self) {
.Scene => "Scenes",
.Mesh => "Meshes",
.Shader => "Shaders",
.ShaderProgram => "ShaderPrograms",
@ -17,6 +19,7 @@ pub const AssetType = enum {
pub fn ext(self: AssetType) []const u8 {
return switch (self) {
.Scene => "scn",
.Mesh => "mesh",
.Shader => "glsl",
.ShaderProgram => "prog",