00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #ifdef WIN32
00043
00044 #endif
00045
00046
00047
00048
00049
00050 #include "OSGConfig.h"
00051
00052 #include <OSGLog.h>
00053
00054 #include <iostream>
00055
00056 #include <assert.h>
00057
00058 #include <OSGLine.h>
00059 #include <OSGMatrix.h>
00060
00061 #include "OSGFrustumVolume.h"
00062 #include "OSGPlane.h"
00063
00064
00071 OSG_USING_NAMESPACE
00072
00073
00074
00075 void FrustumVolume::getCenter(Pnt3f ¢er) const
00076 {
00077 Pnt3f vertices[8];
00078 Line lines [4];
00079
00080 _planeVec[5].intersect(_planeVec[3],lines[3]);
00081 _planeVec[3].intersect(_planeVec[4],lines[2]);
00082 _planeVec[4].intersect(_planeVec[2],lines[0]);
00083 _planeVec[2].intersect(_planeVec[5],lines[1]);
00084
00085 for(Int32 i = 0; i < 4; i++)
00086 {
00087 _planeVec[0].intersectInfinite(lines[i],vertices[ i]);
00088 _planeVec[1].intersectInfinite(lines[i],vertices[4 + i]);
00089 }
00090
00091 center = Pnt3f(0.f, 0.f ,0.f);
00092
00093 for(Int32 i = 0; i < 8; i++)
00094 {
00095 center = center + vertices[i].subZero();
00096 }
00097
00098 center /= 8.f;
00099 }
00100
00101
00102 Real32 FrustumVolume::getScalarVolume() const
00103 {
00104 const Int32 faces[6][4] =
00105 {
00106 {0,1,3,2},
00107 {4,5,7,6},
00108 {0,4,5,1},
00109 {2,6,7,3},
00110 {2,6,4,0},
00111 {1,5,7,3}
00112 };
00113
00114 Pnt3f vertices[8];
00115 Line lines [4];
00116
00117 _planeVec[5].intersect(_planeVec[3], lines[3]);
00118 _planeVec[3].intersect(_planeVec[4], lines[2]);
00119 _planeVec[4].intersect(_planeVec[2], lines[0]);
00120 _planeVec[2].intersect(_planeVec[5], lines[1]);
00121
00122 for(Int32 i = 0; i < 4; i++)
00123 {
00124 _planeVec[0].intersectInfinite(lines[i], vertices[ i]);
00125 _planeVec[1].intersectInfinite(lines[i], vertices[4 + i]);
00126 }
00127
00128
00129 Pnt3f center = Pnt3f(0.f, 0.f, 0.f);
00130
00131 for(Int32 i = 0; i < 8; i++)
00132 {
00133 center = center + vertices[i].subZero();
00134 }
00135
00136 center /= 8.f;
00137
00138 Real32 volume = .0f;
00139
00140 for(Int32 i = 0; i < 6; i++)
00141 {
00142 Real32 height;
00143 Real32 area;
00144
00145 height =
00146 _planeVec[i].getNormal().dot(center) -
00147 _planeVec[i].getDistanceFromOrigin();
00148
00149 Vec3f main_diag = vertices[faces[i][0]] - vertices[faces[i][2]];
00150 Vec3f sec_diag = vertices[faces[i][1]] - vertices[faces[i][3]];
00151
00152 area = osgabs((main_diag.cross(sec_diag)).length() / 2.f);
00153
00154 volume += osgabs((height*area)) / 3.f;
00155 }
00156
00157 return volume;
00158 }
00159
00160
00166 void FrustumVolume::getBounds(Pnt3f &OSG_CHECK_ARG(minPnt),
00167 Pnt3f &OSG_CHECK_ARG(maxPnt)) const
00168 {
00169 }
00170
00171
00172
00173 void FrustumVolume::setPlanes(const Plane &pnear, const Plane &pfar,
00174 const Plane &left, const Plane &right,
00175 const Plane &top, const Plane &bottom)
00176 {
00177 _planeVec[0] = pnear;
00178 _planeVec[1] = pfar;
00179 _planeVec[2] = left;
00180 _planeVec[3] = right;
00181 _planeVec[4] = top;
00182 _planeVec[5] = bottom;
00183 }
00184
00185
00186 void FrustumVolume::setPlanes(const Pnt3f &nlt, const Pnt3f &nlb,
00187 const Pnt3f &nrt, const Pnt3f &nrb,
00188 const Pnt3f &flt, const Pnt3f &flb,
00189 const Pnt3f &frt, const Pnt3f &frb)
00190 {
00191
00192 Plane pnear (nlb,nlt,nrb);
00193 Plane pfar (frb,frt,flb);
00194 Plane pleft (flb,flt,nlb);
00195 Plane pright (nrb,nrt,frb);
00196 Plane ptop (frt,nrt,flt);
00197 Plane pbottom(nlb,nrb,flb);
00198
00199
00200 _planeVec[0] = pnear;
00201 _planeVec[1] = pfar;
00202 _planeVec[2] = pleft;
00203 _planeVec[3] = pright;
00204 _planeVec[4] = ptop;
00205 _planeVec[5] = pbottom;
00206
00207 }
00208
00209
00210 void FrustumVolume::setPlanes(const Matrix &objectClipMat)
00211 {
00212 Vec4f planeEquation[6];
00213 Real32 vectorLength;
00214 Vec3f normal;
00215
00216 planeEquation[0][0] = objectClipMat[0][3] - objectClipMat[0][0];
00217 planeEquation[0][1] = objectClipMat[1][3] - objectClipMat[1][0];
00218 planeEquation[0][2] = objectClipMat[2][3] - objectClipMat[2][0];
00219 planeEquation[0][3] = objectClipMat[3][3] - objectClipMat[3][0];
00220
00221 planeEquation[1][0] = objectClipMat[0][3] + objectClipMat[0][0];
00222 planeEquation[1][1] = objectClipMat[1][3] + objectClipMat[1][0];
00223 planeEquation[1][2] = objectClipMat[2][3] + objectClipMat[2][0];
00224 planeEquation[1][3] = objectClipMat[3][3] + objectClipMat[3][0];
00225
00226 planeEquation[2][0] = objectClipMat[0][3] + objectClipMat[0][1];
00227 planeEquation[2][1] = objectClipMat[1][3] + objectClipMat[1][1];
00228 planeEquation[2][2] = objectClipMat[2][3] + objectClipMat[2][1];
00229 planeEquation[2][3] = objectClipMat[3][3] + objectClipMat[3][1];
00230
00231 planeEquation[3][0] = objectClipMat[0][3] - objectClipMat[0][1];
00232 planeEquation[3][1] = objectClipMat[1][3] - objectClipMat[1][1];
00233 planeEquation[3][2] = objectClipMat[2][3] - objectClipMat[2][1];
00234 planeEquation[3][3] = objectClipMat[3][3] - objectClipMat[3][1];
00235
00236 planeEquation[4][0] = objectClipMat[0][3] + objectClipMat[0][2];
00237 planeEquation[4][1] = objectClipMat[1][3] + objectClipMat[1][2];
00238 planeEquation[4][2] = objectClipMat[2][3] + objectClipMat[2][2];
00239 planeEquation[4][3] = objectClipMat[3][3] + objectClipMat[3][2];
00240
00241 planeEquation[5][0] = objectClipMat[0][3] - objectClipMat[0][2];
00242 planeEquation[5][1] = objectClipMat[1][3] - objectClipMat[1][2];
00243 planeEquation[5][2] = objectClipMat[2][3] - objectClipMat[2][2];
00244 planeEquation[5][3] = objectClipMat[3][3] - objectClipMat[3][2];
00245
00246 for(Int32 i = 0; i < 6; i++)
00247 {
00248 vectorLength =
00249 osgsqrt(planeEquation[i][0] * planeEquation[i][0] +
00250 planeEquation[i][1] * planeEquation[i][1] +
00251 planeEquation[i][2] * planeEquation[i][2]);
00252
00253 planeEquation[i][0] /= vectorLength;
00254 planeEquation[i][1] /= vectorLength;
00255 planeEquation[i][2] /= vectorLength;
00256 planeEquation[i][3] /= -vectorLength;
00257 }
00258
00259
00260 _planeVec[3].set(planeEquation[0]);
00261
00262
00263 _planeVec[2].set(planeEquation[1]);
00264
00265
00266 _planeVec[5].set(planeEquation[2]);
00267
00268
00269 _planeVec[4].set(planeEquation[3]);
00270
00271
00272 _planeVec[0].set(planeEquation[4]);
00273
00274
00275 _planeVec[1].set(planeEquation[5]);
00276 }
00277
00278
00279
00280
00281
00287 void FrustumVolume::extendBy(const Pnt3f &OSG_CHECK_ARG(pt))
00288 {
00289 }
00290
00295 void FrustumVolume::extendBy(const Volume &volume)
00296 {
00297 OSG::extend(*this, volume);
00298 }
00299
00300
00301
00302
00303 bool FrustumVolume::intersect(const Pnt3f &point) const
00304 {
00305 bool retCode = true;
00306
00307 for(Int32 i = 0; i < 6; i++)
00308 {
00309 if((_planeVec[i].getNormal().x() * point.x() +
00310 _planeVec[i].getNormal().y() * point.y() +
00311 _planeVec[i].getNormal().z() * point.z() +
00312 _planeVec[i].getDistanceFromOrigin() ) < 0.f)
00313 {
00314 retCode = false;
00315 break;
00316 }
00317 }
00318
00319 return retCode;
00320 }
00321
00322
00323 bool FrustumVolume::intersect(const Line &line) const
00324 {
00325 return line.intersect(*this);
00326 }
00327
00328
00329 bool FrustumVolume::intersect(const Line &line,
00330 Real32 &minDist,
00331 Real32 &maxDist) const
00332 {
00333 return line.intersect(*this, minDist, maxDist);
00334 }
00335
00336
00337 bool FrustumVolume::intersect(const Volume &volume) const
00338 {
00339 return OSG::intersect(*this, volume);
00340 }
00341
00347 bool FrustumVolume::isOnSurface(const Pnt3f &OSG_CHECK_ARG(point)) const
00348 {
00349 FWARNING(("FrustumVolume::isOnSurface: NYI!\n"));
00350 return false;
00351 }
00352
00353 void FrustumVolume::transform(const Matrix &m)
00354 {
00355 _planeVec[0].transform(m);
00356 _planeVec[1].transform(m);
00357 _planeVec[2].transform(m);
00358 _planeVec[3].transform(m);
00359 _planeVec[4].transform(m);
00360 _planeVec[5].transform(m);
00361 }
00362
00363 const FrustumVolume &FrustumVolume::operator =(const FrustumVolume &b1)
00364 {
00365 for(Int32 i = 0; i < 5; i++)
00366 {
00367 _planeVec[i] = b1._planeVec[i];
00368 }
00369
00370 _state = b1._state;
00371
00372 return *this;
00373 }
00374
00375 void FrustumVolume::dump( UInt32 OSG_CHECK_ARG(uiIndent),
00376 const BitVector OSG_CHECK_ARG(bvFlags )) const
00377 {
00378 #if 1
00379 fprintf(stderr,"Frustum:(%f %f %f:%f)(%f %f %f:%f)(%f %f %f:%f)"
00380 "(%f %f %f:%f)(%f %f %f:%f)(%f %f %f:%f)\n",
00381 _planeVec[0].getNormal()[0],
00382 _planeVec[0].getNormal()[1],
00383 _planeVec[0].getNormal()[2],
00384 _planeVec[0].getDistanceFromOrigin(),
00385 _planeVec[1].getNormal()[0],
00386 _planeVec[1].getNormal()[1],
00387 _planeVec[1].getNormal()[2],
00388 _planeVec[1].getDistanceFromOrigin(),
00389 _planeVec[2].getNormal()[0],
00390 _planeVec[2].getNormal()[1],
00391 _planeVec[2].getNormal()[2],
00392 _planeVec[2].getDistanceFromOrigin(),
00393 _planeVec[3].getNormal()[0],
00394 _planeVec[3].getNormal()[1],
00395 _planeVec[3].getNormal()[2],
00396 _planeVec[3].getDistanceFromOrigin(),
00397 _planeVec[4].getNormal()[0],
00398 _planeVec[4].getNormal()[1],
00399 _planeVec[4].getNormal()[2],
00400 _planeVec[4].getDistanceFromOrigin(),
00401 _planeVec[5].getNormal()[0],
00402 _planeVec[5].getNormal()[1],
00403 _planeVec[5].getNormal()[2],
00404 _planeVec[5].getDistanceFromOrigin() );
00405
00406
00407 #else
00408 PLOG << "Frustum("
00409 << _planeVec[0].getNormal() << ":"
00410 << _planeVec[0].getDistanceFromOrigin() << "|"
00411 << _planeVec[1].getNormal() << ":"
00412 << _planeVec[1].getDistanceFromOrigin() << "|"
00413 << _planeVec[2].getNormal() << ":"
00414 << _planeVec[2].getDistanceFromOrigin() << "|"
00415 << _planeVec[3].getNormal() << ":"
00416 << _planeVec[3].getDistanceFromOrigin() << "|"
00417 << _planeVec[4].getNormal() << ":"
00418 << _planeVec[4].getDistanceFromOrigin() << "|"
00419 << _planeVec[5].getNormal() << ":"
00420 << _planeVec[5].getDistanceFromOrigin() << "|"
00421 << ")";
00422 #endif
00423 }
00424
00425
00426 OSG_BEGIN_NAMESPACE
00427
00428 OSG_BASE_DLLMAPPING
00429 bool operator ==(const FrustumVolume &b1, const FrustumVolume &b2)
00430 {
00431 return ((static_cast<const Volume &>(b1) == b2 ) &&
00432 (b1.getPlanes()[0] == b2.getPlanes()[0]) &&
00433 (b1.getPlanes()[1] == b2.getPlanes()[1]) &&
00434 (b1.getPlanes()[2] == b2.getPlanes()[2]) &&
00435 (b1.getPlanes()[3] == b2.getPlanes()[3]) &&
00436 (b1.getPlanes()[4] == b2.getPlanes()[4]) &&
00437 (b1.getPlanes()[5] == b2.getPlanes()[5]));
00438 }
00439
00450 OSG_BASE_DLLMAPPING
00451 bool intersect(const FrustumVolume &frustum, const Volume &vol,
00452 FrustumVolume::PlaneSet &inplanes)
00453 {
00454 Pnt3f min, max;
00455 vol.getBounds(min, max);
00456
00457 const Plane *frust = frustum.getPlanes();
00458 FrustumVolume::PlaneSet mask = 0x1;
00459
00460
00461
00462
00463 for(Int32 i = 0; i < 6; i++, mask <<= 1)
00464 {
00465 if((inplanes & mask) != 0)
00466 continue;
00467
00468 if(frust[i].isOutHalfSpace(min, max))
00469 return false;
00470
00471 if(frust[i].isInHalfSpace(min, max))
00472 inplanes |= mask;
00473 }
00474
00475 return true;
00476 }
00477
00478 OSG_END_NAMESPACE