const Vec2i = @This(); const std = @import("std"); const engine = @import("engine"); const c = @import("c"); const Recti = engine.geometry.Recti; const Vec2f = engine.geometry.Vec2f; const Layer = engine.Layer; const Color = engine.Color; x: i32, y: i32, pub fn create(x: i32, y: i32) Vec2i { return .{ .x = x, .y = y, }; } pub fn scale(self: *const Vec2i, s: i32) Vec2i { return .{ .x = self.x * s, .y = self.y * s }; } pub fn to_unit_recti(self: *const Vec2i) Recti { return Recti.from_xywh(self.x, self.y, 1, 1); } pub fn add(self: Vec2i, other: Vec2i) Vec2i { return Vec2i { .x = self.x + other.x, .y = self.y + other.y, }; } fn round_up_to_multiple_of_8(n: i32) i32 { // fkn magic. -8 is all 1s, last 3 bits 0 so its a mask. return (n + (8 - 1)) & -8; } // TODO: comptime the entire array and just render with one offset call to render points. // effectively memoize shit with comptime!!! pub fn draw(self: *const Vec2i, comptime radius: i32, color: Color) void { const cx = self.x; const cy = self.y; const fradius: f32 = @floatFromInt(radius); const arr_size: usize = comptime @intCast( round_up_to_multiple_of_8( @intFromFloat(std.math.ceil( fradius * 8.0 * std.math.sqrt1_2 )) ) ); var points: [arr_size]c.SDL_FPoint = undefined; var draw_count: usize = 0; const diameter = (radius * 2); var x: i32 = (radius - 1); var y: i32 = 0; var tx: i32 = 1; var ty: i32 = 1; var err: i32 = (tx - diameter); while (x >= y) { points[draw_count + 0] = c.SDL_FPoint { .x = @floatFromInt(cx + x), .y = @floatFromInt(cy - y) }; points[draw_count + 1] = c.SDL_FPoint { .x = @floatFromInt(cx + x), .y = @floatFromInt(cy + y) }; points[draw_count + 2] = c.SDL_FPoint { .x = @floatFromInt(cx - x), .y = @floatFromInt(cy - y) }; points[draw_count + 3] = c.SDL_FPoint { .x = @floatFromInt(cx - x), .y = @floatFromInt(cy + y) }; points[draw_count + 4] = c.SDL_FPoint { .x = @floatFromInt(cx + y), .y = @floatFromInt(cy - x) }; points[draw_count + 5] = c.SDL_FPoint { .x = @floatFromInt(cx + y), .y = @floatFromInt(cy + x) }; points[draw_count + 6] = c.SDL_FPoint { .x = @floatFromInt(cx - y), .y = @floatFromInt(cy - x) }; points[draw_count + 7] = c.SDL_FPoint { .x = @floatFromInt(cx - y), .y = @floatFromInt(cy + x) }; draw_count = draw_count + 8; if (err <= 0) { y = y + 1; err = err + ty; ty = ty + 2; } if (err > 0) { x = x - 1; tx = tx + 2; err = err + (tx - diameter); } } _ = c.SDL_SetRenderDrawColor(engine.Control.sdl_data.renderer, color.u.r, color.u.g, color.u.b, color.u.a); _ = c.SDL_RenderPoints(engine.Control.sdl_data.renderer, &points, @intCast(draw_count)); } pub fn to_vec2f(self: *const Vec2i) Vec2f { return Vec2f { .x = @floatFromInt(self.x), .y = @floatFromInt(self.y), }; } pub fn distance_from(self: Vec2i, other: Vec2i) f32 { const x: f32 = @floatFromInt(@abs(self.x - other.x)); const y: f32 = @floatFromInt(@abs(self.y - other.y)); return @sqrt(x * x + y * y); } pub fn eql(self: Vec2i, other: Vec2i) bool { return self.x == other.x and self.y == other.y; } pub const ZERO = create(0, 0); pub const ONE = create(1, 1); pub const NORTH = create(0, -1); pub const SOUTH = create(0, 1); pub const EAST = create(1, 0); pub const WEST = create(-1, 0);