33 #include <libFreeWRL.h>
36 #include "RenderFuncs.h"
38 #include "../vrml_parser/Structs.h"
39 #include "../main/headers.h"
41 #include "LinearAlgebra.h"
43 #include "../opencl/OpenCL_Utils.h"
45 #include "Collision.h"
46 #include "../internal.h"
51 static void accumulateFallingClimbing(
double y1,
double y2,
double ystep,
struct point_XYZ *p,
int num,
struct point_XYZ nused,
double *tmin,
double *tmax);
56 #define DJ_KEEP_COMPILER_WARNING 0
64 #define swap(x,y) {double k = x; x = y; y = k; }
65 #define FLOAT_TOLERANCE 0.00000001
66 #if DJ_KEEP_COMPILER_WARNING
67 #define MAX_POLYREP_DISP_RECURSION_COUNT 10
69 #define STEPUP_MAXINCLINE 0.9
72 #define DEBUGPTSPRINT(x,y,z) printf(x,y,z)
74 #define DEBUGPTSPRINT(x,y,z) {}
77 static const struct point_XYZ zero = {0,0,0};
80 float* prd_newc_floats;
81 unsigned int prd_newc_floats_size;
98 struct sCollisionGPU CollisionGPU;
104 double get_poly_mindisp;
109 bool OpenCL_Collision_Program_initialized;
112 void *collision_constructor(){
117 void collision_init(
struct tcollision *t){
121 t->prv = collision_constructor();
124 p->prd_newc_floats = NULL;
125 p->prd_newc_floats_size = 0;
126 p->prd_normals = NULL;
127 p->prd_normals_size = 0;
128 p->clippedPoly1 = NULL;
129 p->clippedPoly1Size = 0;
130 p->clippedPoly2 = NULL;
131 p->clippedPoly2Size = 0;
132 p->clippedPoly3 = NULL;
133 p->clippedPoly3Size = 0;
134 p->clippedPoly4 = NULL;
135 p->clippedPoly4Size = 0;
136 p->clippedPoly5 = NULL;
137 p->clippedPoly5Size = 0;
141 p->CollisionInfo.Count = 0;
142 p->CollisionInfo.Maximum2 = 0.0;
143 p->CollisionInfo.Offset.x = 0.0;
144 p->CollisionInfo.Offset.y = 0.0;
145 p->CollisionInfo.Offset.z = 0.0;
149 p->CollisionGPU.CollideGPU_program = NULL;
150 p->CollisionGPU.CollideGPU_kernel = NULL;
151 p->CollisionGPU.CollideGPU_output_buffer = NULL;
152 p->CollisionGPU.CollideGPU_matrix_buffer = NULL;
153 p->CollisionGPU.CollideGPU_vertex_buffer = NULL;
154 p->CollisionGPU.CollideGPU_index_buffer = NULL;
155 p->CollisionGPU.CollideGPU_returnValues.n = 0;
156 p->CollisionGPU.CollideGPU_returnValues.p = NULL;
158 p->OpenCL_Collision_Program_initialized = FALSE;
163 void collision_clear(
struct tcollision *t){
168 FREE_IF_NZ(p->prd_newc_floats);
169 FREE_IF_NZ(p->prd_normals);
177 return &p->CollisionInfo;
189 void createGPUCollisionProgram () {
192 p->OpenCL_Collision_Program_initialized = collision_initGPUCollide(&p->CollisionGPU);
195 struct sCollisionGPU* GPUCollisionInfo()
198 return &p->CollisionGPU;
200 #endif // HAVE_OPENCL
203 #define make_pt(p,xc,yc,zc) { p.x = (xc); p.y = (yc); p.z = (zc); }
205 int overlapMBBs(GLDOUBLE *MBBmin1, GLDOUBLE *MBBmax1, GLDOUBLE *MBBmin2, GLDOUBLE* MBBmax2)
217 overlap = overlap && !(MBBmin1[i] > MBBmax2[i] || MBBmax1[i] < MBBmin2[i]);
226 double len2 = vecdot(&add,&add);
228 VECADD(ci->Offset,add);
229 if(len2 > ci->Maximum2)
233 static double closest_point_of_segment_to_origin(
struct point_XYZ p1,
struct point_XYZ p2) {
235 double x12 = (p1.x - p2.x);
236 double y12 = (p1.y - p2.y);
237 double z12 = (p1.z - p2.z);
238 double q = ( x12*x12 + y12*y12 + z12*z12 );
241 double i = ((APPROX(q, 0)) ? 0.5 : (p1.x * x12 + p1.y * y12 + p1.z * z12) / q);
256 double k = b.x*n.x + b.y*n.y + b.z*n.z;
276 if(APPROX(q2.x, 0) && APPROX(q2.z, 0)) {
284 quotient = ((-p2.z)*q2.x + p2.x*q2.z);
286 if(APPROX(quotient, 0))
return 0;
288 k = (p1.z*q2.x - q1.z*q2.x - p1.x*q2.z + q1.x*q2.z)/quotient;
291 if((k >= 0.) && (k < 1.)) {
303 static int getk_intersect_line_with_ycylinder(
double* k1,
double* k2,
double r,
struct point_XYZ pp1,
struct point_XYZ n) {
304 double b,a,sqrdelta,delta;
308 a = 2*(n.x*n.x + n.z*n.z);
309 b = -2*(pp1.x*n.x + pp1.z*n.z);
310 delta = (4*((pp1.x*n.x + pp1.z*n.z)*(pp1.x*n.x + pp1.z*n.z)) -
311 4*((n.x*n.x + n.z*n.z))*((pp1.x*pp1.x + pp1.z*pp1.z - r*r)));
312 if(delta < 0.)
return 0;
313 sqrdelta = sqrt(delta);
315 *k1 = (b+sqrdelta)/a;
317 if(APPROX(sqrdelta, 0))
return 1;
319 *k2 = (b-sqrdelta)/a;
328 make_pt(ret,p1.x - (n.x*(p1.y-y))/n.y,y,(p1.z - (n.z*(p1.y-y))/n.y));
338 vecscale(&n,&n,-1.0);
344 ret.x = p.x + (n.x*((n.x*((pp.x - p.x)) + n.z*((pp.z - p.z)))))/(n.x*n.x + n.z*n.z);
345 ret.y = p.y + (n.y*((n.x*((pp.x - p.x)) + n.z*((pp.z - p.z)))))/(n.x*n.x + n.z*n.z);
346 ret.z = p.z + (n.z*((n.x*((pp.x - p.x)) + n.z*((pp.z - p.z)))))/(n.x*n.x + n.z*n.z);
354 static int perpendicular_line_passing_inside_poly(
struct point_XYZ a,
struct point_XYZ* p,
int num) {
364 if(APPROX(vecnormal(&n,&a), 0)) {
368 make_orthogonal_vector_space(&i,&j,n);
370 vecscale(&epsilon,&j,FLOAT_TOLERANCE);
372 for(f = 0; f < num; f++) {
377 VECDIFF(p[(f+1)%num],a,p2);
379 while(APPROX((p1j = vecdot(&p1,&j)), 0)) VECADD(p1,epsilon);
382 while(APPROX((p2j = vecdot(&p2,&j)), 0)) VECADD(p2,epsilon);
385 if(p1j * p2j <= 0 ) {
390 k = (! APPROX(p1j-p2j, 0)) ? (p1j/ (p1j - p2j)) : 0.;
393 p0 = weighted_sum(p1, p2, k);
394 if(vecdot(&p0,&i) >= 0)
400 return sectcount % 2;
408 static int getk_intersect_segment_with_ycylinder(
double* k1,
double* k2,
double r,
struct point_XYZ pp1,
struct point_XYZ pp2) {
409 double b,a,sqrdelta,delta;
413 VECDIFF(pp2,pp1,pp2);
416 a = 2*(pp2.x*pp2.x + pp2.z*pp2.z);
417 b = -2*(pp1.x*pp2.x + pp1.z*pp2.z);
418 delta = (4*((pp1.x*pp2.x + pp1.z*pp2.z)*(pp1.x*pp2.x + pp1.z*pp2.z)) -
419 4*((pp2.x*pp2.x + pp2.z*pp2.z))*((pp1.x*pp1.x + pp1.z*pp1.z - r*r)));
420 if(delta < 0.)
return 0;
421 sqrdelta = sqrt(delta);
423 *k1 = (b+sqrdelta)/a;
424 *k2 = (b-sqrdelta)/a;
426 if(*k1 >= 0. && *k1 <= 1.) res++;
427 if(*k2 >= 0. && *k2 <= 1.) res++;
428 if(res == 1 && (*k1 < 0. || *k1 > 1.)) swap(*k1,*k2);
458 vecdiff(&a,&D,&p[i]);
459 vecdiff(&b,&p[j],&p[i]);
462 inside = inside && vecdot(&last,&c) >= 0.0;
492 d = -vecdot(&n,&p[0]);
495 ndotD = vecdot(&n,&D);
497 if(APPROX(ndotD,0.0) )
503 t = - ( (d + vecdot(&n,&s0)) / ndotD );
505 if( t < 0.0 || t > r )
514 hit = pointOnPlaneInsidePoly(D,p,num,&n);
521 static struct point_XYZ get_poly_radialSample_disp(double y1, double y2, double ystep, double r,struct
point_XYZ* p,
int num,
struct point_XYZ n, double *tmin,
double *tmax)
527 double level[3],dr,dmax,eighth,theta, avmin[3], avmax[3];
532 s0.x = s0.y = s0.z = 0.0;
534 eighth = M_PI * 2.0 / 8.0;
541 avmin[1] = ystep; avmax[1] = y2;
542 if(!overlapMBBs(avmin,avmax,tmin,tmax))
return result;
556 avmin[0] = DOUBLE_MIN(s0.x,s1.x);
557 avmin[1] = DOUBLE_MIN(s0.y,s1.y);
558 avmin[2] = DOUBLE_MIN(s0.z,s1.z);
559 avmax[0] = DOUBLE_MAX(s0.x,s1.x);
560 avmax[1] = DOUBLE_MAX(s0.y,s1.y);
561 avmax[2] = DOUBLE_MAX(s0.z,s1.z);
562 if( overlapMBBs(avmin,avmax,tmin,tmax) )
564 hit = intersectLineSegmentWithPoly(s0,s1,r,p,num,n,&dr);
567 if( (dr > FLOAT_TOLERANCE) && (dr > dmax) )
570 vecscale(&result,&s1,r-dr);
582 static int get_poly_penetration_disp(
double r,
struct point_XYZ* p,
int num,
struct point_XYZ n,
double *tmin,
double *tmax,
struct point_XYZ *result,
double *rmax)
610 if( overlapMBBs(fi->penMin,fi->penMax,tmin,tmax) )
613 hit = intersectLineSegmentWithPoly(s0,fi->penvec,fi->penRadius,p,num,n,&dr);
616 vecscale(result,&fi->penvec,(dr + r));
653 double tmin[3],tmax[3];
656 GLDOUBLE awidth, atop, abottom, astep;
659 naviinfo = (
struct sNaviInfo *)tg->Bindable.naviinfo;
660 awidth = naviinfo->width;
661 atop = naviinfo->width;
662 abottom = -naviinfo->height;
663 astep = -naviinfo->height+naviinfo->step;
667 pp->get_poly_mindisp = 0.0;
672 tmin[0] = tmax[0] = p[0].x;
673 tmin[1] = tmax[1] = p[0].y;
674 tmin[2] = tmax[2] = p[0].z;
677 tmin[0] = DOUBLE_MIN(tmin[0],p[i].x);
678 tmin[1] = DOUBLE_MIN(tmin[1],p[i].y);
679 tmin[2] = DOUBLE_MIN(tmin[2],p[i].z);
680 tmax[0] = DOUBLE_MAX(tmax[0],p[i].x);
681 tmax[1] = DOUBLE_MAX(tmax[1],p[i].y);
682 tmax[2] = DOUBLE_MAX(tmax[2],p[i].z);
689 if(fi->checkPenetration)
693 hit = get_poly_penetration_disp(awidth,p,num,n,tmin,tmax,&presult,&rmax);
697 if(rmax > fi->pendisp)
699 fi->pencorrection = presult;
704 if(fi->checkCylinder && !hit)
706 result = get_poly_radialSample_disp(abottom,atop,astep,awidth,p,num,n,tmin,tmax);
708 hit = !(APPROX(result.x, 0) && APPROX(result.y, 0) && APPROX(result.z, 0));
712 if(fi->checkFall && !hit)
714 accumulateFallingClimbing(abottom,atop,astep,p,num,n,tmin,tmax);
722 result = get_poly_min_disp_with_sphere(awidth, p, num, n);
724 pp->get_poly_mindisp = vecdot(&result,&result);
737 double tmin[3],tmax[3],rmin[3],rmax[3],q[3];
738 double get_poly_mindisp;
739 int clippedPoly4num = 0;
741 get_poly_mindisp = 1E90;
749 memcpy(tmin,&p[0],3*
sizeof(
double));
750 memcpy(tmax,&p[num-1],3*
sizeof(
double));
754 memcpy(q,&p[i],3*
sizeof(
double));
757 tmin[j] = DOUBLE_MIN(tmin[j],q[j]);
758 tmax[j] = DOUBLE_MAX(tmax[j],q[j]);
767 if( !overlapMBBs(rmin,rmax,tmin,tmax) )
774 if(facemask != debugsurface++)
778 if ((num+1)> pp->clippedPoly4Size) {
779 pp->clippedPoly4 = (
struct point_XYZ*) REALLOC(pp->clippedPoly4,
sizeof(
struct point_XYZ) * (num + 1));
780 pp->clippedPoly4Size = num+1;
785 if(APPROX(n.x, 0) && APPROX(n.y, 0) && APPROX(n.z, 0)) {
786 polynormal(&n,&p[0],&p[1],&p[2]);
790 for(i = 0; i < num; i++) {
791 DEBUGPTSPRINT(
"intersect_closestpolypoints_on_surface[%d]= %d\n",i,clippedPoly4num);
792 pp->clippedPoly4[clippedPoly4num++] = weighted_sum(p[i],p[(i+1)%num],closest_point_of_segment_to_origin(p[i],p[(i+1)%num]));
796 pp->clippedPoly4[clippedPoly4num] = closest_point_of_plane_to_origin(p[0],n);
810 if(perpendicular_line_passing_inside_poly(pp->clippedPoly4[clippedPoly4num],p, num)) {
811 DEBUGPTSPRINT(
"perpendicular_line_passing_inside_poly[%d]= %d\n",0,clippedPoly4num);
816 for(i=0; i < clippedPoly4num; i++) {
817 debugpts.push_back(clippedPoly4[i]);
825 for(i = 0; i < clippedPoly4num; i++)
830 double disp = vecdot(&pp->clippedPoly4[i],&pp->clippedPoly4[i]);
834 if(disp < get_poly_mindisp)
836 get_poly_mindisp = disp;
837 result = pp->clippedPoly4[i];
842 if(get_poly_mindisp <= r*r)
852 rl = veclength(result);
859 vecscale(&result,&result,(r-sqrt(get_poly_mindisp)) / rl);
878 static int helper_line_clip_cap(
struct point_XYZ* clippedpoly,
int clippedpolynum,
struct point_XYZ p1,
struct point_XYZ p2,
double r,
struct point_XYZ n,
double y,
int stepping)
886 ppoly[0] = project_on_yplane(p1,n,y);
887 ppoly[1] = project_on_yplane(p2,n,y);
894 for(i= 0; i < 2; i++) {
895 if(ppoly[i].x*ppoly[i].x + ppoly[i].z*ppoly[i].z > r*r) {
898 clippedpoly[clippedpolynum++] = ppoly[i];
910 nsect = getk_intersect_segment_with_ycylinder(&k1,&k2,r,ppoly[0],ppoly[1]);
913 if(fabs(k1-k2) < FLOAT_TOLERANCE)
915 clippedpoly[clippedpolynum++] = weighted_sum(ppoly[0],ppoly[1],k2);
917 clippedpoly[clippedpolynum++] = weighted_sum(ppoly[0],ppoly[1],k1);
922 if(intersect_segment_with_line_on_yplane(&dessect,ppoly[0],ppoly[1],n,zero)) {
923 if(dessect.x*dessect.x + dessect.z*dessect.z < r*r) {
925 clippedpoly[clippedpolynum++] = dessect;
930 return clippedpolynum;
944 int clippedpolynum = 0;
951 if(! APPROX(n.y, 0)) {
952 clippedpolynum = helper_line_clip_cap(clippedpoly, clippedpolynum, p1, p2, r, n, y1, 0);
953 clippedpolynum = helper_line_clip_cap(clippedpoly, clippedpolynum, p1, p2, r, n, y2, 0);
958 if(! APPROX(n.y, 1) && ! APPROX(n.y, -1)) {
966 if(intersect_segment_with_line_on_yplane(&dessect3d,p[0],p[1],n,zero)) {
967 dessect3d = project_on_cylindersurface_plane(dessect3d,n,r);
969 if(dessect3d.y < y2 &&
971 clippedpoly[clippedpolynum++] = dessect3d;
976 for(i = 0; i < num; i++) {
977 nsect = getk_intersect_line_with_ycylinder(&k1, &k2, r, p[i], n);
978 if(nsect == 0)
continue;
981 vecscale(§[i],&n,k2);
982 VECADD(sect[i],p[i]);
984 if(sect[i].y > y1 && sect[i].y < y2) {
985 clippedpoly[clippedpolynum++] = sect[i];
990 if( (APPROX(n.y, 0)) && (
991 (sect[0].y <= y1 && sect[1].y >= y2) ||
992 (sect[1].y <= y1 && sect[0].y >= y2) )) {
993 sect[0].y = (y1+y2)/2;
994 clippedpoly[clippedpolynum++] = sect[0];
1001 for(i=0; i < clippedpolynum; i++) {
1002 debugpts.push_back(clippedpoly[i]);
1007 polydisp = vecdot(&p[0],&n);
1010 for(i = 0; i < clippedpolynum; i++) {
1011 double disp = vecdot(&clippedpoly[i],&n) - polydisp;
1012 if(disp < mindisp) mindisp = disp;
1014 vecscale(&result,&n,mindisp);
1024 double dmax = -1E99;
1027 int clippedPoly5num = 0;
1030 pp->get_poly_mindisp = 1E90;
1032 #ifdef DEBUGFACEMASK
1033 printf(
"facemask = %d, debugsurface = %d\n",facemask,debugsurface);
1034 if((facemask & (1 <<debugsurface++)) )
return zero;
1037 if((p1.y > y2 || p2.y > y2 || n.y < 0) && n.y < STEPUP_MAXINCLINE)
1041 if ((10)> pp->clippedPoly5Size) {
1042 pp->clippedPoly5 = (
struct point_XYZ*) REALLOC(pp->clippedPoly5,
sizeof(
struct point_XYZ) * (10));
1043 pp->clippedPoly5Size = 10;
1047 clippedPoly5num = helper_line_clip_cap(pp->clippedPoly5, clippedPoly5num, p1, p2, r, n, y1,1 );
1050 for(i=0; i < clippedPoly5num; i++) {
1051 debugpts.push_back(clippedPoly5[i]);
1056 for(i = 0; i < clippedPoly5num; i++) {
1057 if(pp->clippedPoly5[i].y > dmax)
1058 dmax = pp->clippedPoly5[i].y;
1065 pp->get_poly_mindisp = y1-dmax;
1069 result.y = pp->get_poly_mindisp;
1084 result = get_line_step_disp(y1,ystep,r,p1,p2,n);
1086 if (! APPROX(result.y, 0)) {
1089 return get_line_normal_disp(y1,y2,r,p1,p2,n);
1102 if((p1.y <= ystep && p1.y > y1 && p1.x*p1.x + p1.z*p1.z < r*r) && (n.y > STEPUP_MAXINCLINE) ) {
1108 y = (n.y < 0.) ? y2 : y1;
1112 if (! APPROX(n.y, 0)) {
1113 cp = project_on_yplane(p1,n,y);
1114 if(cp.x*cp.x + cp.z*cp.z < r*r) {
1115 VECDIFF(cp,p1,result);
1122 if (! APPROX(n.y, 1) && ! APPROX(n.y, -1)) {
1126 nsect = getk_intersect_line_with_ycylinder(&k1, &k2, r, p1, n);
1129 if(k2 >= 0)
return zero;
1130 vecscale(&result,&n,k2);
1134 if(cp.y > y1 && cp.y < y2) {
1154 static const int faces[6][4] = {
1164 for(ci = 0; ci < 8; ci++) p[ci] = p0;
1170 VECADD(p[4],i); VECADD(p[4],j); VECADD(p[4],k);
1171 VECADD(p[5],k); VECADD(p[5],i);
1172 VECADD(p[6],j); VECADD(p[6],k);
1173 VECADD(p[7],i); VECADD(p[7],j);
1176 veccross(&n[0],j,i);
1177 veccross(&n[1],k,j);
1178 veccross(&n[2],i,k);
1179 vecnormal(&n[0],&n[0]);
1180 vecnormal(&n[1],&n[1]);
1181 vecnormal(&n[2],&n[2]);
1182 vecscale(&n[3],&n[0],-1.);
1183 vecscale(&n[4],&n[1],-1.);
1184 vecscale(&n[5],&n[2],-1.);
1189 for(ci = 0; ci < 6; ci++) {
1196 pts[0] = p[faces[ci][0]];
1197 pts[1] = p[faces[ci][1]];
1198 pts[2] = p[faces[ci][2]];
1199 pts[3] = p[faces[ci][3]];
1200 pts[4] = p[faces[ci][0]];
1202 dispv = get_poly_disp_2(pts,4,n[ci]);
1203 disp = vecdot(&dispv,&dispv);
1209 if( (disp > FLOAT_TOLERANCE) && (disp > maxdisp) ){
1222 int fast_ycylinder_box_intersect(
double y1,
double y2,
double r,
struct point_XYZ pcenter,
double xs,
double ys,
double zs) {
1223 double y = pcenter.y < 0 ? y1 : y2;
1225 double lefteq = sqrt(y*y + r*r) + sqrt(xs*xs + ys*ys + zs*zs);
1226 return lefteq*lefteq > vecdot(&pcenter,&pcenter);
1230 double *transformFULL4d(
double *r4,
double *a4,
double *mat);
1231 void __gluMultMatrixVecd(
const GLDOUBLE matrix[16],
const GLDOUBLE in[4], GLDOUBLE out[4]);
1233 int transformMBB4d(GLDOUBLE *rMBBmin, GLDOUBLE *rMBBmax, GLDOUBLE *matTransform, GLDOUBLE* inMBBmin, GLDOUBLE* inMBBmax,
int isAffine)
1242 GLDOUBLE p[3],rx,ry,rz;
1248 rx = i==0? inMBBmin[0] : inMBBmax[0];
1251 ry = j==0? inMBBmin[1] : inMBBmax[1];
1254 rz = k==0? inMBBmin[2] : inMBBmax[2];
1266 transform(&abox[m],&abox[m],matTransform);
1271 pointxyz2double(in,&abox[m]);
1273 __gluMultMatrixVecd(matTransform, in, out);
1275 if(0)
if (fabs(out[3]) < .0001) {
1279 vecscaled(out,out,1.0/out[3]);
1280 double2pointxyz(&abox[m],out);
1287 pointxyz2double(rMBBmin,&abox[0]);
1288 pointxyz2double(rMBBmax,&abox[0]);
1292 pointxyz2double(p,&abox[m]);
1295 rMBBmin[i] = DOUBLE_MIN(rMBBmin[i],p[i]);
1296 rMBBmax[i] = DOUBLE_MAX(rMBBmax[i],p[i]);
1302 void transformMBB(GLDOUBLE *rMBBmin, GLDOUBLE *rMBBmax, GLDOUBLE *matTransform, GLDOUBLE* inMBBmin, GLDOUBLE* inMBBmax){
1304 int isAffine = 1, iret;
1308 iret = transformMBB4d(rMBBmin, rMBBmax, matTransform, inMBBmin, inMBBmax,isAffine);
1314 int fast_ycylinder_MBB_intersect_collisionSpace(
double y1,
double y2,
double r, GLDOUBLE *shape2collision, GLDOUBLE *shapeMBBmin, GLDOUBLE *shapeMBBmax )
1325 GLDOUBLE smin[3], smax[3], avmin[3], avmax[3];
1333 avmin[1] = y1; avmax[1] = y2;
1335 transformMBB(smin,smax,shape2collision,shapeMBBmin,shapeMBBmax);
1336 return overlapMBBs(avmin,avmax,smin,smax);
1340 int fast_sphere_MBB_intersect_collisionSpace(
double r, GLDOUBLE *shape2collision, GLDOUBLE *shapeMBBmin, GLDOUBLE *shapeMBBmax )
1346 GLDOUBLE smin[3], smax[3], avmin[3], avmax[3];
1354 transformMBB(smin,smax,shape2collision,shapeMBBmin,shapeMBBmax);
1355 return overlapMBBs(avmin,avmax,smin,smax);
1361 int fast_ycylinder_cone_intersect(
double y1,
double y2,
double r,
struct point_XYZ pcenter,
double halfheight,
double baseradius) {
1362 double y = pcenter.y < 0 ? y1 : y2;
1364 double lefteq = sqrt(y*y + r*r) + sqrt(halfheight*halfheight + baseradius*baseradius);
1365 return lefteq*lefteq > vecdot(&pcenter,&pcenter);
1372 struct point_XYZ cone_disp(double y1, double y2, double ystep, double r, struct
point_XYZ base, struct
point_XYZ top, double baseradius) {
1384 double mindisp = 1E99;
1388 vecscale(&bn,&base,-1.0);
1390 VECDIFF(top,base,i);
1391 vecscale(&tmp,&i,- vecdot(&i,&bn)/vecdot(&i,&i));
1394 if (APPROX(vecnormal(&bn,&bn), 0)) {
1399 vecnormal(&tmpn,&tmpn);
1400 make_orthogonal_vector_space(&bn,&tmpj,tmpn);
1403 vecscale(&side,&bn,baseradius);
1407 h = vecnormal(&i,&i);
1409 vecscale(&normalbase,&normaltop,-1.0);
1410 vecscale(&i,&i,-baseradius);
1411 vecscale(&normalside,&bn,-h);
1412 VECADD(normalside,i);
1413 vecnormal(&normalside,&normalside);
1414 vecscale(&normalside,&normalside,-1.0);
1421 if( vecdot(&normalside,&top) < 0. ) {
1422 dispv = get_line_disp(y1,y2,ystep,r,top,side,normalside);
1423 disp = vecdot(&dispv,&dispv);
1425 mindispv = dispv, mindisp = disp;
1428 if( vecdot(&normalbase,&base) < 0. ) {
1429 dispv = get_line_disp(y1,y2,ystep,r,base,side,normalbase);
1430 disp = vecdot(&dispv,&dispv);
1432 mindispv = dispv, mindisp = disp;
1435 if( vecdot(&normaltop,&top) < 0. ) {
1436 dispv = get_point_disp(y1,y2,ystep,r,top,normaltop);
1437 disp = vecdot(&dispv,&dispv);
1441 if(! APPROX(disp, 0) && disp < mindisp)
1442 mindispv = dispv, mindisp = disp;
1452 struct point_XYZ cylinder_disp(double y1, double y2, double ystep, double r, struct
point_XYZ base, struct
point_XYZ top, double baseradius) {
1464 double mindisp = 1E99;
1468 vecscale(&bn,&base,-1.0);
1470 VECDIFF(top,base,i);
1471 vecscale(&tmp,&i,- vecdot(&i,&bn)/vecdot(&i,&i));
1474 if (APPROX(vecnormal(&bn,&bn), 0)) {
1479 vecnormal(&tmpn,&tmpn);
1480 make_orthogonal_vector_space(&bn,&tmpj,tmpn);
1482 vecscale(&sidebase,&bn,baseradius);
1484 VECADD(sidetop,sidebase);
1485 VECADD(sidebase,base);
1490 vecscale(&normalbase,&normaltop,-1.0);
1498 if( vecdot(&normalside,&sidetop) < 0. ) {
1499 dispv = get_line_disp(y1,y2,ystep,r,sidetop,sidebase,normalside);
1500 disp = vecdot(&dispv,&dispv);
1502 mindispv = dispv, mindisp = disp;
1505 if( vecdot(&normalbase,&base) < 0. ) {
1506 dispv = get_line_disp(y1,y2,ystep,r,base,sidebase,normalbase);
1507 disp = vecdot(&dispv,&dispv);
1509 mindispv = dispv, mindisp = disp;
1512 if( vecdot(&normaltop,&top) < 0. ) {
1513 dispv = get_line_disp(y1,y2,ystep,r,top,sidetop,normaltop);
1514 disp = vecdot(&dispv,&dispv);
1516 mindispv = dispv, mindisp = disp;
1525 static int intersectionHeightOfVerticalLineWithSurfaceElement(
double* height,
struct point_XYZ* p,
int num,
struct point_XYZ* n,
double *tmin,
double *tmax )
1542 overlap = tmax[0] >= 0.0 && tmin[0] <= 0.0 && tmax[2] >= 0.0 && tmin[2] <= 0.0;
1543 if(!overlap)
return 0;
1545 dd = -vecdot(&p[0],n);
1551 ndotD = vecdot(n,&D);
1553 if( fabs(ndotD) < .1 )
1557 *height = - dd/ndotD;
1562 return pointOnPlaneInsidePoly(D,p,num,n);
1565 static void accumulateFallingClimbing(
double y1,
double y2,
double ystep,
struct point_XYZ *p,
int num,
struct point_XYZ nused,
double *tmin,
double *tmax)
1575 if( intersectionHeightOfVerticalLineWithSurfaceElement(&hh,&p[0],num,&nused, tmin, tmax))
1578 double hhbelowy1 = hh - y1;
1582 if( hh < y1 && hh > -fi->fallHeight)
1586 fi->hfall = hhbelowy1;
1588 if(hhbelowy1 > fi->hfall) fi->hfall = hhbelowy1;
1598 if( fi->isClimb == 0 )
1599 fi->hclimb = hhbelowy1;
1601 fi->hclimb = DOUBLE_MAX(fi->hclimb,hhbelowy1);
1616 if( hh > 0.0 && hh < y2 )
1654 for(i = 0; i < pr->ntri; i++)
1656 p[0].x = pr->actualCoord[pr->cindex[i*3]*3] +dispsum.x;
1657 p[0].y = pr->actualCoord[pr->cindex[i*3]*3+1] +dispsum.y;
1658 p[0].z = pr->actualCoord[pr->cindex[i*3]*3+2] +dispsum.z;
1660 if (ccw) frontfacing = (vecdot(&n[i],&p[0]) < 0);
1661 else frontfacing = (vecdot(&n[i],&p[0]) >= 0);
1673 if( (frontfacing && !(flags & PR_DOUBLESIDED) )
1674 || ( (flags & PR_DOUBLESIDED) && !(flags & (PR_FRONTFACING | PR_BACKFACING) ) )
1675 || (frontfacing && (flags & PR_FRONTFACING))
1676 || (!frontfacing && (flags & PR_BACKFACING)) )
1680 p[1].x = pr->actualCoord[pr->cindex[i*3+1]*3] +dispsum.x;
1681 p[1].y = pr->actualCoord[pr->cindex[i*3+1]*3+1] +dispsum.y;
1682 p[1].z = pr->actualCoord[pr->cindex[i*3+1]*3+2] +dispsum.z;
1683 p[2].x = pr->actualCoord[pr->cindex[i*3+2]*3] +dispsum.x;
1684 p[2].y = pr->actualCoord[pr->cindex[i*3+2]*3+1] +dispsum.y;
1685 p[2].z = pr->actualCoord[pr->cindex[i*3+2]*3+2] +dispsum.z;
1692 vecscale(&nused,&n[i],-1.0);
1733 dispv = get_poly_disp_2(p, 3, nused);
1734 disp = vecdot(&dispv,&dispv);
1738 if(dispv.x != 0 || dispv.y != 0 || dispv.z != 0)
1739 printf(
"polyd: (%f,%f,%f) |%f|\n",dispv.x,dispv.y,dispv.z,disp);
1747 if( (disp > FLOAT_TOLERANCE) && (disp > maxdisp) )
1755 VECADD(dispsum,maxdispv);
1760 #undef POLYREP_DISP2_PERFORMANCE
1761 #ifdef POLYREP_DISP2_PERFORMANCE
1763 static bool timing = FALSE;
1764 static double startTime = 0.0;
1765 static double stopTime = 0.0;
1766 static double accumTime = 0.0;
1767 static int counter = 0;
1783 #ifdef POLYREP_DISP2_PERFORMANCE
1785 printf (
"start timing polyrep_disp2\n");
1789 startTime = Time1970sec();
1795 if ((pr.VBO_buffers[VERTEX_VBO] != 0) && pp->OpenCL_Collision_Program_initialized) {
1797 float awidth = (float) tg->Bindable.naviinfo.width;
1800 for (i=0; i<16; i++) {
1801 mymat[i] = (float) mat[i];
1804 pp->res = run_non_walk_collide_program(
1805 pr.VBO_buffers[VERTEX_VBO],pr.VBO_buffers[INDEX_VBO],mymat, pr.ntri,
1806 pr.ccw, flags, awidth);
1811 #ifdef POLYREP_DISP2_PERFORMANCE
1812 stopTime = Time1970sec();
1813 accumTime += stopTime - startTime;
1815 if (counter == 25) {
1816 printf (
"polyrep_disp2, averaged over 25 runs: %f\n",
1832 pp->res.x=0.0; pp->res.y=0.0; pp->res.z=0.0;
1835 for(i = 0; i < pr.ntri*3; i++) {
1836 if (pr.cindex[i] > maxc) {maxc = pr.cindex[i];}
1840 if (maxc> pp->prd_newc_floats_size) {
1841 pp->prd_newc_floats = REALLOC(pp->prd_newc_floats,maxc*9*
sizeof(
float));
1842 pp->prd_newc_floats_size = maxc;
1846 for(i = 0; i < pr.ntri*3; i++) {
1847 transformf(&pp->prd_newc_floats[pr.cindex[i]*3],&pr.actualCoord[pr.cindex[i]*3],mat);
1850 pr.actualCoord = pp->prd_newc_floats;
1854 if (pr.ntri> pp->prd_normals_size) {
1855 pp->prd_normals = REALLOC(pp->prd_normals,pr.ntri*
sizeof(
struct point_XYZ));
1856 pp->prd_normals_size = pr.ntri;
1859 for(i = 0; i < pr.ntri; i++) {
1860 polynormalf(&pp->prd_normals[i],&pr.actualCoord[pr.cindex[i*3]*3],
1861 &pr.actualCoord[pr.cindex[i*3+1]*3],&pr.actualCoord[pr.cindex[i*3+2]*3]);
1864 pp->res = polyrep_disp_rec2(&pr,pp->prd_normals,pp->res,flags);
1870 #ifdef POLYREP_DISP2_PERFORMANCE
1871 stopTime = Time1970sec();
1872 accumTime += stopTime - startTime;
1874 if (counter == 25) {
1875 printf (
"polyrep_disp2, averaged over 25 runs: %f\n",
1897 double lmaxdisp = 0;
1906 p[0].x = pr->actualCoord[pr->cindex[0]*3] +dispsum.x;
1907 p[0].y = pr->actualCoord[pr->cindex[0]*3+1] +dispsum.y;
1908 p[0].z = pr->actualCoord[pr->cindex[0]*3+2] +dispsum.z;
1910 frontfacing = (vecdot(&n,&p[0]) < 0);
1912 if(!frontfacing && !(flags & PR_DOUBLESIDED))
return dispsum;
1914 if(!frontfacing) vecscale(&n,&n,-1.0);
1916 for(i = 0; i < pr->ntri; i++) {
1917 p[0].x = pr->actualCoord[pr->cindex[i*3]*3] +dispsum.x;
1918 p[0].y = pr->actualCoord[pr->cindex[i*3]*3+1] +dispsum.y;
1919 p[0].z = pr->actualCoord[pr->cindex[i*3]*3+2] +dispsum.z;
1920 p[1].x = pr->actualCoord[pr->cindex[i*3+1]*3] +dispsum.x;
1921 p[1].y = pr->actualCoord[pr->cindex[i*3+1]*3+1] +dispsum.y;
1922 p[1].z = pr->actualCoord[pr->cindex[i*3+1]*3+2] +dispsum.z;
1923 p[2].x = pr->actualCoord[pr->cindex[i*3+2]*3] +dispsum.x;
1924 p[2].y = pr->actualCoord[pr->cindex[i*3+2]*3+1] +dispsum.y;
1925 p[2].z = pr->actualCoord[pr->cindex[i*3+2]*3+2] +dispsum.z;
1928 dispv = get_poly_disp_2(p, 3, n);
1929 disp = -pp->get_poly_mindisp;
1932 printf(
"polyd: (%f,%f,%f) |%f|\n",dispv.x,dispv.y,dispv.z,disp);
1939 if((disp > FLOAT_TOLERANCE) && (disp > lmaxdisp)) {
1945 VECADD(dispsum,maxdispv);
1951 struct point_XYZ planar_polyrep_disp(double y1, double y2, double ystep, double r, struct
X3D_PolyRep pr, GLDOUBLE* mat, prflags flags,
struct point_XYZ n) {
1957 pp->res.x=0.0; pp->res.y=0.0; pp->res.z=0.0;
1960 for(i = 0; i < pr.ntri*3; i++) {
1961 if (pr.cindex[i] > maxc) {maxc = pr.cindex[i];}
1965 if (maxc> pp->prd_newc_floats_size) {
1966 pp->prd_newc_floats = REALLOC(pp->prd_newc_floats,maxc*9*
sizeof(
float));
1967 pp->prd_newc_floats_size = maxc;
1970 for(i = 0; i < pr.ntri*3; i++) {
1971 transformf(&pp->prd_newc_floats[pr.cindex[i]*3],&pr.actualCoord[pr.cindex[i]*3],mat);
1973 pr.actualCoord = pp->prd_newc_floats;
1977 if(APPROX(n.x, 0) && APPROX(n.y, 0) && APPROX(n.z, 0)) {
1978 polynormalf(&n,&pr.actualCoord[pr.cindex[0]*3],&pr.actualCoord[pr.cindex[1]*3],&pr.actualCoord[pr.cindex[2]*3]);
1981 pp->res = planar_polyrep_disp_rec(y1,y2,ystep,r,&pr,n,pp->res,flags);
1991 static void get_collisionoffset(
double *x,
double *y,
double *z)
1999 ci = CollisionInfo();
2001 naviinfo = (
struct sNaviInfo*)tg->Bindable.naviinfo;
2007 xyz.x = xyz.y = xyz.z = 0.0;
2009 if(ci->Count > 0 && !APPROX(vecnormal(&res, &res),0.0) )
2010 vecscale(&xyz, &res, sqrt(ci->Maximum2));
2015 if(fi->canFall && fi->isFall )
2018 double floatfactor = .1;
2019 if(fi->allowClimbing) floatfactor = 0.0;
2021 xyz.y = DOUBLE_MAX(fi->hfall,-fi->fallStep) + naviinfo->height*floatfactor;
2023 xyz.y = fi->hfall + naviinfo->height*floatfactor;
2026 if(fi->isClimb && fi->allowClimbing)
2030 xyz.y = DOUBLE_MIN(fi->hclimb,fi->fallStep);
2037 xyz = fi->pencorrection;
2041 transform3x3(&xyz,&xyz,fi->collision2avatar);
2049 void render_collisions(
int Viewer_type) {
2053 if(!(Viewer_type == VIEWER_WALK || Viewer_type == VIEWER_FLY))
return;
2054 ci = CollisionInfo();
2069 fi->fallHeight = 100.0;
2071 fi->walking = Viewer_type == VIEWER_WALK;
2072 fi->canFall = fi->walking;
2077 fi->allowClimbing = 1;
2079 fi->canPenetrate = 1;
2080 fi->isPenetrate = 0;
2088 avatar2BoundViewpointVerticalAvatar(fi->avatar2collision, fi->collision2avatar);
2093 loadIdentityMatrix(fi->avatar2collision);
2094 loadIdentityMatrix(fi->collision2avatar);
2098 if(fi->walking && fi->canPenetrate)
2103 lastpos = viewer_get_lastP();
2104 transform(&lastpos,&lastpos,fi->avatar2collision);
2106 plen = sqrt(vecdot(&lastpos,&lastpos));
2107 if(APPROX(plen,0.0))
2108 fi->canPenetrate = 0;
2113 fi->penMin[0] = DOUBLE_MIN(pos.x,lastpos.x);
2114 fi->penMin[1] = DOUBLE_MIN(pos.y,lastpos.y);
2115 fi->penMin[2] = DOUBLE_MIN(pos.z,lastpos.z);
2116 fi->penMax[0] = DOUBLE_MAX(pos.x,lastpos.x);
2117 fi->penMax[1] = DOUBLE_MAX(pos.y,lastpos.y);
2118 fi->penMax[2] = DOUBLE_MAX(pos.z,lastpos.z);
2119 fi->penRadius = plen;
2120 vecnormal(&lastpos,&lastpos);
2121 fi->penvec = lastpos;
2126 render_hier(rootNode(), VF_Collision);
2127 if(!fi->isPenetrate)
2132 viewer_lastP_clear();
2134 get_collisionoffset(&(v.x), &(v.y), &(v.z));
2145 #ifdef DEBUG_SCENE_EXPORT
2149 printf(
"X3D_PolyRep makepolyrep() {\n");
2150 printf(
" int cindext[%d] = {",pr.ntri*3);
2151 for(i=0; i < pr.ntri*3-1; i++) {
2152 printf(
"%d,",pr.cindex[i]);
2153 if(pr.cindex[i] > npoints)
2154 npoints = pr.cindex[i];
2156 printf(
"%d};\n",pr.cindex[i]);
2157 if(pr.cindex[i] > npoints)
2158 npoints = pr.cindex[i];
2160 printf(
" float coordt[%d] = {",npoints*3);
2161 for(i=0; i < npoints*3-1; i++)
2162 printf(
"%f,",pr.actualCoord[i]);
2163 printf(
"%f};\n",pr.actualCoord[i]);
2165 printf(
"static int cindex[%d];\nstatic float coord[%d];\n",pr.ntri*3,npoints*3);
2166 printf(
"X3D_PolyRep pr = {0,%d,cindex,coord,NULL,NULL,NULL,NULL,NULL,NULL};\n",pr.ntri);
2167 printf(
"memcpy(cindex,cindext,sizeof(cindex));\n");
2168 printf(
"memcpy(coord,coordt,sizeof(coord));\n");
2169 printf(
"return pr; }\n");
2173 void printmatrix(GLDOUBLE* mat) {
2175 printf(
"void getmatrix(GLDOUBLE* mat, struct point_XYZ disp) {\n");
2176 for(i = 0; i< 16; i++) {
2177 printf(
"mat[%d] = %f%s;\n",i,mat[i],i==12 ?
" +disp.x" : i==13?
" +disp.y" : i==14?
" +disp.z" :
"");