AI_SDB_PlaneClipper.h

Go to the documentation of this file.
00001 #ifndef AI_SDB_PLANECLIPPER_H
00002 #define AI_SDB_PLANECLIPPER_H
00003 
00045 #include "../math/AI_Plane.h"
00046 #include "../math/AI_Sphere.h"
00047 #include "../math/AI_BBox.h"
00048 
00049 // this is currently limited to leave some bitflags available in the AI_SDB_VisitorFlags struct
00050 // NOTE: keep this up-to-date, so visitors can add flags on the higher bits
00051 #define AI_SDB_PLANECLIPPER_MAXPLANES 16
00052 
00053 class AI_SDB_PlaneClipper {
00054 public:
00056     AI_SDB_PlaneClipper();
00058     AI_SDB_PlaneClipper(const AI_SDB_PlaneClipper &copyme);
00060     AI_SDB_PlaneClipper(const AI_Plane *clipplanes, int numplanes);
00061 
00067     AI_SDB_VisitorFlags TestBBox(const AI_BBox &boxtest, AI_SDB_VisitorFlags in);
00068 
00074     AI_SDB_VisitorFlags TestSphere(const AI_Sphere &spheretest, AI_SDB_VisitorFlags in);
00075 
00078     AI_SDB_VisitorFlags TestPoint(const AI_Vector3 &pointtest, AI_SDB_VisitorFlags in);
00079 
00080 protected:
00081     AI_Plane m_planes[AI_SDB_PLANECLIPPER_MAXPLANES];
00082     int m_numplanes;
00083 };
00084 
00085 inline
00086 AI_SDB_PlaneClipper::AI_SDB_PlaneClipper()
00087 {
00088 }
00089 
00090 inline
00091 AI_SDB_PlaneClipper::AI_SDB_PlaneClipper(const AI_SDB_PlaneClipper &copyme)
00092 {
00093     m_numplanes = copyme.m_numplanes;
00094 
00095     for (int i=0; i < copyme.m_numplanes; i++)
00096         m_planes[i] = copyme.m_planes[i];
00097 }
00098 
00099 
00100 inline
00101 AI_SDB_PlaneClipper::AI_SDB_PlaneClipper(const AI_Plane *clipplanes, int numplanes)
00102 : m_numplanes(numplanes)
00103 {
00104     // initialize from user-supplied planes
00105     for (int i=0; i < numplanes; i++)
00106     {
00107         m_planes[i] = clipplanes[i];
00108     }
00109 }
00110 
00111 inline
00112 AI_SDB_VisitorFlags AI_SDB_PlaneClipper::TestBBox(const AI_BBox &boxtest, AI_SDB_VisitorFlags in)
00113 {
00114     // Returns a visibility code indicating the culling status of the
00115     // given axis-aligned box.  The result_info passed in should indicate
00116     // which planes might cull the box, by setting the corresponding
00117     // bit in in.active_planes.
00118     AI_Vector3 center = boxtest.center();
00119     AI_Vector3 extent = boxtest.extents();
00120 
00121     // Check the box against each active frustum AI_Plane.
00122     int bit = 1;
00123     int allplanebits( (1<<m_numplanes) - 1 );
00124     for (int i = 0; i < m_numplanes; i++, bit <<= 1)
00125     {
00126         // do the test only if the specified AI_Plane is active
00127         if ((bit & in.m_activeflags) != 0)
00128         {
00129             const AI_Plane&    p       = m_planes[i];
00130             const AI_Vector3 normal    = p.normal();
00131             
00132             // Check box against this AI_Plane.
00133             float   d = normal % center + p.d; //Calculate closest distance from center point to AI_Plane.
00134             float   extent_toward_plane = ai_abs(extent.x * normal.x)
00135                 + ai_abs(extent.y * normal.y)
00136                 + ai_abs(extent.z * normal.z);
00137             if (d < 0)
00138             {  
00139                 if (-d > extent_toward_plane)
00140                 {
00141                     // Box is definitively on the negative side of the AI_Plane, so it's culled
00142                     return AI_SDB_VisitorFlags(false,true);
00143                 } // else this AI_Plane is ambiguous so leave it active.
00144             } else {
00145                 if (d > extent_toward_plane)
00146                 {
00147                     // Box is accepted by this AI_Plane, so
00148                     // deactivate it, since neither this
00149                     // box or any contained part of it can
00150                     // ever be culled by this AI_Plane.
00151                     in.m_activeflags &= ~bit;
00152                     if ( (in.m_activeflags & allplanebits) == 0)
00153                     {
00154                         // This box is definitively inside all the culling
00155                         // planes, so there's no need to continue.
00156                         return AI_SDB_VisitorFlags(true,false);
00157                     }
00158                 } // else this AI_Plane is ambigious so leave it active.
00159             }
00160         }
00161     }
00162 
00163     return in;  // Box not definitively culled.  Return updated active AI_Plane flags.
00164 }
00165 
00166 inline
00167 AI_SDB_VisitorFlags AI_SDB_PlaneClipper::TestSphere(const AI_Sphere &spheretest, AI_SDB_VisitorFlags ri)
00168 {
00169     // build a bbox from the AI_Sphere and test that
00170     AI_BBox mybbox(spheretest.p, AI_Vector3(spheretest.r, spheretest.r, spheretest.r));
00171     return TestBBox(mybbox, ri);
00172 }
00173 
00174 inline
00175 AI_SDB_VisitorFlags AI_SDB_PlaneClipper::TestPoint(const AI_Vector3 &pointtest, AI_SDB_VisitorFlags ri)
00176 {
00177     // build a bbox from the point and test that
00178     AI_BBox mybbox(pointtest, AI_Vector3(0,0,0));
00179     return TestBBox(mybbox, ri);
00180 }
00181 
00182 #endif