Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

dsooctree.cpp

Go to the documentation of this file.
00001 //
00002 // C++ Implementation: dsooctree
00003 //
00004 // Description:
00005 //
00006 //
00007 // Author: Toti <root@totibox>, (C) 2005
00008 //
00009 // Copyright: See COPYING file that comes with this distribution
00010 //
00011 //
00012 
00013 #include <celengine/dsooctree.h>
00014 
00015 // The octree node into which a dso is placed is dependent on two properties:
00016 // its obsPosition and its luminosity--the fainter the dso, the deeper the node
00017 // in which it will reside.  Each node stores an absolute magnitude; no child
00018 // of the node is allowed contain a dso brighter than this value, making it
00019 // possible to determine quickly whether or not to cull subtrees.
00020 
00021 bool dsoAbsoluteMagnitudePredicate(DeepSkyObject* const & _dso, const float absMag)
00022 {
00023     return _dso->getAbsoluteMagnitude() <= absMag;
00024 }
00025 
00026 
00027 bool dsoStraddlesNodesPredicate(const Point3d& cellCenterPos, DeepSkyObject* const & _dso, const float absMag)
00028 {
00029     //checks if this dso's radius straddles child nodes
00030     float dsoRadius    = _dso->getRadius();
00031 
00032     Point3d dsoPos     = _dso->getPosition();
00033 
00034     return abs(dsoPos.x - cellCenterPos.x) < dsoRadius    ||
00035              abs(dsoPos.y - cellCenterPos.y) < dsoRadius    ||
00036            abs(dsoPos.z - cellCenterPos.z) < dsoRadius;
00037 }
00038 
00039 
00040 double dsoAbsoluteMagnitudeDecayFunction(const double excludingFactor)
00041 {
00042     return excludingFactor + 0.5f;
00043 }
00044 
00045 
00046 template <>
00047 DynamicDSOOctree* DynamicDSOOctree::getChild(DeepSkyObject* const & _obj, const Point3d& cellCenterPos)
00048 {
00049     Point3d objPos    = _obj->getPosition();
00050 
00051     int child = 0;
00052     child     |= objPos.x < cellCenterPos.x ? 0 : XPos;
00053     child     |= objPos.y < cellCenterPos.y ? 0 : YPos;
00054     child     |= objPos.z < cellCenterPos.z ? 0 : ZPos;
00055 
00056     return _children[child];
00057 }
00058 
00059 
00060 template<> unsigned int DynamicDSOOctree::SPLIT_THRESHOLD = 10;
00061 template<> DynamicDSOOctree::LimitingFactorPredicate*
00062            DynamicDSOOctree::limitingFactorPredicate = dsoAbsoluteMagnitudePredicate;
00063 template<> DynamicDSOOctree::StraddlingPredicate*
00064            DynamicDSOOctree::straddlingPredicate = dsoStraddlesNodesPredicate;
00065 template<> DynamicDSOOctree::ExclusionFactorDecayFunction*
00066            DynamicDSOOctree::decayFunction = dsoAbsoluteMagnitudeDecayFunction;
00067 
00068 
00069 // total specialization of the StaticOctree template process*() methods for DSOs:
00070 template<>
00071 void DSOOctree::processVisibleObjects(DSOHandler&    processor,
00072                                       const Point3d& obsPosition,
00073                                       const Planef*  frustumPlanes,
00074                                       float          limitingFactor,
00075                                       double         scale) const
00076 {
00077     // See if this node lies within the view frustum
00078 
00079         // Test the cubic octree node against each one of the five
00080         // planes that define the infinite view frustum.
00081         for (int i=0; i<5; ++i)
00082         {
00083             const Planef* plane = frustumPlanes + i;
00084                   double  r     = scale * (abs(plane->normal.x) +
00085                                            abs(plane->normal.y) +
00086                                            abs(plane->normal.z));
00087 
00088             Vec3d vecDbl((double) plane->normal.x, (double) plane->normal.y, (double) plane->normal.z);
00089 
00090             if (vecDbl * Vec3d(cellCenterPos.x, cellCenterPos.y, cellCenterPos.z) - plane->d < -r)
00091                 return;
00092         }
00093 
00094     // Compute the distance to node; this is equal to the distance to
00095     // the cellCenterPos of the node minus the boundingRadius of the node, scale * SQRT3.
00096     double minDistance = (obsPosition - cellCenterPos).length() - scale * DSOOctree::SQRT3;
00097 
00098     // Process the objects in this node
00099     double dimmest     = minDistance > 0 ? astro::appToAbsMag(limitingFactor, minDistance) : 1000;
00100 
00101     for (unsigned int i=0; i<nObjects; ++i)
00102     {
00103         DeepSkyObject* _obj = _firstObject[i];
00104         float  absMag      = _obj->getAbsoluteMagnitude();
00105         if ( absMag < dimmest)
00106         {
00107             double distance    = obsPosition.distanceTo(_obj->getPosition()) - _obj->getRadius();
00108             float appMag = (distance >= 32.6167)? astro::absToAppMag(absMag, distance): absMag;
00109 
00110             if ( appMag < limitingFactor)
00111                 processor.process(_obj, distance, absMag);
00112         }
00113     }
00114 
00115     // See if any of the objects in child nodes are potentially included
00116     // that we need to recurse deeper.
00117     if (minDistance <= 0 || astro::absToAppMag(exclusionFactor, minDistance) <= limitingFactor)
00118         // Recurse into the child nodes
00119         if (_children != NULL)
00120             for (int i=0; i<8; ++i)
00121             {
00122                 _children[i]->processVisibleObjects(processor,
00123                                                     obsPosition,
00124                                                     frustumPlanes,
00125                                                     limitingFactor,
00126                                                     scale * 0.5f);
00127             }
00128 }
00129 
00130 
00131 template<>
00132 void DSOOctree::processCloseObjects(DSOHandler&    processor,
00133                                     const Point3d& obsPosition,
00134                                     double         boundingRadius,
00135                                     double         scale) const
00136 {
00137     // Compute the distance to node; this is equal to the distance to
00138     // the cellCenterPos of the node minus the boundingRadius of the node, scale * SQRT3.
00139     double nodeDistance    = (obsPosition - cellCenterPos).length() - scale * DSOOctree::SQRT3;    //
00140 
00141     if (nodeDistance > boundingRadius)
00142         return;
00143 
00144     // At this point, we've determined that the cellCenterPos of the node is
00145     // close enough that we must check individual objects for proximity.
00146 
00147     // Compute distance squared to avoid having to sqrt for distance
00148     // comparison.
00149     double radiusSquared    = boundingRadius * boundingRadius;    //
00150 
00151     // Check all the objects in the node.
00152     for (unsigned int i=0; i<nObjects; ++i)
00153     {
00154         DeepSkyObject* _obj = _firstObject[i];        //
00155 
00156         if (obsPosition.distanceToSquared(_obj->getPosition()) < radiusSquared)    //
00157         {
00158             float  absMag      = _obj->getAbsoluteMagnitude();
00159             double distance    = obsPosition.distanceTo(_obj->getPosition()) - _obj->getRadius();
00160 
00161             processor.process(_obj, distance, absMag);
00162         }
00163     }
00164 
00165     // Recurse into the child nodes
00166     if (_children != NULL)
00167     {
00168         for (int i = 0; i < 8; ++i)
00169         {
00170             _children[i]->processCloseObjects(processor,
00171                                               obsPosition,
00172                                               boundingRadius,
00173                                               scale * 0.5f);
00174         }
00175     }
00176 }

Generated on Sat Jan 14 22:30:27 2006 for Celestia by  doxygen 1.4.1