Compare commits
1 Commits
main
...
feature/in
| Author | SHA1 | Date | |
|---|---|---|---|
| 302f96af3f |
@@ -7,39 +7,144 @@ const Mesh = @import("mesh.zig");
|
|||||||
const Shader = @import("shader.zig");
|
const Shader = @import("shader.zig");
|
||||||
const Tree = @import("../tree.zig").Tree;
|
const Tree = @import("../tree.zig").Tree;
|
||||||
|
|
||||||
|
pub const Animation = struct {
|
||||||
|
rotation: zm.Quat,
|
||||||
|
translation: zm.Mat,
|
||||||
|
};
|
||||||
|
|
||||||
pub const JointData = struct {
|
pub const JointData = struct {
|
||||||
mesh: Mesh,
|
mesh: Mesh,
|
||||||
translation: zm.Mat,
|
animated_transform: zm.Mat = zm.identity(),
|
||||||
rotation: zm.Quat,
|
local_bind_transform: zm.Mat,
|
||||||
|
inverse_bind_transform: zm.Mat = zm.identity(),
|
||||||
|
keyframes: [2]Animation,
|
||||||
|
count: usize,
|
||||||
|
|
||||||
|
var counter: usize = 0;
|
||||||
|
|
||||||
|
pub fn init(mesh: Mesh, translation: zm.Mat, rotation: zm.Quat, keyframes: [2]zm.Quat) JointData {
|
||||||
|
const res = JointData{
|
||||||
|
.mesh = mesh,
|
||||||
|
.local_bind_transform = zm.mul(
|
||||||
|
zm.quatToMat(rotation),
|
||||||
|
translation,
|
||||||
|
),
|
||||||
|
.count = counter,
|
||||||
|
.keyframes = .{
|
||||||
|
.{ .rotation = keyframes[0], .translation = translation },
|
||||||
|
.{ .rotation = keyframes[1], .translation = translation },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
counter += 1;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
data: Tree(JointData),
|
data: Tree(JointData),
|
||||||
|
animaton_duration: f32 = 1,
|
||||||
|
animaton_time: f32 = 0,
|
||||||
|
|
||||||
pub fn init(
|
pub fn init(data: Tree(JointData)) !@This() {
|
||||||
data: Tree(JointData),
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
) @This() {
|
defer arena.deinit();
|
||||||
|
const arena_allocator = arena.allocator();
|
||||||
|
|
||||||
|
var c_data = data;
|
||||||
|
|
||||||
|
var iter = try c_data.levelOrderIterator(arena_allocator);
|
||||||
|
|
||||||
|
while (iter.next()) |node| {
|
||||||
|
for (node.children.items) |*child| {
|
||||||
|
child.val.local_bind_transform = zm.mul(
|
||||||
|
child.val.local_bind_transform,
|
||||||
|
node.val.local_bind_transform,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
return .{ .data = data };
|
return .{ .data = data };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(self: *@This(), allocator: std.mem.Allocator, shader: Shader) !void {
|
pub fn draw(self: *@This(), shader: Shader) !void {
|
||||||
var iter = self.data.depthFirstIterator();
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
defer iter.deinit(allocator);
|
defer arena.deinit();
|
||||||
while (try iter.next(allocator)) |node| {
|
const allocator = arena.allocator();
|
||||||
const rotation = node.val.rotation;
|
|
||||||
// var current = node;
|
|
||||||
// while (current.parent) |parent| {
|
|
||||||
// rotation = zm.qmul(rotation, parent.val.rotation);
|
|
||||||
// current = parent;
|
|
||||||
// }
|
|
||||||
|
|
||||||
const model_matrix = zm.mul(zm.quatToMat(rotation), node.val.translation);
|
var iter = try self.data.preOrderIterator(allocator);
|
||||||
const normal_matrix = zm.transpose(zm.inverse(model_matrix));
|
defer iter.deinit(allocator);
|
||||||
|
|
||||||
|
while (iter.next()) |node| {
|
||||||
|
const model_matrix = zm.mul(
|
||||||
|
node.val.animated_transform,
|
||||||
|
node.val.local_bind_transform,
|
||||||
|
);
|
||||||
shader.updateUniformMatrix("u_model_matrix", &.{model_matrix});
|
shader.updateUniformMatrix("u_model_matrix", &.{model_matrix});
|
||||||
shader.updateUniformMatrix("u_normal_matrix", &.{normal_matrix});
|
shader.updateUniformMatrix("u_normal_matrix", &.{zm.transpose(zm.inverse(model_matrix))});
|
||||||
node.val.mesh.draw(shader);
|
node.val.mesh.draw(shader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn animate(self: *@This(), delta_time: f32) !void {
|
||||||
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const arena_allocator = arena.allocator();
|
||||||
|
|
||||||
|
var iter = try self.data.levelOrderIterator(arena_allocator);
|
||||||
|
|
||||||
|
self.animaton_time += delta_time;
|
||||||
|
|
||||||
|
if (self.animaton_time / self.animaton_duration < 1) {
|
||||||
|
while (iter.next()) |node| {
|
||||||
|
node.val.animated_transform = zm.mul(
|
||||||
|
zm.quatToMat(zm.slerp(
|
||||||
|
node.val.keyframes[0].rotation,
|
||||||
|
node.val.keyframes[1].rotation,
|
||||||
|
self.animaton_time / self.animaton_duration,
|
||||||
|
)),
|
||||||
|
node.val.keyframes[0].translation,
|
||||||
|
);
|
||||||
|
|
||||||
|
for (node.children.items) |*child| {
|
||||||
|
child.val.animated_transform = zm.mul(
|
||||||
|
node.val.animated_transform,
|
||||||
|
child.val.animated_transform,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (self.animaton_time / self.animaton_duration < 2) {
|
||||||
|
while (iter.next()) |node| {
|
||||||
|
node.val.animated_transform = zm.mul(
|
||||||
|
zm.quatToMat(zm.slerp(
|
||||||
|
node.val.keyframes[1].rotation,
|
||||||
|
node.val.keyframes[0].rotation,
|
||||||
|
self.animaton_time / self.animaton_duration - 1,
|
||||||
|
)),
|
||||||
|
node.val.keyframes[1].translation,
|
||||||
|
);
|
||||||
|
|
||||||
|
for (node.children.items) |*child| {
|
||||||
|
child.val.animated_transform = zm.mul(
|
||||||
|
child.val.animated_transform,
|
||||||
|
node.val.animated_transform,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.animaton_time = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
iter = try self.data.levelOrderIterator(arena_allocator);
|
||||||
|
|
||||||
|
// while (iter.next()) |node| {
|
||||||
|
// for (node.children.items) |*child| {
|
||||||
|
// child.val.animated_transform = zm.mul(
|
||||||
|
// node.val.animated_transform,
|
||||||
|
// child.val.animated_transform,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *@This(), allocator: std.mem.Allocator) !void {
|
pub fn deinit(self: *@This(), allocator: std.mem.Allocator) !void {
|
||||||
try self.data.deinit(allocator);
|
try self.data.deinit(allocator);
|
||||||
}
|
}
|
||||||
|
|||||||
285
src/main.zig
285
src/main.zig
@@ -133,7 +133,6 @@ pub fn main() !void {
|
|||||||
var previous_time = glfw_helper.getTime();
|
var previous_time = glfw_helper.getTime();
|
||||||
var current_time: f64 = 0;
|
var current_time: f64 = 0;
|
||||||
var delta_time: f64 = undefined;
|
var delta_time: f64 = undefined;
|
||||||
// var frame_counter: u16 = 0;
|
|
||||||
|
|
||||||
// OpenGL setup
|
// OpenGL setup
|
||||||
const clear_color = FloatColor.sky_blue;
|
const clear_color = FloatColor.sky_blue;
|
||||||
@@ -162,8 +161,8 @@ pub fn main() !void {
|
|||||||
model_shader.updateUniformMatrix("u_normal_matrix", &.{zm.identity()});
|
model_shader.updateUniformMatrix("u_normal_matrix", &.{zm.identity()});
|
||||||
floor.draw(model_shader);
|
floor.draw(model_shader);
|
||||||
|
|
||||||
// animateRobot(&frame_counter, robot);
|
try robot.animate(@floatCast(delta_time));
|
||||||
try robot.draw(allocator, model_shader);
|
try robot.draw(model_shader);
|
||||||
},
|
},
|
||||||
.fish => {},
|
.fish => {},
|
||||||
}
|
}
|
||||||
@@ -204,125 +203,207 @@ fn initFloor(textures: ?[]const Texture) Mesh {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn initRobot(allocator: std.mem.Allocator, textures: ?[]const Texture) !Model {
|
fn initRobot(allocator: std.mem.Allocator, textures: ?[]const Texture) !Model {
|
||||||
// var meshes = try std.ArrayList(Mesh).initCapacity(allocator, 14);
|
|
||||||
// var translations = try std.ArrayList(Mat).initCapacity(allocator, 14);
|
|
||||||
|
|
||||||
var shape = Shape.initCube();
|
var shape = Shape.initCube();
|
||||||
defer shape.deinit();
|
defer shape.deinit();
|
||||||
|
|
||||||
shape.unweld();
|
shape.unweld();
|
||||||
shape.computeNormals();
|
shape.computeNormals();
|
||||||
shape.translate(-0.5, -1, -0.5);
|
shape.translate(-0.5, -1, -0.5);
|
||||||
// shape.rotate(std.math.degreesToRadians(180), 1, 0, 0);
|
|
||||||
|
|
||||||
// var foot = shape.clone();
|
|
||||||
// defer foot.deinit();
|
|
||||||
// foot.scale(0.1, 0.025, 0.15);
|
|
||||||
// meshes.appendNTimesAssumeCapacity(Mesh.initShape(foot, textures, .triangles), 2);
|
|
||||||
// translations.appendAssumeCapacity(zm.translation(-0.07, 0.025, 0));
|
|
||||||
// translations.appendAssumeCapacity(zm.translation(0.07, 0.025, 0));
|
|
||||||
|
|
||||||
// var leg = shape.clone();
|
|
||||||
// defer leg.deinit();
|
|
||||||
// leg.scale(0.08, 0.2, 0.08);
|
|
||||||
// meshes.appendNTimesAssumeCapacity(Mesh.initShape(leg, textures, .triangles), 4);
|
|
||||||
// translations.appendAssumeCapacity(zm.translation(-0.07, 0.225, 0));
|
|
||||||
// translations.appendAssumeCapacity(zm.translation(0.07, 0.225, 0));
|
|
||||||
// translations.appendAssumeCapacity(zm.translation(-0.07, 0.425, 0));
|
|
||||||
// translations.appendAssumeCapacity(zm.translation(0.07, 0.425, 0));
|
|
||||||
|
|
||||||
// var arm = shape.clone();
|
|
||||||
// defer arm.deinit();
|
|
||||||
// arm.scale(0.08, 0.2, 0.08);
|
|
||||||
// meshes.appendNTimesAssumeCapacity(Mesh.initShape(arm, textures, .triangles), 4);
|
|
||||||
// translations.appendAssumeCapacity(zm.translation(-0.3 / 2.0 - 0.04, 0.225 + 0.4, 0));
|
|
||||||
// translations.appendAssumeCapacity(zm.translation(0.3 / 2.0 + 0.04, 0.225 + 0.4, 0));
|
|
||||||
// translations.appendAssumeCapacity(zm.translation(-0.3 / 2.0 - 0.04, 0.425 + 0.4, 0));
|
|
||||||
// translations.appendAssumeCapacity(zm.translation(0.3 / 2.0 + 0.04, 0.425 + 0.4, 0));
|
|
||||||
|
|
||||||
// var hand = shape.clone();
|
|
||||||
// defer hand.deinit();
|
|
||||||
// hand.scale(0.025, 0.08, 0.07);
|
|
||||||
// meshes.appendNTimesAssumeCapacity(Mesh.initShape(hand, textures, .triangles), 2);
|
|
||||||
// translations.appendAssumeCapacity(zm.translation(-0.3 / 2.0 - 0.04, 0.425, 0));
|
|
||||||
// translations.appendAssumeCapacity(zm.translation(0.3 / 2.0 + 0.04, 0.425, 0));
|
|
||||||
|
|
||||||
var chest = shape.clone();
|
var chest = shape.clone();
|
||||||
defer chest.deinit();
|
defer chest.deinit();
|
||||||
chest.scale(0.3, 0.4, 0.15);
|
chest.scale(0.3, 0.4, 0.15);
|
||||||
// meshes.appendAssumeCapacity(Mesh.initShape(chest, textures, .triangles));
|
|
||||||
// translations.appendAssumeCapacity(zm.translation(0, 0.425 + 0.4, 0));
|
|
||||||
|
|
||||||
var model_data = Tree(Model.JointData).init(
|
var model_data = Tree(Model.JointData).init(
|
||||||
.{
|
.init(
|
||||||
.mesh = Mesh.initShape(chest, textures, .triangles),
|
.initShape(chest, textures, .triangles),
|
||||||
.translation = zm.translation(0, 0.425 + 0.4, 0),
|
zm.translation(0, 0.825, 0),
|
||||||
.rotation = zm.qidentity(),
|
zm.qidentity(),
|
||||||
},
|
.{ zm.qidentity(), zm.qidentity() },
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
var head = shape.clone();
|
var head = shape.clone();
|
||||||
defer head.deinit();
|
defer head.deinit();
|
||||||
head.scale(0.1, 0.1, 0.1);
|
head.scale(0.1, 0.1, 0.1);
|
||||||
|
head.rotate(std.math.degreesToRadians(180), 1, 0, 0);
|
||||||
|
try model_data.root.append(
|
||||||
|
allocator,
|
||||||
|
.init(
|
||||||
|
.initShape(head, textures, .triangles),
|
||||||
|
zm.translation(0, 0, 0),
|
||||||
|
zm.qidentity(),
|
||||||
|
.{
|
||||||
|
zm.quatFromRollPitchYaw(0, -0.5, 0),
|
||||||
|
zm.quatFromRollPitchYaw(0, 0.5, 0),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
try model_data.root.append(allocator, .{
|
var arm = shape.clone();
|
||||||
.mesh = Mesh.initShape(head, textures, .triangles),
|
defer arm.deinit();
|
||||||
.translation = zm.translation(0, 0.425 + 0.4 + 0.1, 0),
|
arm.scale(0.08, 0.2, 0.08);
|
||||||
.rotation = zm.qidentity(),
|
var right_arm = try model_data.root.create(
|
||||||
});
|
allocator,
|
||||||
// meshes.appendAssumeCapacity(Mesh.initShape(head, textures, .triangles));
|
.init(
|
||||||
// translations.appendAssumeCapacity(zm.translation(0, 0.425 + 0.4 + 0.1, 0));
|
.initShape(arm, textures, .triangles),
|
||||||
|
zm.translation(-0.3 / 2.0 - 0.04, 0, 0),
|
||||||
|
zm.qidentity(),
|
||||||
|
.{
|
||||||
|
zm.quatFromRollPitchYaw(0.6, 0, 0),
|
||||||
|
zm.quatFromRollPitchYaw(-0.6, 0, 0),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
right_arm = try right_arm.create(
|
||||||
|
allocator,
|
||||||
|
.init(
|
||||||
|
.initShape(arm, textures, .triangles),
|
||||||
|
zm.translation(0, -0.2, 0),
|
||||||
|
zm.quatFromRollPitchYaw(-0.6, 0, 0),
|
||||||
|
.{
|
||||||
|
zm.quatFromRollPitchYaw(0.6, 0, 0),
|
||||||
|
zm.quatFromRollPitchYaw(-0.6, 0, 0),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
return Model.init(model_data);
|
var left_arm = try model_data.root.create(
|
||||||
|
allocator,
|
||||||
|
.init(
|
||||||
|
.initShape(arm, textures, .triangles),
|
||||||
|
zm.translation(0.3 / 2.0 + 0.04, 0, 0),
|
||||||
|
zm.qidentity(),
|
||||||
|
.{
|
||||||
|
zm.qidentity(),
|
||||||
|
zm.qidentity(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
left_arm = try left_arm.create(
|
||||||
|
allocator,
|
||||||
|
.init(
|
||||||
|
.initShape(arm, textures, .triangles),
|
||||||
|
zm.translation(0, -0.2, 0),
|
||||||
|
zm.qidentity(),
|
||||||
|
.{
|
||||||
|
zm.qidentity(),
|
||||||
|
zm.qidentity(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
var hand = shape.clone();
|
||||||
|
defer hand.deinit();
|
||||||
|
hand.scale(0.025, 0.08, 0.07);
|
||||||
|
try right_arm.append(
|
||||||
|
allocator,
|
||||||
|
.init(
|
||||||
|
.initShape(hand, textures, .triangles),
|
||||||
|
zm.translation(0, -0.2, 0),
|
||||||
|
zm.qidentity(),
|
||||||
|
.{
|
||||||
|
zm.qidentity(),
|
||||||
|
zm.qidentity(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
try left_arm.append(
|
||||||
|
allocator,
|
||||||
|
.init(
|
||||||
|
.initShape(hand, textures, .triangles),
|
||||||
|
zm.translation(0, -0.2, 0),
|
||||||
|
zm.qidentity(),
|
||||||
|
.{
|
||||||
|
zm.qidentity(),
|
||||||
|
zm.qidentity(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
var leg = shape.clone();
|
||||||
|
defer leg.deinit();
|
||||||
|
leg.scale(0.08, 0.2, 0.08);
|
||||||
|
var right_leg = try model_data.root.create(
|
||||||
|
allocator,
|
||||||
|
.init(
|
||||||
|
.initShape(leg, textures, .triangles),
|
||||||
|
zm.translation(-0.07, -0.4, 0),
|
||||||
|
zm.qidentity(),
|
||||||
|
.{
|
||||||
|
zm.qidentity(),
|
||||||
|
zm.qidentity(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
right_leg = try right_leg.create(
|
||||||
|
allocator,
|
||||||
|
.init(
|
||||||
|
.initShape(leg, textures, .triangles),
|
||||||
|
zm.translation(0, -0.2, 0),
|
||||||
|
zm.qidentity(),
|
||||||
|
.{
|
||||||
|
zm.qidentity(),
|
||||||
|
zm.qidentity(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
var left_leg = try model_data.root.create(
|
||||||
|
allocator,
|
||||||
|
.init(
|
||||||
|
.initShape(leg, textures, .triangles),
|
||||||
|
zm.translation(0.07, -0.4, 0),
|
||||||
|
zm.qidentity(),
|
||||||
|
.{
|
||||||
|
zm.qidentity(),
|
||||||
|
zm.qidentity(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
left_leg = try left_leg.create(
|
||||||
|
allocator,
|
||||||
|
.init(
|
||||||
|
.initShape(leg, textures, .triangles),
|
||||||
|
zm.translation(0, -0.2, 0),
|
||||||
|
zm.qidentity(),
|
||||||
|
.{
|
||||||
|
zm.qidentity(),
|
||||||
|
zm.qidentity(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
var foot = shape.clone();
|
||||||
|
defer foot.deinit();
|
||||||
|
foot.scale(0.1, 0.025, 0.15);
|
||||||
|
try right_leg.append(
|
||||||
|
allocator,
|
||||||
|
.init(
|
||||||
|
.initShape(foot, textures, .triangles),
|
||||||
|
zm.translation(0, -0.2, 0),
|
||||||
|
zm.qidentity(),
|
||||||
|
.{
|
||||||
|
zm.qidentity(),
|
||||||
|
zm.qidentity(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
try left_leg.append(
|
||||||
|
allocator,
|
||||||
|
.init(
|
||||||
|
.initShape(foot, textures, .triangles),
|
||||||
|
zm.translation(0, -0.2, 0),
|
||||||
|
zm.qidentity(),
|
||||||
|
.{
|
||||||
|
zm.qidentity(),
|
||||||
|
zm.qidentity(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return try Model.init(model_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn initRobot(allocator: std.mem.Allocator, textures: ?[]const Texture) Model {
|
|
||||||
// var shape = Shape.initCube();
|
|
||||||
// defer shape.deinit();
|
|
||||||
|
|
||||||
// shape.unweld();
|
|
||||||
// shape.computeNormals();
|
|
||||||
// shape.translate(-0.5, -1, -0.5);
|
|
||||||
|
|
||||||
// var chest = shape.clone();
|
|
||||||
// defer chest.deinit();
|
|
||||||
// chest.scale(0.3, 0.4, 0.15);
|
|
||||||
|
|
||||||
// var model_data = Tree(Model.JointData).init(.{
|
|
||||||
// .mesh = Mesh.initShape(chest, textures, .triangles),
|
|
||||||
// .translation = zm.translation(0, 0.425 + 0.4, 0),
|
|
||||||
// .rotation = zm.qidentity(),
|
|
||||||
// });
|
|
||||||
|
|
||||||
// var head = shape.clone();
|
|
||||||
// defer head.deinit();
|
|
||||||
// head.scale(0.1, 0.1, 0.1);
|
|
||||||
|
|
||||||
// try model_data.root.append(allocator, .{
|
|
||||||
// .mesh = Mesh.initShape(head, textures, .triangles),
|
|
||||||
// .translation = zm.translation(0, 0.425 + 0.4 + 0.1, 0),
|
|
||||||
// .rotation = zm.qidentity(),
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return Model.init(model_data);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn animateRobot(frame_counter: *u16, robot: Model) void {
|
|
||||||
// if (frame_counter.* > robot.animation_frames) {
|
|
||||||
// robot.translations.items[2] = zm.mul(zm.rotationX(-std.math.degreesToRadians(1)), robot.translations.items[2]);
|
|
||||||
// robot.translations.items[3] = zm.mul(zm.rotationX(-std.math.degreesToRadians(1)), robot.translations.items[3]);
|
|
||||||
// } else {
|
|
||||||
// robot.translations.items[2] = zm.mul(zm.rotationX(std.math.degreesToRadians(1)), robot.translations.items[2]);
|
|
||||||
// robot.translations.items[3] = zm.mul(zm.rotationX(std.math.degreesToRadians(1)), robot.translations.items[3]);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// frame_counter.* += 1;
|
|
||||||
|
|
||||||
// if (frame_counter.* > robot.animation_frames * 2) {
|
|
||||||
// frame_counter.* = 0;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn drawGui(light_ubo: zgl.Buffer, light_shader: gl_helper.Shader, light_color: *zm.Vec) void {
|
fn drawGui(light_ubo: zgl.Buffer, light_shader: gl_helper.Shader, light_color: *zm.Vec) void {
|
||||||
if (app_state.render_gui) {
|
if (app_state.render_gui) {
|
||||||
zgui.backend.newFrame(@intCast(app_state.width), @intCast(app_state.height));
|
zgui.backend.newFrame(@intCast(app_state.width), @intCast(app_state.height));
|
||||||
|
|||||||
258
src/tree.zig
258
src/tree.zig
@@ -11,7 +11,6 @@ pub fn Tree(comptime T: type) type {
|
|||||||
const Children = ArrayList(Node);
|
const Children = ArrayList(Node);
|
||||||
const Node = struct {
|
const Node = struct {
|
||||||
val: T,
|
val: T,
|
||||||
// index: usize,
|
|
||||||
children: ArrayList(Node),
|
children: ArrayList(Node),
|
||||||
|
|
||||||
pub fn init(val: T) Node {
|
pub fn init(val: T) Node {
|
||||||
@@ -25,99 +24,195 @@ pub fn Tree(comptime T: type) type {
|
|||||||
const child = Node.init(val);
|
const child = Node.init(val);
|
||||||
try self.children.append(allocator, child);
|
try self.children.append(allocator, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create(self: *Node, allocator: Allocator, val: T) !*Node {
|
||||||
|
const child = Node.init(val);
|
||||||
|
try self.children.append(allocator, child);
|
||||||
|
return &self.children.items[self.children.items.len - 1];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(val: T) @This() {
|
pub fn init(val: T) @This() {
|
||||||
return .{ .root = .init(val) };
|
return .{ .root = .init(val) };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DepthFirstIterator = struct {
|
pub const PreOrderIterator = struct {
|
||||||
const Frame = struct {
|
pre_order: ArrayList(*Node),
|
||||||
parent: ?*Node,
|
index: usize,
|
||||||
index: usize,
|
|
||||||
};
|
|
||||||
const State = enum {
|
|
||||||
GoDeeper,
|
|
||||||
GoBroader,
|
|
||||||
};
|
|
||||||
tree: *Tree(T),
|
|
||||||
current: ?*Node,
|
|
||||||
path: ArrayList(Frame),
|
|
||||||
state: State,
|
|
||||||
|
|
||||||
pub fn init(tree: *Tree(T)) DepthFirstIterator {
|
pub fn init(tree: *Tree(T), allocator: Allocator) !PreOrderIterator {
|
||||||
return DepthFirstIterator{
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
.tree = tree,
|
defer arena.deinit();
|
||||||
.current = &tree.root,
|
const arena_allocator = arena.allocator();
|
||||||
.path = .empty,
|
|
||||||
.state = State.GoDeeper,
|
var stack = try ArrayList(*Node).initCapacity(arena_allocator, 1);
|
||||||
|
stack.appendAssumeCapacity(&tree.root);
|
||||||
|
|
||||||
|
var pre_order = ArrayList(*Node).empty;
|
||||||
|
|
||||||
|
while (stack.items.len > 0) {
|
||||||
|
if (stack.pop()) |tmp| {
|
||||||
|
try pre_order.insert(allocator, 0, tmp);
|
||||||
|
|
||||||
|
for (0..tmp.children.items.len) |i| {
|
||||||
|
try stack.append(arena_allocator, &tmp.children.items[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.index = 0,
|
||||||
|
.pre_order = pre_order,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next(it: *DepthFirstIterator, allocator: Allocator) !?*Node {
|
pub fn next(it: *PreOrderIterator) ?*Node {
|
||||||
// State machine
|
while (it.index < it.pre_order.items.len) {
|
||||||
while (it.current) |current| {
|
const val = it.pre_order.items[it.index];
|
||||||
switch (it.state) {
|
it.index += 1;
|
||||||
State.GoDeeper => {
|
return val;
|
||||||
// Follow child node until deepest possible level
|
|
||||||
if (current.children.items.len > 0) {
|
|
||||||
try it.path.append(allocator, .{
|
|
||||||
.index = 0,
|
|
||||||
.parent = current,
|
|
||||||
});
|
|
||||||
it.current = ¤t.children.items[0];
|
|
||||||
} else {
|
|
||||||
it.state = State.GoBroader;
|
|
||||||
_ = it.path.pop();
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
State.GoBroader => {
|
|
||||||
const last_frame = it.path.pop();
|
|
||||||
if (last_frame) |frame| {
|
|
||||||
if (frame.parent) |parent| {
|
|
||||||
if (parent.children.items.len > frame.index + 1) {
|
|
||||||
it.current = &parent.children.items[frame.index + 1];
|
|
||||||
} else {
|
|
||||||
it.current = parent;
|
|
||||||
// return it.path.pop().?.parent;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// if (parent.children.items.len > current.index + 1) {
|
|
||||||
// it.current = &parent.children.items[current.index + 1];
|
|
||||||
// it.state = .GoDeeper;
|
|
||||||
// } else {
|
|
||||||
// it.current = current.parent;
|
|
||||||
// return current.parent;
|
|
||||||
// }
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(it: *DepthFirstIterator) void {
|
pub fn deinit(self: *PreOrderIterator, allocator: Allocator) void {
|
||||||
it.current = it.tree.root;
|
self.pre_order.deinit(allocator);
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(self: *DepthFirstIterator, allocator: Allocator) void {
|
|
||||||
self.path.deinit(allocator);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn depthFirstIterator(tree: *@This()) DepthFirstIterator {
|
pub fn preOrderIterator(tree: *@This(), allocator: Allocator) !PreOrderIterator {
|
||||||
return DepthFirstIterator.init(tree);
|
return PreOrderIterator.init(tree, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const PostOrderIterator = struct {
|
||||||
|
post_order: ArrayList(*Node),
|
||||||
|
index: usize,
|
||||||
|
|
||||||
|
const Frame = struct {
|
||||||
|
node: *Node,
|
||||||
|
children_index: usize,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn init(tree: *Tree(T), allocator: Allocator) !PostOrderIterator {
|
||||||
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const arena_allocator = arena.allocator();
|
||||||
|
|
||||||
|
var stack = ArrayList(Frame).empty;
|
||||||
|
var current_root_index: usize = 0;
|
||||||
|
var post_order = ArrayList(*Node).empty;
|
||||||
|
|
||||||
|
var curr_node: ?*Node = &tree.root;
|
||||||
|
while (curr_node != null or stack.items.len > 0) {
|
||||||
|
if (curr_node) |cur| {
|
||||||
|
try stack.append(arena_allocator, .{
|
||||||
|
.children_index = current_root_index,
|
||||||
|
.node = cur,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (cur.children.items.len >= 1) {
|
||||||
|
curr_node = &cur.children.items[0];
|
||||||
|
} else {
|
||||||
|
curr_node = null;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack.pop()) |tmp| {
|
||||||
|
try post_order.append(allocator, tmp.node);
|
||||||
|
|
||||||
|
while (stack.items.len > 0 and tmp.children_index == stack.items[stack.items.len - 1].node.children.items.len - 1) {
|
||||||
|
if (stack.pop()) |tmp2| {
|
||||||
|
try post_order.append(allocator, tmp2.node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack.items.len > 0 and stack.items[stack.items.len - 1].node.children.items.len > tmp.children_index + 1) {
|
||||||
|
curr_node = &stack.items[stack.items.len - 1].node.children.items[tmp.children_index + 1];
|
||||||
|
current_root_index = tmp.children_index + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.index = 0,
|
||||||
|
.post_order = post_order,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next(it: *PostOrderIterator) ?*Node {
|
||||||
|
while (it.index < it.post_order.items.len) {
|
||||||
|
const val = it.post_order.items[it.index];
|
||||||
|
it.index += 1;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *PostOrderIterator, allocator: Allocator) void {
|
||||||
|
self.post_order.deinit(allocator);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn postOrderIterator(tree: *@This(), allocator: Allocator) !PostOrderIterator {
|
||||||
|
return PostOrderIterator.init(tree, allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const LevelOrderIterator = struct {
|
||||||
|
level_order: ArrayList(*Node),
|
||||||
|
index: usize,
|
||||||
|
|
||||||
|
pub fn init(tree: *Tree(T), allocator: Allocator) !LevelOrderIterator {
|
||||||
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
|
defer arena.deinit();
|
||||||
|
const arena_allocator = arena.allocator();
|
||||||
|
|
||||||
|
var stack = try ArrayList(*Node).initCapacity(arena_allocator, 1);
|
||||||
|
stack.appendAssumeCapacity(&tree.root);
|
||||||
|
|
||||||
|
var level_order = ArrayList(*Node).empty;
|
||||||
|
|
||||||
|
while (stack.items.len > 0) {
|
||||||
|
if (stack.pop()) |tmp| {
|
||||||
|
try level_order.append(allocator, tmp);
|
||||||
|
|
||||||
|
for (0..tmp.children.items.len) |i| {
|
||||||
|
try stack.append(arena_allocator, &tmp.children.items[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return .{
|
||||||
|
.index = 0,
|
||||||
|
.level_order = level_order,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next(it: *LevelOrderIterator) ?*Node {
|
||||||
|
while (it.index < it.level_order.items.len) {
|
||||||
|
const val = it.level_order.items[it.index];
|
||||||
|
it.index += 1;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *LevelOrderIterator, allocator: Allocator) void {
|
||||||
|
self.level_order.deinit(allocator);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn levelOrderIterator(tree: *@This(), allocator: Allocator) !LevelOrderIterator {
|
||||||
|
return LevelOrderIterator.init(tree, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *@This(), allocator: Allocator) !void {
|
pub fn deinit(self: *@This(), allocator: Allocator) !void {
|
||||||
var iterator = self.depthFirstIterator();
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
defer iterator.deinit(allocator);
|
defer arena.deinit();
|
||||||
while (try iterator.next(allocator)) |node| {
|
const arena_allocator = arena.allocator();
|
||||||
|
|
||||||
|
var iterator = try self.postOrderIterator(arena_allocator);
|
||||||
|
while (iterator.next()) |node| {
|
||||||
node.children.deinit(allocator);
|
node.children.deinit(allocator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,20 +251,17 @@ test "Tree" {
|
|||||||
const UTree = Tree(u16);
|
const UTree = Tree(u16);
|
||||||
|
|
||||||
var tree = UTree.init(10);
|
var tree = UTree.init(10);
|
||||||
defer tree.deinit(allocator);
|
defer tree.deinit(allocator) catch {};
|
||||||
|
|
||||||
try tree.root.append(allocator, 20);
|
try tree.root.append(allocator, 20);
|
||||||
try tree.root.append(allocator, 500);
|
try tree.root.append(allocator, 500);
|
||||||
|
|
||||||
var iterator = tree.depthFirstIterator();
|
try tree.root.children.items[1].append(allocator, 999);
|
||||||
|
|
||||||
|
var iterator = try tree.levelOrderIterator(allocator);
|
||||||
|
defer iterator.deinit(allocator);
|
||||||
std.debug.print("\n", .{});
|
std.debug.print("\n", .{});
|
||||||
while (iterator.next()) |node| {
|
while (iterator.next()) |node| {
|
||||||
var accumulator: u32 = node.val;
|
std.debug.print("Val: {}\n", .{node.val});
|
||||||
var current = node;
|
|
||||||
while (current.parent) |parent| {
|
|
||||||
accumulator *= parent.val;
|
|
||||||
current = parent;
|
|
||||||
}
|
|
||||||
std.debug.print("Val: {} Acc: {}\n", .{ node.val, accumulator });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user