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

staroctree.cpp

Go to the documentation of this file.
00001 //
00002 // C++ Implementation: staroctree
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/staroctree.h>
00014 
00015 
00016 // The octree node into which a star is placed is dependent on two properties:
00017 // its obsPosition and its luminosity--the fainter the star, the deeper the node
00018 // in which it will reside.  Each node stores an absolute magnitude; no child
00019 // of the node is allowed contain a star brighter than this value, making it
00020 // possible to determine quickly whether or not to cull subtrees.
00021 
00022 bool starAbsoluteMagnitudePredicate(const Star& star, const float absMag)
00023 {
00024     return star.getAbsoluteMagnitude() <= absMag;
00025 }
00026 
00027 
00028 bool starOrbitStraddlesNodesPredicate(const Point3f& cellCenterPos, const Star& star, const float absMag)
00029 {
00030     //checks if this star's orbit straddles child nodes
00031     float orbitalRadius    = star.getOrbitalRadius();
00032     if (orbitalRadius == 0.0f)
00033         return false;
00034 
00035     Point3f starPos    = star.getPosition();
00036 
00037     return  abs(starPos.x - cellCenterPos.x) < orbitalRadius    ||
00038              abs(starPos.y - cellCenterPos.y) < orbitalRadius    ||
00039             abs(starPos.z - cellCenterPos.z) < orbitalRadius;
00040 }
00041 
00042 
00043 float starAbsoluteMagnitudeDecayFunction(const float excludingFactor)
00044 {
00045     return astro::lumToAbsMag(astro::absMagToLum(excludingFactor) / 4.0f);
00046 }
00047 
00048 
00049 template<>
00050 DynamicStarOctree* DynamicStarOctree::getChild(const Star&          obj,
00051                                                const Point3f& cellCenterPos)
00052 {
00053     Point3f objPos    = obj.getPosition();
00054 
00055     int child = 0;
00056     child     |= objPos.x < cellCenterPos.x ? 0 : XPos;
00057     child     |= objPos.y < cellCenterPos.y ? 0 : YPos;
00058     child     |= objPos.z < cellCenterPos.z ? 0 : ZPos;
00059 
00060     return _children[child];
00061 }
00062 
00063 
00064 // In testing, changing SPLIT_THRESHOLD from 100 to 50 nearly
00065 // doubled the number of nodes in the tree, but provided only between a
00066 // 0 to 5 percent frame rate improvement.
00067 template<> unsigned int DynamicStarOctree::SPLIT_THRESHOLD = 75;
00068 template<> DynamicStarOctree::LimitingFactorPredicate*
00069            DynamicStarOctree::limitingFactorPredicate = starAbsoluteMagnitudePredicate;
00070 template<> DynamicStarOctree::StraddlingPredicate*
00071            DynamicStarOctree::straddlingPredicate = starOrbitStraddlesNodesPredicate;
00072 template<> DynamicStarOctree::ExclusionFactorDecayFunction*
00073            DynamicStarOctree::decayFunction = starAbsoluteMagnitudeDecayFunction;
00074 
00075 
00076 // total specialization of the StaticOctree template process*() methods for stars:
00077 template<>
00078 void StarOctree::processVisibleObjects(StarHandler&   processor,
00079                                        const Point3f& obsPosition,
00080                                        const Planef*  frustumPlanes,
00081                                        float          limitingFactor,
00082                                        float          scale) const
00083 {
00084     // See if this node lies within the view frustum
00085 
00086         // Test the cubic octree node against each one of the five
00087         // planes that define the infinite view frustum.
00088         for (int i=0; i<5; ++i)
00089         {
00090             const Planef* plane = frustumPlanes + i;
00091                   float   r     = scale * (abs(plane->normal.x) +
00092                                            abs(plane->normal.y) +
00093                                            abs(plane->normal.z));
00094 
00095             if (plane->normal * Vec3f(cellCenterPos.x, cellCenterPos.y, cellCenterPos.z) - plane->d < -r)
00096                 return;
00097         }
00098 
00099     // Compute the distance to node; this is equal to the distance to
00100     // the cellCenterPos of the node minus the boundingRadius of the node, scale * SQRT3.
00101     float minDistance = (obsPosition - cellCenterPos).length() - scale * StarOctree::SQRT3;
00102 
00103     // Process the objects in this node
00104     float dimmest     = minDistance > 0 ? astro::appToAbsMag(limitingFactor, minDistance) : 1000;
00105 
00106     for (unsigned int i=0; i<nObjects; ++i)
00107     {
00108         Star& obj = _firstObject[i];
00109 
00110         if (obj.getAbsoluteMagnitude() < dimmest)
00111         {
00112             float distance    = obsPosition.distanceTo(obj.getPosition());
00113             float appMag      = astro::absToAppMag(obj.getAbsoluteMagnitude(), distance);
00114 
00115             if (appMag < limitingFactor)
00116                 processor.process(obj, distance, appMag);
00117         }
00118     }
00119 
00120     // See if any of the objects in child nodes are potentially included
00121     // that we need to recurse deeper.
00122     if (minDistance <= 0 || astro::absToAppMag(exclusionFactor, minDistance) <= limitingFactor)
00123         // Recurse into the child nodes
00124         if (_children != NULL)
00125             for (int i=0; i<8; ++i)
00126             {
00127                 _children[i]->processVisibleObjects(processor,
00128                                                     obsPosition,
00129                                                     frustumPlanes,
00130                                                     limitingFactor,
00131                                                     scale * 0.5f);
00132             }
00133 }
00134 
00135 
00136 template<>
00137 void StarOctree::processCloseObjects(StarHandler&   processor,
00138                                      const Point3f& obsPosition,
00139                                      float          boundingRadius,
00140                                      float          scale) const
00141 {
00142     // Compute the distance to node; this is equal to the distance to
00143     // the cellCenterPos of the node minus the boundingRadius of the node, scale * SQRT3.
00144     float nodeDistance    = (obsPosition - cellCenterPos).length() - scale * StarOctree::SQRT3;
00145 
00146     if (nodeDistance > boundingRadius)
00147         return;
00148 
00149     // At this point, we've determined that the cellCenterPos of the node is
00150     // close enough that we must check individual objects for proximity.
00151 
00152     // Compute distance squared to avoid having to sqrt for distance
00153     // comparison.
00154     float radiusSquared    = boundingRadius * boundingRadius;
00155 
00156     // Check all the objects in the node.
00157     for (unsigned int i = 0; i < nObjects; ++i)
00158     {
00159         Star& obj = _firstObject[i];
00160 
00161         if (obsPosition.distanceToSquared(obj.getPosition()) < radiusSquared)
00162         {
00163             float distance    = obsPosition.distanceTo(obj.getPosition());
00164             float appMag      = astro::absToAppMag(obj.getAbsoluteMagnitude(), distance);
00165 
00166             processor.process(obj, distance, appMag);
00167         }
00168     }
00169 
00170     // Recurse into the child nodes
00171     if (_children != NULL)
00172     {
00173         for (int i = 0; i < 8; ++i)
00174         {
00175             _children[i]->processCloseObjects(processor,
00176                                               obsPosition,
00177                                               boundingRadius,
00178                                               scale * 0.5f);
00179         }
00180     }
00181 }

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