00001
00008 #ifndef MATHCOMMON_H
00009 #define MATHCOMMON_H
00010
00011 #include <cmath>
00012 #include <assert.h>
00013
00014 #ifndef VECTOR3_H
00015 #include "Vector3.h"
00016 #endif
00017
00018 #ifndef POINT3_H
00019 #include "Point3.h"
00020 #endif
00021
00022 #ifndef MATRIX_H
00023 #include "Matrix.h"
00024 #endif
00025
00031 struct LineSegment
00032 {
00033 Point3f p1;
00034 Point3f p2;
00035 };
00036
00042 struct Ray
00043 {
00044 Point3f p;
00045 Vector3f d;
00046 };
00047
00053 struct Plane
00054 {
00055 Point3f p;
00056 Vector3f n;
00057 };
00058
00064 struct ScreenRect
00065 {
00066 int x1, y1;
00067 int x2, y2;
00068 };
00069
00075 struct Sphere
00076 {
00077 Point3f c;
00078 float r;
00079 };
00080
00086 struct CubeDef
00087 {
00088 Point3f c;
00089 float dim;
00090 };
00091
00097 struct CubePlanes
00098 {
00099 Plane plane[6];
00100 };
00101
00107 struct CubeFrame
00108 {
00109 LineSegment line[12];
00110 };
00111
00124 template<class dataType, class timeType>
00125 dataType Lerp(const dataType &d0, const dataType &d1, const timeType &t)
00126 {
00127 return d0 + (d1 - d0) * t;
00128 }
00129
00136 template<class T>
00137 void Swap(T &v1, T &v2)
00138 {
00139 T tmp = v1;
00140 v1 = v2;
00141 v2 = tmp;
00142 }
00143
00153 template<class T>
00154 T Clamp(const T &val, const T &low, const T &high)
00155 {
00156 if(val < low)
00157 return low;
00158 else if(val > high)
00159 return high;
00160 return val;
00161 }
00162
00170 inline CubePlanes CreatePlanes(const CubeDef &c)
00171 {
00172 CubePlanes p;
00173
00174 float d = c.dim / 2.0f;
00175
00176 p.plane[0].n = Vector3f( 1.0f, 0.0f, 0.0f); p.plane[0].p = Point3f( d, 0.0f, 0.0f);
00177 p.plane[1].n = Vector3f(-1.0f, 0.0f, 0.0f); p.plane[1].p = Point3f(-d, 0.0f, 0.0f);
00178
00179 p.plane[2].n = Vector3f( 0.0f, 1.0f, 0.0f); p.plane[2].p = Point3f(0.0f, d, 0.0f);
00180 p.plane[3].n = Vector3f( 0.0f, -1.0f, 0.0f); p.plane[3].p = Point3f(0.0f, -d, 0.0f);
00181
00182 p.plane[4].n = Vector3f( 0.0f, 0.0f, 1.0f); p.plane[4].p = Point3f(0.0f, 0.0f, d);
00183 p.plane[5].n = Vector3f( 0.0f, 0.0f, -1.0f); p.plane[5].p = Point3f(0.0f, 0.0f, -d);
00184
00185 return p;
00186 }
00187
00195 inline CubeFrame CreateFrame(const CubeDef &c)
00196 {
00197 CubeFrame f;
00198
00199 float d = c.dim / 2.0f;
00200
00201 Point3f dx(d, 0.0f, 0.0f);
00202 Point3f dy(0.0f, d, 0.0f);
00203 Point3f dz(0.0f, 0.0f, d);
00204
00205 Point3f center = c.c;
00206
00207 f.line[0].p1 = center + Point3f(-d, -d, d); f.line[0].p2 = center + Point3f( d, -d, d);
00208 f.line[1].p1 = center + Point3f(-d, -d, d); f.line[1].p2 = center + Point3f(-d, -d, -d);
00209 f.line[2].p1 = center + Point3f(-d, -d, d); f.line[2].p2 = center + Point3f(-d, d, d);
00210
00211 f.line[3].p1 = center + Point3f( d, -d, -d); f.line[3].p2 = center + Point3f( d, -d, d);
00212 f.line[4].p1 = center + Point3f( d, -d, -d); f.line[4].p2 = center + Point3f(-d, -d, -d);
00213 f.line[5].p1 = center + Point3f( d, -d, -d); f.line[5].p2 = center + Point3f( d, d, -d);
00214
00215 f.line[6].p1 = center + Point3f( d, d, d); f.line[6].p2 = center + Point3f(-d, d, d);
00216 f.line[7].p1 = center + Point3f( d, d, d); f.line[7].p2 = center + Point3f( d, d, -d);
00217 f.line[8].p1 = center + Point3f( d, d, d); f.line[8].p2 = center + Point3f( d, -d, d);
00218
00219 f.line[9].p1 = center + Point3f(-d, d, -d); f.line[9].p2 = center + Point3f( d, d, -d);
00220 f.line[10].p1 = center + Point3f(-d, d, -d); f.line[10].p2 = center + Point3f(-d, d, d);
00221 f.line[11].p1 = center + Point3f(-d, d, -d); f.line[11].p2 = center + Point3f(-d, -d, -d);
00222
00223 return f;
00224 }
00225
00234 inline bool Inside(const Point3f &p, const Sphere &s)
00235 {
00236 Vector3f d = p - s.c;
00237 return d.SquaredLength() < (s.r*s.r);
00238 }
00239
00249 inline bool Inside(int x, int y, const ScreenRect &rect)
00250 {
00251 return (x >= rect.x1 && x <= rect.x2 && y <= rect.y1 && y >= rect.y2);
00252 }
00253
00264 inline int Intersect(const LineSegment &line, const Plane &plane, float &t)
00265 {
00266 float d = Dot(plane.p, plane.n);
00267 float numerator = d - Dot(plane.n, line.p1);
00268 float denom = Dot(plane.n, line.p2 - line.p1);
00269
00270 t = numerator / denom;
00271
00272 return denom != 0.0f;
00273 }
00274
00285 inline int Intersect(const Plane &p, const CubeFrame &c, Point3f points[6])
00286 {
00287 int hits = 0;
00288
00289 int i = 0;
00290 while(i < 12 && hits < 6)
00291 {
00292 float t;
00293 if(Intersect(c.line[i], p, t) && t >= 0.0f && t <= 1.0f)
00294 {
00295 points[hits] = c.line[i].p1 + (c.line[i].p2 - c.line[i].p1)*t;
00296 hits++;
00297 }
00298 i++;
00299 }
00300
00301 return hits;
00302 }
00303
00313 inline int Intersect(const LineSegment &line, const Sphere &s, Point3f points[2])
00314 {
00315 const Point3f &p1 = line.p1;
00316 const Point3f &p2 = line.p2;
00317 const Point3f &p3 = s.c;
00318
00319 Point3f pd = p2 - p1;
00320
00321
00322 float un = Dot(p3 - p1, pd);
00323 float ud = Dot(pd, pd);
00324 float u = un / ud;
00325
00326
00327 if(u <= 0 || u >= 1.0f)
00328 return 0;
00329
00330 float a = ud;
00331 float b = 2.0f * Dot(pd, p1 - p3);
00332 float c = Dot(p3, p3) + Dot(p1, p1) - 2.0f * Dot(p3, p1) - s.r * s.r;
00333
00334 float d = b * b - 4 * a * c;
00335
00336 if(d < 0.0f)
00337 return 0;
00338
00339
00340 if(d == 0.0f)
00341 {
00342 float t = -b / (2.0f * a);
00343
00344 points[0] = p1 + pd * t;
00345
00346 return 1;
00347 }
00348
00349
00350 float root = std::sqrt(d);
00351 float t1 = (-b - root) / (2.0f * a);
00352 float t2 = (-b + root) / (2.0f * a);
00353
00354 points[0] = p1 + pd * t1;
00355 points[1] = p1 + pd * t2;
00356
00357 return 2;
00358 }
00359
00369 inline int Intersect(const Ray &r, const Sphere &s, Point3f points[2])
00370 {
00371 Vector3f diff = r.p - s.c;
00372 Point3f dir = r.d;
00373
00374
00375 float b = 2.0f * Dot(r.d, diff);
00376 float c = Dot(diff, diff) - s.r * s.r;
00377
00378 float d = b*b - 4*c;
00379 if(d < 0.0f)
00380 return 0;
00381
00382 float root = std::sqrt(d);
00383
00384 float t0 = (-b - root) / 2.0f;
00385 Point3f p0 = r.p + r.d * t0;
00386
00387 float t1 = (-b + root) / 2.0f;
00388 Point3f p1 = r.p + r.d * t1;
00389
00390 if(t0 < 0.0f && t1 < 0.0f)
00391 return 0;
00392
00393 if(t0 < 0.0f || t1 < 0.0f)
00394 {
00395 if(t0 < 0.0f)
00396 points[0] = Lerp(r.p, dir, t1);
00397 else
00398 points[0] = Lerp(r.p, dir, t0);
00399
00400 return 1;
00401 }
00402
00403 points[0] = Lerp(r.p, dir, t0);
00404 points[1] = Lerp(r.p, dir, t1);
00405 return 2;
00406 }
00407
00416 inline Point3f Average(const Point3f *points, int n)
00417 {
00418 Point3f p(0.0f, 0.0f, 0.0f);
00419 for(int i = 0; i < n; i++)
00420 {
00421 p = p + points[i];
00422 }
00423
00424 return p / (float)n;
00425 }
00426
00436 inline float ReferanceAngle(const Vector3f &ref, const Vector3f &v1, const Vector3f &v2)
00437 {
00438 Vector3f c = Cross(v1, v2);
00439 float angle = std::atan2(c.Length(), Dot(v1, v2));
00440
00441 if(Dot(c, ref) < 0.0f)
00442 return -angle;
00443 return angle;
00444 }
00445
00453 inline void SortPoints(Point3f *points, int n, const Vector3f &normal)
00454 {
00455 assert(n <= 6);
00456
00457 if(n < 3)
00458 return;
00459
00460 Point3f ave = Average(points, n);
00461 Vector3f v1 = points[0] - ave;
00462
00463 float angle[6];
00464
00465 angle[0] = 0;
00466 for(int i = 1; i < n; i++)
00467 {
00468 Vector3f v2 = points[i] - ave;
00469 angle[i] = ReferanceAngle(normal, v1, v2);
00470 }
00471
00472
00473 for(int i = 0; i < n; i++)
00474 {
00475 float a = angle[i];
00476 Point3f p = points[i];
00477
00478 int j = i - 1;
00479 while(j >= 0 && angle[j] > a)
00480 {
00481 angle[j + 1] = angle[j];
00482 points[j + 1] = points[j];
00483
00484 j--;
00485 }
00486
00487 angle[j + 1] = a;
00488 points[j + 1] = p;
00489 }
00490
00491 }
00492
00493 #endif