00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef __BVOLUMES__H__
00013 #define __BVOLUMES__H__
00014
00015 #include <cmath>
00016 #include "common.h"
00017
00018
00019 namespace VRUT
00020 {
00022 class AABB
00023 {
00024 private:
00025 public:
00027 VECTOR3 MinBound;
00029 VECTOR3 MaxBound;
00030
00032 AABB() : MinBound(0,0,0), MaxBound(0,0,0)
00033 {
00034 }
00036 AABB(const AABB & aabb) : MinBound(aabb.MinBound), MaxBound(aabb.MaxBound) {}
00038 ~AABB()
00039 {
00040 }
00041 VECTOR3 Center() const { return 0.5f*(MinBound + MaxBound); }
00043 bool PointIsIn(const VECTOR3 & p) const
00044 {
00045 const float * pt(p._v);
00046 return *pt >= MinBound.x && *pt++ <= MaxBound.x
00047 && *pt >= MinBound.y && *pt++ <= MaxBound.y
00048 && *pt >= MinBound.z && *pt <= MaxBound.z;
00049 }
00050
00055 void ComputeNPvertices(const PLANE * plane, VECTOR3 * nvert, VECTOR3 * pvert) const
00056 {
00057 VECTOR3 normal(plane->_p);
00058 ComputeNPvertices(&normal, nvert, pvert);
00059 }
00060
00065 void ComputeNPvertices(const VECTOR3 * normal, VECTOR3 * nvert, VECTOR3 * pvert) const
00066 {
00067 for (int i = 0; i < 3; i++)
00068 {
00069 bool pos = normal->_v[i] >= 0.0f;
00070 if (nvert) nvert->_v[i] = ( pos ? MinBound[i] : MaxBound[i] );
00071 if (pvert) pvert->_v[i] = ( pos ? MaxBound[i] : MinBound[i] );
00072 }
00073 }
00074
00079 float GetDistFromPointNormal(const VECTOR3 * pos, const VECTOR3 * dir) const
00080 {
00081 VECTOR3 nvert;
00082 ComputeNPvertices(dir, &nvert, (VECTOR3 *)NULL);
00083 return (nvert - *pos).Length();
00084 }
00085
00090 float GetSqrDistFromPointNormal(const VECTOR3 * pos, const VECTOR3 * dir) const
00091 {
00092 VECTOR3 nvert;
00093 ComputeNPvertices(dir, &nvert, (VECTOR3 *)NULL);
00094 return (nvert - *pos).LengthSq();
00095 }
00096
00098 AABB & operator=(const AABB & aabb)
00099 {
00100 MinBound = aabb.MinBound;
00101 MaxBound = aabb.MaxBound;
00102 return *this;
00103 }
00104
00106 AABB operator+(const AABB & aabb) const
00107 {
00108 AABB ret;
00109 ret.MinBound = MinBound;
00110 ret.MaxBound = MaxBound;
00111 ret.Merge(aabb);
00112 return ret;
00113 }
00114
00116 AABB & Merge(const AABB & aabb)
00117 {
00118 float * minB(MinBound._v);
00119 float * maxB(MaxBound._v);
00120 const float * minB2(aabb.MinBound._v);
00121 const float * maxB2(aabb.MaxBound._v);
00122
00123 for (unsigned i = 0; i < 3; i++)
00124 {
00125 if (minB2[i] < minB[i])
00126 minB[i] = minB2[i];
00127 if (maxB2[i] > maxB[i])
00128 maxB[i] = maxB2[i];
00129 }
00130 return *this;
00131 }
00132
00134 AABB Transform(const MATRIX * transMat) const
00135 {
00137 VECTOR3 transedAabb[8];
00138 transedAabb[0] = MinBound;
00139 transedAabb[1] = VECTOR3(MaxBound.x, MinBound.y, MinBound.z);
00140 transedAabb[2] = VECTOR3(MinBound.x, MaxBound.y, MinBound.z);
00141 transedAabb[3] = VECTOR3(MinBound.x, MinBound.y, MaxBound.z);
00142 for (int i = 0; i < 4; i++)
00143 transedAabb[i] = transMat->TransformCoord(transedAabb[i]);
00144
00145 VECTOR3 yaxis = transedAabb[2] - transedAabb[0];
00146 transedAabb[4] = transedAabb[1] + yaxis;
00147 transedAabb[5] = transedAabb[3] + yaxis;
00148 transedAabb[6] = transedAabb[1] + transedAabb[3] - transedAabb[0];
00149 transedAabb[7] = transedAabb[6] + yaxis;
00151 AABB ret;
00152 VECTOR3 * minB(&ret.MinBound);
00153 VECTOR3 * maxB(&ret.MaxBound);
00154 *minB = *maxB = transedAabb[0];
00155 for (int i = 1; i < 8; i++)
00156 {
00157 const float * pos = transedAabb[i]._v;
00158 minB->x = __min(minB->x, *pos);
00159 maxB->x = __max(maxB->x, *pos); pos++;
00160 minB->y = __min(minB->y, *pos);
00161 maxB->y = __max(maxB->y, *pos); pos++;
00162 minB->z = __min(minB->z, *pos);
00163 maxB->z = __max(maxB->z, *pos);
00164 }
00165 return ret;
00166 }
00167
00174 bool Intersects(const Ray & r, float t0 = 0.0f, float t1 = 1e9f, float * dist = NULL) const
00175 {
00176 float tmin = -1e9f;
00177 float tmax = 1e9f;
00178 if (r.direction.x != 0.0f)
00179 {
00180 float invDirX = 1.0f/r.direction.x;
00181 if (invDirX < 0.0f)
00182 {
00183 tmin = (MaxBound.x - r.origin.x) * invDirX;
00184 tmax = (MinBound.x - r.origin.x) * invDirX;
00185 }
00186 else
00187 {
00188 tmin = (MinBound.x - r.origin.x) * invDirX;
00189 tmax = (MaxBound.x - r.origin.x) * invDirX;
00190 }
00191 }
00192 else if (r.origin.x < MinBound.x || r.origin.x > MaxBound.x)
00193 return false;
00194
00195 if (r.direction.y != 0.0f)
00196 {
00197 float tymin, tymax;
00198 float invDirY = 1.0f/r.direction.y;
00199 if (invDirY < 0.0f)
00200 {
00201 tymin = (MaxBound.y - r.origin.y) * invDirY;
00202 tymax = (MinBound.y - r.origin.y) * invDirY;
00203 }
00204 else
00205 {
00206 tymin = (MinBound.y - r.origin.y) * invDirY;
00207 tymax = (MaxBound.y - r.origin.y) * invDirY;
00208 }
00209 if ( (tmin > tymax) || (tymin > tmax) )
00210 return false;
00211 if (tymin > tmin)
00212 tmin = tymin;
00213 if (tymax < tmax)
00214 tmax = tymax;
00215 }
00216 else if (r.origin.y < MinBound.y || r.origin.y > MaxBound.y)
00217 return false;
00218
00219 if (r.direction.z != 0.0f)
00220 {
00221 float tzmin, tzmax;
00222 float invDirZ = 1.0f/r.direction.z;
00223 if (invDirZ < 0.0f)
00224 {
00225 tzmin = (MaxBound.z - r.origin.z) * invDirZ;
00226 tzmax = (MinBound.z - r.origin.z) * invDirZ;
00227 }
00228 else
00229 {
00230 tzmin = (MinBound.z - r.origin.z) * invDirZ;
00231 tzmax = (MaxBound.z - r.origin.z) * invDirZ;
00232 }
00233 if ( (tmin > tzmax) || (tzmin > tmax) )
00234 return false;
00235 if (tzmin > tmin)
00236 tmin = tzmin;
00237 if (tzmax < tmax)
00238 tmax = tzmax;
00239 }
00240 else if (r.origin.z < MinBound.z || r.origin.z > MaxBound.z)
00241 return false;
00242
00243 bool ret = ( (tmin < t1) && (tmax > t0) );
00244 if (ret && dist)
00245 *dist = tmin;
00246
00247 return ret;
00248 }
00249
00251 wxString ToString() const
00252 {
00253 return wxString::Format(wxT("MinBound: %s\nMaxBound: %s"), MinBound.ToString().c_str(), MaxBound.ToString().c_str());
00254 }
00255 };
00256
00257
00259 class BCone
00260 {
00261 public:
00263 VECTOR3 Center;
00265 VECTOR3 Axis;
00267 float Angle;
00268
00270 BCone()
00271 {
00272 Center = VECTOR3(0, 0, 0);
00273 Axis = VECTOR3(0, 1, 0);
00274 Angle = 0.0f;
00275 }
00276
00278 wxString ToString() const
00279 {
00280 return wxString::Format(wxT("Center: %s\nAxis: %s\nAngle: %f\n"), Center.ToString().c_str(), Axis.ToString().c_str(), Angle);
00281 }
00282 };
00283
00284
00286 class BSphere
00287 {
00288 private:
00289 public:
00291 VECTOR3 Center;
00293 float Radius;
00294
00296 BSphere() : Center(0, 0, 0), Radius(0.0f) {}
00298 BSphere(const BSphere & s) : Center(s.Center), Radius(s.Radius) {}
00300 ~BSphere() {}
00301
00303 bool Intersects(const BSphere * s) const
00304 {
00305 float r = Radius + s->Radius;
00306 VECTOR3 d = Center - s->Center;
00307 return d.LengthSq() < r * r;
00308 }
00309
00311 bool Intersects(const BCone * K) const
00312 {
00313 VECTOR3 U = K->Center - (Radius / sinf(K->Angle)) * K->Axis;
00314 VECTOR3 D = Center - U;
00315 float dsqr = D.Dot(D);
00316 float e = K->Axis.Dot(D);
00317 float cs = cosf(K->Angle);
00318 if ( e > 0
00319 && e * e >= dsqr * cs * cs )
00320 {
00321 D = Center - K->Center;
00322 dsqr = D.Dot(D);
00323 e = -K->Axis.Dot(D);
00324 float sn = sinf(K->Angle);
00325 if ( e > 0 && e * e >= dsqr * sn * sn )
00326 return dsqr <= Radius * Radius;
00327 else
00328 return true;
00329 }
00330 return false;
00331 }
00332
00334 BSphere & operator=(const BSphere & s)
00335 {
00336 Center = s.Center;
00337 Radius = s.Radius;
00338 return *this;
00339 }
00340
00342 wxString ToString() const
00343 {
00344 return wxString::Format(wxT("Center: %s\nRadius: %f\n"), Center.ToString().c_str(), Radius);
00345 }
00346 };
00347 };
00348
00349
00350 #endif