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
00043
00044 #include "OSGConfig.h"
00045
00046 #include <iostream>
00047
00048 #include <cassert>
00049
00050 #include "OSGFrustumVolume.h"
00051 #include "OSGLog.h"
00052 #include "OSGMatrix.h"
00053 #include "OSGLine.h"
00054
00055
00062 OSG_BEGIN_NAMESPACE
00063
00064
00065
00066 void FrustumVolume::getCenter(Pnt3r ¢er) const
00067 {
00068 Pnt3r vertices[8];
00069 Line lines [4];
00070
00071 _planeVec[5].intersect(_planeVec[3],lines[3]);
00072 _planeVec[3].intersect(_planeVec[4],lines[2]);
00073 _planeVec[4].intersect(_planeVec[2],lines[0]);
00074 _planeVec[2].intersect(_planeVec[5],lines[1]);
00075
00076 for(Int32 i = 0; i < 4; i++)
00077 {
00078 _planeVec[0].intersectInfinite(lines[i],vertices[ i]);
00079 _planeVec[1].intersectInfinite(lines[i],vertices[4 + i]);
00080 }
00081
00082 center = Pnt3r(0.f, 0.f ,0.f);
00083
00084 for(Int32 i = 0; i < 8; i++)
00085 {
00086 center = center + vertices[i].subZero();
00087 }
00088
00089 center /= 8.f;
00090 }
00091
00092
00093 Real FrustumVolume::getScalarVolume() const
00094 {
00095 const Int32 faces[6][4] =
00096 {
00097 {0,1,3,2},
00098 {4,5,7,6},
00099 {0,4,5,1},
00100 {2,6,7,3},
00101 {2,6,4,0},
00102 {1,5,7,3}
00103 };
00104
00105 Pnt3r vertices[8];
00106 Line lines [4];
00107
00108 _planeVec[5].intersect(_planeVec[3], lines[3]);
00109 _planeVec[3].intersect(_planeVec[4], lines[2]);
00110 _planeVec[4].intersect(_planeVec[2], lines[0]);
00111 _planeVec[2].intersect(_planeVec[5], lines[1]);
00112
00113 for(Int32 i = 0; i < 4; i++)
00114 {
00115 _planeVec[0].intersectInfinite(lines[i], vertices[ i]);
00116 _planeVec[1].intersectInfinite(lines[i], vertices[4 + i]);
00117 }
00118
00119
00120 Pnt3r center = Pnt3r(0.f, 0.f, 0.f);
00121
00122 for(Int32 i = 0; i < 8; i++)
00123 {
00124 center = center + vertices[i].subZero();
00125 }
00126
00127 center /= 8.f;
00128
00129 Real volume = .0f;
00130
00131 for(Int32 i = 0; i < 6; i++)
00132 {
00133 Real height;
00134 Real area;
00135
00136 height =
00137 _planeVec[i].getNormal().dot(center) -
00138 _planeVec[i].getDistanceFromOrigin();
00139
00140 Vec3r main_diag = vertices[faces[i][0]] - vertices[faces[i][2]];
00141 Vec3r sec_diag = vertices[faces[i][1]] - vertices[faces[i][3]];
00142
00143 area = osgAbs((main_diag.cross(sec_diag)).length() / 2.f);
00144
00145 volume += osgAbs((height*area)) / 3.f;
00146 }
00147
00148 return volume;
00149 }
00150
00151
00155 void FrustumVolume::getBounds(Pnt3r &minPnt,
00156 Pnt3r &maxPnt ) const
00157 {
00158 Pnt3r corners[8];
00159
00160 this->getCorners(corners[0], corners[1], corners[2], corners[3],
00161 corners[4], corners[5], corners[6], corners[7] );
00162
00163 minPnt[0] = TypeTraits<Pnt3r::ValueType>::getMax();
00164 minPnt[1] = TypeTraits<Pnt3r::ValueType>::getMax();
00165 minPnt[2] = TypeTraits<Pnt3r::ValueType>::getMax();
00166
00167 maxPnt[0] = TypeTraits<Pnt3r::ValueType>::getMin();
00168 maxPnt[1] = TypeTraits<Pnt3r::ValueType>::getMin();
00169 maxPnt[2] = TypeTraits<Pnt3r::ValueType>::getMin();
00170
00171 for(UInt32 i = 0; i < 8; ++i)
00172 {
00173 minPnt[0] = osgMin(minPnt[0], corners[i][0]);
00174 minPnt[1] = osgMin(minPnt[1], corners[i][1]);
00175 minPnt[2] = osgMin(minPnt[2], corners[i][2]);
00176
00177 maxPnt[0] = osgMax(maxPnt[0], corners[i][0]);
00178 maxPnt[1] = osgMax(maxPnt[1], corners[i][1]);
00179 maxPnt[2] = osgMax(maxPnt[2], corners[i][2]);
00180 }
00181 }
00182
00185 void FrustumVolume::getCorners(Pnt3r &nlt, Pnt3r &nlb,
00186 Pnt3r &nrt, Pnt3r &nrb,
00187 Pnt3r &flt, Pnt3r &flb,
00188 Pnt3r &frt, Pnt3r &frb ) const
00189 {
00190 Line edges[4];
00191
00192 _planeVec[PLANE_BOTTOM].intersect(_planeVec[PLANE_RIGHT ], edges[3]);
00193 _planeVec[PLANE_RIGHT ].intersect(_planeVec[PLANE_TOP ], edges[2]);
00194 _planeVec[PLANE_TOP ].intersect(_planeVec[PLANE_LEFT ], edges[0]);
00195 _planeVec[PLANE_LEFT ].intersect(_planeVec[PLANE_BOTTOM], edges[1]);
00196
00197 _planeVec[PLANE_NEAR].intersectInfinite(edges[0], nlt);
00198 _planeVec[PLANE_FAR ].intersectInfinite(edges[0], flt);
00199 _planeVec[PLANE_NEAR].intersectInfinite(edges[1], nlb);
00200 _planeVec[PLANE_FAR ].intersectInfinite(edges[1], flb);
00201 _planeVec[PLANE_NEAR].intersectInfinite(edges[2], nrt);
00202 _planeVec[PLANE_FAR ].intersectInfinite(edges[2], frt);
00203 _planeVec[PLANE_NEAR].intersectInfinite(edges[3], nrb);
00204 _planeVec[PLANE_FAR ].intersectInfinite(edges[3], frb);
00205 }
00206
00207
00208
00209 void FrustumVolume::setPlanes(const Plane &pnear, const Plane &pfar,
00210 const Plane &left, const Plane &right,
00211 const Plane &top, const Plane &bottom)
00212 {
00213 _planeVec[0] = pnear;
00214 _planeVec[1] = pfar;
00215 _planeVec[2] = left;
00216 _planeVec[3] = right;
00217 _planeVec[4] = top;
00218 _planeVec[5] = bottom;
00219 }
00220
00221
00222 void FrustumVolume::setPlanes(const Pnt3r &nlt, const Pnt3r &nlb,
00223 const Pnt3r &nrt, const Pnt3r &nrb,
00224 const Pnt3r &flt, const Pnt3r &flb,
00225 const Pnt3r &frt, const Pnt3r &frb)
00226 {
00227
00228 Plane pnear (nlb,nlt,nrb);
00229 Plane pfar (frb,frt,flb);
00230 Plane pleft (flb,flt,nlb);
00231 Plane pright (nrb,nrt,frb);
00232 Plane ptop (frt,nrt,flt);
00233 Plane pbottom(nlb,nrb,flb);
00234
00235
00236 _planeVec[0] = pnear;
00237 _planeVec[1] = pfar;
00238 _planeVec[2] = pleft;
00239 _planeVec[3] = pright;
00240 _planeVec[4] = ptop;
00241 _planeVec[5] = pbottom;
00242
00243 }
00244
00245
00246 void FrustumVolume::setPlanes(const Matrixr &objectClipMat)
00247 {
00248 Vec4r planeEquation[6];
00249 Real vectorLength;
00250 Vec3r normal;
00251
00252 planeEquation[0][0] = objectClipMat[0][3] - objectClipMat[0][0];
00253 planeEquation[0][1] = objectClipMat[1][3] - objectClipMat[1][0];
00254 planeEquation[0][2] = objectClipMat[2][3] - objectClipMat[2][0];
00255 planeEquation[0][3] = objectClipMat[3][3] - objectClipMat[3][0];
00256
00257 planeEquation[1][0] = objectClipMat[0][3] + objectClipMat[0][0];
00258 planeEquation[1][1] = objectClipMat[1][3] + objectClipMat[1][0];
00259 planeEquation[1][2] = objectClipMat[2][3] + objectClipMat[2][0];
00260 planeEquation[1][3] = objectClipMat[3][3] + objectClipMat[3][0];
00261
00262 planeEquation[2][0] = objectClipMat[0][3] + objectClipMat[0][1];
00263 planeEquation[2][1] = objectClipMat[1][3] + objectClipMat[1][1];
00264 planeEquation[2][2] = objectClipMat[2][3] + objectClipMat[2][1];
00265 planeEquation[2][3] = objectClipMat[3][3] + objectClipMat[3][1];
00266
00267 planeEquation[3][0] = objectClipMat[0][3] - objectClipMat[0][1];
00268 planeEquation[3][1] = objectClipMat[1][3] - objectClipMat[1][1];
00269 planeEquation[3][2] = objectClipMat[2][3] - objectClipMat[2][1];
00270 planeEquation[3][3] = objectClipMat[3][3] - objectClipMat[3][1];
00271
00272 planeEquation[4][0] = objectClipMat[0][3] + objectClipMat[0][2];
00273 planeEquation[4][1] = objectClipMat[1][3] + objectClipMat[1][2];
00274 planeEquation[4][2] = objectClipMat[2][3] + objectClipMat[2][2];
00275 planeEquation[4][3] = objectClipMat[3][3] + objectClipMat[3][2];
00276
00277 planeEquation[5][0] = objectClipMat[0][3] - objectClipMat[0][2];
00278 planeEquation[5][1] = objectClipMat[1][3] - objectClipMat[1][2];
00279 planeEquation[5][2] = objectClipMat[2][3] - objectClipMat[2][2];
00280 planeEquation[5][3] = objectClipMat[3][3] - objectClipMat[3][2];
00281
00282 for(Int32 i = 0; i < 6; i++)
00283 {
00284 vectorLength =
00285 osgSqrt(planeEquation[i][0] * planeEquation[i][0] +
00286 planeEquation[i][1] * planeEquation[i][1] +
00287 planeEquation[i][2] * planeEquation[i][2]);
00288
00289 planeEquation[i][0] /= vectorLength;
00290 planeEquation[i][1] /= vectorLength;
00291 planeEquation[i][2] /= vectorLength;
00292 planeEquation[i][3] /= -vectorLength;
00293 }
00294
00295
00296 _planeVec[3].set(planeEquation[0]);
00297
00298
00299 _planeVec[2].set(planeEquation[1]);
00300
00301
00302 _planeVec[5].set(planeEquation[2]);
00303
00304
00305 _planeVec[4].set(planeEquation[3]);
00306
00307
00308 _planeVec[0].set(planeEquation[4]);
00309
00310
00311 _planeVec[1].set(planeEquation[5]);
00312 }
00313
00314
00315
00316
00317
00323 void FrustumVolume::extendBy(const Pnt3r &OSG_CHECK_ARG(pt))
00324 {
00325 }
00326
00331 void FrustumVolume::extendBy(const Volume &volume)
00332 {
00333 OSG::extend(*this, volume);
00334 }
00335
00336
00337
00338
00339 bool FrustumVolume::intersect(const Pnt3r &point) const
00340 {
00341 bool retCode = true;
00342
00343 for(Int32 i = 0; i < 6; i++)
00344 {
00345 if((_planeVec[i].getNormal().x() * point.x() +
00346 _planeVec[i].getNormal().y() * point.y() +
00347 _planeVec[i].getNormal().z() * point.z() -
00348 _planeVec[i].getDistanceFromOrigin() ) < 0.f)
00349 {
00350 retCode = false;
00351 break;
00352 }
00353 }
00354
00355 return retCode;
00356 }
00357
00358
00359 bool FrustumVolume::intersect(const Line &line) const
00360 {
00361 return line.intersect(*this);
00362 }
00363
00364
00365 bool FrustumVolume::intersect(const Line &line,
00366 Real &minDist,
00367 Real &maxDist) const
00368 {
00369 return line.intersect(*this, minDist, maxDist);
00370 }
00371
00372
00373 bool FrustumVolume::intersect(const Volume &volume) const
00374 {
00375 return OSG::intersect(*this, volume);
00376 }
00377
00383 bool FrustumVolume::isOnSurface(const Pnt3r &OSG_CHECK_ARG(point)) const
00384 {
00385 FWARNING(("FrustumVolume::isOnSurface: NYI!\n"));
00386 return false;
00387 }
00388
00389 void FrustumVolume::transform(const Matrixr &m)
00390 {
00391 _planeVec[0].transform(m);
00392 _planeVec[1].transform(m);
00393 _planeVec[2].transform(m);
00394 _planeVec[3].transform(m);
00395 _planeVec[4].transform(m);
00396 _planeVec[5].transform(m);
00397 }
00398
00399 FrustumVolume &FrustumVolume::operator =(const FrustumVolume &rhs)
00400 {
00401 if(this == &rhs)
00402 return *this;
00403
00404 for(Int32 i = 0; i < 6; i++)
00405 {
00406 _planeVec[i] = rhs._planeVec[i];
00407 }
00408
00409 _state = rhs._state;
00410
00411 return *this;
00412 }
00413
00414 bool FrustumVolume::operator ==(const FrustumVolume &rhs) const
00415 {
00416 return ((static_cast<const Volume &>(*this) == rhs) &&
00417 (_planeVec[0] == rhs._planeVec[0] ) &&
00418 (_planeVec[1] == rhs._planeVec[1] ) &&
00419 (_planeVec[2] == rhs._planeVec[2] ) &&
00420 (_planeVec[3] == rhs._planeVec[3] ) &&
00421 (_planeVec[4] == rhs._planeVec[4] ) &&
00422 (_planeVec[5] == rhs._planeVec[5] ));
00423 }
00424
00425 void FrustumVolume::dump( UInt32 OSG_CHECK_ARG(uiIndent),
00426 const BitVector OSG_CHECK_ARG(bvFlags )) const
00427 {
00428 #if 1
00429 fprintf(stderr,"Frustum:(%f %f %f:%f)(%f %f %f:%f)(%f %f %f:%f)"
00430 "(%f %f %f:%f)(%f %f %f:%f)(%f %f %f:%f)\n",
00431 _planeVec[0].getNormal()[0],
00432 _planeVec[0].getNormal()[1],
00433 _planeVec[0].getNormal()[2],
00434 _planeVec[0].getDistanceFromOrigin(),
00435 _planeVec[1].getNormal()[0],
00436 _planeVec[1].getNormal()[1],
00437 _planeVec[1].getNormal()[2],
00438 _planeVec[1].getDistanceFromOrigin(),
00439 _planeVec[2].getNormal()[0],
00440 _planeVec[2].getNormal()[1],
00441 _planeVec[2].getNormal()[2],
00442 _planeVec[2].getDistanceFromOrigin(),
00443 _planeVec[3].getNormal()[0],
00444 _planeVec[3].getNormal()[1],
00445 _planeVec[3].getNormal()[2],
00446 _planeVec[3].getDistanceFromOrigin(),
00447 _planeVec[4].getNormal()[0],
00448 _planeVec[4].getNormal()[1],
00449 _planeVec[4].getNormal()[2],
00450 _planeVec[4].getDistanceFromOrigin(),
00451 _planeVec[5].getNormal()[0],
00452 _planeVec[5].getNormal()[1],
00453 _planeVec[5].getNormal()[2],
00454 _planeVec[5].getDistanceFromOrigin() );
00455
00456
00457 #else
00458 print(PLOG);
00459 #endif
00460 }
00461
00462 void FrustumVolume::print(std::ostream &os) const
00463 {
00464 os << "Frustum ("
00465 << _planeVec[0].getNormal() << ":"
00466 << _planeVec[0].getDistanceFromOrigin() << "|"
00467 << _planeVec[1].getNormal() << ":"
00468 << _planeVec[1].getDistanceFromOrigin() << "|"
00469 << _planeVec[2].getNormal() << ":"
00470 << _planeVec[2].getDistanceFromOrigin() << "|"
00471 << _planeVec[3].getNormal() << ":"
00472 << _planeVec[3].getDistanceFromOrigin() << "|"
00473 << _planeVec[4].getNormal() << ":"
00474 << _planeVec[4].getDistanceFromOrigin() << "|"
00475 << _planeVec[5].getNormal() << ":"
00476 << _planeVec[5].getDistanceFromOrigin()
00477 << ") ";
00478 printState(os);
00479 }
00480
00481
00492 OSG_BASE_DLLMAPPING
00493 bool intersect(const OSG::FrustumVolume &frustum,
00494 const OSG::Volume &vol,
00495 OSG::FrustumVolume::PlaneSet &inplanes)
00496 {
00497
00498
00499
00500 if(vol.isEmpty() == true)
00501 {
00502 return false;
00503 }
00504 else if(vol.isInfinite() == true)
00505 {
00506 return true;
00507 }
00508 else
00509 {
00510 Pnt3r min, max;
00511
00512 vol.getBounds(min, max);
00513
00514 const Plane *frust = frustum.getPlanes();
00515 FrustumVolume::PlaneSet mask = 0x1;
00516
00517
00518
00519
00520 for(Int32 i = 0; i < 6; i++, mask <<= 1)
00521 {
00522 if((inplanes & mask) != 0)
00523 continue;
00524
00525 if(frust[i].isOutHalfSpace(min, max))
00526 return false;
00527
00528 if(frust[i].isInHalfSpace(min, max))
00529 inplanes |= mask;
00530 }
00531 }
00532
00533 return true;
00534 }
00535
00536 OSG_END_NAMESPACE