25 [[nodiscard]]
bool contains(glm::vec2 p)
const noexcept
27 return p.x >=
min.x && p.x <=
max.x
28 && p.y >=
min.y && p.y <=
max.y;
33 return min.x <= other.max.x &&
max.x >= other.min.x
34 &&
min.y <= other.max.y &&
max.y >= other.min.y;
37 [[nodiscard]]
float width() const noexcept {
return max.x -
min.x; }
38 [[nodiscard]]
float height() const noexcept {
return max.y -
min.y; }
40 [[nodiscard]] glm::vec2
center() const noexcept {
return (
min +
max) * 0.5F; }
44 return { .
min =
min + offset, .max =
max + offset };
49 return { .
min =
min - glm::vec2(margin), .max =
max + glm::vec2(margin) };
67 float x,
float y,
float w,
float h,
68 uint32_t win_w, uint32_t win_h)
noexcept
70 auto nx = [&](
float px) {
71 return (px /
static_cast<float>(win_w)) * 2.0F - 1.0F;
73 auto ny = [&](
float py) {
74 return 1.0F - (py /
static_cast<float>(win_h)) * 2.0F;
76 return { .
min = glm::vec2(nx(x), ny(y +
h)), .max = glm::vec2(nx(x + w), ny(y)) };
85 glm::vec2 ndc_position, glm::vec2 ndc_scale)
noexcept
87 glm::vec2 half = ndc_scale * 0.5F;
88 return { .
min = ndc_position - half, .max = ndc_position + half };
109 [[nodiscard]]
bool contains(
const glm::vec3& p)
const noexcept
121 glm::vec3 oc = ray.origin -
center;
122 float b = glm::dot(oc, ray.direction);
124 return b *
b - c >= 0.0F;
147 [[nodiscard]]
bool contains(
const glm::vec3& p)
const noexcept
149 return p.x >=
min.x && p.x <=
max.x
150 && p.y >=
min.y && p.y <=
max.y
151 && p.z >=
min.z && p.z <=
max.z;
156 return min.x <= other.max.x &&
max.x >= other.min.x
157 &&
min.y <= other.max.y &&
max.y >= other.min.y
158 &&
min.z <= other.max.z &&
max.z >= other.min.z;
161 [[nodiscard]] glm::vec3
center() const noexcept {
return (
min +
max) * 0.5F; }
167 return { .
min =
min + offset, .max =
max + offset };
172 return { .
min =
min - glm::vec3(margin), .max =
max + glm::vec3(margin) };
182 return { .
min = c - half, .max = c + half };
191 return { .
min = s.center - glm::vec3(s.radius),
192 .max = s.center + glm::vec3(s.radius) };
207[[nodiscard]]
inline std::function<bool(glm::vec2)>
210 float r2 = radius * radius;
211 return [center, r2](glm::vec2 p) {
212 glm::vec2 d = p - center;
213 return d.x * d.x + d.y * d.y <= r2;
226[[nodiscard]]
inline std::function<bool(glm::vec2)>
229 std::vector<glm::vec2> verts(vertices.begin(), vertices.end());
230 return [verts = std::move(verts)](glm::vec2 p) {
232 size_t n = verts.size();
233 for (
size_t i = 0; i < n; ++i) {
234 glm::vec2
a = verts[i];
235 glm::vec2
b = verts[(i + 1) % n];
238 float cross = (
b.x -
a.x) * (p.y -
a.y)
239 - (
b.y -
a.y) * (p.x -
a.x);
245 float cross = (
b.x -
a.x) * (p.y -
a.y)
246 - (
b.y -
a.y) * (p.x -
a.x);
266[[nodiscard]]
inline std::function<bool(glm::vec2)>
269 std::vector<glm::vec2> pts(
points.begin(),
points.end());
270 float t2 = half_thickness * half_thickness;
271 return [pts = std::move(pts), t2](glm::vec2 p) {
272 for (
size_t i = 0; i + 1 < pts.size(); ++i) {
273 glm::vec2
a = pts[i];
274 glm::vec2
b = pts[i + 1];
275 glm::vec2 ab =
b -
a;
276 float len2 = glm::dot(ab, ab);
279 glm::vec2 ap = p -
a;
280 d2 = glm::dot(ap, ap);
282 float t = glm::clamp(glm::dot(p -
a, ab) / len2, 0.0F, 1.0F);
283 glm::vec2 proj =
a + t * ab;
284 glm::vec2 diff = p - proj;
285 d2 = glm::dot(diff, diff);
307[[nodiscard]]
inline std::function<bool(glm::vec3)>
310 float r2 = radius * radius;
311 return [center, r2](
const glm::vec3& p) {
312 glm::vec3 d = p - center;
313 return glm::dot(d, d) <= r2;
327[[nodiscard]]
inline std::function<bool(glm::vec3)>
330 std::vector<std::pair<glm::vec3, float>> ps(planes.begin(), planes.end());
331 return [ps = std::move(ps)](
const glm::vec3& p) {
332 return std::ranges::all_of(
334 [&p](
const auto& plane) {
335 const auto& [n, d] = plane;
336 return glm::dot(n, p) >= d;
353[[nodiscard]]
inline std::function<bool(glm::vec3)>
355 std::span<const glm::vec2> footprint,
359 std::vector<glm::vec2> verts(footprint.begin(), footprint.end());
360 return [verts = std::move(verts), y_min, y_max](
const glm::vec3& p) {
361 if (p.y < y_min || p.y > y_max)
363 glm::vec2
q { p.x, p.z };
365 const size_t n = verts.size();
366 for (
size_t i = 0; i < n; ++i) {
367 glm::vec2
a = verts[i];
368 glm::vec2
b = verts[(i + 1) % n];
371 float cross = (
b.x -
a.x) * (
q.y -
a.y)
372 - (
b.y -
a.y) * (
q.x -
a.x);
378 float cross = (
b.x -
a.x) * (
q.y -
a.y)
379 - (
b.y -
a.y) * (
q.x -
a.x);
396[[nodiscard]]
inline std::function<bool(glm::vec2)>
398 std::function<
bool(glm::vec2)>
a,
399 std::function<
bool(glm::vec2)>
b)
401 return [
a = std::move(
a),
b = std::move(
b)](glm::vec2 p) {
409[[nodiscard]]
inline std::function<bool(glm::vec2)>
411 std::function<
bool(glm::vec2)>
a,
412 std::function<
bool(glm::vec2)>
b)
414 return [
a = std::move(
a),
b = std::move(
b)](glm::vec2 p) {
423[[nodiscard]]
inline std::function<bool(glm::vec2)>
425 std::function<
bool(glm::vec2)>
a,
426 std::function<
bool(glm::vec2)>
b)
428 return [
a = std::move(
a),
b = std::move(
b)](glm::vec2 p) {
429 return a(p) && !
b(p);
445 uint32_t
width, uint32_t height)
457[[nodiscard]]
inline std::function<bool(glm::vec3)>
459 std::function<
bool(glm::vec3)>
a,
460 std::function<
bool(glm::vec3)>
b)
462 return [
a = std::move(
a),
b = std::move(
b)](
const glm::vec3& p) {
470[[nodiscard]]
inline std::function<bool(glm::vec3)>
472 std::function<
bool(glm::vec3)>
a,
473 std::function<
bool(glm::vec3)>
b)
475 return [
a = std::move(
a),
b = std::move(
b)](
const glm::vec3& p) {
483[[nodiscard]]
inline std::function<bool(glm::vec3)>
485 std::function<
bool(glm::vec3)>
a,
486 std::function<
bool(glm::vec3)>
b)
488 return [
a = std::move(
a),
b = std::move(
b)](
const glm::vec3& p) {
489 return a(p) && !
b(p);
std::vector< glm::vec2 > * points
std::function< bool(glm::vec3)> convex_region(std::span< const std::pair< glm::vec3, float > > planes)
Containment test for a convex volume defined by inward-facing half-planes.
std::function< bool(glm::vec2)> intersect_bounds(std::function< bool(glm::vec2)> a, std::function< bool(glm::vec2)> b)
Intersection of two containment tests.
std::function< bool(glm::vec2)> polygon_bounds(std::span< const glm::vec2 > vertices)
Containment test for a convex or concave polygon.
std::function< bool(glm::vec3)> extruded_polygon_region(std::span< const glm::vec2 > footprint, float y_min, float y_max)
Containment test for a vertically extruded 2D polygon.
std::function< bool(glm::vec2)> subtract_bounds(std::function< bool(glm::vec2)> a, std::function< bool(glm::vec2)> b)
Difference of two containment tests.
glm::uvec2 ndc_size_to_pixels(const AABB2D ®ion, uint32_t width, uint32_t height)
Convert an NDC AABB's extent to integer pixel dimensions.
std::function< bool(glm::vec2)> stroke_bounds(std::span< const glm::vec2 > points, float half_thickness)
Containment test for a polyline with a uniform half-thickness.
std::function< bool(glm::vec2)> circular_bounds(glm::vec2 center, float radius) noexcept
Containment test for a circle.
std::function< bool(glm::vec2)> union_bounds(std::function< bool(glm::vec2)> a, std::function< bool(glm::vec2)> b)
Union of two containment tests.
static AABB2D from_pixel(float x, float y, float w, float h, uint32_t win_w, uint32_t win_h) noexcept
Construct from pixel-space top-left rect, converted to NDC.
static AABB2D from_ndc(glm::vec2 center, glm::vec2 half) noexcept
float height() const noexcept
AABB2D expanded(float margin) const noexcept
bool overlaps(const AABB2D &other) const noexcept
bool contains(glm::vec2 p) const noexcept
AABB2D translated(glm::vec2 offset) const noexcept
glm::vec2 center() const noexcept
float width() const noexcept
static AABB2D from_buffer_transform(glm::vec2 ndc_position, glm::vec2 ndc_scale) noexcept
Construct from a TextureBuffer NDC position and scale.
Axis-aligned bounding rectangle in a 2D coordinate space.
glm::vec3 center() const noexcept
bool contains(const glm::vec3 &p) const noexcept
bool overlaps(const AABB3D &other) const noexcept
glm::vec3 half_extent() const noexcept
static AABB3D from_sphere(const BoundingSphere &s) noexcept
Construct the tightest AABB enclosing a BoundingSphere.
static AABB3D from_center(const glm::vec3 &c, const glm::vec3 &half) noexcept
Construct from a center point and half-extents.
AABB3D translated(const glm::vec3 &offset) const noexcept
AABB3D expanded(float margin) const noexcept
glm::vec3 extent() const noexcept
Axis-aligned bounding box in 3D world space.
bool overlaps_ray(const Ray &ray) const noexcept
Returns true if the ray passes through or originates inside the sphere.
bool contains(const glm::vec3 &p) const noexcept
Spherical fast-reject hint in world space.
Origin and normalized direction in world space.