v4k-git-backup/engine/split/fwk_collide.c

1426 lines
43 KiB
C

/* poly */
poly poly_alloc(int cnt) {
poly p = {0};
p.cnt = cnt;
p.verts = REALLOC(p.verts, sizeof(p.verts[0]) * cnt); // array_resize(p.verts, cnt);
return p;
}
void poly_free(poly *p) {
REALLOC(p->verts, 0); // array_free(p->verts);
poly z = {0};
*p = z;
}
/* plane */
vec4 plane4(vec3 p, vec3 n) {
return vec34(n, -dot3(n,p));
}
/* pyramid */
poly pyramid(vec3 from, vec3 to, float size) {
/* calculate axis */
vec3 up, right, forward = norm3( sub3(to, from) );
ortho3(&right, &up, forward);
/* calculate extend */
vec3 xext = scale3(right, size);
vec3 yext = scale3(up, size);
vec3 nxext = scale3(right, -size);
vec3 nyext = scale3(up, -size);
/* calculate base vertices */
poly p = {0};
p.verts = REALLOC(p.verts, sizeof(p.verts[0]) * (5+1)); p.cnt = 5; /*+1 for diamond case*/ // array_resize(p.verts, 5+1); p.cnt = 5;
p.verts[0] = add3(add3(from, xext), yext); /*a*/
p.verts[1] = add3(add3(from, xext), nyext); /*b*/
p.verts[2] = add3(add3(from, nxext), nyext); /*c*/
p.verts[3] = add3(add3(from, nxext), yext); /*d*/
p.verts[4] = to; /*r*/
return p;
}
/* pyramid */
poly diamond(vec3 from, vec3 to, float size) {
vec3 mid = add3(from, scale3(sub3(to, from), 0.5f));
poly p = pyramid(mid, to, size);
p.verts[5] = from; p.cnt = 6;
return p;
}
// ---
static void transform_(vec3 *r, vec3 v, const float *r33, vec3 t3) {
for (int i = 0; i < 3; ++i) {
i[&r->x] = i[&v.x] * r33[i*3+0];
i[&r->x] += i[&v.x] * r33[i*3+1];
i[&r->x] += i[&v.x] * r33[i*3+2];
i[&r->x] += i[&t3.x];
}
}
static void transformS(vec3 *v, const float *r33, vec3 t3) {
vec3 tmp = *v;
transform_(v, tmp, r33, t3);
}
static void transformT(vec3 *r, vec3 v, const float *r33, vec3 t3) {
for (int i = 0; i < 3; ++i) {
float p = i[&v.x] - i[&t3.x];
i[&r->x] = p * r33[0*3+i];
i[&r->x] += p * r33[1*3+i];
i[&r->x] += p * r33[2*3+i];
}
}
static void transformST(vec3 *v, const float *r33, vec3 t3) {
vec3 tmp = *v;
transformT(v, tmp, r33, t3);
}
/* ============================================================================
*
* COLLISION
*
* =========================================================================== */
static __thread hit hits[16] = {0};
static __thread int hit_index = -1;
#define hit_next() &hits[ (++hit_index) & 15 ]
static float line_closest_line_(float *t1, float *t2, vec3 *c1, vec3 *c2, line l, line m) {
vec3 r, d1, d2;
d1 = sub3(l.b, l.a); /* direction vector segment s1 */
d2 = sub3(m.b, m.a); /* direction vector segment s2 */
r = sub3(l.a, m.a);
float i = dot3(d1, d1);
float e = dot3(d2, d2);
float f = dot3(d2, r);
if (i <= C_EPSILON && e <= C_EPSILON) {
/* both segments degenerate into points */
vec3 d12;
*t1 = *t2 = 0.0f;
*c1 = l.a;
*c2 = m.a;
d12 = sub3(*c1, *c2);
return dot3(d12,d12);
}
if (i > C_EPSILON) {
float c = dot3(d1,r);
if (e > C_EPSILON) {
/* non-degenerate case */
float b = dot3(d1,d2);
float denom = i*e - b*b;
/* compute closest point on L1/L2 if not parallel else pick any t2 */
if (denom != 0.0f)
*t1 = clampf(0.0f, (b*f - c*e) / denom, 1.0f);
else *t1 = 0.0f;
/* cmpute point on L2 closest to S1(s) */
*t2 = (b*(*t1) + f) / e;
if (*t2 < 0.0f) {
*t2 = 0.0f;
*t1 = clampf(0.0f, -c/i, 1.0f);
} else if (*t2 > 1.0f) {
*t2 = 1.0f;
*t1 = clampf(0.0f, (b-c)/i, 1.0f);
}
} else {
/* second segment degenerates into a point */
*t1 = clampf(0.0f, -c/i, 1.0f);
*t2 = 0.0f;
}
} else {
/* first segment degenerates into a point */
*t2 = clampf(0.0f, f/e, 1.0f);
*t1 = 0.0f;
}
/* calculate closest points */
vec3 n, d12;
n = scale3(d1, *t1);
*c1 = add3(l.a, n);
n = scale3(d2, *t2);
*c2 = add3(m.a, n);
/* calculate squared distance */
d12 = sub3(*c1, *c2);
return dot3(d12,d12);
}
vec3 line_closest_point(line l, vec3 p) {
vec3 ab = sub3(l.b,l.a), pa = sub3(p,l.a);
float t = dot3(pa,ab) / dot3(ab,ab);
return add3(l.a, scale3(ab, t < 0 ? 0 : t > 1 ? 1 : t));
}
float line_distance2_point(line l, vec3 p) {
vec3 ab = sub3(l.a,l.b), ap = sub3(l.a,p), bp = sub3(l.b,p);
/* handle cases p proj outside ab */
float e = dot3(ap,ab); if (e <= 0) return dot3(ap,ap);
float f = dot3(ab,ab); if (e >= f) return dot3(bp,bp);
return dot3(ap,ap) - (e*e)/f;
}
float ray_test_plane(ray r, vec4 plane) {
/* Ray: P = origin + rd * t
* Plane: plane_normal * P + d = 0
*
* Substitute:
* normal * (origin + rd*t) + d = 0
*
* Solve for t:
* plane_normal * origin + plane_normal * rd*t + d = 0
* -(plane_normal*rd*t) = plane_normal * origin + d
*
* plane_normal * origin + d
* t = -1 * -------------------------
* plane_normal * rd
*
* Result:
* Behind: t < 0
* Infront: t >= 0
* Parallel: t = 0
* Intersection point: ro + rd * t
*/
vec3 p = ptr3(&plane.x);
float n = -(dot3(p,r.p) + plane.w);
if (fabs(n) < 0.0001f) return 0.0f;
return n/(dot3(p,r.d));
}
float ray_test_triangle(ray r, triangle tr) {
float t = 0;
vec3 di0, di1, di2;
vec3 d21, d02, in;
vec3 n, d10, d20;
vec3 in0, in1, in2;
/* calculate triangle normal */
d10 = sub3(tr.p1,tr.p0);
d20 = sub3(tr.p2,tr.p0);
d21 = sub3(tr.p2,tr.p1);
d02 = sub3(tr.p0,tr.p2);
n = cross3(d10,d20);
/* check for plane intersection */
vec4 p = plane4(tr.p0, n);
t = ray_test_plane(r, p);
if (t <= 0.0f) return t;
/* intersection point */
in = scale3(r.d,t);
in = add3(in,r.p);
/* check if point inside triangle in plane */
di0 = sub3(in, tr.p0);
di1 = sub3(in, tr.p1);
di2 = sub3(in, tr.p2);
in0 = cross3(d10, di0);
in1 = cross3(d21, di1);
in2 = cross3(d02, di2);
if (dot3(in0,n) < 0.0f)
return -1;
if (dot3(in1,n) < 0.0f)
return -1;
if (dot3(in2,n) < 0.0f)
return -1;
return t;
}
int ray_test_sphere(float *t0, float *t1, ray r, sphere s) {
vec3 a;
float tc,td,d2,r2;
a = sub3(s.c,r.p);
tc = dot3(r.d,a);
if (tc < 0) return 0;
r2 = s.r*s.r;
d2 = dot3(a,a) - tc*tc;
if (d2 > r2) return 0;
td = sqrtf(r2 - d2);
*t0 = tc - td;
*t1 = tc + td;
return 1;
}
int ray_test_aabb(float *t0, float *t1, ray r, aabb a) {
float t0x = (a.min.x - r.p.x) / r.d.x;
float t0y = (a.min.y - r.p.y) / r.d.y;
float t0z = (a.min.z - r.p.z) / r.d.z;
float t1x = (a.max.x - r.p.x) / r.d.x;
float t1y = (a.max.y - r.p.y) / r.d.y;
float t1z = (a.max.z - r.p.z) / r.d.z;
float tminx = minf(t0x, t1x);
float tminy = minf(t0y, t1y);
float tminz = minf(t0z, t1z);
float tmaxx = maxf(t0x, t1x);
float tmaxy = maxf(t0y, t1y);
float tmaxz = maxf(t0z, t1z);
if (tminx > tmaxy || tminy > tmaxx)
return 0;
*t0 = maxf(tminx, tminy);
*t1 = minf(tmaxy, tmaxx);
if (*t0 > tmaxz || tminz> *t1)
return 0;
*t0 = maxf(*t0, tminz);
*t1 = minf(*t1, tmaxz);
return 1;
}
vec3 sphere_closest_point(sphere s, vec3 p) {
vec3 d = norm3(sub3(p, s.c));
return add3(s.c, scale3(d,s.r));
}
int sphere_test_sphere(sphere a, sphere b) {
vec3 d = sub3(b.c, a.c);
float r = a.r + b.r;
if (dot3(d,d) > r*r)
return 0;
return 1;
}
hit *sphere_hit_sphere(sphere a, sphere b) {
vec3 d = sub3(b.c, a.c);
float r = a.r + b.r;
float d2 = dot3(d,d);
if (d2 > r*r) return 0;
hit *m = hit_next();
float l = sqrtf(d2);
float linv = 1.0f / ((l != 0) ? l: 1.0f);
m->normal = scale3(d, linv);
m->depth = r - l;
d = scale3(m->normal, b.r);
m->contact_point = sub3(b.c, d);
return m;
}
int sphere_test_aabb(sphere s, aabb a) {
return aabb_test_sphere(a, s);
}
hit *sphere_hit_aabb(sphere s, aabb a) {
/* find closest aabb point to sphere center point */
vec3 ap = aabb_closest_point(a, s.c);
vec3 d = sub3(s.c, ap);
float d2 = dot3(d, d);
if (d2 > s.r*s.r) return 0;
hit *m = hit_next();
/* calculate distance vector between sphere and aabb center points */
vec3 ac = add3(a.min, scale3(sub3(a.max, a.min), 0.5f));
d = sub3(ac, s.c);
/* normalize distance vector */
float l2 = dot3(d,d);
float l = l2 != 0.0f ? sqrtf(l2): 1.0f;
float linv = 1.0f/l;
d = scale3(d, linv);
m->normal = d;
m->contact_point = scale3(m->normal, s.r);
m->contact_point = add3(s.c, m->contact_point);
/* calculate penetration depth */
vec3 sp = sphere_closest_point(s, ap);
d = sub3(sp, ap);
m->depth = sqrtf(dot3(d,d)) - l;
return m;
}
int sphere_test_capsule(sphere s, capsule c) {
return capsule_test_sphere(c, s);
}
hit *sphere_hit_capsule(sphere s, capsule c) {
#if 0
// original code
/* find closest capsule point to sphere center point */
hit *m = hit_next();
vec3 cp = capsule_closest_point(c, s.c);
m->normal = sub3(cp, s.c);
float d2 = dot3(m->normal, m->normal);
if (d2 > s.r*s.r) return 0;
/* normalize hit normal vector */
m->normal = norm3(m->normal);
/* calculate penetration depth */
m->depth = d2 - s.r*s.r;
m->depth = m->depth != 0.0f ? sqrtf(m->depth): 0.0f;
m->contact_point = add3(s.c, scale3(m->normal, s.r));
return m;
#else
// aproximation of I would expect this function to return instead
vec3 l = sub3(c.a,c.b); float len = len3(l);
vec3 d = norm3(l);
ray r = ray(add3(c.a,scale3(d,-2*len)), d);
s.r += c.r;
hit *h = ray_hit_sphere(r, s);
if(!h) return 0;
s.r -= c.r;
h->contact_point = add3(s.c,scale3(norm3(sub3(h->contact_point,s.c)),s.r));
return h;
#endif
}
int sphere_test_poly(sphere s, poly p) {
return poly_test_sphere(p, s);
}
void aabb_rebalance_transform(aabb *b, aabb a, mat33 m, vec3 t) {
for (int i = 0; i < 3; ++i) {
i[&b->min.x] = i[&b->max.x] = i[&t.x];
for (int j = 0; j < 3; ++j) {
float e = m[i*3+j] * j[&a.min.x];
float f = m[i*3+j] * j[&a.max.x];
if (e < f) {
i[&b->min.x] += e;
i[&b->max.x] += f;
} else {
i[&b->min.x] += f;
i[&b->max.x] += e;
}
}
}
}
vec3 aabb_closest_point(aabb a, vec3 p) {
vec3 res;
for (int i = 0; i < 3; ++i) {
float v = i[&p.x];
if (v < i[&a.min.x]) v = i[&a.min.x];
if (v > i[&a.max.x]) v = i[&a.max.x];
i[&res.x] = v;
}
return res;
}
float aabb_distance2_point(aabb a, vec3 p) {
float r = 0;
for (int i = 0; i < 3; ++i) {
float v = i[&p.x];
if (v < i[&a.min.x]) r += (i[&a.min.x]-v) * (i[&a.min.x]-v);
if (v > i[&a.max.x]) r += (v-i[&a.max.x]) * (v-i[&a.max.x]);
} return r;
}
int aabb_contains_point(aabb a, vec3 p) {
if (p.x < a.min.x || p.x > a.max.x) return 0;
if (p.y < a.min.y || p.y > a.max.y) return 0;
if (p.z < a.min.z || p.z > a.max.z) return 0;
return 1;
}
int aabb_test_aabb(aabb a, aabb b) {
if (a.max.x < b.min.x || a.min.x > b.max.x) return 0;
if (a.max.y < b.min.y || a.min.y > b.max.y) return 0;
if (a.max.z < b.min.z || a.min.z > b.max.z) return 0;
return 1;
}
hit *aabb_hit_aabb(aabb a, aabb b) {
if (!aabb_test_aabb(a, b))
return 0;
hit *m = hit_next();
/* calculate distance vector between both aabb center points */
vec3 ac, bc, d;
ac = sub3(a.max, a.min);
bc = sub3(b.max, b.min);
ac = scale3(ac, 0.5f);
bc = scale3(bc, 0.5f);
ac = add3(a.min, ac);
bc = add3(b.min, bc);
d = sub3(bc, ac);
/* normalize distance vector */
float l2 = dot3(d,d);
float l = l2 != 0.0f ? sqrtf(l2): 1.0f;
float linv = 1.0f/l;
d = scale3(d, linv);
/* calculate contact point */
m->normal = d;
m->contact_point = aabb_closest_point(a, bc);
d = sub3(m->contact_point, ac);
/* calculate penetration depth */
float r2 = dot3(d,d);
float r = sqrtf(r2);
m->depth = r - l;
return m;
}
int aabb_test_sphere(aabb a, sphere s) {
/* compute squared distance between sphere center and aabb */
float d2 = aabb_distance2_point(a, s.c);
/* intersection if distance is smaller/equal sphere radius*/
return d2 <= s.r*s.r;
}
hit *aabb_hit_sphere(aabb a, sphere s) {
/* find closest aabb point to sphere center point */
hit *m = hit_next();
m->contact_point = aabb_closest_point(a, s.c);
vec3 d = sub3(s.c, m->contact_point);
float d2 = dot3(d, d);
if (d2 > s.r*s.r) return 0;
/* calculate distance vector between aabb and sphere center points */
vec3 ac = add3(a.min, scale3(sub3(a.max, a.min), 0.5f));
d = sub3(s.c, ac);
/* normalize distance vector */
float l2 = dot3(d,d);
float l = l2 != 0.0f ? sqrtf(l2): 1.0f;
float linv = 1.0f/l;
d = scale3(d, linv);
/* calculate penetration depth */
m->normal = d;
d = sub3(m->contact_point, ac);
m->depth = sqrtf(dot3(d,d));
return m;
}
int aabb_test_capsule(aabb a, capsule c) {
return capsule_test_aabb(c, a);
}
hit *aabb_hit_capsule(aabb a, capsule c) {
/* calculate aabb center point */
vec3 ac = add3(a.min, scale3(sub3(a.max, a.min), 0.5f));
/* calculate closest point from aabb to point on capsule and check if inside aabb */
vec3 cp = capsule_closest_point(c, ac);
if (!aabb_contains_point(a, cp))
return 0;
hit *m = hit_next();
/* vector and distance between both capsule closests point and aabb center*/
vec3 d; float d2;
d = sub3(cp, ac);
d2 = dot3(d,d);
/* calculate penetration depth from closest aabb point to capsule */
vec3 ap = aabb_closest_point(a, cp);
vec3 dt = sub3(ap, cp);
m->depth = sqrtf(dot3(dt,dt));
/* calculate normal */
float l = sqrtf(d2);
float linv = 1.0f / ((l != 0.0f) ? l: 1.0f);
m->normal = scale3(d, linv);
m->contact_point = ap;
return m;
}
int aabb_test_poly(aabb a, poly p) {
return poly_test_aabb(p, a);
}
float capsule_distance2_point(capsule c, vec3 p) {
float d2 = line_distance2_point(line(c.a,c.b), p);
return d2 - (c.r*c.r);
}
vec3 capsule_closest_point(capsule c, vec3 p) {
/* calculate closest point to internal capsule segment */
vec3 pp = line_closest_point(line(c.a,c.b), p);
/* extend point out by radius in normal direction */
vec3 d = norm3(sub3(p,pp));
return add3(pp, scale3(d, c.r));
}
int capsule_test_capsule(capsule a, capsule b) {
float t1, t2;
vec3 c1, c2;
float d2 = line_closest_line_(&t1, &t2, &c1, &c2, line(a.a,a.b), line(b.a,b.b));
float r = a.r + b.r;
return d2 <= r*r;
}
hit *capsule_hit_capsule(capsule a, capsule b) {
float t1, t2;
vec3 c1, c2;
float d2 = line_closest_line_(&t1, &t2, &c1, &c2, line(a.a,a.b), line(b.a,b.b));
float r = a.r + b.r;
if (d2 > r*r) return 0;
hit *m = hit_next();
/* calculate normal from both closest points for each segement */
vec3 cp, d;
m->normal = sub3(c2, c1);
m->normal = norm3(m->normal);
/* calculate contact point from closest point and depth */
m->contact_point = capsule_closest_point(a, c2);
cp = capsule_closest_point(b, c1);
d = sub3(c1, cp);
m->depth = sqrtf(dot3(d,d));
return m;
}
int capsule_test_sphere(capsule c, sphere s) {
/* squared distance bwetween sphere center and capsule line segment */
float d2 = line_distance2_point(line(c.a,c.b), s.c);
float r = s.r + c.r;
return d2 <= r * r;
}
hit *capsule_hit_sphere(capsule c, sphere s) {
/* find closest capsule point to sphere center point */
hit *m = hit_next();
m->contact_point = capsule_closest_point(c, s.c);
m->normal = sub3(s.c, m->contact_point);
float d2 = dot3(m->normal, m->normal);
if (d2 > s.r*s.r) return 0;
/* normalize hit normal vector */
float l = d2 != 0.0f ? sqrtf(d2): 1;
float linv = 1.0f/l;
m->normal = scale3(m->normal, linv);
/* calculate penetration depth */
m->depth = d2 - s.r*s.r;
m->depth = m->depth != 0.0f ? sqrtf(m->depth): 0.0f;
return m;
}
int capsule_test_aabb(capsule c, aabb a) {
/* calculate aabb center point */
vec3 ac = scale3(sub3(a.max, a.min), 0.5f);
/* calculate closest point from aabb to point on capsule and check if inside aabb */
vec3 p = capsule_closest_point(c, ac);
return aabb_contains_point(a, p);
}
hit *capsule_hit_aabb(capsule c, aabb a) {
/* calculate aabb center point */
vec3 ac = add3(a.min, scale3(sub3(a.max, a.min), 0.5f));
/* calculate closest point from aabb to point on capsule and check if inside aabb */
vec3 cp = capsule_closest_point(c, ac);
if (!aabb_contains_point(a, cp))
return 0;
hit *m = hit_next();
/* vector and distance between both capsule closests point and aabb center*/
vec3 d; float d2;
d = sub3(ac, cp);
d2 = dot3(d,d);
/* calculate penetration depth from closest aabb point to capsule */
vec3 ap = aabb_closest_point(a, cp);
vec3 dt = sub3(ap, cp);
m->depth = sqrtf(dot3(dt,dt));
/* calculate normal */
float l = sqrtf(d2);
float linv = 1.0f / ((l != 0.0f) ? l: 1.0f);
m->normal = scale3(d, linv);
m->contact_point = cp;
return m;
}
int capsule_test_poly(capsule c, poly p) {
return poly_test_capsule(p, c);
}
int line_support(vec3 *support, vec3 d, vec3 a, vec3 b) {
int i = 0;
float adot = dot3(a, d);
float bdot = dot3(b, d);
if (adot < bdot) {
*support = b;
i = 1;
} else *support = a;
return i;
}
int poly_support(vec3 *support, vec3 d, poly p) {
int imax = 0;
float dmax = dot3(*p.verts, d);
for (int i = 1; i < p.cnt; ++i) {
/* find vertex with max dot product in direction d */
float dot = dot3(p.verts[i], d);
if (dot < dmax) continue;
imax = i, dmax = dot;
} *support = p.verts[imax];
return imax;
}
int poly_hit_sphere(struct gjk_result *res,
poly p,
sphere s) {
/* initial guess */
vec3 d = {0};
gjk_support gs = {0};
gs.a = *p.verts;
gs.b = s.c;
d = sub3(gs.b, gs.a);
/* run gjk algorithm */
gjk_simplex gsx = {0};
while (gjk(&gsx, &gs, &d)) {
vec3 n = scale3(d, -1);
gs.aid = poly_support(&gs.a, n, p);
d = sub3(gs.b, gs.a);
}
/* check distance between closest points */
*res = gjk_analyze(&gsx);
return res->distance_squared <= s.r*s.r;
}
int poly_hit_sphere_transform(struct gjk_result *res, poly p, vec3 pos3, mat33 rot33, sphere s) {
/* initial guess */
vec3 d = {0};
gjk_support gs = {0};
gs.a = *p.verts;
gs.b = s.c;
transformS(&gs.a, rot33, pos3);
d = sub3(gs.b, gs.a);
/* run gjk algorithm */
gjk_simplex gsx = {0};
while (gjk(&gsx, &gs, &d)) {
vec3 n = scale3(d, -1);
vec3 da; transformT(&da, n, rot33, pos3);
gs.aid = poly_support(&gs.a, da, p);
transformS(&gs.a, rot33, pos3);
d = sub3(gs.b, gs.a);
}
/* check distance between closest points */
*res = gjk_analyze(&gsx);
return res->distance_squared <= s.r*s.r;
}
int poly_test_sphere(poly p, sphere s) {
struct gjk_result res;
return poly_hit_sphere(&res, p, s);
}
int poly_test_sphere_transform(poly p, vec3 pos3, mat33 rot33, sphere s) {
struct gjk_result res;
return poly_hit_sphere_transform(&res, p, pos3, rot33, s);
}
int poly_hit_capsule(struct gjk_result *res, poly p, capsule c) {
/* initial guess */
vec3 d = {0};
gjk_support s = {0};
s.a = *p.verts;
s.b = c.a;
d = sub3(s.b, s.a);
/* run gjk algorithm */
gjk_simplex gsx = {0};
while (gjk(&gsx, &s, &d)) {
vec3 n = scale3(d, -1);
s.aid = poly_support(&s.a, n, p);
s.bid = line_support(&s.b, d, c.a, c.b);
d = sub3(s.b, s.a);
}
/* check distance between closest points */
assert(gsx.iter < gsx.max_iter);
*res = gjk_analyze(&gsx);
return res->distance_squared <= c.r*c.r;
}
int poly_test_capsule(poly p, capsule c) {
struct gjk_result res;
return poly_hit_capsule(&res, p, c);
}
int poly_hit_capsule_transform(struct gjk_result *res, poly p, vec3 pos3, mat33 rot33, capsule c) {
/* initial guess */
vec3 d = {0};
gjk_support gs = {0};
gs.a = *p.verts;
gs.b = c.a;
transformS(&gs.a, rot33, pos3);
d = sub3(gs.b, gs.a);
/* run gjk algorithm */
gjk_simplex gsx = {0};
while (gjk(&gsx, &gs, &d)) {
vec3 n = scale3(d, -1);
vec3 da; transformT(&da, n, rot33, pos3);
gs.aid = poly_support(&gs.a, da, p);
gs.bid = line_support(&gs.b, d, c.a, c.b);
transformS(&gs.a, rot33, pos3);
d = sub3(gs.b, gs.a);
}
/* check distance between closest points */
*res = gjk_analyze(&gsx);
return res->distance_squared <= c.r*c.r;
}
int poly_test_capsule_transform(poly p, vec3 pos3, mat33 rot33, capsule c) {
struct gjk_result res;
return poly_hit_capsule_transform(&res, p, pos3, rot33, c);
}
int poly_hit_poly_transform(struct gjk_result *res,
poly a, vec3 at3, mat33 ar33,
poly b, vec3 bt3, mat33 br33) {
/* initial guess */
vec3 d = {0};
gjk_support gs = {0};
gs.a = *a.verts;
gs.b = *b.verts;
transformS(&gs.a, ar33, at3);
transformS(&gs.b, br33, bt3);
d = sub3(gs.b, gs.a);
/* run gjk algorithm */
gjk_simplex gsx = {0};
while (gjk(&gsx, &gs, &d)) {
/* transform direction */
vec3 n = scale3(d, -1);
vec3 da; transformT(&da, n, ar33, at3);
vec3 db; transformT(&db, d, br33, bt3);
/* run support function on tranformed directions */
gs.aid = poly_support(&gs.a, da, a);
gs.bid = poly_support(&gs.b, db, b);
/* calculate distance vector on transformed points */
transformS(&gs.a, ar33, at3);
transformS(&gs.b, br33, bt3);
d = sub3(gs.b, gs.a);
}
*res = gjk_analyze(&gsx);
return gsx.hit;
}
int poly_hit_poly(struct gjk_result *res,
poly a,
poly b) {
/* initial guess */
vec3 d = {0};
gjk_support gs = {0};
gs.a = *a.verts;
gs.b = *b.verts;
d = sub3(gs.b, gs.a);
/* run gjk algorithm */
gjk_simplex gsx = {0};
while (gjk(&gsx, &gs, &d)) {
vec3 n = scale3(d, -1);
gs.aid = poly_support(&gs.a, n, a);
gs.bid = poly_support(&gs.b, d, b);
d = sub3(gs.b, gs.a);
}
*res = gjk_analyze(&gsx);
return gsx.hit;
}
int poly_test_poly(poly a, poly b) {
struct gjk_result res;
return poly_hit_poly(&res, a, b);
}
int poly_test_poly_transform(poly a, vec3 apos3, mat33 arot33,
poly b, vec3 bpos3, mat33 brot33) {
struct gjk_result res;
return poly_hit_poly_transform(&res, a, apos3, arot33, b, bpos3, brot33);
}
int poly_hit_aabb(struct gjk_result *res, poly p, aabb a) {
vec3 box[8];
box[0] = vec3(a.min.x, a.min.y, a.min.z),
box[1] = vec3(a.min.x, a.min.y, a.max.z);
box[2] = vec3(a.min.x, a.max.y, a.min.z);
box[3] = vec3(a.min.x, a.max.y, a.max.z);
box[4] = vec3(a.max.x, a.min.y, a.min.z);
box[5] = vec3(a.max.x, a.min.y, a.max.z);
box[6] = vec3(a.max.x, a.max.y, a.min.z);
box[7] = vec3(a.max.x, a.max.y, a.max.z);
return poly_hit_poly(res, p, poly(&box[0], 8));
}
int poly_hit_aabb_transform(struct gjk_result *res, poly p, vec3 pos3, mat33 rot33, aabb a) {
vec3 zero = {0};
vec3 id[3] = {{1,0,0},{0,1,0},{0,0,1}};
vec3 box[8];
box[0] = vec3(a.min.x, a.min.y, a.min.z),
box[1] = vec3(a.min.x, a.min.y, a.max.z);
box[2] = vec3(a.min.x, a.max.y, a.min.z);
box[3] = vec3(a.min.x, a.max.y, a.max.z);
box[4] = vec3(a.max.x, a.min.y, a.min.z);
box[5] = vec3(a.max.x, a.min.y, a.max.z);
box[6] = vec3(a.max.x, a.max.y, a.min.z);
box[7] = vec3(a.max.x, a.max.y, a.max.z);
return poly_hit_poly_transform(res, p, pos3, rot33, poly(&box[0], 8), zero, id[0].v3);
}
int poly_test_aabb(poly p, aabb a) {
struct gjk_result res;
return poly_hit_aabb(&res, p, a);
}
int poly_test_aabb_transform(poly p, vec3 apos3, mat33 arot33, aabb a) {
struct gjk_result res;
return poly_hit_aabb_transform(&res, p, apos3, arot33, a);
}
/* ============================================================================
*
* COLLISION VOLUME
*
* =========================================================================== */
hit *ray_hit_plane(ray r, plane p) {
vec4 pf = plane4(p.p, p.n);
float t = ray_test_plane(r, pf);
if (t <= 0.0f) return 0;
hit *o = hit_next();
o->p = add3(r.p, scale3(r.d, t));
o->t0 = o->t1 = t;
o->n = scale3(p.n, -1.0f);
return o;
}
hit *ray_hit_triangle(ray r, triangle tr) {
float t = ray_test_triangle(r, tr);
if (t <= 0) return 0;
hit *o = hit_next();
o->t0 = o->t1 = t;
o->p = add3(r.p, scale3(r.d, t));
o->n = norm3(cross3(sub3(tr.p1,tr.p0),sub3(tr.p2,tr.p0)));
return o;
}
hit *ray_hit_sphere(ray r, sphere s) {
hit *o = hit_next();
if (!ray_test_sphere(&o->t0, &o->t1, r, s))
return 0;
o->p = add3(r.p, scale3(r.d, minf(o->t0,o->t1)));
o->n = norm3(sub3(o->p, s.c));
return o;
}
hit *ray_hit_aabb(ray r, aabb a) {
hit *o = hit_next();
vec3 pnt, ext, c;
float d, min;
if (!ray_test_aabb(&o->t0, &o->t1, r, a))
return 0;
o->p = add3(r.p, scale3(r.d, minf(o->t0,o->t1)));
ext = sub3(a.max, a.min);
c = add3(a.min, scale3(ext,0.5f));
pnt = sub3(o->p, c);
min = fabs(ext.x - fabs(pnt.x));
o->n = scale3(vec3(1,0,0), signf(pnt.x));
d = fabs(ext.y - fabs(pnt.y));
if (d < min) {
min = d;
o->n = scale3(vec3(0,1,0), signf(pnt.y));
}
d = fabs(ext.z - fabs(pnt.z));
if (d < min)
o->n = scale3(vec3(0,0,1), signf(pnt.z));
return o;
}
frustum frustum_build(mat44 pv) {
frustum f;
f.l = vec4(pv[ 3]+pv[ 0], pv[ 7]+pv[ 4], pv[11]+pv[ 8], pv[15]+pv[12]);
f.r = vec4(pv[ 3]-pv[ 0], pv[ 7]-pv[ 4], pv[11]-pv[ 8], pv[15]-pv[12]);
f.t = vec4(pv[ 3]-pv[ 1], pv[ 7]-pv[ 5], pv[11]-pv[ 9], pv[15]-pv[13]);
f.b = vec4(pv[ 3]+pv[ 1], pv[ 7]+pv[ 5], pv[11]+pv[ 9], pv[15]+pv[13]);
f.n = vec4(pv[ 3]+pv[ 2], pv[ 7]+pv[ 6], pv[11]+pv[10], pv[15]+pv[14]);
f.f = vec4(pv[ 3]-pv[ 2], pv[ 7]-pv[ 6], pv[11]-pv[10], pv[15]-pv[14]);
for (int i = 0; i < 6; i++) f.pl[i] = scale4(f.pl[i], 1 / len3(f.pl[i].xyz));
return f;
}
int frustum_test_sphere(frustum f, sphere s) {
for(int i = 0; i < 6; i++) {
if((dot3(f.pl[i].xyz, s.c) + f.pl[i].w + s.r) < 0) return 0;
}
return 1;
}
int frustum_test_aabb(frustum f, aabb a) {
for(int i = 0; i < 6; i++) {
vec3 v = vec3(f.pl[i].x > 0 ? a.max.x : a.min.x, f.pl[i].y > 0 ? a.max.y : a.min.y, f.pl[i].z > 0 ? a.max.z : a.min.z);
if((dot3(f.pl[i].xyz, v) + f.pl[i].w) < 0) return 0;
}
return 1;
}
void collide_demo() { // debug draw collisions // @fixme: fix leaks: poly_free()
// animation
static float dx = 0, dy = 0;
float delta = (0.25f / 60.f);
dx = dx + delta * 2.0f;
dy = dy + delta * 0.8f;
#if 0
// 3D
glEnable(GL_DEPTH_TEST);
// grid
ddraw_grid(0);
#endif
{
// Triangle-Ray Intersection*/
vec3 ro, rd;
int suc;
triangle tri = { vec3(-9,1,28), vec3(-10,0,28), vec3(-11,1,28) };
// ray
ro = vec3(-10,-1,20);
rd = vec3(-10+0.4f*sin(dx), 2.0f*cos(dy), 29.81023f);
rd = sub3(rd, ro);
rd = norm3(rd);
ray r = ray(ro, rd);
hit *hit = ray_hit_triangle(r, tri);
if (hit) {
// point of intersection
ddraw_color(RED);
ddraw_box(hit->p, vec3(0.10f, 0.10f, 0.10f));
// intersection normal
ddraw_color(BLUE);
vec3 v = add3(hit->p, hit->n);
ddraw_arrow(hit->p, v);
}
// line
ddraw_color(RED);
rd = scale3(rd,10);
rd = add3(ro,rd);
ddraw_line(ro, rd);
// triangle
if (hit) ddraw_color(RED);
else ddraw_color(WHITE);
ddraw_triangle(tri.p0,tri.p1,tri.p2);
}
{
// Plane-Ray Intersection*/
vec3 ro, rd;
mat33 rot;
// ray
static float d = 0;
d += delta * 2.0f;
ro = vec3(0,-1,20);
rd = vec3(0.1f, 0.5f, 9.81023f);
rd = sub3(rd, ro);
rd = norm3(rd);
// rotation
rotation33(rot, deg(d), 0,1,0);
rd = mulv33(rot, rd);
// intersection
ray r = ray(ro, rd);
plane pl = plane(vec3(0,0,28), vec3(0,0,1));
hit *hit = ray_hit_plane(r, pl);
if (hit) {
// point of intersection
ddraw_color(RED);
ddraw_box(hit->p, vec3(0.10f, 0.10f, 0.10f));
// intersection normal
ddraw_color(BLUE);
vec3 v = add3(hit->p, hit->n);
ddraw_arrow(hit->p, v);
ddraw_color(RED);
}
// line
ddraw_color(RED);
rd = scale3(rd,9);
rd = add3(ro,rd);
ddraw_line(ro, rd);
// plane
if (hit) ddraw_color(RED);
else ddraw_color(WHITE);
ddraw_plane(vec3(0,0,28), vec3(0,0,1), 3.0f);
}
{
// Sphere-Ray Intersection*/
vec3 ro, rd;
sphere s;
// ray
ro = vec3(0,-1,0);
rd = vec3(0.4f*sin(dx), 2.0f*cos(dy), 9.81023f);
rd = sub3(rd, ro);
rd = norm3(rd);
ray r = ray(ro, rd);
s = sphere(vec3(0,0,8), 1);
hit *hit = ray_hit_sphere(r, s);
if(hit) {
// points of intersection
vec3 in = add3(ro,scale3(rd,hit->t0));
ddraw_color(GREEN);
ddraw_box(in, vec3(0.05f, 0.05f, 0.05f));
in = add3(ro,scale3(rd,hit->t1));
ddraw_color(YELLOW);
ddraw_box(in, vec3(0.05f, 0.05f, 0.05f));
// intersection normal
ddraw_color(BLUE);
vec3 v = add3(hit->p, hit->n);
ddraw_arrow(hit->p, v);
ddraw_color(RED);
}
// line
ddraw_color(RED);
rd = scale3(rd,10);
rd = add3(ro,rd);
ddraw_line(ro, rd);
// sphere
if (hit) ddraw_color(RED);
else ddraw_color(WHITE);
ddraw_sphere(vec3(0,0,8), 1);
}
{ // ray-aabb
aabb bounds = aabb(vec3(10-0.5f,-0.5f,7.5f), vec3(10.5f,0.5f,8.5f));
vec3 ro = vec3(10,-1,0);
vec3 rd = vec3(10+0.4f*sin(dx), 2.0f*cos(dy), 9.81023f);
rd = norm3(sub3(rd, ro));
ray r = ray(ro, rd);
hit *hit = ray_hit_aabb(r, bounds);
if(hit) {
// points of intersection
vec3 in;
in = scale3(rd,hit->t0);
in = add3(ro,in);
ddraw_color(RED);
ddraw_box(in, vec3(0.05f, 0.05f, 0.05f));
in = scale3(rd,hit->t1);
in = add3(ro,in);
ddraw_color(RED);
ddraw_box(in, vec3(0.05f, 0.05f, 0.05f));
// intersection normal
ddraw_color(BLUE);
vec3 v = add3(hit->p, hit->n);
ddraw_arrow(hit->p, v);
ddraw_color(RED);
} else ddraw_color(WHITE);
ddraw_box(vec3(10,0,8), vec3(1,1,1));
// line
ddraw_color(RED);
rd = scale3(rd,10);
rd = add3(ro,rd);
ddraw_line(ro, rd);
}
{
// Sphere-Sphere intersection*/
sphere a = sphere(vec3(-10,0,8), 1);
sphere b = sphere(vec3(-10+0.6f*sin(dx), 3.0f*cos(dy),8), 1);
hit *m = sphere_hit_sphere(a, b);
if (m) {
vec3 v;
ddraw_color(BLUE);
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
v = add3(m->contact_point, m->normal);
ddraw_arrow(m->contact_point, v);
ddraw_color(RED);
} else ddraw_color(WHITE);
ddraw_sphere(a.c, 1);
ddraw_sphere(b.c, 1);
}
{
// AABB-AABB intersection*/
const float x = 10+0.6f*sin(dx);
const float y = 3.0f*cos(dy);
const float z = 20.0f;
aabb a = aabb(vec3(10-0.5f,-0.5f,20-0.5f), vec3(10+0.5f,0.5f,20.5f));
aabb b = aabb(vec3(x-0.5f,y-0.5f,z-0.5f), vec3(x+0.5f,y+0.5f,z+0.5f));
hit *m = aabb_hit_aabb(a, b);
if(m) {
vec3 v;
ddraw_color(BLUE);
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
v = add3(m->contact_point, m->normal);
ddraw_arrow(m->contact_point, v);
ddraw_color(RED);
} else ddraw_color(WHITE);
ddraw_box(vec3(10,0,20), vec3(1,1,1));
ddraw_box(vec3(x,y,z), vec3(1,1,1));
}
{
// Capsule-Capsule intersection*/
const float x = 20+0.4f*sin(dx);
const float y = 3.0f*cos(dy);
const float z = 28.5f;
capsule a = capsule(vec3(20.0f,-1.0f,28.0f), vec3(20.0f,1.0f,28.0f), 0.2f);
capsule b = capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z-1.0f), 0.2f);
hit *m = capsule_hit_capsule(a, b);
if( m ) {
vec3 v;
ddraw_color(BLUE);
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
v = add3(m->contact_point, m->normal);
ddraw_arrow(m->contact_point, v);
ddraw_color(RED);
} else ddraw_color(WHITE);
ddraw_capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z-1.0f), 0.2f);
ddraw_capsule(vec3(20.0f,-1.0f,28.0f), vec3(20.0f,1.0f,28.0f), 0.2f);
}
{
// AABB-Sphere intersection*/
aabb a = aabb(vec3(20-0.5f,-0.5f,7.5f), vec3(20.5f,0.5f,8.5f));
sphere s = sphere(vec3(20+0.6f*sin(dx), 3.0f*cos(dy),8), 1);
hit *m = aabb_hit_sphere(a, s);
if(m) {
vec3 v;
ddraw_color(BLUE);
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
v = add3(m->contact_point, m->normal);
ddraw_arrow(m->contact_point, v);
ddraw_color(RED);
} else ddraw_color(WHITE);
ddraw_box(vec3(20,0,8), vec3(1,1,1));
ddraw_sphere(s.c, 1);
}
{
// Sphere-AABB intersection*/
const float x = 10+0.6f*sin(dx);
const float y = 3.0f*cos(dy);
const float z = -8.0f;
sphere s = sphere(vec3(10,0,-8), 1);
aabb a = aabb(vec3(x-0.5f,y-0.5f,z-0.5f), vec3(x+0.5f,y+0.5f,z+0.5f));
hit *m = sphere_hit_aabb(s, a);
if(m) {
vec3 v;
ddraw_color(BLUE);
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
v = add3(m->contact_point, m->normal);
ddraw_arrow(m->contact_point, v);
ddraw_color(RED);
} else ddraw_color(WHITE);
ddraw_box(vec3(x,y,z), vec3(1,1,1));
ddraw_sphere(s.c, 1);
}
{
// Capsule-Sphere intersection*/
capsule c = capsule(vec3(-20.5f,-1.0f,7.5f), vec3(-20+0.5f,1.0f,8.5f), 0.2f);
sphere b = sphere(vec3(-20+0.6f*sin(dx), 3.0f*cos(dy),8), 1);
hit *m = capsule_hit_sphere(c, b);
if(m) {
vec3 v;
ddraw_color(BLUE);
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
v = add3(m->contact_point, m->normal);
ddraw_arrow(m->contact_point, v);
ddraw_color(RED);
} else ddraw_color(WHITE);
ddraw_sphere(b.c, 1);
ddraw_capsule(vec3(-20.5f,-1.0f,7.5f), vec3(-20+0.5f,1.0f,8.5f), 0.2f);
}
{
// Sphere-Capsule intersection*/
const float x = 20+0.4f*sin(dx);
const float y = 3.0f*cos(dy);
const float z = -8;
sphere s = sphere(vec3(20,0,-8), 1);
capsule c = capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z-1.0f), 0.2f);
hit *m = sphere_hit_capsule(s, c);
if(m) {
vec3 v;
ddraw_color(BLUE);
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
v = add3(m->contact_point, m->normal);
ddraw_arrow(m->contact_point, v);
ddraw_color(RED);
} else ddraw_color(WHITE);
ddraw_capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z-1.0f), 0.2f);
ddraw_sphere(s.c, 1);
}
{
// Capsule-AABB intersection*/
const float x = -20+0.6f*sin(dx);
const float y = 3.0f*cos(dy);
const float z = 28.0f;
capsule c = capsule(vec3(-20.5f,-1.0f,27.5f), vec3(-20+0.5f,1.0f,28.5f), 0.2f);
aabb b = aabb(vec3(x-0.5f,y-0.5f,z-0.5f), vec3(x+0.5f,y+0.5f,z+0.5f));
hit *m = capsule_hit_aabb(c, b);
if(m) {
vec3 v;
ddraw_color(BLUE);
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
v = add3(m->contact_point, m->normal);
ddraw_arrow(m->contact_point, v);
ddraw_color(RED);
} else ddraw_color(WHITE);
ddraw_box(vec3(x,y,z), vec3(1,1,1));
ddraw_capsule(vec3(-20.5f,-1.0f,27.5f), vec3(-20+0.5f,1.0f,28.5f), 0.2f);
}
{
// AABB-Capsule intersection*/
const float x = 0.4f*sin(dx);
const float y = 3.0f*cos(dy);
const float z = -8;
aabb a = aabb(vec3(-0.5f,-0.5f,-8.5f), vec3(0.5f,0.5f,-7.5f));
capsule c = capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z-1.0f), 0.2f);
hit *m = aabb_hit_capsule(a, c);
if(m) {
ddraw_color(RED);
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
ddraw_arrow(m->contact_point, add3(m->contact_point, m->normal));
} else ddraw_color(WHITE);
ddraw_capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z-1.0f), 0.2f);
ddraw_box(vec3(0,0,-8.0f), vec3(1,1,1));
}
{
// poly(Pyramid)-Sphere (GJK) intersection*/
sphere s = sphere(vec3(-10+0.6f*sin(dx), 3.0f*cos(dy),-8), 1);
poly pyr = pyramid(vec3(-10.5f,-0.5f,-7.5f), vec3(-10.5f,1.0f,-7.5f), 1.0f);
gjk_result gjk;
if (poly_hit_sphere(&gjk, pyr, s))
ddraw_color(RED);
else ddraw_color(WHITE);
ddraw_sphere(s.c, 1);
ddraw_pyramid(vec3(-10.5f,-0.5f,-7.5f), 0.5f/*vec3(-10.5f,1.0f,-7.5f)*/, 1.0f);
poly_free(&pyr);
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
ddraw_line(gjk.p0, gjk.p1);
}
{
// poly(Diamond)-Sphere (GJK) intersection*/
sphere s = sphere(vec3(-20+0.6f*sin(dx), 3.0f*cos(dy),-8), 1);
poly dmd = diamond(vec3(-20.5f,-0.5f,-7.5f), vec3(-20.5f,1.0f,-7.5f), 0.5f);
gjk_result gjk;
if (poly_hit_sphere(&gjk, dmd, s))
ddraw_color(RED);
else ddraw_color(WHITE);
ddraw_sphere(s.c, 1);
ddraw_diamond(vec3(-20.5f,-0.5f,-7.5f), vec3(-20.5f,1.0f,-7.5f), 0.5f);
poly_free(&dmd);
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
ddraw_line(gjk.p0, gjk.p1);
}
{
// poly(Pyramid)-Capsule (GJK) intersection*/
const float x = 0.4f*sin(dx);
const float y = 3.0f*cos(dy);
const float z = -15;
capsule c = capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z), 0.2f);
poly pyr = pyramid(vec3(-0.5f,-0.5f,-15.5f), vec3(-0.5f,1.0f,-15.5f), 1.0f);
gjk_result gjk;
if (poly_hit_capsule(&gjk, pyr, c))
ddraw_color(RED);
else ddraw_color(WHITE);
ddraw_capsule(c.a, c.b, c.r);
ddraw_pyramid(vec3(-0.5f,-0.5f,-15.5f), 0.5f/*vec3(-0.5f,1.0f,-15.5f)*/, 1.0f);
poly_free(&pyr);
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
ddraw_line(gjk.p0, gjk.p1);
}
{
// poly(Diamond)-Capsule (GJK) intersection*/
const float x = -10 + 0.4f*sin(dx);
const float y = 3.0f*cos(dy);
const float z = -15;
capsule c = capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z), 0.2f);
poly dmd = diamond(vec3(-10.5f,-0.5f,-15.5f), vec3(-10.5f,1.0f,-15.5f), 0.5f);
gjk_result gjk;
if (poly_hit_capsule(&gjk, dmd, c))
ddraw_color(RED);
else ddraw_color(WHITE);
ddraw_capsule(c.a, c.b, c.r);
ddraw_diamond(vec3(-10.5f,-0.5f,-15.5f), vec3(-10.5f,1.0f,-15.5f), 0.5f);
poly_free(&dmd);
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
ddraw_line(gjk.p0, gjk.p1);
}
{
// poly(Diamond)-poly(Pyramid) (GJK) intersection*/
const float x = -20 + 0.4f*sin(dx);
const float y = 3.0f*cos(dy);
const float z = -15;
poly pyr = pyramid(vec3(x,y-0.5f,z), vec3(x,y+1,z), 0.8f);
poly dmd = diamond(vec3(-20.5f,-0.5f,-15.5f), vec3(-20.5f,1.0f,-15.5f), 0.5f);
gjk_result gjk;
if (poly_hit_poly(&gjk, dmd, pyr))
ddraw_color(RED);
else ddraw_color(WHITE);
ddraw_pyramid(vec3(x,y-0.5f,z), 1/*vec3(x,y+1,z)*/, 1/*0.8f*/);
ddraw_diamond(vec3(-20.5f,-0.5f,-15.5f), vec3(-20.5f,1.0f,-15.5f), 0.5f);
poly_free(&dmd);
poly_free(&pyr);
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
ddraw_line(gjk.p0, gjk.p1);
}
{
// poly(Pyramid)-poly(Diamond) (GJK) intersection*/
const float x = 10 + 0.4f*sin(dx);
const float y = 3.0f*cos(dy);
const float z = -15;
poly dmd = diamond(vec3(x,y-0.5f,z), vec3(x,y+1,z), 0.5f);
poly pyr = pyramid(vec3(10.5f,-0.5f,-15.5f), vec3(10.5f,1.0f,-15.5f), 1.0f);
gjk_result gjk;
if (poly_hit_poly(&gjk, dmd, pyr))
ddraw_color(RED);
else ddraw_color(WHITE);
ddraw_diamond(vec3(x,y-0.5f,z), vec3(x,y+1,z), 0.5f);
ddraw_pyramid(vec3(10.5f,-0.5f,-15.5f), 0.5f/*vec3(10.5f,1.0f,-15.5f)*/, 1.0f);
poly_free(&dmd);
poly_free(&pyr);
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
ddraw_line(gjk.p0, gjk.p1);
}
{
// poly(Diamond)-AABB (GJK) intersection*/
const float x = 20 + 0.4f*sin(dx);
const float y = 3.0f*cos(dy);
const float z = -15;
poly dmd = diamond(vec3(x,y-0.5f,z), vec3(x,y+1,z), 0.5f);
aabb a = aabb(vec3(19.5f,-0.5f,-14.5f), vec3(20.5f,0.5f,-15.5f));
gjk_result gjk;
if (poly_hit_aabb(&gjk, dmd, a))
ddraw_color(RED);
else ddraw_color(WHITE);
poly_free(&dmd);
ddraw_diamond(vec3(x,y-0.5f,z), vec3(x,y+1,z), 0.5f);
ddraw_box(vec3(20,0,-15), vec3(1,1,1));
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
ddraw_line(gjk.p0, gjk.p1);
}
}