Remove the corner helpers akgl_collide_rectangles no longer uses
akgl_rectangle_points, akgl_collide_point_rectangle, akgl_Point and akgl_RectanglePoints go. They were the intermediate form of an implementation that changed: akgl_collide_rectangles was eight corner-containment tests built on them, and it has been four span comparisons since the cross-case fix. Nothing outside tests/ called either function, and a point-in-rectangle test is four comparisons a caller can write without a struct conversion in front of them. akgl_collide_rectangles stays. It has two correct callers in the sidescroller asking a game-level overlap question -- a coin, a hazard, from an updatefunc -- where a bool is the whole answer and a proxy plus a narrowphase call would be computing a normal nothing reads. TODO.md records the split rather than leaving it to be rediscovered. Public API removal, so 194 exported akgl_ symbols against 196, and the manual's counts move with them. The perf suite loses its rectangle_points row; the all-pairs sweep stays as the control it is now labelled, and PERFORMANCE.md says what 0.8.0 measured against it -- 188.5 us for 32,640 pairs at 256 actors, where a whole step with collision attached is 54.1 us doing strictly more. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KzBDV2fqgnUAcqCKqKvc71
This commit is contained in:
@@ -1,15 +1,16 @@
|
||||
/**
|
||||
* @file util.h
|
||||
* @brief Axis-aligned collision tests, path resolution, and two test-only image helpers.
|
||||
* @brief A rectangle overlap test, path resolution, and two test-only image helpers.
|
||||
*
|
||||
* The grab bag. Three unrelated groups live here: rectangle/point overlap for
|
||||
* the physics backend, path resolution for the asset loaders, and a pair of
|
||||
* pixel-comparison routines that exist only so tests can assert on what was
|
||||
* actually drawn.
|
||||
* The grab bag. Three unrelated groups live here: one rectangle overlap test,
|
||||
* path resolution for the asset loaders, and a pair of pixel-comparison routines
|
||||
* that exist only so tests can assert on what was actually drawn.
|
||||
*
|
||||
* All the geometry here is axis-aligned and treats edges as touching: a point
|
||||
* exactly on a boundary is inside. There is no rotation support and no
|
||||
* separating-axis test.
|
||||
* akgl_collide_rectangles is axis-aligned and treats edges as touching: two
|
||||
* rectangles sharing an edge and nothing more overlap. It answers a *game's*
|
||||
* question -- a pickup, a minimap marker, a UI hit test -- and is deliberately
|
||||
* not what the physics step uses. Anything that should push or be pushed wants a
|
||||
* collision shape and akgl_collision_test; see `akgl/collision.h`.
|
||||
*/
|
||||
|
||||
#ifndef _AKGL_UTIL_H_
|
||||
@@ -20,71 +21,12 @@
|
||||
#include <stdbool.h>
|
||||
#include <akgl/staticstring.h>
|
||||
|
||||
/** @brief An integer point. Carries a `z` the collision routines do not use. */
|
||||
typedef struct akgl_Point {
|
||||
int x; /**< Horizontal position, in whatever space the caller is working in. */
|
||||
int y; /**< Vertical position. */
|
||||
int z; /**< Depth. Never written by akgl_rectangle_points and never read by the collision tests. */
|
||||
} akgl_Point;
|
||||
|
||||
/**
|
||||
* @brief The four corners of an axis-aligned rectangle, precomputed.
|
||||
*
|
||||
* The form akgl_collide_point_rectangle wants. akgl_rectangle_points derives one
|
||||
* of these from an `SDL_FRect`.
|
||||
*
|
||||
* @note akgl_collide_rectangles used to be built on this, corner by corner, and
|
||||
* missed the cross case that way -- two rectangles overlapping in a plus
|
||||
* sign have no corner of either inside the other. It compares edge spans
|
||||
* in `float32_t` since 0.8.0 and does not go through here at all.
|
||||
*/
|
||||
typedef struct akgl_RectanglePoints {
|
||||
akgl_Point topleft; /**< (x, y). */
|
||||
akgl_Point topright; /**< (x + w, y). */
|
||||
akgl_Point bottomleft; /**< (x, y + h). */
|
||||
akgl_Point bottomright; /**< (x + w, y + h). */
|
||||
} akgl_RectanglePoints;
|
||||
|
||||
/**
|
||||
* @brief Expand a rectangle into its four corner points.
|
||||
*
|
||||
* Coordinates are truncated from `float` to `int` on the way in, so a rectangle
|
||||
* at x = 10.9 has its corners at 10. That is deliberate for tile-grid work and
|
||||
* wrong for sub-pixel work; callers needing the latter should not round-trip
|
||||
* through this.
|
||||
*
|
||||
* @param dest Receives the corners. Required.
|
||||
* @param rect The rectangle, in any coordinate space. Required. `w` and `h` are
|
||||
* taken as extents from `x`/`y`, so a negative one produces a
|
||||
* rectangle whose "bottom right" is above and left of its "top
|
||||
* left" -- which every test here then reports as empty.
|
||||
* @return `NULL` on success, otherwise an error context owned by the caller.
|
||||
* @throws AKERR_NULLPOINTER If @p dest or @p rect is `NULL`.
|
||||
*/
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_rectangle_points(akgl_RectanglePoints *dest, SDL_FRect *rect);
|
||||
/**
|
||||
* @brief Test whether a point falls inside a rectangle, edges included.
|
||||
*
|
||||
* Compares against `topleft` and `bottomright` only, so it assumes @p r is
|
||||
* well-formed -- the two corners actually being the minimum and maximum. `z` is
|
||||
* ignored on both sides: this is a 2D test.
|
||||
*
|
||||
* @param p The point to test. Required.
|
||||
* @param r The rectangle, as corners from akgl_rectangle_points. Required.
|
||||
* @param collide Receives `true` when the point is inside or exactly on an edge,
|
||||
* `false` otherwise. Required -- the return value is the error
|
||||
* context. Not written on any failure path.
|
||||
* @return `NULL` on success, otherwise an error context owned by the caller.
|
||||
* @throws AKERR_NULLPOINTER If @p p, @p r, or @p collide is `NULL`.
|
||||
*/
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_collide_point_rectangle(akgl_Point *p, akgl_RectanglePoints *r, bool *collide);
|
||||
/**
|
||||
* @brief Test whether two rectangles overlap, edges included.
|
||||
*
|
||||
* Tests all eight corners -- each rectangle's four against the other -- and
|
||||
* stops at the first hit. Checking both directions is what catches the case
|
||||
* where one rectangle is entirely inside the other and so has no corner within
|
||||
* its neighbour.
|
||||
* Compares the two rectangles' spans on both axes: they overlap when neither is
|
||||
* wholly to one side of the other. Four comparisons, in `float32_t`, with no
|
||||
* intermediate form.
|
||||
*
|
||||
* @param r1 First rectangle. Required.
|
||||
* @param r2 Second rectangle. Required. Order does not matter.
|
||||
@@ -99,8 +41,15 @@ akerr_ErrorContext AKERR_NOIGNORE *akgl_collide_point_rectangle(akgl_Point *p, a
|
||||
* the other, and every corner test said no. It is a span comparison on
|
||||
* both axes now. Two consequences for a caller upgrading: that
|
||||
* arrangement starts reporting `true`, and the comparison is in `float`
|
||||
* rather than through akgl_Point's `int` members, so an overlap smaller
|
||||
* than one pixel is no longer truncated away.
|
||||
* rather than through the removed akgl_Point's `int` members, so an
|
||||
* overlap smaller than one pixel is no longer truncated away.
|
||||
*
|
||||
* @note akgl_rectangle_points, akgl_collide_point_rectangle, akgl_Point and
|
||||
* akgl_RectanglePoints were removed in 0.8.0. They existed to feed the
|
||||
* corner form this no longer uses, and nothing outside `tests/` called
|
||||
* either function. A point-in-rectangle test is four comparisons a caller
|
||||
* can write; the intermediate struct was the only thing this header was
|
||||
* adding.
|
||||
*/
|
||||
akerr_ErrorContext AKERR_NOIGNORE *akgl_collide_rectangles(SDL_FRect *r1, SDL_FRect *r2, bool *collide);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user