16 #define SMALL_NUM 1E-6
18 #define UNINITIALIZED_VALUE -1234567.8f
21 static void accurate_square_root(
float A,
float B,
float C,
float discriminant,
float *root1,
float *root2 )
__UNUSED;
51 if (denominator > 1e-10) {
52 num_s = matrix_determinant_from_vectors(&delta, v2, &cross);
55 num_t = matrix_determinant_from_vectors(&delta, v1, &cross);
119 const vec3d *plane_pnt,
const vec3d *plane_norm,
120 const vec3d *ray_origin,
const vec3d *ray_direction,
131 new_pnt->
xyz.x = -FLT_MAX;
132 new_pnt->
xyz.y = -FLT_MAX;
133 new_pnt->
xyz.z = -FLT_MAX;
163 const vec3d *plane_pnt,
const vec3d *plane_norm,
172 plane_pnt,plane_norm,
176 if ( t < 0.0
f )
return 0;
177 if ( t > 1.0
f )
return 0;
190 vec3d d,dn,
w,closest_point;
191 float mag_d,dist,w_dist,int_dist;
203 return (int_dist<sphere_rad)?1:0;
207 dn.
xyz.x = d.
xyz.x / mag_d;
208 dn.
xyz.y = d.
xyz.y / mag_d;
209 dn.
xyz.z = d.
xyz.z / mag_d;
213 if (w_dist < -sphere_rad)
216 if (w_dist > mag_d+sphere_rad)
223 if (dist < sphere_rad) {
224 float dist2,rad2,shorten;
227 rad2 = sphere_rad*sphere_rad;
229 shorten =
fl_sqrt(rad2 - dist2);
231 int_dist = w_dist-shorten;
233 if (int_dist > mag_d || int_dist < 0.0
f) {
257 vec3d d,dn,
w,closest_point;
258 float mag_d,dist,w_dist,int_dist;
270 return (int_dist<sphere_rad)?1:0;
274 dn.
xyz.x = d.
xyz.x / mag_d;
275 dn.
xyz.y = d.
xyz.y / mag_d;
276 dn.
xyz.z = d.
xyz.z / mag_d;
280 if (w_dist < -sphere_rad)
287 if (dist < sphere_rad) {
288 float dist2,rad2,shorten;
291 rad2 = sphere_rad*sphere_rad;
293 shorten =
fl_sqrt(rad2 - dist2);
295 int_dist = w_dist-shorten;
297 if (int_dist < 0.0
f) {
323 int middle = ((1<<0) | (1<<1) | (1<<2));
327 float candidate_plane[3];
329 for (i = 0; i < 3; i++) {
330 if (p0->
a1d[i] < min->
a1d[i]) {
331 candidate_plane[
i] = min->
a1d[
i];
333 }
else if (p0->
a1d[i] > max->
a1d[i]) {
334 candidate_plane[
i] = max->
a1d[
i];
341 if (middle == ((1<<0) | (1<<1) | (1<<2))) {
347 for (i = 0; i < 3; i++) {
348 if ( (middle & (1<<i)) || (pdir->
a1d[i] == 0.0f) ) {
351 maxt[
i] = (candidate_plane[
i] - p0->
a1d[
i]) / pdir->
a1d[i];
357 for (i = 1; i < 3; i++) {
358 if (maxt[which_plane] < maxt[i]) {
364 if (maxt[which_plane] < 0.0
f) {
368 for (i = 0; i < 3; i++) {
369 if (which_plane == i) {
370 hitpt->
a1d[
i] = candidate_plane[
i];
372 hitpt->
a1d[
i] = (maxt[which_plane] * pdir->
a1d[
i]) + p0->
a1d[i];
387 static int ij_table[3][2] = {
418 #define delta 0.0001f
426 norm = (
float *)norm1;
433 if (t.
xyz.x > t.
xyz.y)
if (t.
xyz.x > t.
xyz.z) i0=0;
else i0=2;
434 else if (t.
xyz.y > t.
xyz.z) i0=1;
else i0=2;
436 if (norm[i0] > 0.0
f) {
437 i1 = ij_table[i0][0];
438 i2 = ij_table[i0][1];
441 i1 = ij_table[i0][1];
442 i2 = ij_table[i0][0];
453 u0 = P[i1] - verts[0]->
a1d[i1];
454 v0 = P[i2] - verts[0]->
a1d[i2];
458 u1 = verts[
i-1]->
a1d[i1] - verts[0]->
a1d[i1];
459 u2 = verts[
i ]->
a1d[i1] - verts[0]->
a1d[i1];
461 v1 = verts[
i-1]->
a1d[i2] - verts[0]->
a1d[i2];
462 v2 = verts[
i ]->
a1d[i2] - verts[0]->
a1d[i2];
467 if ((beta >=0.0
f) && (beta<=1.0f)) {
468 alpha = (v0 - beta*
v2)/v1;
469 inter = ((alpha>=0.0f)&&(alpha+beta<=1.0
f));
473 beta = (v0*u1 - u0*
v1) / (v2*u1 - u2*v1);
474 if ((beta >=0.0
f) && (beta<=1.0f)) {
476 alpha = (u0 - beta*
u2)/u1;
477 inter = ((alpha>=0.0f)&&(alpha+beta<=1.0
f));
481 }
while ((!inter) && (++
i < nv) );
483 if ( inter && uvls && u_out && v_out ) {
484 gamma = 1.0f - (alpha+beta);
485 *u_out = gamma * uvls[0].
u + alpha*uvls[
i-1].
u + beta*uvls[
i].
u;
486 *v_out = gamma * uvls[0].
v + alpha*uvls[
i-1].
v + beta*uvls[
i].
v;
498 static int check_sphere_point(
const vec3d *point,
const vec3d *sphere_start,
const vec3d *sphere_vel,
float radius,
float *collide_time );
517 const vec3d *plane_normal,
const vec3d *plane_point,
float *hit_time,
float *crossing_time)
519 float D, xs0_dot_norm, vs_dot_norm;
524 xs0_dot_norm =
vm_vec_dot( plane_normal, sphere_center_start );
525 vs_dot_norm =
vm_vec_dot( plane_normal, sphere_velocity);
528 if (
fl_abs(vs_dot_norm) > 1e-30) {
529 t1 = (-D - xs0_dot_norm + sphere_radius) / vs_dot_norm;
530 t2 = (-D - xs0_dot_norm - sphere_radius) / vs_dot_norm;
545 if (t1 > 0 && t1 < 1) {
552 *crossing_time = t2 -
t1;
554 return ( (t1 < 1) && (t2 > 0) );
571 float sphere_radius,
vec3d *edge_point1,
vec3d *edge_point2,
float *collide_time)
580 vec3d Xe_proj, Xs_proj;
587 vec3d x_hat, y_hat, z_hat;
588 float max_edge_parameter;
593 max_edge_parameter =
vm_vec_mag( &edge_velocity );
619 float edge_parameter;
622 vm_vec_sub( &temp_vec, intersect_point, &V0 );
623 edge_parameter =
vm_vec_dot( &temp_vec, &x_hat );
625 if ( edge_parameter < 0 || edge_parameter > max_edge_parameter ) {
629 return ( check_sphere_point(intersect_point, sphere_center_start, sphere_velocity, sphere_radius, collide_time) );
642 static int check_sphere_point(
const vec3d *point,
const vec3d *sphere_start,
const vec3d *sphere_vel,
float radius,
float *collide_time )
645 float delta_x_sqr, vs_sqr, delta_x_dot_vs;
650 delta_x_dot_vs =
vm_vec_dot( &delta_x, sphere_vel );
652 float discriminant = delta_x_dot_vs*delta_x_dot_vs - vs_sqr*(delta_x_sqr - radius*radius);
653 if (discriminant < 0) {
657 float radical, time1, time2;
658 radical =
fl_sqrt(discriminant);
659 time1 = (-delta_x_dot_vs + radical) / vs_sqr;
660 time2 = (-delta_x_dot_vs - radical) / vs_sqr;
668 if (time1 >= 0 && time1 <= 1.0) {
669 *collide_time = time1;
673 if (time2 >= 0 && time2 <= 1.0) {
674 *collide_time = time2;
699 float best_sphere_time;
701 float delta_x_dot_ve, delta_x_dot_vs, ve_dot_vs, ve_sqr, vs_sqr, delta_x_sqr;
702 vec3d temp_edge_hit, temp_sphere_hit;
703 float t_sphere_hit = 0.0f;
704 float A,
B, C,
temp, discriminant, invA;
705 float root, root1, root2;
706 float Rs2 = (Rs * Rs);
707 float Rs_point2 = (0.2f * Rs);
709 best_sphere_time = FLT_MAX;
713 for (i = 0; i < nv; i++) {
748 A = ve_dot_vs*ve_dot_vs - ve_sqr*vs_sqr;
749 B = delta_x_dot_ve*ve_dot_vs - delta_x_dot_vs*ve_sqr;
750 C = delta_x_dot_ve*delta_x_dot_ve + Rs2*ve_sqr - delta_x_sqr*ve_sqr;
752 discriminant = B*B - A*C;
753 if (discriminant > 0.0
f) {
755 root = sqrt(discriminant);
756 root1 = (-B + root) * invA;
757 root2 = (-B - root) * invA;
766 if ( (root1 < 0.0
f) && (root1 >= -0.05f) )
770 if ( (root1 <= 1.0
f) && (root1 >= 0.0f) ) {
771 t_sphere_hit = root1;
781 if (t_sphere_hit >= best_sphere_time)
788 B = ve_sqr * (delta_x_dot_ve*vs_sqr - delta_x_dot_vs*ve_dot_vs);
789 C = 2.0f*delta_x_dot_ve*delta_x_dot_vs*ve_dot_vs + Rs2*ve_dot_vs*ve_dot_vs
790 - delta_x_sqr*ve_dot_vs*ve_dot_vs - delta_x_dot_ve*delta_x_dot_ve*vs_sqr;
792 discriminant = B*B - A*C;
796 if (discriminant < 0.0
f)
801 root1 = (-B + root) * invA;
802 root2 = (-B - root) * invA;
805 if ( (root1 <= 1.0
f) && (root1 >= 0.0f) ) {
809 if (
fl_abs(q - Rs2) < Rs_point2 ) {
814 if ( (root2 <= 1.0
f) && (root2 >= 0.0
f) ) {
818 if (
fl_abs(q - Rs2) < Rs_point2 ) {
830 C = delta_x_sqr - Rs2;
832 float sphere_v0, sphere_v1;
839 discriminant = B*B - A*C;
840 if (discriminant > 0.0
f) {
842 root1 = (-B + root) * invA;
843 root2 = (-B - root) * invA;
852 if ( (root1 < 1.0
f) && (root1 > 0.0f) ) {
865 C = delta_x_sqr - Rs2;
868 discriminant = B*B - A*C;
869 if (discriminant > 0.0
f) {
871 root1 = (-B + root) * invA;
872 root2 = (-B - root) * invA;
881 if ( (root1 < 1.0
f) && (root1 > 0.0f) ) {
890 t_sphere_hit = sphere_v0;
895 if (sphere_v1 < sphere_v0) {
896 t_sphere_hit = sphere_v1;
900 }
else if ( v1_hit ) {
902 t_sphere_hit = sphere_v1;
913 if (t_sphere_hit < best_sphere_time) {
914 best_sphere_time = t_sphere_hit;
915 *hit_point = temp_edge_hit;
919 if (best_sphere_time <= 1.0
f) {
920 *hit_time = best_sphere_time;
937 vec3d delta_x, line_velocity;
940 vm_vec_sub(&line_velocity, line_point2, line_point1);
941 vm_vec_sub(&delta_x, line_point1, fixed_point);
971 vec3d delta_x, delta_v;
972 float discriminant, separation, delta_x_dot_delta_v, delta_v_sqr, delta_x_sqr;
976 Assert( (!(t1) && !(t2)) || (t1 && t2) );
980 separation = radius_p + radius_s;
983 if (delta_x_sqr < separation*separation) {
995 delta_x_dot_delta_v =
vm_vec_dot(&delta_x, &delta_v);
998 discriminant = delta_x_dot_delta_v*delta_x_dot_delta_v - delta_v_sqr*(delta_x_sqr - separation*separation);
1000 if (discriminant < 0) {
1004 float radical =
fl_sqrt(discriminant);
1006 time1 = (-delta_x_dot_delta_v + radical) / delta_v_sqr;
1007 time2 = (-delta_x_dot_delta_v - radical) / delta_v_sqr;
1011 if (time1 > time2) {
1023 if (time1 > 1 || time2 < 0) {
1046 vec3d closest_point, closest_separation;
1050 vm_vec_sub(&closest_separation, &closest_point, poly_center);
1052 max_sep =
vm_vec_mag(&closest_separation) + poly_r;
1054 if ( max_sep > sphere_r ) {
1066 vec3d vx_cross_vy, delta_l, delta_l_cross_vx, delta_l_cross_vy;
1082 static void accurate_square_root(
float A,
float B,
float C,
float discriminant,
float *root1,
float *root2 )
1084 float root =
fl_sqrt(discriminant);
1087 *root1 = 2.0f*C / (-B - root);
1088 *root2 = (-B - root) / (2.0
f*A);
1090 *root1 = (-B + root) / (2.0
f*A);
1091 *root2 = 2.0f*C / (-B + root);
1111 if (start->
xyz.x > maxs->
xyz.x) {
1112 box_pt->
xyz.x = maxs->
xyz.x;
1114 }
else if (start->
xyz.x < mins->
xyz.x) {
1115 box_pt->
xyz.x = mins->
xyz.x;
1118 box_pt->
xyz.x = start->
xyz.x;
1121 if (start->
xyz.y > maxs->
xyz.y) {
1122 box_pt->
xyz.y = maxs->
xyz.y;
1124 }
else if (start->
xyz.y < mins->
xyz.y) {
1125 box_pt->
xyz.y = mins->
xyz.y;
1128 box_pt->
xyz.y = start->
xyz.y;
1131 if (start->
xyz.z > maxs->
xyz.z) {
1132 box_pt->
xyz.z = maxs->
xyz.z;
1134 }
else if (start->
xyz.z < mins->
xyz.z) {
1135 box_pt->
xyz.z = mins->
xyz.z;
1138 box_pt->
xyz.z = start->
xyz.z;
void vm_vec_projection_onto_plane(vec3d *projection, const vec3d *src, const vec3d *unit_normal)
int fvi_polyedge_sphereline(vec3d *hit_point, const vec3d *xs0, const vec3d *vs, float Rs, int nv, vec3d const *const *verts, float *hit_time)
void vm_vec_scale_add(vec3d *dest, const vec3d *src1, const vec3d *src2, float k)
float vm_vec_mag(const vec3d *v)
struct vec3d::@225::@227 xyz
void fvi_closest_point_on_line_segment(vec3d *closest_point, const vec3d *fixed_point, const vec3d *line_point1, const vec3d *line_point2)
void vm_vec_scale_add2(vec3d *dest, const vec3d *src, float k)
GLfloat GLfloat GLfloat v2
float vm_vec_mag_squared(const vec3d *v)
float fvi_point_dist_plane(const vec3d *plane_pnt, const vec3d *plane_norm, const vec3d *point)
int fvi_sphere_plane(vec3d *intersect_point, const vec3d *sphere_center_start, const vec3d *sphere_velocity, float sphere_radius, const vec3d *plane_normal, const vec3d *plane_point, float *hit_time, float *crossing_time)
void vm_vec_add2(vec3d *dest, const vec3d *src)
int fvi_point_face(const vec3d *checkp, int nv, vec3d const *const *verts, const vec3d *norm1, float *u_out, float *v_out, const uv_pair *uvls)
int fvi_sphere_perp_edge(vec3d *intersect_point, const vec3d *sphere_center_start, const vec3d *sphere_velocity, float sphere_radius, vec3d *edge_point1, vec3d *edge_point2, float *collide_time)
void vm_vec_sub2(vec3d *dest, const vec3d *src)
float vm_vec_dist(const vec3d *v0, const vec3d *v1)
float vm_vec_dist_squared(const vec3d *v0, const vec3d *v1)
int fvi_ray_sphere(vec3d *intp, const vec3d *p0, const vec3d *p1, const vec3d *sphere_pos, float sphere_rad)
void vm_vec_copy_scale(vec3d *dest, const vec3d *src, float s)
int fvi_cull_polyface_sphere(const vec3d *poly_center, float poly_r, const vec3d *sphere_start, const vec3d *sphere_end, float sphere_r)
void vm_vec_sub(vec3d *dest, const vec3d *src0, const vec3d *src1)
#define UNINITIALIZED_VALUE
INT32 INT32 * denominator
GLdouble GLdouble GLdouble GLdouble q
void fvi_closest_line_line(const vec3d *x0, const vec3d *vx, const vec3d *y0, const vec3d *vy, float *x_time, float *y_time)
void fvi_two_lines_in_3space(const vec3d *p1, const vec3d *v1, const vec3d *p2, const vec3d *v2, float *s, float *t)
int fvi_check_sphere_sphere(const vec3d *x_p0, const vec3d *x_p1, const vec3d *x_s0, const vec3d *x_s1, float radius_p, float radius_s, float *t1, float *t2)
float vm_vec_copy_normalize(vec3d *dest, const vec3d *src)
int fvi_segment_sphere(vec3d *intp, const vec3d *p0, const vec3d *p1, const vec3d *sphere_pos, float sphere_rad)
void vm_project_point_onto_plane(vec3d *new_point, const vec3d *point, const vec3d *plane_normal, const vec3d *plane_point)
int vm_vec_cmp(const vec3d *a, const vec3d *b)
float vm_vec_dot(const vec3d *v0, const vec3d *v1)
float fvi_ray_plane(vec3d *new_pnt, const vec3d *plane_pnt, const vec3d *plane_norm, const vec3d *ray_origin, const vec3d *ray_direction, float rad)
vec3d * vm_vec_cross(vec3d *dest, const vec3d *src0, const vec3d *src1)
GLclampf GLclampf GLclampf alpha
int fvi_segment_plane(vec3d *new_pnt, const vec3d *plane_pnt, const vec3d *plane_norm, const vec3d *p0, const vec3d *p1, float rad)
int fvi_ray_boundingbox(const vec3d *min, const vec3d *max, const vec3d *p0, const vec3d *pdir, vec3d *hitpt)
int project_point_onto_bbox(const vec3d *mins, const vec3d *maxs, const vec3d *start, vec3d *box_pt)
GLfloat GLfloat GLfloat GLfloat v3