AI_SDB_SphereClipper.h

Go to the documentation of this file.
00001 #ifndef AI_SDB_SPHERECLIPPER_H
00002 #define AI_SDB_SPHERECLIPPER_H
00003 
00018 #include "../math/AI_Plane.h"
00019 #include "../math/AI_Sphere.h"
00020 #include "../math/AI_BBox.h"
00021 #include "AI_SDB_VisitorBase.h"
00022 
00023 class AI_SDB_SphereClipper {
00024 public:
00025     AI_SDB_SphereClipper();
00026     AI_SDB_SphereClipper(const AI_SDB_SphereClipper &copyme);
00027     AI_SDB_SphereClipper(const AI_Vector3 &center, float radius);
00028     AI_SDB_SphereClipper(const AI_Sphere &clipsphere);
00029 
00030     AI_SDB_VisitorFlags TestBBox(const AI_BBox &boxtest, AI_SDB_VisitorFlags in);
00031     AI_SDB_VisitorFlags TestSphere(const AI_Sphere &spheretest, AI_SDB_VisitorFlags in);
00032     AI_SDB_VisitorFlags TestPoint(const AI_Vector3 &pointtest, AI_SDB_VisitorFlags in);
00033 
00034 protected:
00035     AI_Sphere m_sphere;
00036 };
00037 
00038 inline
00039 AI_SDB_SphereClipper::AI_SDB_SphereClipper() : m_sphere(0,0,0,0)
00040 {
00041 }
00042 
00043 inline
00044 AI_SDB_SphereClipper::AI_SDB_SphereClipper(const AI_SDB_SphereClipper &copyme)
00045 {
00046     m_sphere = copyme.m_sphere;
00047 }
00048 
00049 
00050 inline
00051 AI_SDB_SphereClipper::AI_SDB_SphereClipper(const AI_Vector3 &center, float radius)
00052 {
00053     m_sphere = AI_Sphere(center,radius);
00054 }
00055 
00056 inline
00057 AI_SDB_SphereClipper::AI_SDB_SphereClipper(const AI_Sphere &clipsphere)
00058 {
00059     m_sphere = clipsphere;
00060 }
00061 
00062 inline
00063 AI_SDB_VisitorFlags AI_SDB_SphereClipper::TestBBox(const AI_BBox &boxtest, AI_SDB_VisitorFlags ri)
00064 {
00065     // flag already off? then we're done
00066     if ( (ri.m_activeflags & 1) == 0)
00067         return ri;
00068 
00069     // compare radius and distance
00070     // Convert to a bounding AI_Sphere and test it
00071     AI_Sphere virtsphere(boxtest.center(), boxtest.extents().len());
00072 
00073     return TestSphere(virtsphere, ri);
00074 }
00075 
00076 inline
00077 AI_SDB_VisitorFlags AI_SDB_SphereClipper::TestSphere(const AI_Sphere &spheretest, AI_SDB_VisitorFlags ri)
00078 {
00079     // flag already off? then we're done
00080     if ( (ri.m_activeflags & 1) == 0)
00081         return ri;
00082 
00083     // compare radius and distance
00084     AI_Vector3 d(m_sphere.p - spheretest.p);
00085     float rsum = m_sphere.r + spheretest.r;
00086     float dsquared = d.lensquared();
00087 
00088     // if the spheres are more distant than the sum of their two radii,
00089     // then cull it totally
00090     if (dsquared > (rsum*rsum))
00091         return AI_SDB_VisitorFlags(false);
00092 
00093     // if the test AI_Sphere is of smaller radius than the clip AI_Sphere, and
00094     // the centers are closer than the differences of the two radii, the
00095     // test AI_Sphere is completely enclosed within the clip AI_Sphere and we
00096     // should turn the active_flag off, so that children within the test
00097     // AI_Sphere don't need to be clip tested at all
00098     if (spheretest.r < m_sphere.r)
00099     {
00100         float rdiff = m_sphere.r - spheretest.r;
00101         if ( dsquared < (rdiff*rdiff) )
00102         {
00103             ri.m_activeflags &= ~1;
00104             ri.m_test = true;
00105             return ri;
00106         }
00107     }
00108 
00109     // non-conclusive test, just return the AI_SDB_VisitorFlags as-is
00110     return ri;
00111 }
00112 
00113 inline
00114 AI_SDB_VisitorFlags AI_SDB_SphereClipper::TestPoint(const AI_Vector3 &pointtest, AI_SDB_VisitorFlags ri)
00115 {
00116     // flag already off? then we're done
00117     if ( (ri.m_activeflags & 1) == 0)
00118         return ri;
00119 
00120     // compare radius and distance
00121     // build a bbox from the point and test that
00122     AI_BBox mybbox(pointtest, AI_Vector3(0,0,0));
00123     return TestBBox(mybbox, ri);
00124 }
00125 
00126 #endif
00127