74#ifndef PICO_HIT_MAX_POLY_VERTS
75#define PICO_HIT_MAX_POLY_VERTS 16
335#ifdef PICO_HIT_IMPLEMENTATION
338 #define PICO_HIT_ASSERT(expr) ((void)0)
340 #ifndef PICO_HIT_ASSERT
342 #define PICO_HIT_ASSERT(expr) (assert(expr))
346#define PH_ASSERT PICO_HIT_ASSERT
353static void ph_init_result(
ph_sat_t* result);
356static void ph_project_poly(
const ph_poly_t* poly,
362static void ph_project_circle(
const ph_circle_t *circle,
371static int ph_closest_vertex(
const ph_poly_t *poly,
pv2 point);
374static pv2 ph_closest_point_on_segment(
pv2 end_point_a,
pv2 end_point_b,
pv2 point);
380static int ph_find_incident_edge(
const ph_poly_t* poly,
pv2 normal);
383static int ph_clip_segment_to_line(
pv2* in_points,
pv2* out_points,
pv2 plane_normal,
pfloat offset);
388 pfloat a11, a12, a21, a22;
392static pfloat ph_m2_det(ph_m2 m);
395static ph_m2 ph_m2_inverse(ph_m2 m,
pfloat det);
398static pv2 ph_m2_map(ph_m2 m,
pv2 v);
425 for (
int i = 0; i < count; i++)
427 poly.
vertices[i] = vertices[count - i - 1];
433 for (
int i = 0; i < count; i++)
442 for (
int i = 0; i < count; i++)
476 { pos.
x, pos.
y + size.
y },
477 { pos.
x + size.
x, pos.
y + size.
y },
478 { pos.
x + size.
x, pos.
y }
499 ph_init_result(result);
502 for (
int i = 0; i < poly_a->
count; i++)
504 pfloat poly_a_min, poly_a_max, poly_b_min, poly_b_max;
507 ph_project_poly(poly_a, poly_a->
normals[i], &poly_a_min, &poly_a_max);
510 ph_project_poly(poly_b, poly_a->
normals[i], &poly_b_min, &poly_b_max);
513 pfloat overlap = ph_calc_overlap(poly_a_min, poly_a_max, poly_b_min, poly_b_max);
520 if (result && overlap < result->overlap)
528 for (
int i = 0; i < poly_b->
count; i++)
530 pfloat poly_b_min, poly_b_max, poly_a_min, poly_a_max;
533 ph_project_poly(poly_b, poly_b->
normals[i], &poly_b_min, &poly_b_max);
536 ph_project_poly(poly_a, poly_b->
normals[i], &poly_a_min, &poly_a_max);
539 pfloat overlap = ph_calc_overlap(poly_b_min, poly_b_max, poly_a_min, poly_a_max);
546 if (result && overlap < result->overlap)
583 ph_init_result(result);
585 for (
int i = 0; i < poly->
count; i++)
589 float poly_min, poly_max, circle_min, circle_max;
592 ph_project_poly(poly, axis, &poly_min, &poly_max);
595 ph_project_circle(circle, axis, &circle_min, &circle_max);
598 float overlap = ph_calc_overlap(poly_min, poly_max, circle_min, circle_max);
605 if (result && overlap < result->overlap)
613 int closest = ph_closest_vertex(poly, circle->
center);
618 pfloat poly_min, poly_max, circle_min, circle_max;
621 ph_project_poly(poly, axis, &poly_min, &poly_max);
624 ph_project_circle(circle, axis, &circle_min, &circle_max);
627 pfloat overlap = ph_calc_overlap(poly_min, poly_max, circle_min, circle_max);
634 if (result && overlap < result->overlap)
687 ph_init_result(result);
700 pfloat total_radius2 = total_radius * total_radius;
703 if (dist2 >= total_radius2)
712 pfloat overlap = total_radius - dist;
749 int best_edge_a = ph_find_best_edge(poly_a, normal, &max_dot_a);
750 int best_edge_b = ph_find_best_edge(poly_b,
pv2_reflect(normal), &max_dot_b);
757 if (max_dot_a > max_dot_b)
761 ref_index = best_edge_a;
767 ref_index = best_edge_b;
772 int inc_index = ph_find_incident_edge(inc_poly, normal);
787 if (
pv2_dot(ref_normal, normal) < 0.0f)
791 pv2 clip_in[2] = { inc_v1, inc_v2 };
792 pv2 clip_out[2] = { 0 };
795 pv2 side_normal1 = ref_tangent;
797 int num_clipped = ph_clip_segment_to_line(clip_in, clip_out, side_normal1, offset1);
805 num_clipped = ph_clip_segment_to_line(clip_out, clip_in, side_normal2, offset2);
811 for (
int i = 0; i < num_clipped; i++)
815 if (separation <= 0.0f)
818 contact->
point = clip_in[i];
819 contact->
depth = -separation;
822 if (manifold->
count >= 2)
827 return (manifold->
count > 0);
850 for (
int i = 0; i < poly->
count; i++)
852 int next = (i + 1) % poly->
count;
854 pv2 point = ph_closest_point_on_segment(
861 float dist2 =
pv2_dot(diff, diff);
863 if (dist2 < min_dist2)
929 manifold->
normal = normal;
962 pfloat det = ph_m2_det(m);
967 ph_m2 m_inv = ph_m2_inverse(m, det);
970 pv2 p = ph_m2_map(m_inv, c);
972 bool hit = 0.0f <= p.
x && p.
x <= 1.0f &&
973 0.0f <= p.
y && p.
y <= 1.0f;
994 bool has_hit =
false;
996 for (
int i = 0; i < poly->
count; i++)
998 int next = (i + 1) % poly->
count;
1009 if (raycast->
dist < min_dist)
1011 min_dist = raycast->
dist;
1012 min_normal = raycast->
normal;
1023 raycast->
dist = min_dist;
1024 raycast->
normal = min_normal;
1046 if (c > 0.0f && b > 0.0f)
1049 pfloat discr = b * b - c;
1063 raycast->
dist = dist;
1079 for (
int i = 0; i < poly->
count; i++)
1112static void ph_init_result(
ph_sat_t* result)
1136static void ph_project_poly(
const ph_poly_t* poly,
1149 for (
int i = 1; i < poly->
count; i++)
1164 *min = proj - circle->
radius;
1165 *max = proj + circle->
radius;
1168static int ph_closest_vertex(
const ph_poly_t *poly,
pv2 point)
1173 for (
int i = 0; i < poly->
count; i++)
1178 if (dist2 < min_dist2)
1189static pv2 ph_closest_point_on_segment(
pv2 end_point_a,
pv2 end_point_b,
pv2 point)
1211 for (
int i = 0; i < poly->
count; i++)
1226static int ph_find_incident_edge(
const ph_poly_t* poly,
pv2 normal)
1232 for (
int i = 0; i < poly->
count; i++)
1246static int ph_clip_segment_to_line(
pv2* in_points,
pv2* out_points,
pv2 plane_normal,
pfloat offset)
1250 float d0 =
pv2_dot(plane_normal, in_points[0]) - offset;
1251 float d1 =
pv2_dot(plane_normal, in_points[1]) - offset;
1254 if (d0 >= 0.0f) out_points[num_out++] = in_points[0];
1255 if (d1 >= 0.0f) out_points[num_out++] = in_points[1];
1260 pfloat alpha = d0 / (d0 - d1);
1262 out_points[num_out++] = intersection;
1269static pfloat ph_m2_det(ph_m2 m)
1271 return m.a11 * m.a22 - m.a21 * m.a12;
1275static ph_m2 ph_m2_inverse(ph_m2 m,
pfloat det)
1277 pfloat inv_det = 1.0f / det;
1278 return (ph_m2) { m.a22 * inv_det, -m.a12 * inv_det, -m.a21 * inv_det, m.a11 * inv_det };
1282static pv2 ph_m2_map(ph_m2 m,
pv2 v)
1284 return (
pv2){ m.a11 * v.
x + m.a12 * v.
y, m.a21 * v.
x + m.a22 * v.
y };
ph_poly_t ph_make_poly(const pv2 vertices[], int count, bool reverse)
Initializes a polygon.
bool ph_sat_poly_circle(const ph_poly_t *poly, const ph_circle_t *circle, ph_sat_t *result)
Tests to see if a convex polygon overlaps a circle.
ph_poly_t ph_transform_poly(const pt2 *transform, const ph_poly_t *poly)
Transforms a polygon using an affine transform.
bool ph_sat_circle_poly(const ph_circle_t *circle, const ph_poly_t *poly, ph_sat_t *result)
Tests to see if a circle overlaps a polygon.
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_manifold_circle_poly(const ph_circle_t *circle, const ph_poly_t *poly, ph_manifold_t *manifold)
Tests if a circle and polygon collide and generates contact information.
bool ph_manifold_circle_circle(const ph_circle_t *circle_a, const ph_circle_t *circle_b, ph_manifold_t *manifold)
Tests if two circles collide and generates contact information.
#define PICO_HIT_MAX_POLY_VERTS
Definition pico_hit.h:75
ph_circle_t ph_make_circle(pv2 center, pfloat radius)
Initializes a circle.
bool ph_manifold_poly_circle(const ph_poly_t *poly, const ph_circle_t *circle, ph_manifold_t *manifold)
Tests if a polygon and circle collide and generates contact information.
bool ph_ray_circle(const ph_ray_t *ray, const ph_circle_t *circle, ph_raycast_t *raycast)
Tests if ray intersects a circle.
bool ph_sat_poly_poly(const ph_poly_t *poly_a, const ph_poly_t *poly_b, ph_sat_t *result)
Tests to see if one convex polygon overlaps with another.
ph_poly_t ph_aabb_to_poly(const pb2 *aabb)
Converts an axis-aligned bounding box (AABB) to a polygon.
bool ph_manifold_poly_poly(const ph_poly_t *poly_a, const ph_poly_t *poly_b, ph_manifold_t *manifold)
Tests if a polygon collides with another polygon and generates contact information.
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_sat_t *result)
Tests to see if two circles overlap.
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.
ph_ray_t ph_make_ray(pv2 origin, pv2 dir, pfloat len)
Constructs a ray.
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 pfloat pt2_det(const pt2 *t)
Returns the determinant of the transform.
Definition pico_math.h:560
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 PM_EPSILON
Definition pico_math.h:139
PM_INLINE pfloat pv2_len(pv2 v)
Returns the length of the vector.
Definition pico_math.h:328
#define pf_max
Definition pico_math.h:161
#define pf_min
Definition pico_math.h:162
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
#define PM_FLOAT_MIN
Definition pico_math.h:145
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 center
Center of circle.
Definition pico_hit.h:83
Definition pico_hit.h:122
pfloat overlap
Amount of overlap between two shapes along colliding axis (MTD)
Definition pico_hit.h:124
ph_contact_t contacts[2]
Contact points (maximum of two)
Definition pico_hit.h:125
int count
Numer of contacts.
Definition pico_hit.h:126
pv2 normal
Contact normal (from SAT)
Definition pico_hit.h:123
A polygon shape Must use CCW (counter-clockwise) winding.
Definition pico_hit.h:92
pv2 centroid
Definition pico_hit.h:97
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
pv2 vertices[PICO_HIT_MAX_POLY_VERTS]
Polygon vertices.
Definition pico_hit.h:94
int count
Number of vertices in polygon.
Definition pico_hit.h:93
A ray (directed line segment)
Definition pico_hit.h:133
pv2 dir
The direction of the ray (normalized)
Definition pico_hit.h:135
pv2 origin
The origin of the ray.
Definition pico_hit.h:134
pfloat len
The length of the ray.
Definition pico_hit.h:136
Raycast information.
Definition pico_hit.h:143
pv2 normal
The surface normal at the point of impact.
Definition pico_hit.h:144
pfloat dist
The distance from the ray's origin to the point of impact.
Definition pico_hit.h:145
A collision result Provides information about a collision. Normals always point from the target shape...
Definition pico_hit.h:106
pfloat overlap
Amount of overlap between two shapes along colliding axis (MTD)
Definition pico_hit.h:108
pv2 normal
Normal to colliding edge (in direction of MTV)
Definition pico_hit.h:107
pv2 mtv
Minimum Translation Vector (MTV) defined by `mtv = normal * overlap.
Definition pico_hit.h:109
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