const std = @import("std"); const term = @import("term.zig"); const Winsize = term.Winsize; pub const Direction = struct { x: i8 = 1, y: i8 = 1, z: i8 = 1, }; pub const Point = struct { x: i32 = 0, y: i32 = 0, z: i32 = 0, direction: Direction = .{ .x = 1, .y = 1, .z = 1 }, //for movement state }; pub const Vec3 = struct { a: Point = .{ .x = 0, .y = 0, .z = 0, .direction = .{ .x = 0, .y = 0, .z = 0 } }, b: Point = .{ .x = 0, .y = 0, .z = 0, .direction = .{ .x = 0, .y = 0, .z = 0 } }, c: Point = .{ .x = 0, .y = 0, .z = 0, .direction = .{ .x = 0, .y = 0, .z = 0 } }, }; pub const Triangle = struct { bufa: *i32, bufb: *i32, bufc: *i32, }; pub fn LinkedList() type { return struct { const Self = @This(); //means this struc,ref to the most inner scope const Node = struct { point: Point, next: ?*Node }; head: ?*Node, length: u32, allocator: std.mem.Allocator, current: ?*Node, pub fn new(allocator: std.mem.Allocator) Self { return .{ .head = null, .current = null, .length = 0, .allocator = allocator, }; } pub fn add(self: *Self, point: Point) !void { var allocator = self.allocator; var newNode = allocator.create(Node) catch |err| { std.debug.print("error allocation, {}", .{err}); return err; }; newNode.point = point; newNode.next = self.head; self.head = newNode; self.length += 1; } pub fn next(self: *Self) Point { var elem: ?*Node = undefined; if (self.current == null) { elem = self.head; self.current = self.head.?.next; } else { elem = self.current; self.current = self.current.?.next; } return elem.?.point; } pub fn dump(self: *Self) ![]Point { const allocator = self.allocator; var node = self.head; var point: []Point = &.{}; //empty slice var i: usize = 0; while (node != null) : (i += 1) { point = allocator.realloc(point, i + 1) catch |err| { std.debug.print("error allocation for slice:{}\n", .{err}); return err; }; point[i] = node.?.point; node = node.?.next; } return point; } }; } test "test linked list" { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); const allocator = arena.allocator(); defer arena.deinit(); var polygon = LinkedList().new(allocator); try polygon.add(.{ .x = 10, .y = 11, .z = 0 }); try polygon.add(.{ .x = 11, .y = 12, .z = 0 }); try polygon.add(.{ .x = 12, .y = 13, .z = 0 }); try polygon.add(.{ .x = 12, .y = 14, .z = 0 }); try polygon.add(.{ .x = 12, .y = 15, .z = 0 }); try polygon.add(.{ .x = 12, .y = 16, .z = 0 }); const points: []Point = try polygon.dump(); for (points) |point| { std.debug.print("Point dump:{}\n", .{point}); } std.debug.print("next:{}\n", .{polygon.next()}); std.debug.print("next:{}\n", .{polygon.next()}); std.debug.print("typeof:{}\n", .{@TypeOf(polygon)}); } pub fn polygon_draw(buf: []u8, w: Winsize, poly: *LinkedList()) !void { var i: u8 = 0; var previous: Point = poly.next(); var current: Point = undefined; while (i < poly.length) : (i += 1) { current = poly.next(); try bresenham(buf, w, previous, current); previous = current; } } pub fn pixel(buffer: []u8, w: Winsize, x: i64, y: i64, symbol: u21) !void { const i: usize = @intCast(4 * (x + y * w.ws_col)); if (i < buffer.len) { //-1 ?? const slice = buffer[i .. i + 4]; _ = try std.unicode.utf8Encode(symbol, slice); //TODO: check length, set not used bytes to zero } else { //print("Error illegal memory access\n", .{}); } } pub fn bresenham(buf: []u8, w: Winsize, p1: Point, p2: Point) !void { var x: i32 = p1.x; var y: i32 = p1.y; const dx = (p2.x - p1.x); const dy = (p2.y - p1.y); var er: i64 = 0; if (dx >= dy and dy > 0 and dx > 0) { while (x <= p2.x) : (x += 1) { _ = try pixel(buf, w, x, y, '█'); er += dy; if (2 * er >= dx) { y += 1; er -= dx; } } } else if (dx <= dy and dy >= 0 and dx >= 0) { while (y <= p2.y) : (y += 1) { _ = try pixel(buf, w, x, y, '█'); er += dx; if (2 * er >= dy) { x += 1; er -= dy; } } } else if (@abs(dy) <= dx and dy <= 0 and dx >= 0) { while (x <= p2.x) : (x += 1) { _ = try pixel(buf, w, x, y, '█'); er -= dy; if (2 * er >= dx) { y -= 1; er -= dx; } } } else if (@abs(dy) >= dx and dy <= 0 and dx >= 0) { while (y >= p2.y) : (y -= 1) { _ = try pixel(buf, w, x, y, '█'); er += dx; if (2 * er >= dy) { x += 1; er += dy; } } } else if (@abs(dx) <= dy and dx <= 0 and dy >= 0) { while (y <= p2.y) : (y += 1) { _ = try pixel(buf, w, x, y, '█'); er += @abs(dx); if (2 * er >= dy) { x -= 1; er -= dy; } } } else if (@abs(dx) >= dy and dy >= 0 and dx <= 0) { while (x >= p2.x) : (x -= 1) { _ = try pixel(buf, w, x, y, '█'); er += dy; if (2 * er >= @abs(dx)) { y += 1; er -= @abs(dx); } } } else if (dx <= dy and dx <= 0 and dy <= 0) { while (x >= p2.x) : (x -= 1) { _ = try pixel(buf, w, x, y, '█'); er += @abs(dy); if (2 * er >= @abs(dx)) { y -= 1; er -= @abs(dx); } } } else if (dx >= dy and dy <= 0 and dx <= 0) { while (y >= p2.y) : (y -= 1) { //print("x:{},y:{},er:{},dx:{},dy:{}\n", .{ x, y, er, dx, dy }); _ = try pixel(buf, w, x, y, '█'); er += @abs(dx); if (2 * er >= @abs(dx)) { x -= 1; er -= @abs(dy); } } } } pub fn triangle(buffer: []u8, w: Winsize, vector: Vec3) !void { try bresenham(buffer, w, vector.a, vector.b); try bresenham(buffer, w, vector.b, vector.c); try bresenham(buffer, w, vector.c, vector.a); }