hadean-zig/src/engine/geometry/Vec2i.zig

115 lines
3.2 KiB
Zig
Raw Normal View History

2024-08-21 15:57:18 -04:00
const Vec2i = @This();
const std = @import("std");
2025-01-09 11:02:29 -05:00
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;
2024-09-03 13:13:28 -04:00
2024-08-21 15:57:18 -04:00
x: i32,
y: i32,
2024-09-03 13:13:28 -04:00
pub fn create(x: i32, y: i32) Vec2i {
2024-08-21 15:57:18 -04:00
return .{
.x = x,
.y = y,
};
}
2024-09-03 13:13:28 -04:00
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);
}
2024-10-15 09:01:44 -04:00
pub fn add(self: Vec2i, other: Vec2i) Vec2i {
return Vec2i {
.x = self.x + other.x,
.y = self.y + other.y,
};
}
2025-01-09 11:02:29 -05:00
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),
};
}
2025-02-15 06:17:46 -05:00
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;
}
2024-09-03 13:13:28 -04:00
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);