mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-05-23 06:34:18 -04:00
1048 lines
27 KiB
C
1048 lines
27 KiB
C
#include "sys_math3d.h"
|
|
|
|
xyz_t ZeroVec = { 0.0f, 0.0f, 0.0f };
|
|
s_xyz ZeroSVec = { 0, 0, 0 };
|
|
|
|
/* Unused function .bss symbols */
|
|
#ifdef MUST_MATCH
|
|
FORCESTRIP void _bss_func00() {
|
|
static Math3D_linef_c l1;
|
|
static Math3D_linef_c ls1;
|
|
static Math3D_linef_c p2cl;
|
|
|
|
l1 = ls1 = p2cl;
|
|
}
|
|
#endif
|
|
|
|
extern f32 Math3d_normalizeXyz_t(xyz_t* a) {
|
|
f32 l, v;
|
|
|
|
l = Math3DVecLength(a);
|
|
|
|
if ((float)fabsf(l) < 0.008f) {
|
|
return 0.0f;
|
|
}
|
|
v = (1.0f / l);
|
|
a->x *= v;
|
|
a->y *= v;
|
|
a->z *= v;
|
|
return l;
|
|
}
|
|
|
|
extern void Math3DInDivPos1(const xyz_t* v, const xyz_t* d, f32 t, xyz_t* c) {
|
|
c->x = (v->x + (d->x * t));
|
|
c->y = (v->y + (d->y * t));
|
|
c->z = (v->z + (d->z * t));
|
|
}
|
|
|
|
extern void Math3DInDivPos2(const xyz_t* v, const xyz_t* d, xyz_t* c, f32 t) {
|
|
xyz_t df;
|
|
|
|
xyz_t_sub(d, v, &df);
|
|
Math3DInDivPos1(v, &df, t, c);
|
|
}
|
|
|
|
/* @unused, @fabricated*/
|
|
FORCESTRIP f32 Math3D_Check2DInArea() {
|
|
return 2.0f;
|
|
}
|
|
|
|
static int Math3DCheck3PointMinMaxAreaInside2D(f32 x0, f32 y0, f32 x1, f32 y1, f32 x2, f32 y2, f32 cx, f32 cy, f32 r) {
|
|
f32 minx, maxx, miny, maxy;
|
|
|
|
minx = maxx = x0;
|
|
miny = maxy = y0;
|
|
|
|
if (minx > x1) {
|
|
minx = x1;
|
|
} else if (minx < x1) {
|
|
maxx = x1;
|
|
}
|
|
|
|
if (miny > y1) {
|
|
miny = y1;
|
|
} else if (maxy < y1) {
|
|
maxy = y1;
|
|
}
|
|
|
|
if (minx > x2) {
|
|
minx = x2;
|
|
} else if (maxx < x2) {
|
|
maxx = x2;
|
|
}
|
|
|
|
if (miny > y2) {
|
|
miny = y2;
|
|
} else if (maxy < y2) {
|
|
maxy = y2;
|
|
}
|
|
|
|
if ((minx - r) <= cx && (maxx + r) >= cx && (miny - r) <= cy && (maxy + r) >= cy) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int Math3DCheck3PointMinMaxAreaInside3D(xyz_t* v0, xyz_t* v1, xyz_t* v2, xyz_t* c, f32 r) {
|
|
xyz_t min;
|
|
xyz_t max;
|
|
|
|
min.x = max.x = v0->x;
|
|
min.y = max.y = v0->y;
|
|
min.z = max.z = v0->z;
|
|
|
|
if (min.x > v1->x) {
|
|
min.x = v1->x;
|
|
} else if (max.x < v1->x) {
|
|
max.x = v1->x;
|
|
}
|
|
|
|
if (min.y > v1->y) {
|
|
min.y = v1->y;
|
|
} else if (max.y < v1->y) {
|
|
max.y = v1->y;
|
|
}
|
|
|
|
if (min.z > v1->z) {
|
|
min.z = v1->z;
|
|
} else if (max.z < v1->z) {
|
|
max.z = v1->z;
|
|
}
|
|
|
|
if (min.x > v2->x) {
|
|
min.x = v2->x;
|
|
} else if (max.x < v2->x) {
|
|
max.x = v2->x;
|
|
}
|
|
|
|
if (min.y > v2->y) {
|
|
min.y = v2->y;
|
|
} else if (max.y < v2->y) {
|
|
max.y = v2->y;
|
|
}
|
|
|
|
if (min.z > v2->z) {
|
|
min.z = v2->z;
|
|
} else if (max.z < v2->z) {
|
|
max.z = v2->z;
|
|
}
|
|
|
|
if (((min.x - r) <= c->x) && ((max.x + r) >= c->x) && ((min.y - r) <= c->y) && ((max.y + r) >= c->y) &&
|
|
((min.z - r) <= c->z) && ((max.z + r) >= c->z)) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
extern f32 Math3DVecLengthSquare2D(f32 a, f32 b) {
|
|
return ((a * a) + (b * b));
|
|
}
|
|
|
|
extern f32 Math3DVecLength2D(f32 a, f32 b) {
|
|
return sqrtf(Math3DVecLengthSquare2D(a, b));
|
|
}
|
|
|
|
extern f32 Math3DLengthSquare2D(f32 x0, f32 y0, f32 x1, f32 y1) {
|
|
return Math3DVecLengthSquare2D(x0 - x1, y0 - y1);
|
|
}
|
|
|
|
extern f32 Math3DLength2D(f32 x0, f32 x1, f32 y0, f32 y1) {
|
|
return sqrtf(Math3DLengthSquare2D(x0, x1, y0, y1));
|
|
}
|
|
|
|
extern f32 Math3DVecLengthSquare(xyz_t* v) {
|
|
return (v->x * v->x) + (v->y * v->y) + (v->z * v->z);
|
|
}
|
|
|
|
extern f32 Math3DVecLength(xyz_t* v) {
|
|
f32 sqr_len = Math3DVecLengthSquare(v);
|
|
return sqrt(sqr_len);
|
|
}
|
|
|
|
extern f32 Math3DLengthSquare(xyz_t* a, xyz_t* b) {
|
|
xyz_t d;
|
|
xyz_t_sub(a, b, &d);
|
|
return Math3DVecLengthSquare(&d);
|
|
}
|
|
|
|
extern f32 Math3DLength(xyz_t* a, xyz_t* b) {
|
|
return search_position_distance(a, b);
|
|
}
|
|
|
|
static f32 Math3DLength_s_f(s_xyz* a, xyz_t* b) {
|
|
xyz_t d;
|
|
|
|
d.x = a->x - b->x;
|
|
d.y = a->y - b->y;
|
|
d.z = a->z - b->z;
|
|
return Math3DVecLength(&d);
|
|
}
|
|
|
|
extern void Math3DVectorProduct2Vec(const xyz_t* a, xyz_t* b, xyz_t* ret) {
|
|
ret->x = (a->y * b->z) - (a->z * b->y);
|
|
ret->y = (a->z * b->x) - (a->x * b->z);
|
|
ret->z = (a->x * b->y) - (a->y * b->x);
|
|
}
|
|
|
|
extern void Math3DVectorProductXYZ(xyz_t* va, xyz_t* vb, xyz_t* vc, xyz_t* ret) {
|
|
static xyz_t vec01;
|
|
static xyz_t vec02;
|
|
|
|
xyz_t_sub(vb, va, &vec01);
|
|
xyz_t_sub(vc, va, &vec02);
|
|
Math3DVectorProduct2Vec(&vec01, &vec02, ret);
|
|
}
|
|
|
|
/* Unused function .bss symbols */
|
|
#ifdef MUST_MATCH
|
|
FORCESTRIP void _bss_func01() {
|
|
static xyz_t tp0;
|
|
static xyz_t tp1;
|
|
static xyz_t tp2;
|
|
static xyz_t cross_pos;
|
|
static xyz_t min_p;
|
|
static xyz_t max_p;
|
|
static xyz_t lps_p;
|
|
static xyz_t lpe_p;
|
|
|
|
tp0 = tp1 = tp2 = cross_pos = min_p = max_p = lps_p = lpe_p;
|
|
}
|
|
#endif
|
|
|
|
extern void Math3DPlane(xyz_t* va, xyz_t* vb, xyz_t* vc, f32* nox, f32* noy, f32* noz, f32* odist) {
|
|
static xyz_t mult_vec;
|
|
|
|
f32 nm;
|
|
f32 nminv;
|
|
Math3DVectorProductXYZ(va, vb, vc, &mult_vec);
|
|
|
|
nm = sqrtf((mult_vec.x * mult_vec.x) + (mult_vec.y * mult_vec.y) + (mult_vec.z * mult_vec.z));
|
|
|
|
if (!(fabsf(nm) < 0.008f)) {
|
|
nminv = 1.0f / nm;
|
|
*nox = mult_vec.x * nminv;
|
|
*noy = mult_vec.y * nminv;
|
|
*noz = mult_vec.z * nminv;
|
|
*odist = -((*nox * va->x) + (*noy * va->y) + (*noz * va->z));
|
|
} else {
|
|
*odist = 0.0f;
|
|
*noz = 0.0f;
|
|
*noy = 0.0f;
|
|
*nox = 0.0f;
|
|
}
|
|
}
|
|
|
|
/* Unused function .bss symbols */
|
|
#ifdef MUST_MATCH
|
|
FORCESTRIP xyz_t* _bss_func02() {
|
|
static xyz_t pos;
|
|
|
|
return &pos;
|
|
}
|
|
#endif
|
|
|
|
/* Unused function .bss symbols */
|
|
#ifdef MUST_MATCH
|
|
FORCESTRIP xyz_t* _bss_func03() {
|
|
static xyz_t pos;
|
|
|
|
return &pos;
|
|
}
|
|
#endif
|
|
|
|
extern f32 Math3DPlaneFunc(f32 nox, f32 noy, f32 noz, f32 odist, xyz_t* pl) {
|
|
return ((nox * pl->x) + (noy * pl->y) + (noz * pl->z) + odist);
|
|
}
|
|
|
|
extern f32 Math3DLengthPlaneAndPos(f32 nox, f32 noy, f32 noz, f32 odist, xyz_t* pl) {
|
|
f32 res = fabsf(Math3DSignedLengthPlaneAndPos(nox, noy, noz, odist, pl));
|
|
return res;
|
|
}
|
|
|
|
extern f32 Math3DSignedLengthPlaneAndPos(f32 nox, f32 noy, f32 noz, f32 odist, xyz_t* pl) {
|
|
|
|
f32 nm;
|
|
|
|
nm = sqrtf((nox * nox) + (noy * noy) + (noz * noz));
|
|
|
|
if (F32_IS_ZERO(nm)) {
|
|
return 0.0f;
|
|
}
|
|
|
|
return Math3DPlaneFunc(nox, noy, noz, odist, pl) / nm;
|
|
}
|
|
|
|
extern int Math3DTriangleCrossYCheck_general(xyz_t* v0, xyz_t* v1, xyz_t* v2, f32 z, f32 x, f32 dt, f32 dist, f32 noy) {
|
|
f32 dvovi;
|
|
f32 dvive;
|
|
f32 dvevo;
|
|
f32 edge;
|
|
f32 dist_sq;
|
|
|
|
if (!Math3DCheck3PointMinMaxAreaInside2D(v0->z, v0->x, v1->z, v1->x, v2->z, v2->x, z, x, dist)) {
|
|
return FALSE;
|
|
}
|
|
|
|
dist_sq = dist * dist;
|
|
|
|
if (((v0->z - z) * (v0->z - z)) + ((v0->x - x) * (v0->x - x)) < dist_sq ||
|
|
((v1->z - z) * (v1->z - z)) + ((v1->x - x) * (v1->x - x)) < dist_sq ||
|
|
((v2->z - z) * (v2->z - z)) + ((v2->x - x) * (v2->x - x)) < dist_sq) {
|
|
return TRUE;
|
|
}
|
|
|
|
dvovi = (((v0->z - z) * (v1->x - x)) - (v0->x - x) * (v1->z - z));
|
|
dvive = (((v1->z - z) * (v2->x - x)) - (v1->x - x) * (v2->z - z));
|
|
dvevo = (((v2->z - z) * (v0->x - x)) - (v2->x - x) * (v0->z - z));
|
|
|
|
if ((dvovi <= dt) && (dvive <= dt) && (dvevo <= dt) || (dvovi >= -dt) && (dvive >= -dt) && (dvevo >= -dt)) {
|
|
return TRUE;
|
|
}
|
|
|
|
if (fabsf(noy) > 0.5f) {
|
|
if (Math3D_pointVsLineSegmentLengthSquare2D(z, x, v0->z, v0->x, v1->z, v1->x, &edge) && (edge < dist_sq)) {
|
|
return TRUE;
|
|
}
|
|
if (Math3D_pointVsLineSegmentLengthSquare2D(z, x, v1->z, v1->x, v2->z, v2->x, &edge) && (edge < dist_sq)) {
|
|
return TRUE;
|
|
}
|
|
if (Math3D_pointVsLineSegmentLengthSquare2D(z, x, v2->z, v2->x, v0->z, v0->x, &edge) && (edge < dist_sq)) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static int Math3DTriangleCrossYCheck_chparam(xyz_t* v0, xyz_t* v1, xyz_t* v2, f32 z, f32 x, f32 dt, f32 noy) {
|
|
return Math3DTriangleCrossYCheck_general(v0, v1, v2, z, x, dt, 1.0f, noy);
|
|
}
|
|
|
|
extern int Math3DTriangleCrossYLine_scope(xyz_t* v0, xyz_t* v1, xyz_t* v2, f32 nox, f32 noy, f32 noz, f32 dst, f32 z,
|
|
f32 x, f32* yint, f32 y0, f32 y1) {
|
|
xyz_t pl;
|
|
f32 das, dbs;
|
|
if ((float)__fabs(noy) < 0.008f) {
|
|
return 0;
|
|
}
|
|
|
|
pl.x = x;
|
|
pl.y = y0;
|
|
pl.z = z;
|
|
|
|
das = Math3DPlaneFunc(nox, noy, noz, dst, &pl);
|
|
pl.y = y1;
|
|
dbs = Math3DPlaneFunc(nox, noy, noz, dst, &pl);
|
|
|
|
if ((das > 0.0f) && (dbs > 0.0f) || (das < 0.0f) && (dbs < 0.0f)) {
|
|
return 0;
|
|
}
|
|
|
|
if (Math3DTriangleCrossYCheck_general(v0, v1, v2, z, x, 300.0f, 1.0f, noy)) {
|
|
*yint = (((-nox * x) - (noz * z)) - dst) / noy;
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int Math3DTriangleCrossXCheck_general(xyz_t* v0, xyz_t* v1, xyz_t* v2, f32 y, f32 z, f32 dt, f32 dist, f32 nox) {
|
|
f32 dvovi, dvive, dvevo;
|
|
f32 edge;
|
|
f32 dist_sq;
|
|
|
|
if (!Math3DCheck3PointMinMaxAreaInside2D(v0->y, v0->z, v1->y, v1->z, v2->y, v2->z, y, z, dist)) {
|
|
return 0;
|
|
}
|
|
dist_sq = (dist * dist);
|
|
|
|
if ((((v0->y - y) * (v0->y - y)) + ((v0->z - z) * (v0->z - z)) < dist_sq) ||
|
|
(((v1->y - y) * (v1->y - y)) + ((v1->z - z) * (v1->z - z)) < dist_sq) ||
|
|
(((v2->y - y) * (v2->y - y)) + ((v2->z - z) * (v2->z - z)) < dist_sq)) {
|
|
return 1;
|
|
}
|
|
|
|
dvovi = (((v0->y - y) * (v1->z - z)) - (v0->z - z) * (v1->y - y));
|
|
dvive = (((v1->y - y) * (v2->z - z)) - (v1->z - z) * (v2->y - y));
|
|
dvevo = (((v2->y - y) * (v0->z - z)) - (v2->z - z) * (v0->y - y));
|
|
|
|
if (((dvovi <= dt) && (dvive <= dt) && (dvevo <= dt)) || ((dvovi >= -dt) && (dvive >= -dt) && (dvevo >= -dt))) {
|
|
return 1;
|
|
}
|
|
|
|
if (fabsf(nox) > 0.5f) {
|
|
if (Math3D_pointVsLineSegmentLengthSquare2D(y, z, v0->y, v0->z, v1->y, v1->z, &edge) && (edge < dist_sq)) {
|
|
return 1;
|
|
}
|
|
if (Math3D_pointVsLineSegmentLengthSquare2D(y, z, v1->y, v1->z, v2->y, v2->z, &edge) && (edge < dist_sq)) {
|
|
return 1;
|
|
}
|
|
if (Math3D_pointVsLineSegmentLengthSquare2D(y, z, v2->y, v2->z, v0->y, v0->z, &edge) && (edge < dist_sq)) {
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int Math3DTriangleCrossXCheck_chparam(xyz_t* v0, xyz_t* v1, xyz_t* v2, f32 y, f32 z, f32 dt, f32 nox) {
|
|
return Math3DTriangleCrossXCheck_general(v0, v1, v2, y, z, dt, 1.0f, nox);
|
|
}
|
|
|
|
extern int Math3DTriangleCrossZCheck_general(xyz_t* v0, xyz_t* v1, xyz_t* v2, f32 x, f32 y, f32 dt, f32 dist, f32 noz) {
|
|
f32 dvovi, dvive, dvevo;
|
|
f32 edge;
|
|
f32 dist_sq;
|
|
f32 v01temp;
|
|
f32 v10temp;
|
|
|
|
if (!Math3DCheck3PointMinMaxAreaInside2D(v0->x, v0->y, v1->x, v1->y, v2->x, v2->y, x, y, dist)) {
|
|
return 0;
|
|
}
|
|
dist_sq = (dist * dist);
|
|
|
|
if ((SQ(x - v0->x) + SQ(y - v0->y)) < dist_sq || (SQ(x - v1->x) + SQ(y - v1->y)) < dist_sq ||
|
|
(SQ(x - v2->x) + SQ(y - v2->y)) < dist_sq) {
|
|
return 1;
|
|
}
|
|
|
|
dvovi = ((v0->x - x) * (v1->y - y)) - ((v0->y - y) * (v1->x - x));
|
|
dvive = ((v1->x - x) * (v2->y - y)) - ((v1->y - y) * (v2->x - x));
|
|
dvevo = ((v2->x - x) * (v0->y - y)) - ((v2->y - y) * (v0->x - x));
|
|
|
|
if (((dvovi <= dt) && (dvive <= dt) && (dvevo <= dt)) || ((dvovi >= -dt) && (dvive >= -dt) && (dvevo >= -dt))) {
|
|
return 1;
|
|
}
|
|
|
|
if ((float)__fabs(noz) > 0.5f) {
|
|
if (Math3D_pointVsLineSegmentLengthSquare2D(x, y, v0->x, v0->y, v1->x, v1->y, &edge) && (edge < dist_sq)) {
|
|
return 1;
|
|
}
|
|
if (Math3D_pointVsLineSegmentLengthSquare2D(x, y, v1->x, v1->y, v2->x, v2->y, &edge) && (edge < dist_sq)) {
|
|
return 1;
|
|
}
|
|
if (Math3D_pointVsLineSegmentLengthSquare2D(x, y, v2->x, v2->y, v0->x, v0->y, &edge) && (edge < dist_sq)) {
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int Math3DTriangleCrossZCheck_chparam(xyz_t* v0, xyz_t* v1, xyz_t* v2, f32 x, f32 y, f32 dt, f32 noz) {
|
|
return Math3DTriangleCrossZCheck_general(v0, v1, v2, x, y, dt, 1.0f, noz);
|
|
}
|
|
|
|
extern int Math3D_sphereCollisionPoint(Math3D_sphere_c* s, xyz_t* p) {
|
|
if (Math3DLength_s_f(&s->center, p) < s->radius) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
extern int Math3D_pointVsLineSegmentLengthSquare2D(f32 x0, f32 y0, f32 x1, f32 y1, f32 x2, f32 y2, f32* lsq) {
|
|
static xyz_t h;
|
|
|
|
f32 diffx, diffy;
|
|
f32 d;
|
|
f32 pr;
|
|
int r = 0;
|
|
diffx = x2 - x1;
|
|
diffy = y2 - y1;
|
|
|
|
d = (diffx * diffx) + (diffy * diffy);
|
|
|
|
if ((float)__fabs(d) < 0.008f) {
|
|
*lsq = 0;
|
|
return 0;
|
|
}
|
|
|
|
pr = (((x0 - x1) * diffx) + (y0 - y1) * diffy) / d;
|
|
if (pr >= 0.0f && pr <= 1.0f) {
|
|
r = 1;
|
|
}
|
|
|
|
h.x = (diffx * pr) + x1;
|
|
h.y = (diffy * pr) + y1;
|
|
|
|
*lsq = ((h.x - x0) * (h.x - x0)) + ((h.y - y0) * (h.y - y0));
|
|
return r;
|
|
}
|
|
|
|
extern int Math3D_sphereCrossLineSegment(Math3D_sphere_c* s, Math3D_linef_c* l) {
|
|
static xyz_t h;
|
|
f32 lc;
|
|
f32 delta_sq;
|
|
xyz_t linediff;
|
|
|
|
f32 r_sq;
|
|
f32 cen_x_sq;
|
|
f32 cen_y_sq;
|
|
f32 cen_z_sq;
|
|
|
|
f32 ofs_x;
|
|
f32 ofs_y;
|
|
f32 ofs_z;
|
|
|
|
f32 x;
|
|
f32 y;
|
|
f32 z;
|
|
|
|
if ((Math3D_sphereCollisionPoint(s, &l->a)) || Math3D_sphereCollisionPoint(s, &l->b)) {
|
|
return 1;
|
|
}
|
|
|
|
x = l->b.x - l->a.x;
|
|
y = l->b.y - l->a.y;
|
|
z = l->b.z - l->a.z;
|
|
|
|
delta_sq = SQ(x) + SQ(y) + SQ(z);
|
|
|
|
if (fabsf(delta_sq) < 0.008f) {
|
|
return 0;
|
|
}
|
|
|
|
lc = (((x * (s->center.x - l->a.x)) + (y * (s->center.y - l->a.y))) + (z * (s->center.z - l->a.z))) / delta_sq;
|
|
|
|
if (lc < 0.0f || lc > 1.0f) {
|
|
return 0;
|
|
}
|
|
|
|
h.x = (x * lc) + l->a.x;
|
|
h.y = (y * lc) + l->a.y;
|
|
h.z = (z * lc) + l->a.z;
|
|
|
|
if (SQ(h.x - s->center.x) + SQ(h.y - s->center.y) + SQ(h.z - s->center.z) <= SQ((f32)s->radius)) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
extern void Math3D_sphereCrossTriangleCalc_cp(Math3D_sphere_c* s, Math3D_triangle_c* tri, xyz_t* ip) {
|
|
static xyz_t tr_center;
|
|
static xyz_t sp_center;
|
|
|
|
f32 dst, sr;
|
|
|
|
tr_center.x = ((tri->vtx[0].x + tri->vtx[1].x) * 0.5f);
|
|
tr_center.y = ((tri->vtx[0].y + tri->vtx[1].y) * 0.5f);
|
|
tr_center.z = ((tri->vtx[0].z + tri->vtx[1].z) * 0.5f);
|
|
|
|
sp_center.x = s->center.x;
|
|
sp_center.y = s->center.y;
|
|
sp_center.z = s->center.z;
|
|
|
|
dst = Math3DLength(&tr_center, &sp_center);
|
|
|
|
if (fabsf(dst) < 0.008f) {
|
|
ip->x = sp_center.x;
|
|
ip->y = sp_center.y;
|
|
ip->z = sp_center.z;
|
|
return;
|
|
}
|
|
|
|
sr = s->radius / dst;
|
|
Math3DInDivPos2(&sp_center, &tr_center, ip, sr);
|
|
}
|
|
|
|
extern int Math3D_sphereCrossTriangle3_cp(Math3D_sphere_c* s, Math3D_triangle_c* tri, xyz_t* ip) {
|
|
static xyz_t center;
|
|
static Math3D_linef_c ls;
|
|
static xyz_t cross;
|
|
|
|
f32 r, nox, noy, noz, pd;
|
|
|
|
center.x = s->center.x;
|
|
center.y = s->center.y;
|
|
center.z = s->center.z;
|
|
|
|
r = s->radius;
|
|
|
|
if (!Math3DCheck3PointMinMaxAreaInside3D(&tri->vtx[0], &tri->vtx[1], &tri->vtx[2], ¢er, r)) {
|
|
return 0;
|
|
}
|
|
|
|
pd = Math3DLengthPlaneAndPos(tri->plane.normal.x, tri->plane.normal.y, tri->plane.normal.z, tri->plane.originDist,
|
|
¢er);
|
|
|
|
if (pd > r) {
|
|
return 0;
|
|
}
|
|
ls.a = tri->vtx[0];
|
|
ls.b = tri->vtx[1];
|
|
if (Math3D_sphereCrossLineSegment(s, &ls)) {
|
|
Math3D_sphereCrossTriangleCalc_cp(s, tri, ip);
|
|
return 1;
|
|
}
|
|
|
|
ls.a = tri->vtx[1];
|
|
ls.b = tri->vtx[2];
|
|
if (Math3D_sphereCrossLineSegment(s, &ls)) {
|
|
Math3D_sphereCrossTriangleCalc_cp(s, tri, ip);
|
|
return 1;
|
|
}
|
|
|
|
ls.a = tri->vtx[2];
|
|
ls.b = tri->vtx[0];
|
|
if (Math3D_sphereCrossLineSegment(s, &ls)) {
|
|
Math3D_sphereCrossTriangleCalc_cp(s, tri, ip);
|
|
return 1;
|
|
}
|
|
|
|
nox = tri->plane.normal.x * pd;
|
|
noy = tri->plane.normal.y * pd;
|
|
noz = tri->plane.normal.z * pd;
|
|
|
|
if (Math3DPlaneFunc(tri->plane.normal.x, tri->plane.normal.y, tri->plane.normal.z, tri->plane.originDist, ¢er) >
|
|
0.0f) {
|
|
|
|
cross.x = center.x - nox;
|
|
cross.y = center.y - noy;
|
|
cross.z = center.z - noz;
|
|
} else {
|
|
cross.x = center.x + nox;
|
|
cross.y = center.y + noy;
|
|
cross.z = center.z + noz;
|
|
}
|
|
|
|
if (fabsf(tri->plane.normal.y) > 0.5f) {
|
|
|
|
if (Math3DTriangleCrossYCheck_chparam(&tri->vtx[0], &tri->vtx[1], &tri->vtx[2], cross.z, cross.x, 0.0f,
|
|
tri->plane.normal.y)) {
|
|
Math3D_sphereCrossTriangleCalc_cp(s, tri, ip);
|
|
return 1;
|
|
}
|
|
} else if (fabsf(tri->plane.normal.x) > 0.5f) {
|
|
if (Math3DTriangleCrossXCheck_chparam(&tri->vtx[0], &tri->vtx[1], &tri->vtx[2], cross.y, cross.z, 0.0f,
|
|
tri->plane.normal.x)) {
|
|
Math3D_sphereCrossTriangleCalc_cp(s, tri, ip);
|
|
return 1;
|
|
}
|
|
} else if (Math3DTriangleCrossZCheck_chparam(&tri->vtx[0], &tri->vtx[1], &tri->vtx[2], cross.x, cross.y, 0.0f,
|
|
tri->plane.normal.z)) {
|
|
Math3D_sphereCrossTriangleCalc_cp(s, tri, ip);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
extern int Math3D_pipeVsPos(Math3D_pipe_c* c, xyz_t* p) {
|
|
f32 l;
|
|
f32 r;
|
|
f32 top;
|
|
f32 bottom;
|
|
f32 d;
|
|
f32 rr;
|
|
|
|
l = c->center.x - p->x;
|
|
r = c->center.z - p->z;
|
|
top = c->center.y + (f32)c->offset;
|
|
bottom = top + (f32)c->height;
|
|
d = SQ(l) + SQ(r);
|
|
rr = SQ((f32)c->radius);
|
|
|
|
if (d < rr && (top < p->y) && (bottom > p->y)) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
extern int Math3D_pipeCrossLine(Math3D_pipe_c* c, xyz_t* la, xyz_t* lb, xyz_t* ia, xyz_t* ib) {
|
|
f32 z = 0.0f;
|
|
int f = 0;
|
|
int sa, sb, i, co;
|
|
xyz_t ca, cb, ab, intpos[4];
|
|
f32 fa = 0.0f;
|
|
f32 fba = 0.0f;
|
|
f32 fb;
|
|
f32 bix;
|
|
f32 biz;
|
|
f32 tix;
|
|
f32 tiz;
|
|
f32 rsqd;
|
|
f32 iba;
|
|
f32 ibd;
|
|
f32 t2;
|
|
f32 t;
|
|
f32 t3;
|
|
f32 rsq;
|
|
f32 dc;
|
|
|
|
if (Math3D_pipeVsPos(c, la) && Math3D_pipeVsPos(c, lb)) {
|
|
*ia = *la;
|
|
*ib = *lb;
|
|
return 2;
|
|
}
|
|
|
|
ca.x = la->x - c->center.x;
|
|
ca.y = la->y - c->center.y - c->offset;
|
|
ca.z = la->z - c->center.z;
|
|
|
|
cb.x = lb->x - c->center.x;
|
|
cb.y = lb->y - c->center.y - c->offset;
|
|
cb.z = lb->z - c->center.z;
|
|
|
|
xyz_t_sub(&cb, &ca, &ab);
|
|
|
|
rsq = SQ((f32)c->radius);
|
|
|
|
if (!F32_IS_ZERO(ab.y)) {
|
|
fb = -ca.y / ab.y;
|
|
if ((fb >= z) && (fb <= 1.0f)) {
|
|
bix = (ab.x * fb) + ca.x;
|
|
biz = (ab.z * fb) + ca.z;
|
|
|
|
if ((SQ(bix) + SQ(biz)) < rsq) {
|
|
intpos[0].x = (f32)bix + (f32)c->center.x;
|
|
intpos[0].y = (f32)c->center.y + (f32)c->offset;
|
|
intpos[0].z = (f32)biz + (f32)c->center.z;
|
|
f |= 1;
|
|
}
|
|
}
|
|
fa = ((f32)c->height - (f32)ca.y) / ab.y;
|
|
if ((fa >= z) && (fa <= 1.0f)) {
|
|
tix = ((f32)ab.x * (f32)fa) + (f32)ca.x;
|
|
tiz = ((f32)ab.z * (f32)fa) + (f32)ca.z;
|
|
|
|
if ((SQ(tix) + SQ(tiz)) < rsq) {
|
|
intpos[1].x = (f32)tix + (f32)c->center.x;
|
|
intpos[1].y = (f32)c->center.y + (f32)c->offset + (f32)c->height;
|
|
intpos[1].z = (f32)tiz + (f32)c->center.z;
|
|
f |= 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
t3 = (SQ(ab.x) + SQ(ab.z));
|
|
t2 = 2.0f * t3;
|
|
t = 2.0f * (ab.x * ca.x + ab.z * ca.z);
|
|
rsqd = (SQ(ca.x) + SQ(ca.z)) - rsq;
|
|
|
|
if (!F32_IS_ZERO(t2)) {
|
|
dc = (SQ(t) - 4.0f * t3 * rsqd);
|
|
|
|
if (dc < z) {
|
|
return 0;
|
|
}
|
|
|
|
if (dc > z) {
|
|
sa = sb = 1;
|
|
} else {
|
|
sa = 1;
|
|
sb = 0;
|
|
}
|
|
|
|
dc = z >= 0.0f ? sqrtf(dc) : 0.0f;
|
|
|
|
if (sa == 1) {
|
|
fa = (-t + dc) / t2;
|
|
}
|
|
if (sb == 1) {
|
|
fba = (-t - dc) / t2;
|
|
}
|
|
} else if (!F32_IS_ZERO(t)) {
|
|
fa = -rsqd / t;
|
|
sa = 1;
|
|
sb = 0;
|
|
} else {
|
|
return 0;
|
|
}
|
|
|
|
if (sa == 1 && sb == 0) {
|
|
if (z > fa || fa > 1.0f) {
|
|
return 0;
|
|
}
|
|
} else {
|
|
int what = 1;
|
|
int what2;
|
|
if (!(z > fa || fa > 1.0f)) {
|
|
what = 0;
|
|
}
|
|
|
|
what2 = 1;
|
|
if (!(z > fba || fba > 1.0f)) {
|
|
what2 = 0;
|
|
}
|
|
|
|
if (what && what2) {
|
|
return 0;
|
|
}
|
|
|
|
if (what) {
|
|
sa = 0;
|
|
}
|
|
|
|
if (what2) {
|
|
sb = 0;
|
|
}
|
|
}
|
|
if ((sa == 1) && ((fa * ab.y + ca.y) < z || (fa * ab.y + ca.y) > c->height)) {
|
|
sa = 0;
|
|
}
|
|
if ((sb == 1) && ((fba * ab.y + ca.y) < z || (fba * ab.y + ca.y) > c->height)) {
|
|
sb = 0;
|
|
}
|
|
if (sa == 0 && sb == 0) {
|
|
return 0;
|
|
}
|
|
|
|
if (sa == 1 && sb == 1) {
|
|
intpos[2].x = (fa * ab.x + ca.x) + c->center.x;
|
|
intpos[2].y = (fa * ab.y + ca.y) + c->center.y + c->offset;
|
|
intpos[2].z = (fa * ab.z + ca.z) + c->center.z;
|
|
f |= 4;
|
|
intpos[3].x = (fba * ab.x + ca.x) + c->center.x;
|
|
intpos[3].y = (fba * ab.y + ca.y) + c->center.y + c->offset;
|
|
intpos[3].z = (fba * ab.z + ca.z) + c->center.z;
|
|
f |= 8;
|
|
} else if (sa == 1) {
|
|
intpos[2].x = (fa * ab.x + ca.x) + c->center.x;
|
|
intpos[2].y = (fa * ab.y + ca.y) + c->center.y + c->offset;
|
|
intpos[2].z = (fa * ab.z + ca.z) + c->center.z;
|
|
f |= 4;
|
|
} else if (sb == 1) {
|
|
intpos[2].x = (fba * ab.x + ca.x) + c->center.x;
|
|
intpos[2].y = (fba * ab.y + ca.y) + c->center.y + c->offset;
|
|
intpos[2].z = (fba * ab.z + ca.z) + c->center.z;
|
|
f |= 4;
|
|
}
|
|
co = 0;
|
|
for (i = 0; i < 4; i++) {
|
|
if (f & (1 << i)) {
|
|
if (co == 0) {
|
|
*ia = intpos[i];
|
|
} else if (co == 1) {
|
|
if (Math3DLengthSquare(ia, la) < Math3DLengthSquare(ia, &intpos[i])) {
|
|
*ib = intpos[i];
|
|
break;
|
|
} else {
|
|
*ib = *ia;
|
|
*ia = intpos[i];
|
|
break;
|
|
}
|
|
}
|
|
co++;
|
|
}
|
|
}
|
|
return co;
|
|
}
|
|
|
|
extern int Math3D_pipeCrossTriangle_cp(Math3D_pipe_c* c, Math3D_triangle_c* tri, xyz_t* in) {
|
|
static xyz_t cross1;
|
|
static xyz_t cross2;
|
|
static Math3D_sphere_c sph1;
|
|
static Math3D_sphere_c sph2;
|
|
|
|
f32 ct;
|
|
f32 cb;
|
|
f32 mind;
|
|
f32 asq;
|
|
f32 yin;
|
|
f32 civovi;
|
|
f32 rdvovi;
|
|
xyz_t cic;
|
|
xyz_t vovi;
|
|
xyz_t dmf;
|
|
|
|
cb = c->center.y + (f32)c->offset;
|
|
ct = cb + (f32)c->height;
|
|
|
|
if (((cb > tri->vtx[0].y) && (cb > tri->vtx[1].y) && (cb > tri->vtx[2].y)) ||
|
|
((ct < tri->vtx[0].y) && (ct < tri->vtx[1].y) && (ct < tri->vtx[2].y))) {
|
|
return FALSE;
|
|
}
|
|
|
|
mind = 1.e38f;
|
|
if (Math3D_pipeCrossLine(c, &tri->vtx[0], &tri->vtx[1], &cross1, &cross2)) {
|
|
asq = Math3DLengthSquare(&cross1, &tri->vtx[0]);
|
|
mind = asq;
|
|
*in = cross1;
|
|
}
|
|
if (Math3D_pipeCrossLine(c, &tri->vtx[2], &tri->vtx[1], &cross1, &cross2)) {
|
|
asq = Math3DLengthSquare(&cross1, &tri->vtx[2]);
|
|
if (mind > asq) {
|
|
*in = cross1;
|
|
mind = asq;
|
|
}
|
|
}
|
|
if (Math3D_pipeCrossLine(c, &tri->vtx[0], &tri->vtx[2], &cross1, &cross2)) {
|
|
asq = Math3DLengthSquare(&cross1, &tri->vtx[0]);
|
|
if (mind > asq) {
|
|
*in = cross1;
|
|
mind = asq;
|
|
}
|
|
}
|
|
|
|
if (mind != 1.e38f) {
|
|
return TRUE;
|
|
}
|
|
|
|
if (Math3DTriangleCrossYLine_scope(&tri->vtx[0], &tri->vtx[1], &tri->vtx[2], tri->plane.normal.x,
|
|
tri->plane.normal.y, tri->plane.normal.z, tri->plane.originDist, c->center.z,
|
|
c->center.x, &yin, cb, ct)) {
|
|
|
|
cic.x = c->center.x;
|
|
cic.y = yin;
|
|
cic.z = c->center.z;
|
|
|
|
vovi.x = (tri->vtx[0].x + tri->vtx[1].x) * 0.5f;
|
|
vovi.y = (tri->vtx[0].y + tri->vtx[1].y) * 0.5f;
|
|
vovi.z = (tri->vtx[0].z + tri->vtx[1].z) * 0.5f;
|
|
|
|
xyz_t_sub(&vovi, &cic, &dmf);
|
|
|
|
civovi = sqrtf(SQ(dmf.x) + SQ(dmf.z));
|
|
|
|
if (fabsf(civovi) < 0.008f) {
|
|
xyz_t_move(in, &vovi);
|
|
} else {
|
|
rdvovi = c->radius / civovi;
|
|
Math3DInDivPos1(&cic, &dmf, rdvovi, in);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
sph1.center.x = sph2.center.x = c->center.x;
|
|
sph1.center.z = sph2.center.z = c->center.z;
|
|
sph1.center.y = ct;
|
|
sph2.center.y = cb;
|
|
sph1.radius = sph2.radius = c->radius;
|
|
|
|
if ((Math3D_sphereCrossTriangle3_cp(&sph1, tri, in)) || (Math3D_sphereCrossTriangle3_cp(&sph2, tri, in))) {
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
extern int Math3D_sphereCrossSphere_cl(Math3D_sphere_c* a, Math3D_sphere_c* b, f32* in) {
|
|
f32 cdist;
|
|
|
|
return (Math3D_sphereCrossSphere_cl_cc(a, b, in, &cdist));
|
|
}
|
|
|
|
extern int Math3D_sphereCrossSphere_cl_cc(Math3D_sphere_c* a, Math3D_sphere_c* b, f32* in, f32* cdist) {
|
|
f32 dx = (f32)a->center.x - (f32)b->center.x;
|
|
f32 dy = (f32)a->center.y - (f32)b->center.y;
|
|
f32 dz = (f32)a->center.z - (f32)b->center.z;
|
|
|
|
*cdist = sqrt(dx * dx + dy * dy + dz * dz);
|
|
|
|
*in = ((f32)a->radius + (f32)b->radius) - *cdist;
|
|
|
|
if (*in > 0.008f) {
|
|
return 1;
|
|
}
|
|
*in = 0.0f;
|
|
return 0;
|
|
}
|
|
|
|
extern int Math3D_sphereVsPipe_cl(Math3D_sphere_c* s, Math3D_pipe_c* c, f32* in) {
|
|
f32 cdist;
|
|
return Math3D_sphereVsPipe_cl_cc(s, c, in, &cdist);
|
|
}
|
|
|
|
extern int Math3D_sphereVsPipe_cl_cc(Math3D_sphere_c* s, Math3D_pipe_c* c, f32* in, f32* cdist) {
|
|
|
|
static Math3D_sphereF_c sphereF;
|
|
static Math3D_pipeF_c pipeF;
|
|
|
|
f32 x;
|
|
f32 z;
|
|
f32 ct;
|
|
f32 cb;
|
|
f32 cr;
|
|
|
|
if (s->radius <= 0 || c->radius <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
sphereF.center.y = s->center.y;
|
|
sphereF.radius = s->radius;
|
|
pipeF.center.y = c->center.y;
|
|
pipeF.offset = c->offset;
|
|
pipeF.height = c->height;
|
|
|
|
x = (f32)s->center.x - c->center.x;
|
|
z = (f32)s->center.z - c->center.z;
|
|
|
|
cb = pipeF.center.y + pipeF.offset;
|
|
ct = pipeF.center.y + pipeF.offset + pipeF.height;
|
|
cr = (f32)s->radius + c->radius;
|
|
|
|
*cdist = sqrtf(SQ(x) + SQ(z));
|
|
|
|
if (cr < *cdist) {
|
|
return FALSE;
|
|
}
|
|
|
|
if ((sphereF.center.y + sphereF.radius >= cb) && (sphereF.center.y - sphereF.radius <= ct)) {
|
|
*in = cr - *cdist;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern int Math3D_pipeVsPipe_cl(Math3D_pipe_c* a, Math3D_pipe_c* b, f32* d) {
|
|
f32 di;
|
|
|
|
return Math3D_pipeVsPipe_cl_cc(a, b, d, &di);
|
|
}
|
|
|
|
extern int Math3D_pipeVsPipe_cl_cc(Math3D_pipe_c* a, Math3D_pipe_c* b, f32* d, f32* di) {
|
|
static Math3D_pipeF_c pipe1f;
|
|
static Math3D_pipeF_c pipe2f;
|
|
|
|
xyz_t_move_s_xyz(&pipe1f.center, &a->center);
|
|
pipe1f.radius = a->radius;
|
|
pipe1f.offset = a->offset;
|
|
pipe1f.height = a->height;
|
|
|
|
xyz_t_move_s_xyz(&pipe2f.center, &b->center);
|
|
pipe2f.radius = b->radius;
|
|
pipe2f.offset = b->offset;
|
|
pipe2f.height = b->height;
|
|
|
|
*di = sqrtf((pipe1f.center.x - pipe2f.center.x) * (pipe1f.center.x - pipe2f.center.x) +
|
|
(pipe1f.center.z - pipe2f.center.z) * (pipe1f.center.z - pipe2f.center.z));
|
|
|
|
if (*di > (pipe1f.radius + pipe2f.radius)) {
|
|
return 0;
|
|
}
|
|
|
|
if (((pipe1f.center.y + pipe1f.offset) + pipe1f.height) < (pipe2f.center.y + pipe2f.offset) ||
|
|
(((pipe1f.center.y + pipe1f.offset) > (pipe2f.center.y + pipe2f.offset) + pipe2f.height))) {
|
|
return 0;
|
|
}
|
|
*d = pipe1f.radius + pipe2f.radius - *di;
|
|
return 1;
|
|
}
|
|
|
|
extern void sMath_RotateY(xyz_t* v, f32 y) {
|
|
f32 cos = cosf_table(y);
|
|
f32 sin = sinf_table(y);
|
|
xyz_t temp = *v;
|
|
|
|
v->x = temp.x * cos + temp.z * sin;
|
|
v->z = -temp.x * sin + temp.z * cos;
|
|
}
|
|
|
|
extern void sMath_RotateX(xyz_t* v, f32 x) {
|
|
f32 cos = cosf_table(x);
|
|
f32 sin = sinf_table(x);
|
|
xyz_t temp = *v;
|
|
|
|
v->y = temp.y * cos - temp.z * sin;
|
|
v->z = temp.y * sin + temp.z * cos;
|
|
}
|
|
|
|
extern void sMath_RotateZ(xyz_t* v, f32 z) {
|
|
f32 cos = cosf_table(z);
|
|
f32 sin = sinf_table(z);
|
|
xyz_t temp = *v;
|
|
|
|
v->x = temp.x * cos - temp.y * sin;
|
|
v->y = temp.x * sin + temp.y * cos;
|
|
}
|