74#ifndef PICO_HIT_MAX_POLY_VERTS
75#define PICO_HIT_MAX_POLY_VERTS 16
272#ifdef PICO_HIT_IMPLEMENTATION
275 #define PICO_HIT_ASSERT(expr) ((void)0)
277 #ifndef PICO_HIT_ASSERT
279 #define PICO_HIT_ASSERT(expr) (assert(expr))
283#define SAT_ASSERT PICO_HIT_ASSERT
311} ph_voronoi_region_t;
319static ph_voronoi_region_t ph_voronoi_region(
pv2 point,
pv2 line);
324 pfloat a11, a12, a21, a22;
328static pfloat ph_m2_det(ph_m2 m);
331static ph_m2 ph_m2_inverse(ph_m2 m,
pfloat det);
334static pv2 ph_m2_map(ph_m2 m,
pv2 v);
351 SAT_ASSERT(vertices);
358 for (
int i = 0; i < vertex_count; i++)
364 for (
int i = 0; i < vertex_count; i++)
366 int next = (i + 1) == vertex_count ? 0 : i + 1;
368 pv2 v1 = vertices[i];
369 pv2 v2 = vertices[next];
395 { pos.
x, pos.
y + size.
y },
396 { pos.
x + size.
x, pos.
y + size.
y },
397 { pos.
x + size.
x, pos.
y }
411 ph_init_manifold(manifold);
417 pfloat overlap = ph_axis_overlap(poly_a, poly_b, poly_a->
normals[i]);
425 ph_update_manifold(manifold, poly_a->
normals[i], overlap);
432 pfloat overlap = ph_axis_overlap(poly_b, poly_a, poly_b->
normals[i]);
440 ph_update_manifold(manifold, poly_b->
normals[i], overlap);
454 ph_init_manifold(manifold);
466 for (
int i = 0; i < count; i++)
468 int next = (i + 1) == count ? 0 : i + 1;
469 int prev = (i - 1) <= 0 ? count - 1 : i - 1;
479 ph_voronoi_region_t region = ph_voronoi_region(point, edge);
482 if (region == PH_VORONOI_LEFT)
490 edge = poly->
edges[prev];
492 region = ph_voronoi_region(point2, edge);
494 if (region == PH_VORONOI_RIGHT)
519 ph_update_manifold(manifold, normal, overlap);
524 else if (region == PH_VORONOI_RIGHT)
527 edge = poly->
edges[next];
529 region = ph_voronoi_region(point2, edge);
531 if (region == PH_VORONOI_LEFT)
543 ph_update_manifold(manifold, normal, overlap);
558 if (diff > 0.0f && abs_diff > circle->
radius)
567 ph_update_manifold(manifold, normal, overlap);
599 SAT_ASSERT(circle_a);
600 SAT_ASSERT(circle_b);
603 ph_init_manifold(manifold);
616 pfloat total_radius2 = total_radius * total_radius;
619 if (dist2 >= total_radius2)
628 pfloat overlap = total_radius - dist;
634 ph_update_manifold(manifold, normal, overlap);
660 pfloat det = ph_m2_det(m);
665 ph_m2 m_inv = ph_m2_inverse(m, det);
668 pv2 p = ph_m2_map(m_inv, c);
670 bool hit = 0.0f <= p.
x && p.
x <= 1.0f &&
671 0.0f <= p.
y && p.
y <= 1.0f;
692 bool has_hit =
false;
707 if (raycast->
dist < min_dist)
709 min_dist = raycast->
dist;
710 min_normal = raycast->
normal;
721 raycast->
dist = min_dist;
722 raycast->
normal = min_normal;
744 if (c > 0.0f && b > 0.0f)
761 raycast->
dist = dist;
812 SAT_ASSERT(manifold);
821 SAT_ASSERT(manifold);
826 if (abs_overlap < manifold->overlap)
829 manifold->
overlap = abs_overlap;
834 else if (overlap > 0.0f)
835 manifold->
normal = normal;
880 ph_axis_range(poly_a, axis, range_a);
881 ph_axis_range(poly_b, axis, range_b);
884 if (range_a[1] < range_b[0] || range_b[1] < range_a[0])
888 pfloat overlap1 = range_a[1] - range_b[0];
889 pfloat overlap2 = range_b[1] - range_a[0];
892 return (overlap2 > overlap1) ? overlap1 : -overlap2;
895static ph_voronoi_region_t ph_voronoi_region(
pv2 point,
pv2 line)
901 return PH_VORONOI_LEFT;
903 return PH_VORONOI_RIGHT;
905 return PH_VORONOI_MIDDLE;
909static pfloat ph_m2_det(ph_m2 m)
911 return m.a11 * m.a22 - m.a21 * m.a12;
915static ph_m2 ph_m2_inverse(ph_m2 m,
pfloat det)
917 pfloat inv_det = 1.0f / det;
918 return (ph_m2) { m.a22 * inv_det, -m.a12 * inv_det, -m.a21 * inv_det, m.a11 * inv_det };
922static pv2 ph_m2_map(ph_m2 m,
pv2 v)
924 return (
pv2){ m.a11 * v.
x + m.a12 * v.
y, m.a21 * v.
x + m.a22 * v.
y };
ph_poly_t ph_transform_poly(const pt2 *transform, const ph_poly_t *poly)
Transforms a polygon using an affine transform.
ph_ray_t ph_make_ray(pv2 pos, pv2 dir, pfloat dist)
Constructs a ray.
pb2 ph_poly_to_aabb(const ph_poly_t *poly)
Returns the bounding box for the given polygon.
ph_circle_t ph_transform_circle(const pt2 *transform, const ph_circle_t *circle)
Transforms a circle using an affine transform.
bool ph_sat_poly_poly(const ph_poly_t *poly_a, const ph_poly_t *poly_b, ph_manifold_t *manifold)
Tests to see if one polygon overlaps with another.
#define PICO_HIT_MAX_POLY_VERTS
Definition pico_hit.h:75
ph_poly_t ph_make_poly(const pv2 vertices[], int vertex_count)
Initializes a polygon.
bool ph_ray_circle(const ph_ray_t *ray, const ph_circle_t *circle, ph_raycast_t *raycast)
Tests if ray intersects a circle.
ph_poly_t ph_aabb_to_poly(const pb2 *aabb)
Converts and axis-aligned bounding box (AABB) to a polygon.
pb2 ph_circle_to_aabb(const ph_circle_t *circle)
Returns the bounding box for the given circle.
bool ph_ray_line(const ph_ray_t *ray, pv2 s1, pv2 s2, ph_raycast_t *raycast)
Tests if ray intersects a (directed) line segment.
bool ph_sat_circle_circle(const ph_circle_t *circle_a, const ph_circle_t *circle_b, ph_manifold_t *manifold)
Tests to see if two circles overlap.
bool ph_sat_poly_circle(const ph_poly_t *poly, const ph_circle_t *circle, ph_manifold_t *manifold)
Tests to see if a polygon overlaps a circle.
bool ph_sat_circle_poly(const ph_circle_t *circle, const ph_poly_t *poly, ph_manifold_t *manifold)
Tests to see if a circle overlaps a polygon.
ph_circle_t ph_make_circle(pv2 pos, pfloat radius)
Initializes a circle.
bool ph_ray_poly(const ph_ray_t *ray, const ph_poly_t *poly, ph_raycast_t *raycast)
Tests if ray intersects a polygon.
pv2 ph_ray_at(const ph_ray_t *ray, pfloat dist)
Finds the point along the ray at the specified distance from the origin.
A 2D math library for games.
PM_INLINE pfloat pv2_dot(pv2 v1, pv2 v2)
Dot product.
Definition pico_math.h:312
#define pv2_make(x, y)
Constructs a vector.
Definition pico_math.h:268
#define pv2_zero()
Returns the zero vector.
Definition pico_math.h:423
PM_INLINE pv2 pv2_scale(pv2 v, pfloat c)
Scales a vector.
Definition pico_math.h:304
PM_INLINE pv2 pv2_normalize(pv2 v)
Normalizes a vector (sets its length to one)
Definition pico_math.h:338
PM_INLINE pv2 pb2_get_pos(const pb2 *b)
Returns the position of an AABB.
Definition pico_math.h:666
PM_INLINE bool pf_equal(pfloat c1, pfloat c2)
Returns true if the values are within epsilon of one another.
Definition pico_math.h:221
PM_INLINE pv2 pv2_sub(pv2 v1, pv2 v2)
Subtracts two vectors.
Definition pico_math.h:294
float pfloat
A single precision floating point number.
Definition pico_math.h:137
#define PM_FLOAT_MAX
Definition pico_math.h:146
#define pb2_make_minmax(min, max)
Definition pico_math.h:651
#define pf_sqrt
Definition pico_math.h:148
#define pf_abs
Definition pico_math.h:154
PM_INLINE pfloat pv2_len2(pv2 v)
Returns the square of the length of the vector.
Definition pico_math.h:320
PM_INLINE pv2 pv2_perp(pv2 v)
Construct a vector that is perpendicular to the specified vector.
Definition pico_math.h:363
PM_INLINE pv2 pb2_get_size(const pb2 *b)
Returns the dimensions of an AABB.
Definition pico_math.h:674
PM_INLINE pv2 pv2_add(pv2 v1, pv2 v2)
Adds two vectors.
Definition pico_math.h:284
pb2 pb2_enclosing(const pv2 verts[], int count)
Computes the minimum box containing all of the vertices.
PM_INLINE pv2 pv2_reflect(pv2 v)
Negates a vector (scales it by -1.0)
Definition pico_math.h:353
PM_INLINE pv2 pt2_map(const pt2 *t, pv2 v)
Transforms a vector.
Definition pico_math.h:549
A 2D axis-aligned-bounding-box (AABB)
Definition pico_math.h:189
A circle shape.
Definition pico_hit.h:82
pfloat radius
Radius of the circle.
Definition pico_hit.h:84
pv2 pos
Center of circle.
Definition pico_hit.h:83
A collision manifold Provides information about a collision. Normals always point from shape 1 to sha...
Definition pico_hit.h:115
pfloat overlap
Amount of overlap between two shapes along colliding axis (MTD)
Definition pico_hit.h:117
pv2 vector
Vector defined by vector = normal * overlap
Definition pico_hit.h:118
pv2 normal
Normal to colliding edge (in direction of MTV)
Definition pico_hit.h:116
A polygon shape Must use CCW (counter-clockwise) winding.
Definition pico_hit.h:92
pv2 normals[PICO_HIT_MAX_POLY_VERTS]
Polygon edge normals.
Definition pico_hit.h:95
pv2 edges[PICO_HIT_MAX_POLY_VERTS]
Edges of polygon.
Definition pico_hit.h:96
int vertex_count
Number of vertices in polygon.
Definition pico_hit.h:93
pv2 vertices[PICO_HIT_MAX_POLY_VERTS]
Polygon vertices.
Definition pico_hit.h:94
A ray (directed line segment)
Definition pico_hit.h:103
pv2 pos
The origin of the ray.
Definition pico_hit.h:104
pv2 dir
The direction of the ray (normalized)
Definition pico_hit.h:105
pfloat dist
The length of the ray.
Definition pico_hit.h:106
Raycast information.
Definition pico_hit.h:125
pv2 normal
The surface normal at the point of impact.
Definition pico_hit.h:126
pfloat dist
The distance fromt the origin to the point of impact.
Definition pico_hit.h:127
A 2D transform.
Definition pico_math.h:181
A 2D vector.
Definition pico_math.h:173
pfloat y
Definition pico_math.h:174
pfloat x
Definition pico_math.h:174