Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

OSGFrustumVolume.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *                 Copyright (C) 2000 by the OpenSG Forum                    *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028  *                                                                           *
00029 \*---------------------------------------------------------------------------*/
00030 /*---------------------------------------------------------------------------*\
00031  *                                Changes                                    *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037  *                                                                           *
00038 \*---------------------------------------------------------------------------*/
00039 
00040 // System declarations
00041 
00042 #ifdef WIN32
00043 //#include <iosfwd>
00044 #endif
00045 
00046 //---------------------------------------------------------------------------
00047 //  Includes
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 /*-------------------------------- get ------------------------------------*/
00074 
00075 void FrustumVolume::getCenter(Pnt3f &center) 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 /*------------------------------ feature ----------------------------------*/
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   // right
00260   _planeVec[3].set(planeEquation[0]);
00261 
00262   // left
00263   _planeVec[2].set(planeEquation[1]);
00264 
00265   // bottom
00266   _planeVec[5].set(planeEquation[2]);
00267 
00268   // top
00269   _planeVec[4].set(planeEquation[3]);
00270 
00271   // near
00272   _planeVec[0].set(planeEquation[4]);
00273 
00274   // far
00275   _planeVec[1].set(planeEquation[5]);
00276 }
00277 
00278 
00279 
00280 /*-------------------------- extending ------------------------------------*/
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 /*-------------------------- intersection ---------------------------------*/
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     // check the box against the 6 planes, adjust the inplanes set
00461     // accordingly
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

Generated on Thu Aug 25 04:05:17 2005 for OpenSG by  doxygen 1.4.3