105 lines
2.8 KiB
Zig
105 lines
2.8 KiB
Zig
const std = @import("std");
|
|
const Vec4f = @import("vec.zig").Vec4f;
|
|
const Mat4f = @import("vec.zig").Mat4f;
|
|
|
|
const BoxData = packed struct {};
|
|
|
|
pub fn Box(comptime Vec: type, comptime Shift: comptime_int) type {
|
|
return packed struct {
|
|
const Self = @This();
|
|
|
|
pub const empty = Self{
|
|
.lo = Vec.s(1 << Shift),
|
|
.hi = Vec.s(-(1 << Shift)),
|
|
};
|
|
|
|
lo: Vec,
|
|
hi: Vec,
|
|
|
|
pub inline fn new(lo: Vec, hi: Vec) Self {
|
|
return Self{
|
|
.lo = lo,
|
|
.hi = hi,
|
|
};
|
|
}
|
|
|
|
pub inline fn center(self: Self) Vec {
|
|
return self.lo.lerpvs(self.hi, 0.5);
|
|
}
|
|
|
|
pub inline fn size(self: Self) Vec {
|
|
return self.hi.sub(self.lo);
|
|
}
|
|
|
|
pub inline fn extents(self: Self) Vec {
|
|
return self.size().mulvs(0.5);
|
|
}
|
|
|
|
pub inline fn contains(self: Self, pt: Vec) bool {
|
|
return pt.gteq(self.lo).all3() and pt.lteq(self.hi).all3();
|
|
}
|
|
|
|
pub inline fn area(self: Self) f32 {
|
|
const sz = self.size();
|
|
return sz.x * sz.y * if (Vec.nelem > 2) sz.z else 1;
|
|
}
|
|
|
|
pub inline fn fromPts(pts: []const Vec) Self {
|
|
var lo = Vec.s(1 << Shift);
|
|
var hi = Vec.s(-(1 << Shift));
|
|
for (pts) |pt| {
|
|
lo = lo.min(pt);
|
|
hi = hi.max(pt);
|
|
}
|
|
|
|
return Self{
|
|
.lo = lo,
|
|
.hi = hi,
|
|
};
|
|
}
|
|
|
|
pub inline fn uni(lhs: Self, rhs: Self) Self {
|
|
return Self{
|
|
.lo = lhs.lo.min(rhs.lo),
|
|
.hi = lhs.hi.max(rhs.hi),
|
|
};
|
|
}
|
|
|
|
pub inline fn intersect(lhs: Self, rhs: Self) Self {
|
|
var lo = lhs.lo.min(rhs.lo);
|
|
var hi = lhs.hi.max(rhs.hi);
|
|
const mid = lo.lerpvs(hi, 0.5);
|
|
const inverted = lo.gt(hi);
|
|
lo = lo.select(mid, inverted);
|
|
hi = hi.select(mid, inverted);
|
|
|
|
return Self{
|
|
.lo = lo,
|
|
.hi = hi,
|
|
};
|
|
}
|
|
|
|
// TODO: genericise
|
|
pub inline fn transform(matrix: Mat4f, box: Self) Self {
|
|
var ct = box.center();
|
|
var exts = box.hi.sub(ct);
|
|
ct = matrix.mulPt(ct);
|
|
exts = matrix.mulExtents(exts);
|
|
return Self{
|
|
.lo = ct.sub(exts),
|
|
.hi = ct.add(exts),
|
|
};
|
|
}
|
|
};
|
|
}
|
|
|
|
// pub const Box2d = Box(Vec2f); // need to understand the shift magic
|
|
pub const Box3d = Box(Vec4f, 20);
|
|
|
|
test "Box3d" {
|
|
const b1 = Box3d.fromPts(&.{ Vec4f.s(1), Vec4f.s(-1) });
|
|
try std.testing.expectEqual(@as(f32, 8), b1.area());
|
|
const v1 = Vec4f.s(0.5);
|
|
try std.testing.expect(b1.contains(v1));
|
|
}
|