repo: hackvr-turbo action: commit revision: path_from: revision_from: 20c1491b2db314a059932760bfe4dd9e95e4b4b7: path_to: revision_to:
commit 20c1491b2db314a059932760bfe4dd9e95e4b4b7 Author: Felix (xq) QueißnerDate: Fri Jul 3 11:18:04 2020 +0200 "Porting" to ZLM, adds group filtered and unfiltered group iterators. diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000000000000000000000000000000..98863a0254ffaf0a7359c20ebd1fc339d66d58f0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/zlm"] + path = lib/zlm + url = https://github.com/ziglibs/zlm diff --git a/SPEC.md b/SPEC.md
--- a/SPEC.md +++ b/SPEC.md @@ -3,6 +3,35 @@ **Note:** This specification is inofficial and based on the development of HackVR Turbo (which is based on the original hackvr) +## Virtual Environment + +The HackVR virtual environment is structured in a tree of groups. Each group contains a set of polygons with 1 … n vertices. Each polygon may have it's own color, chosen from a palette. This environment is built and modified via commands on `stdin`. Interactions by the user with the environment are passed to `stdout`. + +### Groups +Groups are unordered sets of polygons with a transformation in 3D space. Each vertex of the polygons is relative to the group origin. Transformations on the group (or any of its parents) will thus indirectly apply to the vertices. + +### Polygons (Shapes) +Each polygon may have 1 (circle) up to n (n-gon) vertices. Each polygon is allowed to have any orientation in space, but is required to have all vertices to be on a plane. HackVR is allowed to enforce this and normalize all polygons to be on their mean plane. +A polygon also has a velocity relative to its group and a color, chosen from a palette. + +### Colors (Palette) +HackVR has a default palette with 16 different colors: + +| Color Index | Visual Description / Name | Default Value | +|-------------|---------------------------|---------------| +| 0 | Black | #111111 | +| 1 | White | #EEEEEE | + +### Coordinate System + +HackVR uses the right-handed OpenGL coordinate system. In a standard-oriented view, the camera has the following coordinates: + +| Direction | Vector | +|-----------|------------| +| Right | (1, 0, 0) | +| Upward | (0, 1, 0) | +| Forward | (0, 0, -1) | + ## I/O HackVR communicates via `stdin`/`stdout`. Commands are passed on a line-by-line basis, each line is terminated by a LF character, optionally preceeded by a CR character. Each line must be encoded in valid UTF-8. @@ -27,12 +56,17 @@ Everything after a `#` in a line is considered a comment and will be ignored by ### `version` ### `[groupspec] deleteallexcept grou*` +Deletes all groups not matching `grou*`. ### `[groupspec] deletegroup grou*` +Deletes all groups matching `grou*`. ### `[groupspec] assimilate grou*` ### `[groupspec] renamegroup group` +Renames and merges groups. Selects all groups with `groupspec` and renames them to `group`. When multiple groups are selected, those groups are merged into the master group. + +> TODO: Define how transforms will merge ### `[groupspec] status` **deprecated** @@ -58,8 +92,7 @@ Closes hackvr only if the id that is doing it is the same as yours.` ### `[groupspec] ping any-string-without-spaces` -### `[groupspec] scale x y z` - +d ### `[groupspec] rotate [+]x [+]y [+]z` ### `[groupspec] periodic` @@ -84,8 +117,15 @@ when a group is clicked on using the name set from the command line. usually `$U - Encoding is assumed UTF-8 - Max. line length excluding the `\n` is 1024 bytes +- Polygons are required to be *flat* ## TODO -- Define coordinate system -- Define relative coordinate system for "forward/backward/…" \ No newline at end of file +- Define relative coordinate system for "forward/backward/…" +- Full color table +- Imlement `subsume` command + +### Questions +- Shape velocity +- Transformation order/execution +- Colors \ No newline at end of file diff --git a/build.zig b/build.zig
--- a/build.zig
+++ b/build.zig
@@ -5,6 +5,7 @@ const hackvr = std.build.Pkg{
.path = "lib/hackvr/lib.zig",
.dependencies = &[_]std.build.Pkg{
fixed_list,
+ zlm,
},
};
@@ -13,6 +14,11 @@ const fixed_list = std.build.Pkg{
.path = "lib/fixed_list.zig",
};
+const zlm = std.build.Pkg{
+ .name = "zlm",
+ .path = "lib/zlm/zlm.zig",
+};
+
pub fn build(b: *std.build.Builder) void {
// Standard target options allows the person running `zig build` to choose
// what target to build for. Here we do not override the defaults, which
@@ -32,11 +38,13 @@ pub fn build(b: *std.build.Builder) void {
exe.linkSystemLibrary("epoxy");
exe.addPackage(hackvr);
+ exe.addPackage(zlm);
exe.install();
const hackvr_tests = b.addTest("lib/hackvr/lib.zig");
hackvr_tests.addPackage(fixed_list);
+ hackvr_tests.addPackage(zlm);
const test_step = b.step("test", "Runs all tests");
test_step.dependOn(&hackvr_tests.step);
diff --git a/lib/hackvr/lib.zig b/lib/hackvr/lib.zig
--- a/lib/hackvr/lib.zig
+++ b/lib/hackvr/lib.zig
@@ -1,4 +1,5 @@
const std = @import("std");
+const zlm = @import("zlm");
pub const parsing = @import("parser.zig");
@@ -9,11 +10,7 @@ comptime {
pub const real = f32;
-pub const Vec3D = struct {
- x: real,
- y: real,
- z: real,
-};
+pub const Vec3D = zlm.Vec3;
pub const Attribute = struct {
color: u8, //color. not sure how I plan on using this.
@@ -36,10 +33,13 @@ pub const Group = struct {
/// flat list of all shapes
shapes: std.ArrayList(Shape3D),
+ transform: zlm.Mat4,
+
pub fn init(allocator: *std.mem.Allocator, name: []const u8) Self {
return Self{
.name = name,
.shapes = std.ArrayList(Shape3D).init(allocator),
+ .transform = zlm.Mat4.identity,
};
}
@@ -91,6 +91,44 @@ pub const State = struct {
grp.* = Group.init(self.allocator, name_ptr);
return grp;
}
+
+ /// Returns an iterator yielding all groups.
+ pub fn iterator(self: *Self) GroupIterator {
+ return GroupIterator{
+ .state = self,
+ .index = 0,
+ .pattern = null,
+ };
+ }
+
+ /// Returns an iterator yielding all groups that match the pattern.
+ pub fn findGroups(self: *Self, pattern: []const u8) GroupIterator {
+ return GroupIterator{
+ .state = self,
+ .index = 0,
+ .pattern = pattern,
+ };
+ }
+
+ pub const GroupIterator = struct {
+ state: *Self,
+ index: usize,
+ pattern: ?[]const u8,
+
+ pub fn next(self: *@This()) ?*Group {
+ while (self.index < self.state.groups.items.len) {
+ const grp = &self.state.groups.items[self.index];
+ self.index += 1;
+
+ if (self.pattern) |pattern| {
+ if (!wildcardEquals(pattern, grp.name))
+ continue;
+ }
+ return grp;
+ }
+ return null;
+ }
+ };
};
pub fn applyEventToState(state: *State, event: parsing.Event) !void {
@@ -119,20 +157,77 @@ pub fn applyEventToState(state: *State, event: parsing.Event) !void {
.points = try std.mem.dupe(&state.arena.allocator, Vec3D, cmd.polygon),
};
},
+ .move => |cmd| {
+ // semantics unclear
+ },
+ .rotate => |cmd| {
+ // semantics unclear
+ },
else => {
std.debug.print("Event {} not implemented yet!\n", .{@as(parsing.EventType, event)});
},
}
}
-test "state.getOrCreateGroup" {
+test "State.iterator" {
var state = State.init(std.testing.allocator);
defer state.deinit();
- const grp1 = try state.getOrCreateGroup("grp");
- const grp2 = try state.getOrCreateGroup("grp");
+ const grp1 = try state.getOrCreateGroup("grp1");
+ const grp2 = try state.getOrCreateGroup("grp2");
+ const grp3 = try state.getOrCreateGroup("grp3");
+
+ var found1 = false;
+ var found2 = false;
+ var found3 = false;
+
+ var iter = state.iterator();
+ while (iter.next()) |grp| {
+ if (grp == grp1) {
+ std.testing.expectEqual(false, found1);
+ found1 = true;
+ }
+ if (grp == grp2) {
+ std.testing.expectEqual(false, found2);
+ found2 = true;
+ }
+ if (grp == grp3) {
+ std.testing.expectEqual(false, found3);
+ found3 = true;
+ }
+ }
+
+ std.testing.expect(found1 and found2 and found3);
+}
+
+test "State.findGroups" {
+ var state = State.init(std.testing.allocator);
+ defer state.deinit();
+
+ const grp1 = try state.getOrCreateGroup("a_1");
+ const grp2 = try state.getOrCreateGroup("a_2");
+ const grp3 = try state.getOrCreateGroup("b_1");
+
+ var found1 = false;
+ var found2 = false;
+ var found3 = false;
+
+ var iter = state.findGroups("a*");
+ while (iter.next()) |grp| {
+ if (grp == grp1) {
+ std.testing.expectEqual(false, found1);
+ found1 = true;
+ }
+ if (grp == grp2) {
+ std.testing.expectEqual(false, found2);
+ found2 = true;
+ }
+ if (grp == grp3) {
+ std.testing.expect(false);
+ }
+ }
- std.testing.expect(grp1 == grp2);
+ std.testing.expect(found1 and found2 and !found3);
}
test "applyEventToState (add_shape)" {
diff --git a/lib/zlm b/lib/zlm
new file mode 160000
index 0000000000000000000000000000000000000000..3d948806d30245c1ba575f53fc361490f7db9f12
--- /dev/null
+++ b/lib/zlm
@@ -0,0 +1 @@
+Subproject commit 3d948806d30245c1ba575f53fc361490f7db9f12
-----END OF PAGE-----