|
1 /************************************************************************* |
|
2 * * |
|
3 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * |
|
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org * |
|
5 * * |
|
6 * This library is free software; you can redistribute it and/or * |
|
7 * modify it under the terms of EITHER: * |
|
8 * (1) The GNU Lesser General Public License as published by the Free * |
|
9 * Software Foundation; either version 2.1 of the License, or (at * |
|
10 * your option) any later version. The text of the GNU Lesser * |
|
11 * General Public License is included with this library in the * |
|
12 * file LICENSE.TXT. * |
|
13 * (2) The BSD-style license that is included with this library in * |
|
14 * the file LICENSE-BSD.TXT. * |
|
15 * * |
|
16 * This library is distributed in the hope that it will be useful, * |
|
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
|
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * |
|
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. * |
|
20 * * |
|
21 *************************************************************************/ |
|
22 |
|
23 /* |
|
24 Code for Convex Collision Detection |
|
25 By Rodrigo Hernandez |
|
26 */ |
|
27 //#include <algorithm> |
|
28 #include <ode/common.h> |
|
29 #include <ode/collision.h> |
|
30 #include <ode/matrix.h> |
|
31 #include <ode/rotation.h> |
|
32 #include <ode/odemath.h> |
|
33 #include "collision_kernel.h" |
|
34 #include "collision_std.h" |
|
35 #include "collision_util.h" |
|
36 |
|
37 #include "set.h" |
|
38 #include <ode/ode.h> |
|
39 |
|
40 #define dMIN(A,B) ((A)>(B) ? B : A) |
|
41 #define dMAX(A,B) ((A)>(B) ? A : B) |
|
42 |
|
43 //**************************************************************************** |
|
44 // Convex public API |
|
45 dxConvex::dxConvex (dSpaceID space, |
|
46 dReal *_planes, |
|
47 unsigned int _planecount, |
|
48 dReal *_points, |
|
49 unsigned int _pointcount, |
|
50 unsigned int *_polygons) : |
|
51 dxGeom (space,1) |
|
52 { |
|
53 |
|
54 //fprintf(stdout,"dxConvex Constructor planes %X\n",_planes); |
|
55 type = dConvexClass; |
|
56 planes = _planes; |
|
57 planecount = _planecount; |
|
58 // we need points as well |
|
59 points = _points; |
|
60 pointcount = _pointcount; |
|
61 polygons=_polygons; |
|
62 FillEdges(); |
|
63 } |
|
64 |
|
65 |
|
66 void dxConvex::computeAABB() |
|
67 { |
|
68 // this can, and should be optimized |
|
69 dVector3 point; |
|
70 dMULTIPLY0_331 (point,final_posr->R,points); |
|
71 aabb[0] = point[0]+final_posr->pos[0]; |
|
72 aabb[1] = point[0]+final_posr->pos[0]; |
|
73 aabb[2] = point[1]+final_posr->pos[1]; |
|
74 aabb[3] = point[1]+final_posr->pos[1]; |
|
75 aabb[4] = point[2]+final_posr->pos[2]; |
|
76 aabb[5] = point[2]+final_posr->pos[2]; |
|
77 for(unsigned int i=3;i<(pointcount*3);i+=3) |
|
78 { |
|
79 dMULTIPLY0_331 (point,final_posr->R,&points[i]); |
|
80 aabb[0] = dMIN(aabb[0],point[0]+final_posr->pos[0]); |
|
81 aabb[1] = dMAX(aabb[1],point[0]+final_posr->pos[0]); |
|
82 aabb[2] = dMIN(aabb[2],point[1]+final_posr->pos[1]); |
|
83 aabb[3] = dMAX(aabb[3],point[1]+final_posr->pos[1]); |
|
84 aabb[4] = dMIN(aabb[4],point[2]+final_posr->pos[2]); |
|
85 aabb[5] = dMAX(aabb[5],point[2]+final_posr->pos[2]); |
|
86 } |
|
87 } |
|
88 |
|
89 /*! \brief Populates the edges set, should be called only once whenever |
|
90 the polygon array gets updated */ |
|
91 void dxConvex::FillEdges() |
|
92 { |
|
93 unsigned int *points_in_poly=polygons; |
|
94 unsigned int *index=polygons+1; |
|
95 for(unsigned int i=0;i<planecount;++i) |
|
96 { |
|
97 for(unsigned int j=0;j<*points_in_poly;++j) |
|
98 { |
|
99 pair* p = new pair(dMIN(index[j],index[(j+1)%*points_in_poly]), |
|
100 dMAX(index[j],index[(j+1)%*points_in_poly])); |
|
101 edges->addElem(*p); |
|
102 } |
|
103 points_in_poly+=(*points_in_poly+1); |
|
104 index=points_in_poly+1; |
|
105 } |
|
106 |
|
107 } |
|
108 |
|
109 EXPORT_C dGeomID dCreateConvex (dSpaceID space,dReal *_planes,unsigned int _planecount, |
|
110 dReal *_points, |
|
111 unsigned int _pointcount, |
|
112 unsigned int *_polygons) |
|
113 { |
|
114 //fprintf(stdout,"dxConvex dCreateConvex\n"); |
|
115 return new dxConvex(space,_planes, _planecount, |
|
116 _points, |
|
117 _pointcount, |
|
118 _polygons); |
|
119 } |
|
120 |
|
121 EXPORT_C void dGeomSetConvex (dGeomID g,dReal *_planes,unsigned int _planecount, |
|
122 dReal *_points, |
|
123 unsigned int _pointcount, |
|
124 unsigned int *_polygons) |
|
125 { |
|
126 //fprintf(stdout,"dxConvex dGeomSetConvex\n"); |
|
127 dxConvex *s = (dxConvex*) g; |
|
128 s->planes = _planes; |
|
129 s->planecount = _planecount; |
|
130 s->points = _points; |
|
131 s->pointcount = _pointcount; |
|
132 s->polygons=_polygons; |
|
133 } |
|
134 |
|
135 //**************************************************************************** |
|
136 // Helper Inlines |
|
137 // |
|
138 |
|
139 /*! \brief Returns Whether or not the segment ab intersects plane p |
|
140 \param a origin of the segment |
|
141 \param b segment destination |
|
142 \param p plane to test for intersection |
|
143 \param t returns the time "t" in the segment ray that gives us the intersecting |
|
144 point |
|
145 \param q returns the intersection point |
|
146 \return true if there is an intersection, otherwise false. |
|
147 */ |
|
148 bool IntersectSegmentPlane(dVector3 a, |
|
149 dVector3 b, |
|
150 dVector4 p, |
|
151 dReal &t, |
|
152 dVector3 q) |
|
153 { |
|
154 // Compute the t value for the directed line ab intersecting the plane |
|
155 dVector3 ab; |
|
156 ab[0]= b[0] - a[0]; |
|
157 ab[1]= b[1] - a[1]; |
|
158 ab[2]= b[2] - a[2]; |
|
159 |
|
160 t = dDIV((p[3] - dDOT(p,a)),dDOT(p,ab)); |
|
161 |
|
162 // If t in [0..1] compute and return intersection point |
|
163 if (t >= REAL(0.0) && t <= REAL(1.0)) |
|
164 { |
|
165 q[0] = a[0] + dMUL(t,ab[0]); |
|
166 q[1] = a[1] + dMUL(t,ab[1]); |
|
167 q[2] = a[2] + dMUL(t,ab[2]); |
|
168 return true; |
|
169 } |
|
170 // Else no intersection |
|
171 return false; |
|
172 } |
|
173 |
|
174 /*! \brief Returns the Closest Point in Ray 1 to Ray 2 |
|
175 \param Origin1 The origin of Ray 1 |
|
176 \param Direction1 The direction of Ray 1 |
|
177 \param Origin1 The origin of Ray 2 |
|
178 \param Direction1 The direction of Ray 3 |
|
179 \param t the time "t" in Ray 1 that gives us the closest point |
|
180 (closest_point=Origin1+(Direction*t). |
|
181 \return true if there is a closest point, false if the rays are paralell. |
|
182 */ |
|
183 inline bool ClosestPointInRay(const dVector3 Origin1, |
|
184 const dVector3 Direction1, |
|
185 const dVector3 Origin2, |
|
186 const dVector3 Direction2, |
|
187 dReal& t) |
|
188 { |
|
189 dVector3 w = {Origin1[0]-Origin2[0], |
|
190 Origin1[1]-Origin2[1], |
|
191 Origin1[2]-Origin2[2]}; |
|
192 dReal a = dDOT(Direction1 , Direction1); |
|
193 dReal b = dDOT(Direction1 , Direction2); |
|
194 dReal c = dDOT(Direction2 , Direction2); |
|
195 dReal d = dDOT(Direction1 , w); |
|
196 dReal e = dDOT(Direction2 , w); |
|
197 dReal denominator = dMUL(a,c)-dMUL(b,b); |
|
198 if(denominator==REAL(0.0f)) |
|
199 { |
|
200 return false; |
|
201 } |
|
202 t = dDIV((dMUL(a,e)-dMUL(b,d)),denominator); |
|
203 return true; |
|
204 } |
|
205 |
|
206 /*! \brief Returns the Ray on which 2 planes intersect if they do. |
|
207 \param p1 Plane 1 |
|
208 \param p2 Plane 2 |
|
209 \param p Contains the origin of the ray upon returning if planes intersect |
|
210 \param d Contains the direction of the ray upon returning if planes intersect |
|
211 \return true if the planes intersect, false if paralell. |
|
212 */ |
|
213 inline bool IntersectPlanes(const dVector4 p1, const dVector4 p2, dVector3 p, dVector3 d) |
|
214 { |
|
215 // Compute direction of intersection line |
|
216 //Cross(p1, p2,d); |
|
217 dCROSS(d,=,p1,p2); |
|
218 |
|
219 // If d is (near) zero, the planes are parallel (and separated) |
|
220 // or coincident, so they're not considered intersecting |
|
221 dReal denom = dDOT(d, d); |
|
222 if (denom < dEpsilon) return false; |
|
223 |
|
224 dVector3 n; |
|
225 n[0]=dMUL(p1[3],p2[0]) - dMUL(p2[3],p1[0]); |
|
226 n[1]=dMUL(p1[3],p2[1]) - dMUL(p2[3],p1[1]); |
|
227 n[2]=dMUL(p1[3],p2[2]) - dMUL(p2[3],p1[2]); |
|
228 // Compute point on intersection line |
|
229 //Cross(n, d,p); |
|
230 dCROSS(p,=,n,d); |
|
231 p[0] = dDIV(p[0],denom); |
|
232 p[1] = dDIV(p[1],denom); |
|
233 p[2] = dDIV(p[2],denom); |
|
234 return true; |
|
235 } |
|
236 |
|
237 /*! \brief Finds out if a point lies inside a 2D polygon |
|
238 \param p Point to test |
|
239 \param polygon a pointer to the start of the convex polygon index buffer |
|
240 \param out the closest point in the polygon if the point is not inside |
|
241 \return true if the point lies inside of the polygon, false if not. |
|
242 */ |
|
243 inline bool IsPointInPolygon(dVector3 p, |
|
244 unsigned int *polygon, |
|
245 dxConvex *convex, |
|
246 dVector3 out) |
|
247 { |
|
248 // p is the point we want to check, |
|
249 // polygon is a pointer to the polygon we |
|
250 // are checking against, remember it goes |
|
251 // number of vertices then that many indexes |
|
252 // out returns the closest point on the border of the |
|
253 // polygon if the point is not inside it. |
|
254 size_t pointcount=polygon[0]; |
|
255 dVector3 a; |
|
256 dVector3 b; |
|
257 dVector3 c; |
|
258 dVector3 ab; |
|
259 dVector3 ac; |
|
260 dVector3 ap; |
|
261 dVector3 bp; |
|
262 dReal d1; |
|
263 dReal d2; |
|
264 dReal d3; |
|
265 dReal d4; |
|
266 dReal vc; |
|
267 polygon++; // skip past pointcount |
|
268 for(size_t i=0;i<pointcount;++i) |
|
269 { |
|
270 dMULTIPLY0_331 (a,convex->final_posr->R,&convex->points[(polygon[i]*3)]); |
|
271 a[0]=convex->final_posr->pos[0]+a[0]; |
|
272 a[1]=convex->final_posr->pos[1]+a[1]; |
|
273 a[2]=convex->final_posr->pos[2]+a[2]; |
|
274 |
|
275 dMULTIPLY0_331 (b,convex->final_posr->R, |
|
276 &convex->points[(polygon[(i+1)%pointcount]*3)]); |
|
277 b[0]=convex->final_posr->pos[0]+b[0]; |
|
278 b[1]=convex->final_posr->pos[1]+b[1]; |
|
279 b[2]=convex->final_posr->pos[2]+b[2]; |
|
280 |
|
281 dMULTIPLY0_331 (c,convex->final_posr->R, |
|
282 &convex->points[(polygon[(i+2)%pointcount]*3)]); |
|
283 c[0]=convex->final_posr->pos[0]+c[0]; |
|
284 c[1]=convex->final_posr->pos[1]+c[1]; |
|
285 c[2]=convex->final_posr->pos[2]+c[2]; |
|
286 |
|
287 ab[0] = b[0] - a[0]; |
|
288 ab[1] = b[1] - a[1]; |
|
289 ab[2] = b[2] - a[2]; |
|
290 ac[0] = c[0] - a[0]; |
|
291 ac[1] = c[1] - a[1]; |
|
292 ac[2] = c[2] - a[2]; |
|
293 ap[0] = p[0] - a[0]; |
|
294 ap[1] = p[1] - a[1]; |
|
295 ap[2] = p[2] - a[2]; |
|
296 d1 = dDOT(ab,ap); |
|
297 d2 = dDOT(ac,ap); |
|
298 if (d1 <= REAL(0.0f) && d2 <= REAL(0.0f)) |
|
299 { |
|
300 out[0]=a[0]; |
|
301 out[1]=a[1]; |
|
302 out[2]=a[2]; |
|
303 return false; |
|
304 } |
|
305 bp[0] = p[0] - b[0]; |
|
306 bp[1] = p[1] - b[1]; |
|
307 bp[2] = p[2] - b[2]; |
|
308 d3 = dDOT(ab,bp); |
|
309 d4 = dDOT(ac,bp); |
|
310 if (d3 >= REAL(0.0f) && d4 <= d3) |
|
311 { |
|
312 out[0]=b[0]; |
|
313 out[1]=b[1]; |
|
314 out[2]=b[2]; |
|
315 return false; |
|
316 } |
|
317 vc = dMUL(d1,d4) - dMUL(d3,d2); |
|
318 if (vc <= REAL(0.0f) && d1 >= REAL(0.0f) && d3 <= REAL(0.0f)) |
|
319 { |
|
320 dReal v = dDIV(d1,(d1 - d3)); |
|
321 out[0] = a[0] + dMUL(ab[0],v); |
|
322 out[1] = a[1] + dMUL(ab[1],v); |
|
323 out[2] = a[2] + dMUL(ab[2],v); |
|
324 return false; |
|
325 } |
|
326 } |
|
327 return true; |
|
328 } |
|
329 |
|
330 int dCollideConvexPlane (dxGeom *o1, dxGeom *o2, int flags, |
|
331 dContactGeom *contact, int skip) |
|
332 { |
|
333 |
|
334 dxConvex *Convex = (dxConvex*) o1; |
|
335 dxPlane *Plane = (dxPlane*) o2; |
|
336 unsigned int contacts=0; |
|
337 unsigned int maxc = flags & NUMC_MASK; |
|
338 dVector3 v1; |
|
339 dVector3 v2; |
|
340 bool Hit=false; |
|
341 |
|
342 dMULTIPLY0_331 (v1,Convex->final_posr->R,Convex->points); |
|
343 v1[0]=Convex->final_posr->pos[0]+v1[0]; |
|
344 v1[1]=Convex->final_posr->pos[1]+v1[1]; |
|
345 v1[2]=Convex->final_posr->pos[2]+v1[2]; |
|
346 |
|
347 dReal distance1 = (dMUL(Plane->p[0],v1[0]) + // Ax + |
|
348 dMUL(Plane->p[1],v1[1]) + // Bx + |
|
349 dMUL(Plane->p[2],v1[2])) - Plane->p[3]; // Cz - D |
|
350 if(distance1<=0) |
|
351 { |
|
352 CONTACT(contact,skip*contacts)->normal[0] = Plane->p[0]; |
|
353 CONTACT(contact,skip*contacts)->normal[1] = Plane->p[1]; |
|
354 CONTACT(contact,skip*contacts)->normal[2] = Plane->p[2]; |
|
355 CONTACT(contact,skip*contacts)->pos[0] = v1[0]; |
|
356 CONTACT(contact,skip*contacts)->pos[1] = v1[1]; |
|
357 CONTACT(contact,skip*contacts)->pos[2] = v1[2]; |
|
358 CONTACT(contact,skip*contacts)->depth = -distance1; |
|
359 CONTACT(contact,skip*contacts)->g1 = Convex; |
|
360 CONTACT(contact,skip*contacts)->g2 = Plane; |
|
361 contacts++; |
|
362 } |
|
363 for(unsigned int i=1;i<Convex->pointcount;++i) |
|
364 { |
|
365 dMULTIPLY0_331 (v2,Convex->final_posr->R,&Convex->points[(i*3)]); |
|
366 v2[0]=Convex->final_posr->pos[0]+v2[0]; |
|
367 v2[1]=Convex->final_posr->pos[1]+v2[1]; |
|
368 v2[2]=Convex->final_posr->pos[2]+v2[2]; |
|
369 dReal distance2 = (dMUL(Plane->p[0],v2[0]) + // Ax + |
|
370 dMUL(Plane->p[1],v2[1]) + // Bx + |
|
371 dMUL(Plane->p[2],v2[2])) - Plane->p[3]; // Cz + D |
|
372 if(!Hit) |
|
373 /* |
|
374 Avoid multiplication |
|
375 if we have already determined there is a hit |
|
376 */ |
|
377 { |
|
378 if(dMUL(distance1,distance2) <= REAL(0.0)) |
|
379 { |
|
380 // there is a hit. |
|
381 Hit=true; |
|
382 } |
|
383 } |
|
384 if((distance2<=0)&&(contacts<maxc)) |
|
385 { |
|
386 CONTACT(contact,skip*contacts)->normal[0] = Plane->p[0]; |
|
387 CONTACT(contact,skip*contacts)->normal[1] = Plane->p[1]; |
|
388 CONTACT(contact,skip*contacts)->normal[2] = Plane->p[2]; |
|
389 CONTACT(contact,skip*contacts)->pos[0] = v2[0]; |
|
390 CONTACT(contact,skip*contacts)->pos[1] = v2[1]; |
|
391 CONTACT(contact,skip*contacts)->pos[2] = v2[2]; |
|
392 CONTACT(contact,skip*contacts)->depth = -distance2; |
|
393 CONTACT(contact,skip*contacts)->g1 = Convex; |
|
394 CONTACT(contact,skip*contacts)->g2 = Plane; |
|
395 contacts++; |
|
396 } |
|
397 } |
|
398 if(Hit) return contacts; |
|
399 return 0; |
|
400 } |
|
401 |
|
402 int dCollideSphereConvex (dxGeom *o1, dxGeom *o2, int /*flags*/, |
|
403 dContactGeom *contact, int /*skip*/) |
|
404 { |
|
405 |
|
406 dxSphere *Sphere = (dxSphere*) o1; |
|
407 dxConvex *Convex = (dxConvex*) o2; |
|
408 dReal dist,closestdist=dInfinity; |
|
409 dVector4 plane; |
|
410 // dVector3 contactpoint; |
|
411 dVector3 offsetpos,out,temp; |
|
412 unsigned int *pPoly=Convex->polygons; |
|
413 int closestplane=0; |
|
414 bool sphereinside=true; |
|
415 /* |
|
416 Do a good old sphere vs plane check first, |
|
417 if a collision is found then check if the contact point |
|
418 is within the polygon |
|
419 */ |
|
420 // offset the sphere final_posr->position into the convex space |
|
421 offsetpos[0]=Sphere->final_posr->pos[0]-Convex->final_posr->pos[0]; |
|
422 offsetpos[1]=Sphere->final_posr->pos[1]-Convex->final_posr->pos[1]; |
|
423 offsetpos[2]=Sphere->final_posr->pos[2]-Convex->final_posr->pos[2]; |
|
424 //fprintf(stdout,"Begin Check\n"); |
|
425 for(unsigned int i=0;i<Convex->planecount;++i) |
|
426 { |
|
427 // apply rotation to the plane |
|
428 dMULTIPLY0_331(plane,Convex->final_posr->R,&Convex->planes[(i*4)]); |
|
429 plane[3]=(&Convex->planes[(i*4)])[3]; |
|
430 // Get the distance from the sphere origin to the plane |
|
431 dist = (dMUL(plane[0],offsetpos[0]) + // Ax + |
|
432 dMUL(plane[1],offsetpos[1]) + // Bx + |
|
433 dMUL(plane[2],offsetpos[2])) - plane[3]; // Cz - D |
|
434 if(dist>REAL(0.0)) |
|
435 { |
|
436 // if we get here, we know the center of the sphere is |
|
437 // outside of the convex hull. |
|
438 if(dist<Sphere->radius) |
|
439 { |
|
440 // if we get here we know the sphere surface penetrates |
|
441 // the plane |
|
442 if(IsPointInPolygon(Sphere->final_posr->pos,pPoly,Convex,out)) |
|
443 { |
|
444 // finally if we get here we know that the |
|
445 // sphere is directly touching the inside of the polyhedron |
|
446 //fprintf(stdout,"Contact! distance=%f\n",dist); |
|
447 contact->normal[0] = plane[0]; |
|
448 contact->normal[1] = plane[1]; |
|
449 contact->normal[2] = plane[2]; |
|
450 contact->pos[0] = Sphere->final_posr->pos[0]+ |
|
451 (-dMUL(contact->normal[0],Sphere->radius)); |
|
452 contact->pos[1] = Sphere->final_posr->pos[1]+ |
|
453 (-dMUL(contact->normal[1],Sphere->radius)); |
|
454 contact->pos[2] = Sphere->final_posr->pos[2]+ |
|
455 (-dMUL(contact->normal[2],Sphere->radius)); |
|
456 contact->depth = Sphere->radius-dist; |
|
457 contact->g1 = Sphere; |
|
458 contact->g2 = Convex; |
|
459 return 1; |
|
460 } |
|
461 else |
|
462 { |
|
463 // the sphere may not be directly touching |
|
464 // the polyhedron, but it may be touching |
|
465 // a point or an edge, if the distance between |
|
466 // the closest point on the poly (out) and the |
|
467 // center of the sphere is less than the sphere |
|
468 // radius we have a hit. |
|
469 temp[0] = (Sphere->final_posr->pos[0]-out[0]); |
|
470 temp[1] = (Sphere->final_posr->pos[1]-out[1]); |
|
471 temp[2] = (Sphere->final_posr->pos[2]-out[2]); |
|
472 dist=(dMUL(temp[0],temp[0])+dMUL(temp[1],temp[1])+dMUL(temp[2],temp[2])); |
|
473 // avoid the sqrt unless really necesary |
|
474 if(dist<dMUL(Sphere->radius,Sphere->radius)) |
|
475 { |
|
476 // We got an indirect hit |
|
477 dist=dSqrt(dist); |
|
478 contact->normal[0] = dDIV(temp[0],dist); |
|
479 contact->normal[1] = dDIV(temp[1],dist); |
|
480 contact->normal[2] = dDIV(temp[2],dist); |
|
481 contact->pos[0] = Sphere->final_posr->pos[0]+ |
|
482 (-dMUL(contact->normal[0],Sphere->radius)); |
|
483 contact->pos[1] = Sphere->final_posr->pos[1]+ |
|
484 (-dMUL(contact->normal[1],Sphere->radius)); |
|
485 contact->pos[2] = Sphere->final_posr->pos[2]+ |
|
486 (-dMUL(contact->normal[2],Sphere->radius)); |
|
487 contact->depth = Sphere->radius-dist; |
|
488 contact->g1 = Sphere; |
|
489 contact->g2 = Convex; |
|
490 return 1; |
|
491 } |
|
492 } |
|
493 } |
|
494 sphereinside=false; |
|
495 } |
|
496 if(sphereinside) |
|
497 { |
|
498 if(closestdist>dFabs(dist)) |
|
499 { |
|
500 closestdist=dFabs(dist); |
|
501 closestplane=i; |
|
502 } |
|
503 } |
|
504 pPoly+=pPoly[0]+1; |
|
505 } |
|
506 if(sphereinside) |
|
507 { |
|
508 // if the center of the sphere is inside |
|
509 // the Convex, we need to pop it out |
|
510 dMULTIPLY0_331(contact->normal, |
|
511 Convex->final_posr->R, |
|
512 &Convex->planes[(closestplane*4)]); |
|
513 contact->pos[0] = Sphere->final_posr->pos[0]; |
|
514 contact->pos[1] = Sphere->final_posr->pos[1]; |
|
515 contact->pos[2] = Sphere->final_posr->pos[2]; |
|
516 contact->depth = closestdist+Sphere->radius; |
|
517 contact->g1 = Sphere; |
|
518 contact->g2 = Convex; |
|
519 return 1; |
|
520 } |
|
521 return 0; |
|
522 } |
|
523 |
|
524 int dCollideConvexBox (dxGeom */*o1*/, dxGeom */*o2*/, int /*flags*/, |
|
525 dContactGeom */*contact*/, int /*skip*/) |
|
526 { |
|
527 return 0; |
|
528 } |
|
529 |
|
530 int dCollideConvexCapsule (dxGeom */*o1*/, dxGeom */*o2*/, |
|
531 int /*flags*/, dContactGeom */*contact*/, int /*skip*/) |
|
532 { |
|
533 return 0; |
|
534 } |
|
535 |
|
536 /*! |
|
537 \brief Retrieves the proper convex and plane index between 2 convex objects. |
|
538 |
|
539 Seidel's Algorithm does not discriminate between 2 different Convex Hulls, |
|
540 it only cares about planes, so we feed it the planes of Convex 1 followed |
|
541 by the planes of Convex 2 as a single collection of planes, |
|
542 given an index into the single collection, |
|
543 this function determines the correct convex object and index to retrieve |
|
544 the current plane. |
|
545 |
|
546 \param c1 Convex 1 |
|
547 \param c2 Convex 2 |
|
548 \param i Plane Index to retrieve |
|
549 \param index contains the translated index uppon return |
|
550 \return a pointer to the convex object containing plane index "i" |
|
551 */ |
|
552 inline dxConvex* GetPlaneIndex(dxConvex& c1, |
|
553 dxConvex& c2, |
|
554 unsigned int i,unsigned int& index) |
|
555 { |
|
556 if(i>=c1.planecount) |
|
557 { |
|
558 index = i-c1.planecount; |
|
559 return &c2; |
|
560 } |
|
561 index=i; |
|
562 return &c1; |
|
563 } |
|
564 |
|
565 inline void dumpplanes(dxConvex& cvx) |
|
566 { |
|
567 // This is just a dummy debug function |
|
568 dVector4 plane; |
|
569 fprintf(stdout,"DUMP PLANES\n"); |
|
570 for (unsigned int i=0;i<cvx.planecount;++i) |
|
571 { |
|
572 dMULTIPLY0_331(plane,cvx.final_posr->R,&cvx.planes[(i*4)]); |
|
573 // Translate |
|
574 plane[3]= |
|
575 (cvx.planes[(i*4)+3])+ |
|
576 (dMUL(plane[0],cvx.final_posr->pos[0]) + |
|
577 dMUL(plane[1],cvx.final_posr->pos[1]) + |
|
578 dMUL(plane[2],cvx.final_posr->pos[2])); |
|
579 fprintf(stdout,"%f %f %f %f\n",plane[0],plane[1],plane[2],plane[3]); |
|
580 } |
|
581 } |
|
582 |
|
583 // this variable is for debuggin purpuses only, should go once everything works |
|
584 /* |
|
585 \brief Tests whether 2 convex objects collide |
|
586 |
|
587 Seidel's algorithm is a method to solve linear programs, |
|
588 it finds the optimum vertex "v" of a set of functions, |
|
589 in our case, the set of functions are the plane functions |
|
590 for the 2 convex objects being tested. |
|
591 We don't really care about the value optimum vertex though, |
|
592 but the 2 convex objects only collide if this vertex exists, |
|
593 otherwise, the set of functions is said to be "empty" or "void". |
|
594 |
|
595 Seidel's Original algorithm is recursive and not bound to any number |
|
596 of dimensions, the one I present here is Iterative rather than recursive |
|
597 and bound to 3 dimensions, which is what we care about. |
|
598 |
|
599 If you're interested (and you should be!) on the algorithm, the paper |
|
600 by Raimund Seidel himself should explain a lot better than I did, you can |
|
601 find it here: http://www.cs.berkeley.edu/~jrs/meshpapers/SeidelLP.pdf |
|
602 |
|
603 If posible, read the section about Linear Programming in |
|
604 Christer Ericson's RealTime Collision Detection book. |
|
605 |
|
606 \note currently there seem to be some issues with this function since |
|
607 it doesn't detect collisions except for the most simple tests :(. |
|
608 */ |
|
609 bool SeidelLP(dxConvex& cvx1,dxConvex& cvx2) |
|
610 { |
|
611 dVector3 c={1,0,0}; // The Objective vector can be anything |
|
612 dVector3 solution; // We dont really need the solution so its local |
|
613 dxConvex *cvx; |
|
614 unsigned int index; |
|
615 unsigned int planecount=cvx1.planecount+cvx2.planecount; |
|
616 dReal sum,min,max,med; |
|
617 dVector3 c1; // ,c2; |
|
618 dVector4 aoveral,aoveram; // these will contain cached computations |
|
619 unsigned int l,m,n; // l and m are the axes to the zerod dimensions, n is the axe for the last dimension |
|
620 unsigned int i,j,k; |
|
621 dVector4 eq1,eq2,eq3; // cached equations for 3d,2d and 1d respectivelly |
|
622 // Get the support mapping for a HUGE bounding box in direction c |
|
623 solution[0]= (c[0]>0) ? dInfinity : -dInfinity; |
|
624 solution[1]= (c[1]>0) ? dInfinity : -dInfinity; |
|
625 solution[2]= (c[2]>0) ? dInfinity : -dInfinity; |
|
626 for( i=0;i<planecount;++i) |
|
627 { |
|
628 // Isolate plane equation |
|
629 cvx=GetPlaneIndex(cvx1,cvx2,i,index); |
|
630 // Rotate |
|
631 dMULTIPLY0_331(eq1,cvx->final_posr->R,&cvx->planes[(index*4)]); |
|
632 |
|
633 // Translate |
|
634 eq1[3]=(cvx->planes[(index*4)+3])+ |
|
635 (dMUL(eq1[0],cvx->final_posr->pos[0]) + |
|
636 dMUL(eq1[1],cvx->final_posr->pos[1]) + |
|
637 dMUL(eq1[2],cvx->final_posr->pos[2])); |
|
638 // if(!hit) |
|
639 // { |
|
640 // fprintf(stdout,"Plane I %d: %f %f %f %f\n",i, |
|
641 // cvx->planes[(index*4)+0], |
|
642 // cvx->planes[(index*4)+1], |
|
643 // cvx->planes[(index*4)+2], |
|
644 // cvx->planes[(index*4)+3]); |
|
645 // fprintf(stdout,"Transformed Plane %d: %f %f %f %f\n",i, |
|
646 // eq1[0], |
|
647 // eq1[1],eq1[2],eq1[3]); |
|
648 // fprintf(stdout,"POS %f,%f,%f\n", |
|
649 // cvx->final_posr->pos[0], |
|
650 // cvx->final_posr->pos[1], |
|
651 // cvx->final_posr->pos[2]); |
|
652 // } |
|
653 // find if the solution is behind the current plane |
|
654 sum= |
|
655 (dMUL(eq1[0],solution[0])+ |
|
656 dMUL(eq1[1],solution[1])+ |
|
657 dMUL(eq1[2],solution[2]))-eq1[3]; |
|
658 // if not we need to discard the current solution |
|
659 if(sum>0) |
|
660 { |
|
661 // go down a dimension by eliminating a variable |
|
662 // first find l |
|
663 l=0; |
|
664 for( j=0;j<3;++j) |
|
665 { |
|
666 if(dFabs(eq1[j])>dFabs(eq1[l])) |
|
667 { |
|
668 l=j; |
|
669 } |
|
670 } |
|
671 if(eq1[l]==0) |
|
672 { |
|
673 if(!GetGlobalData()->hit) |
|
674 { |
|
675 fprintf(stdout,"Plane %d: %f %f %f %f is invalid\n",i, |
|
676 eq1[0],eq1[1],eq1[2],eq1[3]); |
|
677 } |
|
678 return false; |
|
679 } |
|
680 // then compute a/a[l] c1 and solution |
|
681 aoveral[0]=dDIV(eq1[0],eq1[l]); |
|
682 aoveral[1]=dDIV(eq1[1],eq1[l]); |
|
683 aoveral[2]=dDIV(eq1[2],eq1[l]); |
|
684 aoveral[3]=dDIV(eq1[3],eq1[l]); |
|
685 c1[0]=c[0]-dMUL(dDIV(c[l],eq1[l]),eq1[0]); |
|
686 c1[1]=c[1]-dMUL(dDIV(c[l],eq1[l]),eq1[1]); |
|
687 c1[2]=c[2]-dMUL(dDIV(c[l],eq1[l]),eq1[2]); |
|
688 solution[0]=solution[0]-dMUL(dDIV(solution[l],eq1[l]),eq1[0]); |
|
689 solution[1]=solution[1]-dMUL(dDIV(solution[l],eq1[l]),eq1[1]); |
|
690 solution[2]=solution[2]-dMUL(dDIV(solution[l],eq1[l]),eq1[2]); |
|
691 // iterate a to get the new equations with the help of a/a[l] |
|
692 for( j=0;j<planecount;++j) |
|
693 { |
|
694 if(i!=j) |
|
695 { |
|
696 cvx=GetPlaneIndex(cvx1,cvx2,j,index); |
|
697 // Rotate |
|
698 dMULTIPLY0_331(eq2,cvx->final_posr->R,&cvx->planes[(index*4)]); |
|
699 // Translate |
|
700 eq2[3]=(cvx->planes[(index*4)+3])+ |
|
701 (dMUL(eq2[0],cvx->final_posr->pos[0]) + |
|
702 dMUL(eq2[1],cvx->final_posr->pos[1]) + |
|
703 dMUL(eq2[2],cvx->final_posr->pos[2])); |
|
704 |
|
705 // if(!hit) |
|
706 // { |
|
707 // fprintf(stdout,"Plane J %d: %f %f %f %f\n",j, |
|
708 // cvx->planes[(index*4)+0], |
|
709 // cvx->planes[(index*4)+1], |
|
710 // cvx->planes[(index*4)+2], |
|
711 // cvx->planes[(index*4)+3]); |
|
712 // fprintf(stdout,"Transformed Plane %d: %f %f %f %f\n",j, |
|
713 // eq2[0], |
|
714 // eq2[1], |
|
715 // eq2[2], |
|
716 // eq2[3]); |
|
717 // fprintf(stdout,"POS %f,%f,%f\n", |
|
718 // cvx->final_posr->pos[0], |
|
719 // cvx->final_posr->pos[1], |
|
720 // cvx->final_posr->pos[2]); |
|
721 // } |
|
722 |
|
723 // Take The equation down a dimension |
|
724 eq2[0]-=dMUL(cvx->planes[(index*4)+l],aoveral[0]); |
|
725 eq2[1]-=dMUL(cvx->planes[(index*4)+l],aoveral[1]); |
|
726 eq2[2]-=dMUL(cvx->planes[(index*4)+l],aoveral[2]); |
|
727 eq2[3]-=dMUL(cvx->planes[(index*4)+l],aoveral[3]); |
|
728 sum= |
|
729 (dMUL(eq2[0],solution[0])+ |
|
730 dMUL(eq2[1],solution[1])+ |
|
731 dMUL(eq2[2],solution[2]))-eq2[3]; |
|
732 if(sum>0) |
|
733 { |
|
734 m=0; |
|
735 for( k=0;k<3;++k) |
|
736 { |
|
737 if(dFabs(eq2[k])>dFabs(eq2[m])) |
|
738 { |
|
739 m=k; |
|
740 } |
|
741 } |
|
742 if(eq2[m]==0) |
|
743 { |
|
744 /* |
|
745 if(!hit) fprintf(stdout, |
|
746 "Plane %d: %f %f %f %f is invalid\n",j, |
|
747 eq2[0],eq2[1],eq2[2],eq2[3]); |
|
748 */ |
|
749 return false; |
|
750 } |
|
751 // then compute a/a[m] c1 and solution |
|
752 aoveram[0]=dDIV(eq2[0],eq2[m]); |
|
753 aoveram[1]=dDIV(eq2[1],eq2[m]); |
|
754 aoveram[2]=dDIV(eq2[2],eq2[m]); |
|
755 aoveram[3]=dDIV(eq2[3],eq2[m]); |
|
756 c1[0]=c[0]-dMUL(dDIV(c[m],eq2[m]),eq2[0]); |
|
757 c1[1]=c[1]-dMUL(dDIV(c[m],eq2[m]),eq2[1]); |
|
758 c1[2]=c[2]-dMUL(dDIV(c[m],eq2[m]),eq2[2]); |
|
759 solution[0]=solution[0]-dMUL(dDIV(solution[m],eq2[m]),eq2[0]); |
|
760 solution[1]=solution[1]-dMUL(dDIV(solution[m],eq2[m]),eq2[1]); |
|
761 solution[2]=solution[2]-dMUL(dDIV(solution[m],eq2[m]),eq2[2]); |
|
762 // figure out the value for n by elimination |
|
763 n = (l==0) ? ((m==1)? 2:1):((m==0)?((l==1)?2:1):0); |
|
764 // iterate a to get the new equations with the help of a/a[l] |
|
765 min=-dInfinity; |
|
766 max=med=dInfinity; |
|
767 for(k=0;k<planecount;++k) |
|
768 { |
|
769 if((i!=k)&&(j!=k)) |
|
770 { |
|
771 cvx=GetPlaneIndex(cvx1,cvx2,k,index); |
|
772 // Rotate |
|
773 dMULTIPLY0_331(eq3,cvx->final_posr->R,&cvx->planes[(index*4)]); |
|
774 // Translate |
|
775 eq3[3]=(cvx->planes[(index*4)+3])+ |
|
776 (dMUL(eq3[0],cvx->final_posr->pos[0]) + |
|
777 dMUL(eq3[1],cvx->final_posr->pos[1]) + |
|
778 dMUL(eq3[2],cvx->final_posr->pos[2])); |
|
779 // if(!hit) |
|
780 // { |
|
781 // fprintf(stdout,"Plane K %d: %f %f %f %f\n",k, |
|
782 // cvx->planes[(index*4)+0], |
|
783 // cvx->planes[(index*4)+1], |
|
784 // cvx->planes[(index*4)+2], |
|
785 // cvx->planes[(index*4)+3]); |
|
786 // fprintf(stdout,"Transformed Plane %d: %f %f %f %f\n",k, |
|
787 // eq3[0], |
|
788 // eq3[1], |
|
789 // eq3[2], |
|
790 // eq3[3]); |
|
791 // fprintf(stdout,"POS %f,%f,%f\n", |
|
792 // cvx->final_posr->pos[0], |
|
793 // cvx->final_posr->pos[1], |
|
794 // cvx->final_posr->pos[2]); |
|
795 // } |
|
796 |
|
797 // Take the equation Down to 1D |
|
798 eq3[0]-=dMUL(cvx->planes[(index*4)+m],aoveram[0]); |
|
799 eq3[1]-=dMUL(cvx->planes[(index*4)+m],aoveram[1]); |
|
800 eq3[2]-=dMUL(cvx->planes[(index*4)+m],aoveram[2]); |
|
801 eq3[3]-=dMUL(cvx->planes[(index*4)+m],aoveram[3]); |
|
802 if(eq3[n]>REAL(0.0)) |
|
803 { |
|
804 max=dMIN(max,dDIV(eq3[3],eq3[n])); |
|
805 } |
|
806 else if(eq3[n]<0) |
|
807 { |
|
808 min=dMAX(min,dDIV(eq3[3],eq3[n])); |
|
809 } |
|
810 else |
|
811 { |
|
812 med=dMIN(med,eq3[3]); |
|
813 } |
|
814 } |
|
815 } |
|
816 if ((max<min)||(med<0)) |
|
817 { |
|
818 // if(!hit) fprintf(stdout,"((max<min)||(med<0)) ((%f<%f)||(%f<0))",max,min,med); |
|
819 if(!GetGlobalData()->hit) |
|
820 { |
|
821 dumpplanes(cvx1); |
|
822 dumpplanes(cvx2); |
|
823 } |
|
824 //fprintf(stdout,"Planes %d %d\n",i,j); |
|
825 return false; |
|
826 |
|
827 } |
|
828 // find the value for the solution in one dimension |
|
829 solution[n] = (c1[n]>=0) ? max:min; |
|
830 // lift to 2D |
|
831 solution[m] = dMUL((eq2[3]-dMUL(eq2[n],solution[n])),eq2[m]); |
|
832 // lift to 3D |
|
833 solution[l] = dDIV((eq1[3]-(dMUL(eq1[m],solution[m])+ |
|
834 dMUL(eq1[n],solution[n]))),eq1[l]); |
|
835 } |
|
836 } |
|
837 } |
|
838 } |
|
839 } |
|
840 return true; |
|
841 } |
|
842 |
|
843 /*! \brief A Support mapping function for convex shapes |
|
844 \param dir direction to find the Support Point for |
|
845 \param cvx convex object to find the support point for |
|
846 \param out the support mapping in dir. |
|
847 */ |
|
848 inline void Support(dVector3 dir,dxConvex& cvx,dVector3 out) |
|
849 { |
|
850 dVector3 point; |
|
851 dMULTIPLY0_331 (point,cvx.final_posr->R,cvx.points); |
|
852 point[0]+=cvx.final_posr->pos[0]; |
|
853 point[1]+=cvx.final_posr->pos[1]; |
|
854 point[2]+=cvx.final_posr->pos[2]; |
|
855 |
|
856 dReal max = dDOT(point,dir); |
|
857 dReal tmp; |
|
858 for (unsigned int i = 1; i < cvx.pointcount; ++i) |
|
859 { |
|
860 dMULTIPLY0_331 (point,cvx.final_posr->R,cvx.points+i*3); |
|
861 point[0]+=cvx.final_posr->pos[0]; |
|
862 point[1]+=cvx.final_posr->pos[1]; |
|
863 point[2]+=cvx.final_posr->pos[2]; |
|
864 tmp = dDOT(point, dir); |
|
865 if (tmp > max) |
|
866 { |
|
867 out[0]=point[0]; |
|
868 out[1]=point[1]; |
|
869 out[2]=point[2]; |
|
870 max = tmp; |
|
871 } |
|
872 } |
|
873 } |
|
874 |
|
875 inline void ComputeInterval(dxConvex& cvx,dVector4 axis,dReal& min,dReal& max) |
|
876 { |
|
877 dVector3 point; |
|
878 dReal value; |
|
879 //fprintf(stdout,"Compute Interval Axis %f,%f,%f\n",axis[0],axis[1],axis[2]); |
|
880 dMULTIPLY0_331 (point,cvx.final_posr->R,cvx.points); |
|
881 //fprintf(stdout,"initial point %f,%f,%f\n",point[0],point[1],point[2]); |
|
882 point[0]+=cvx.final_posr->pos[0]; |
|
883 point[1]+=cvx.final_posr->pos[1]; |
|
884 point[2]+=cvx.final_posr->pos[2]; |
|
885 max = min = dDOT(axis,cvx.points); |
|
886 for (unsigned int i = 1; i < cvx.pointcount; ++i) |
|
887 { |
|
888 dMULTIPLY0_331 (point,cvx.final_posr->R,cvx.points+i*3); |
|
889 point[0]+=cvx.final_posr->pos[0]; |
|
890 point[1]+=cvx.final_posr->pos[1]; |
|
891 point[2]+=cvx.final_posr->pos[2]; |
|
892 value=dDOT(axis,point); |
|
893 if(value<min) |
|
894 { |
|
895 min=value; |
|
896 } |
|
897 else if(value>max) |
|
898 { |
|
899 max=value; |
|
900 } |
|
901 } |
|
902 //fprintf(stdout,"Compute Interval Min Max %f,%f\n",min,max); |
|
903 } |
|
904 |
|
905 /*! \brief Does an axis separation test between the 2 convex shapes |
|
906 using faces and edges */ |
|
907 int TestConvexIntersection(dxConvex& cvx1,dxConvex& cvx2, int flags, |
|
908 dContactGeom *contact, int skip) |
|
909 { |
|
910 dVector4 plane,savedplane = {}; |
|
911 dReal min1,max1,min2,max2; |
|
912 dVector3 e1,e2,t; |
|
913 int maxc = flags & NUMC_MASK; // this is causing a segfault |
|
914 //int maxc = 3; |
|
915 int contacts=0; |
|
916 dxConvex *g1=0,*g2=0; |
|
917 unsigned int *pPoly; |
|
918 dVector3 v; |
|
919 // Test faces of cvx1 for separation |
|
920 pPoly=cvx1.polygons; |
|
921 for(unsigned int i=0;i<cvx1.planecount;++i) |
|
922 { |
|
923 // -- Apply Transforms -- |
|
924 // Rotate |
|
925 dMULTIPLY0_331(plane,cvx1.final_posr->R,cvx1.planes+i*4); |
|
926 dNormalize3(plane); |
|
927 // Translate |
|
928 plane[3]= |
|
929 (cvx1.planes[(i*4)+3])+ |
|
930 (dMUL(plane[0],cvx1.final_posr->pos[0]) + |
|
931 dMUL(plane[1],cvx1.final_posr->pos[1]) + |
|
932 dMUL(plane[2],cvx1.final_posr->pos[2])); |
|
933 ComputeInterval(cvx1,plane,min1,max1); |
|
934 ComputeInterval(cvx2,plane,min2,max2); |
|
935 //fprintf(stdout,"width %f\n",max1-min1); |
|
936 if(max2<min1 || max1<min2) return 0; |
|
937 #if 1 |
|
938 // this one ON works |
|
939 else if ((max1>min2)&&(max1<max2)) |
|
940 { |
|
941 savedplane[0]=plane[0]; |
|
942 savedplane[1]=plane[1]; |
|
943 savedplane[2]=plane[2]; |
|
944 savedplane[3]=plane[3]; |
|
945 g1=&cvx2; // cvx2 moves |
|
946 g2=&cvx1; |
|
947 } |
|
948 #endif |
|
949 pPoly+=pPoly[0]+1; |
|
950 } |
|
951 // Test faces of cvx2 for separation |
|
952 pPoly=cvx2.polygons; |
|
953 for(unsigned int i=0;i<cvx2.planecount;++i) |
|
954 { |
|
955 // fprintf(stdout,"Poly verts %d\n",pPoly[0]); |
|
956 // -- Apply Transforms -- |
|
957 // Rotate |
|
958 dMULTIPLY0_331(plane, |
|
959 cvx2.final_posr->R, |
|
960 cvx2.planes+i*4); |
|
961 dNormalize3(plane); |
|
962 // Translate |
|
963 plane[3]= |
|
964 (cvx2.planes[(i*4)+3])+ |
|
965 (dMUL(plane[0],cvx2.final_posr->pos[0]) + |
|
966 dMUL(plane[1],cvx2.final_posr->pos[1]) + |
|
967 dMUL(plane[2],cvx2.final_posr->pos[2])); |
|
968 ComputeInterval(cvx2,plane,min1,max1); |
|
969 ComputeInterval(cvx1,plane,min2,max2); |
|
970 //fprintf(stdout,"width %f\n",max1-min1); |
|
971 if(max2<min1 || max1<min2) return 0; |
|
972 #if 1 |
|
973 // this one ON does not work |
|
974 else if ((max1>min2)&&(max1<max2)) |
|
975 { |
|
976 savedplane[0]=plane[0]; |
|
977 savedplane[1]=plane[1]; |
|
978 savedplane[2]=plane[2]; |
|
979 savedplane[3]=plane[3]; |
|
980 g1=&cvx1; // cvx1 moves |
|
981 g2=&cvx2; |
|
982 } |
|
983 #endif |
|
984 pPoly+=pPoly[0]+1; |
|
985 } |
|
986 |
|
987 // Test cross products of pairs of edges with new set structure |
|
988 iterator* it1=cvx1.edges->setIterator(); |
|
989 iterator* it2=cvx2.edges->setIterator(); |
|
990 |
|
991 it1->setToFirst(); |
|
992 it2->setToFirst(); |
|
993 int i, j; |
|
994 |
|
995 for(i = 1; i <= cvx1.edges->length(); i++) { |
|
996 pair* p1 = new pair(); |
|
997 *p1 = it1->getElem(); |
|
998 int first1 = p1->getNum1(); |
|
999 int second1 = p1->getNum2(); |
|
1000 |
|
1001 dMULTIPLY0_331 (t,cvx1.final_posr->R,cvx1.points+first1*3); |
|
1002 dMULTIPLY0_331 (e1,cvx1.final_posr->R,cvx1.points+second1*3); |
|
1003 e1[0]-=t[0]; |
|
1004 e1[1]-=t[1]; |
|
1005 e1[2]-=t[2]; |
|
1006 |
|
1007 for(j = 1; j <= cvx2.edges->length(); j++) { |
|
1008 pair* p2 = new pair(); |
|
1009 *p2 = it2->getElem(); |
|
1010 int first2 = p2->getNum1(); |
|
1011 int second2 = p2->getNum2(); |
|
1012 |
|
1013 dMULTIPLY0_331 (t,cvx2.final_posr->R,cvx2.points+first2*3); |
|
1014 dMULTIPLY0_331 (e2,cvx2.final_posr->R,cvx2.points+second2*3); |
|
1015 e2[0]-=t[0]; |
|
1016 e2[1]-=t[1]; |
|
1017 e2[2]-=t[2]; |
|
1018 dCROSS(plane,=,e1,e2); |
|
1019 plane[3]=0; |
|
1020 ComputeInterval(cvx1,plane,min1,max1); |
|
1021 ComputeInterval(cvx2,plane,min2,max2); |
|
1022 if(max2<min1 || max1 < min2) return 0; |
|
1023 |
|
1024 it2->next(); |
|
1025 } |
|
1026 |
|
1027 it1->next(); |
|
1028 it2->setToFirst(); |
|
1029 } |
|
1030 |
|
1031 // If we get here, there was a collision |
|
1032 static int cvxhit=0; |
|
1033 contacts=0; |
|
1034 if(cvxhit<2) |
|
1035 fprintf(stdout,"Plane: %f,%f,%f,%f\n", |
|
1036 savedplane[0], |
|
1037 savedplane[1], |
|
1038 savedplane[2], |
|
1039 savedplane[3]); |
|
1040 for(unsigned int i=0;i<g1->pointcount;++i) |
|
1041 { |
|
1042 if(contacts==maxc) break; |
|
1043 dMULTIPLY0_331 (v,g1->final_posr->R,&g1->points[(i*3)]); |
|
1044 v[0]=g1->final_posr->pos[0]+v[0]; |
|
1045 v[1]=g1->final_posr->pos[1]+v[1]; |
|
1046 v[2]=g1->final_posr->pos[2]+v[2]; |
|
1047 dReal distance = (dMUL(savedplane[0],v[0]) + // Ax + |
|
1048 dMUL(savedplane[1],v[1]) + // Bx + |
|
1049 dMUL(savedplane[2],v[2])) - savedplane[3]; // Cz + D |
|
1050 |
|
1051 if((contacts<maxc)&&(distance<0)) |
|
1052 { |
|
1053 CONTACT(contact,skip*contacts)->normal[0] = savedplane[0]; |
|
1054 CONTACT(contact,skip*contacts)->normal[1] = savedplane[1]; |
|
1055 CONTACT(contact,skip*contacts)->normal[2] = savedplane[2]; |
|
1056 CONTACT(contact,skip*contacts)->pos[0]=v[0]; |
|
1057 CONTACT(contact,skip*contacts)->pos[1]=v[1]; |
|
1058 CONTACT(contact,skip*contacts)->pos[2]=v[2]; |
|
1059 CONTACT(contact,skip*contacts)->depth = -distance; |
|
1060 CONTACT(contact,skip*contacts)->g1 = g1; |
|
1061 CONTACT(contact,skip*contacts)->g2 = g2; |
|
1062 if(cvxhit<2) |
|
1063 fprintf(stdout,"Contact: %f,%f,%f depth %f\n", |
|
1064 CONTACT(contact,skip*contacts)->pos[0], |
|
1065 CONTACT(contact,skip*contacts)->pos[1], |
|
1066 CONTACT(contact,skip*contacts)->pos[2], |
|
1067 CONTACT(contact,skip*contacts)->depth); |
|
1068 contacts++; |
|
1069 } |
|
1070 } |
|
1071 cvxhit++; |
|
1072 return contacts; |
|
1073 } |
|
1074 |
|
1075 int dCollideConvexConvex (dxGeom *o1, dxGeom *o2, int flags, |
|
1076 dContactGeom *contact, int skip) |
|
1077 { |
|
1078 |
|
1079 // if(!hit) fprintf(stdout,"dCollideConvexConvex\n"); |
|
1080 dxConvex *Convex1 = (dxConvex*) o1; |
|
1081 dxConvex *Convex2 = (dxConvex*) o2; |
|
1082 int contacts = TestConvexIntersection(*Convex1,*Convex2,flags,contact,skip); |
|
1083 if(contacts) |
|
1084 { |
|
1085 //fprintf(stdout,"We have a Hit!\n"); |
|
1086 } |
|
1087 return contacts; |
|
1088 } |
|
1089 |
|
1090 |
|
1091 |
|
1092 // Ray - Convex collider by David Walters, June 2006 |
|
1093 int dCollideRayConvex( dxGeom *o1, dxGeom *o2, |
|
1094 int /*flags*/, dContactGeom *contact, int /*skip*/ ) |
|
1095 { |
|
1096 |
|
1097 dxRay* ray = (dxRay*) o1; |
|
1098 dxConvex* convex = (dxConvex*) o2; |
|
1099 |
|
1100 contact->g1 = ray; |
|
1101 contact->g2 = convex; |
|
1102 |
|
1103 dReal alpha, beta, nsign; |
|
1104 int flag; |
|
1105 |
|
1106 // |
|
1107 // Compute some useful info |
|
1108 // |
|
1109 |
|
1110 flag = 0; // Assume start point is behind all planes. |
|
1111 |
|
1112 for ( unsigned int i = 0; i < convex->planecount; ++i ) |
|
1113 { |
|
1114 // Alias this plane. |
|
1115 dReal* plane = convex->planes + i * 4; |
|
1116 |
|
1117 // If alpha >= 0 then start point is outside of plane. |
|
1118 alpha = dDOT( plane, ray->final_posr->pos ) - plane[3]; |
|
1119 |
|
1120 // If any alpha is positive, then |
|
1121 // the ray start is _outside_ of the hull |
|
1122 if ( alpha >= 0 ) |
|
1123 { |
|
1124 flag = 1; |
|
1125 break; |
|
1126 } |
|
1127 } |
|
1128 |
|
1129 // If the ray starts inside the convex hull, then everything is flipped. |
|
1130 nsign = ( flag ) ? REAL( 1.0 ) : REAL( -1.0 ); |
|
1131 |
|
1132 |
|
1133 // |
|
1134 // Find closest contact point |
|
1135 // |
|
1136 |
|
1137 // Assume no contacts. |
|
1138 contact->depth = dInfinity; |
|
1139 |
|
1140 for ( unsigned int i = 0; i < convex->planecount; ++i ) |
|
1141 { |
|
1142 // Alias this plane. |
|
1143 dReal* plane = convex->planes + i * 4; |
|
1144 |
|
1145 // If alpha >= 0 then point is outside of plane. |
|
1146 alpha = dMUL(nsign,( dDOT( plane, ray->final_posr->pos ) - plane[3] )); |
|
1147 |
|
1148 // Compute [ plane-normal DOT ray-normal ], (/flip) |
|
1149 beta = dMUL(dDOT13( plane, ray->final_posr->R+2 ),nsign); |
|
1150 |
|
1151 // Ray is pointing at the plane? ( beta < 0 ) |
|
1152 // Ray start to plane is within maximum ray length? |
|
1153 // Ray start to plane is closer than the current best distance? |
|
1154 if ( beta < -dEpsilon && |
|
1155 alpha >= REAL(0.0) && alpha <= ray->length && |
|
1156 alpha < contact->depth ) |
|
1157 { |
|
1158 // Compute contact point on convex hull surface. |
|
1159 contact->pos[0] = ray->final_posr->pos[0] + dMUL(alpha,ray->final_posr->R[0*4+2]); |
|
1160 contact->pos[1] = ray->final_posr->pos[1] + dMUL(alpha,ray->final_posr->R[1*4+2]); |
|
1161 contact->pos[2] = ray->final_posr->pos[2] + dMUL(alpha,ray->final_posr->R[2*4+2]); |
|
1162 |
|
1163 flag = 0; |
|
1164 |
|
1165 // For all _other_ planes. |
|
1166 for ( unsigned int j = 0; j < convex->planecount; ++j ) |
|
1167 { |
|
1168 if ( i == j ) |
|
1169 continue; // Skip self. |
|
1170 |
|
1171 // Alias this plane. |
|
1172 dReal* planej = convex->planes + j * 4; |
|
1173 |
|
1174 // If beta >= 0 then start is outside of plane. |
|
1175 beta = dDOT( planej, contact->pos ) - plane[3]; |
|
1176 |
|
1177 // If any beta is positive, then the contact point |
|
1178 // is not on the surface of the convex hull - it's just |
|
1179 // intersecting some part of its infinite extent. |
|
1180 if ( beta > dEpsilon ) |
|
1181 { |
|
1182 flag = 1; |
|
1183 break; |
|
1184 } |
|
1185 } |
|
1186 |
|
1187 // Contact point isn't outside hull's surface? then it's a good contact! |
|
1188 if ( flag == 0 ) |
|
1189 { |
|
1190 // Store the contact normal, possibly flipped. |
|
1191 contact->normal[0] = dMUL(nsign,plane[0]); |
|
1192 contact->normal[1] = dMUL(nsign,plane[1]); |
|
1193 contact->normal[2] = dMUL(nsign,plane[2]); |
|
1194 |
|
1195 // Store depth |
|
1196 contact->depth = alpha; |
|
1197 } |
|
1198 } |
|
1199 } |
|
1200 |
|
1201 // Contact? |
|
1202 return ( contact->depth <= ray->length ); |
|
1203 } |
|
1204 |
|
1205 |
|
1206 //<-- Convex Collision |