00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "vec2.h"
00011 #include "misc.h"
00012 #include <iostream>
00013 #include "math.h"
00014 #include <assert.h>
00015 #include "Obb2D.h"
00016
00024 bool intersectRayCircle(const CVec2& m, float r, const CVec2& x, const CVec2& t, float& f)
00025 {
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 float invtSqr=1.0f/t.sqr();
00036 float p = 2.0f*((x-m)*t)*invtSqr;
00037 float q = ((m-x).sqr() - r*r)*invtSqr;
00038 float diskr = p*p*0.25f - q;
00039
00040 if (diskr < 0)
00041 {
00042 return false;
00043 }
00044
00045 diskr=sqrtf(diskr);
00046 f = -0.5f*p - diskr;
00047
00048 if (f<0)
00049 {
00050 f = -0.5f*p + diskr;
00051 if (f>0)
00052 {
00053 return true;
00054 }
00055 else
00056 {
00057 return false;
00058 }
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 return true;
00074
00075 }
00076
00077
00078 bool intersectRayLineSegment(const CVec2& a, const CVec2& b, const CVec2& x, const CVec2& t, float&f)
00079 {
00080 CVec2 n=(b-a).getNormal();
00081
00082 float denom=t*n;
00083
00084 if (fabs(denom)<0.000001f)
00085 return false;
00086
00087 f=(n*a-n*x)/denom;
00088
00089 if (f<0)
00090 {
00091 return false;
00092 }
00093
00094 CVec2 pt=x+t*f;
00095 if ((a-pt)*(b-pt)<0)
00096 return true;
00097 return false;
00098 }
00099
00100 float shortestDistanceToLineSegment(const CVec2& a, const CVec2& b, const CVec2& x)
00101 {
00102 CVec2 dir=b-a;
00103
00104 if ( (dir*dir) < 0.00001 )
00105 {
00106 float m1=(x-a).magnitude();
00107 float m2=(x-b).magnitude();
00108 if (m1<m2) return m1;
00109 else return m2;
00110 }
00111
00112 float r=(dir*x-dir*a)/(dir*dir);
00113 if (r<=0.0f)
00114 return (x-a).magnitude();
00115 if (r>=1.0f)
00116 return (x-b).magnitude();
00117
00118 return (a+r*dir-x).magnitude();
00119
00120 }
00121
00122 bool intersectRayCapsule(const CVec2& x, const CVec2& t, const CVec2& a, const CVec2& b, float radius, float& f)
00123 {
00124 f=99999999;
00125 float r;
00126 bool hadInt=false;
00127 if (intersectRayCircle(a,radius,x,t,r))
00128 {
00129 if (r<f)
00130 f=r;
00131 hadInt=true;
00132 }
00133 if (intersectRayCircle(b,radius,x,t,r))
00134 {
00135 if (r<f)
00136 f=r;
00137 hadInt=true;
00138 }
00139 CVec2 n=normalize(b-a).getNormal();
00140 if (intersectRayLineSegment(a+radius*n,b+radius*n,x,t,r))
00141 {
00142 if (r<f)
00143 f=r;
00144 hadInt=true;
00145 }
00146 if (intersectRayLineSegment(a-radius*n,b-radius*n,x,t,r))
00147 {
00148 if (r<f)
00149 f=r;
00150 hadInt=true;
00151 }
00152 return hadInt;
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162 bool intersectPathCircle(const CVec2& c, const CVec2& p, float r0, const CVec2& hd, const CVec2& m1, float r1, float& angle)
00163 {
00164 CVec2 vec=p-m1;
00165 float s=vec.sqr();
00166 if (s>sqr(fabs(r0)+r1))
00167 return false;
00168
00169 if (s<sqr(fabs(r0)-r1))
00170 return false;
00171
00172 float d=sqrtf(s);
00173
00174 float b=(r0*r0-r1*r1+s)/(2*d);
00175
00176 CVec2 mid=p-vec*(b/d);
00177
00178 float h=sqrtf(r0*r0-b*b);
00179
00180
00181 CVec2 n=(vec*(h/d)).getNormal();
00182
00183
00184
00185
00186 CVec2 p1=(mid+n-p);
00187 CVec2 p2=(mid-n-p);
00188
00189 CVec2 pc=normalize(c-p);
00190
00191 float angle0=acosf(normalize(p1)*pc);
00192 float angle1=acosf(normalize(p2)*pc);
00193
00194
00195
00196 if ((p1*hd)<0) angle0=2*M_PI-angle0;
00197 if ((p2*hd)<0) angle1=2*M_PI-angle1;
00198
00199 if (angle0<angle1) angle=angle0;
00200 else angle=angle1;
00201
00202
00203
00204 return true;
00205
00206
00207 }
00208
00209 bool intersectPathLine(const CVec2& c, const CVec2& p, float r0, const CVec2& hd, const CVec2& p1, const CVec2& p2, float& angle)
00210 {
00211 CVec2 vec=p2-p1;
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221 if (((p1-p).sqr()<r0*r0)&&((p2-p).sqr()<r0*r0))
00222 return false;
00223
00224
00225 float invtSqr=1.0f/vec.sqr();
00226 float pa = 2.0f*((p1-p)*vec)*invtSqr;
00227 float qi = ((p-p1).sqr() - r0*r0)*invtSqr;
00228 float diskr = pa*pa*0.25f - qi;
00229
00230 if (diskr < 0)
00231 {
00232 return false;
00233 }
00234
00235 float sqrtfdiskr=sqrtf(diskr);
00236
00237 float f1 = -0.5f*pa - sqrtfdiskr;
00238 float f2 = -0.5f*pa + sqrtfdiskr;
00239
00240 if (f1>1) return false;
00241 if (f2<0) return false;
00242
00243
00244
00245 CVec2 int1=p1+f1*vec;
00246 CVec2 int2=p1+f2*vec;
00247
00248
00249
00250 CVec2 pc=normalize(c-p);
00251
00252 float angle0=acosf(normalize(int1-p)*pc);
00253 float angle1=acosf(normalize(int2-p)*pc);
00254
00255
00256 if ((int1-p)*hd<0)
00257 {
00258 angle0=2*M_PI-angle0;
00259 }
00260 if ((int2-p)*hd<0)
00261 {
00262 angle1=2*M_PI-angle1;
00263 }
00264
00265
00266 if (angle0<angle1) angle=angle0;
00267 else angle=angle1;
00268
00269 if (f1<0) angle=angle1;
00270 if (f2>1) angle=angle0;
00271
00272
00273
00274 return true;
00275
00276 }
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 bool intersectPathCapsule(const CVec2& c, const CVec2& p, float r0, const CVec2& hd, const CVec2& a, const CVec2& b, float radius, float& f)
00288 {
00289 f=99999999;
00290 float r;
00291 bool hadInt=false;
00292 if (intersectPathCircle(c,p,r0,hd,a,radius,r))
00293 {
00294 if (r<f)
00295 f=r;
00296 hadInt=true;
00297 }
00298 if (intersectPathCircle(c,p,r0,hd,b,radius,r))
00299 {
00300 if (r<f)
00301 f=r;
00302 hadInt=true;
00303 }
00304 CVec2 n=normalize(b-a).getNormal();
00305 if (intersectPathLine(c,p,r0,hd,a+radius*n,b+radius*n,r))
00306 {
00307 if (r<f)
00308 f=r;
00309 hadInt=true;
00310 }
00311 if (intersectPathLine(c,p,r0,hd,a-radius*n,b-radius*n,r))
00312 {
00313 if (r<f)
00314 f=r;
00315 hadInt=true;
00316 }
00317 return hadInt;
00318 }
00319
00320
00321 bool isInAABB(const std::pair<CVec2,CVec2>& aabb, const CVec2& p)
00322 {
00323 const CVec2& mins=aabb.first;
00324 const CVec2& maxs=aabb.second;
00325 if ((p[0]>mins[0]) &&(p[1]>mins[1])&&(p[0]<maxs[0]) &&(p[1]<maxs[1]))
00326 return true;
00327 return false;
00328 }
00329
00330 bool testAABBOverlap(const std::pair<CVec2,CVec2>& a, const std::pair<CVec2,CVec2>& b)
00331 {
00332 const CVec2& vMins=b.first;
00333 const CVec2& vMaxs=b.second;
00334 CVec2 B=(vMins+vMaxs)*0.5f;
00335 CVec2 A=(a.first+a.second)*0.5f;
00336 CVec2 E=a.second-A;
00337 CVec2 bE=vMaxs-B;
00338
00339 const CVec2 T = B - A;
00340 return fabs(T[0]) <= (E[0] + bE[0])
00341 &&
00342 fabs(T[1]) <= (E[1] + bE[1]);
00343
00344 }
00345
00346 float computeOBBIntersection(const CVec2& a, const CVec2& b, const CVec2& c, const CVec2& d, float size)
00347 {
00348 OBB2D g;
00349 CVec2 dab=normalize(b-a)*size;
00350 CVec2 nab=dab.getNormal();
00351 g[0]=a+nab-dab;
00352 g[1]=a-nab-dab;
00353 g[2]=b-nab+dab;
00354 g[3]=b+nab+dab;
00355
00356
00357 OBB2D h;
00358 CVec2 dcd=normalize(d-c)*size;
00359 CVec2 ncd=dcd.getNormal();
00360 h[0]=c+ncd-dcd;
00361 h[1]=c-ncd-dcd;
00362 h[2]=d-ncd+dcd;
00363 h[3]=d+ncd+dcd;
00364
00365 std::pair<CVec2,CVec2> aabb=g.computeAABB();
00366 std::pair<CVec2,CVec2> aabb2=h.computeAABB();
00367
00368
00369
00370
00371
00372 if (!testAABBOverlap(aabb,aabb2))
00373 {
00374 return 0;
00375 }
00376
00377
00378
00379
00380
00381
00382
00383
00384 return h.computeClippedArea(g)/(2*size*((a-b).magnitude()+2*size));
00385
00386 }
00387
00388
00389
00390