staroctree.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:7k
源码类别:

OpenGL

开发平台:

Visual C++

  1. //
  2. // C++ Implementation: staroctree
  3. //
  4. // Description:
  5. //
  6. //
  7. // Author: Toti <root@totibox>, (C) 2005
  8. //
  9. // Copyright: See COPYING file that comes with this distribution
  10. //
  11. //
  12. #include <celengine/staroctree.h>
  13. // Maximum permitted orbital radius for stars, in light years. Orbital
  14. // radii larger than this value are not guaranteed to give correct
  15. // results. The problem case is extremely faint stars (such as brown
  16. // dwarfs.) The distance from the viewer to star's barycenter is used
  17. // rough estimate of the brightness for the purpose of culling. When the
  18. // star is very faint, this estimate may not work when the star is
  19. // far from the barycenter. Thus, the star octree traversal will always
  20. // render stars with orbits that are closer than MAX_STAR_ORBIT_RADIUS.
  21. static const float MAX_STAR_ORBIT_RADIUS = 1.0f;
  22. // The octree node into which a star is placed is dependent on two properties:
  23. // its obsPosition and its luminosity--the fainter the star, the deeper the node
  24. // in which it will reside.  Each node stores an absolute magnitude; no child
  25. // of the node is allowed contain a star brighter than this value, making it
  26. // possible to determine quickly whether or not to cull subtrees.
  27. bool starAbsoluteMagnitudePredicate(const Star& star, const float absMag)
  28. {
  29.     return star.getAbsoluteMagnitude() <= absMag;
  30. }
  31. bool starOrbitStraddlesNodesPredicate(const Point3f& cellCenterPos, const Star& star, const float)
  32. {
  33.     //checks if this star's orbit straddles child nodes
  34.     float orbitalRadius    = star.getOrbitalRadius();
  35.     if (orbitalRadius == 0.0f)
  36.         return false;
  37.     Point3f starPos    = star.getPosition();
  38.     return  abs(starPos.x - cellCenterPos.x) < orbitalRadius    ||
  39.             abs(starPos.y - cellCenterPos.y) < orbitalRadius    ||
  40.             abs(starPos.z - cellCenterPos.z) < orbitalRadius;
  41. }
  42. float starAbsoluteMagnitudeDecayFunction(const float excludingFactor)
  43. {
  44.     return astro::lumToAbsMag(astro::absMagToLum(excludingFactor) / 4.0f);
  45. }
  46. template<>
  47. DynamicStarOctree* DynamicStarOctree::getChild(const Star&          obj,
  48.                                                const Point3f& cellCenterPos)
  49. {
  50.     Point3f objPos    = obj.getPosition();
  51.     int child = 0;
  52.     child     |= objPos.x < cellCenterPos.x ? 0 : XPos;
  53.     child     |= objPos.y < cellCenterPos.y ? 0 : YPos;
  54.     child     |= objPos.z < cellCenterPos.z ? 0 : ZPos;
  55.     return _children[child];
  56. }
  57. // In testing, changing SPLIT_THRESHOLD from 100 to 50 nearly
  58. // doubled the number of nodes in the tree, but provided only between a
  59. // 0 to 5 percent frame rate improvement.
  60. template<> unsigned int DynamicStarOctree::SPLIT_THRESHOLD = 75;
  61. template<> DynamicStarOctree::LimitingFactorPredicate*
  62.            DynamicStarOctree::limitingFactorPredicate = starAbsoluteMagnitudePredicate;
  63. template<> DynamicStarOctree::StraddlingPredicate*
  64.            DynamicStarOctree::straddlingPredicate = starOrbitStraddlesNodesPredicate;
  65. template<> DynamicStarOctree::ExclusionFactorDecayFunction*
  66.            DynamicStarOctree::decayFunction = starAbsoluteMagnitudeDecayFunction;
  67. // total specialization of the StaticOctree template process*() methods for stars:
  68. template<>
  69. void StarOctree::processVisibleObjects(StarHandler&   processor,
  70.                                        const Point3f& obsPosition,
  71.                                        const Planef*  frustumPlanes,
  72.                                        float          limitingFactor,
  73.                                        float          scale) const
  74. {
  75.     // See if this node lies within the view frustum
  76.         // Test the cubic octree node against each one of the five
  77.         // planes that define the infinite view frustum.
  78.         for (int i=0; i<5; ++i)
  79.         {
  80.             const Planef* plane = frustumPlanes + i;
  81.                   float   r     = scale * (abs(plane->normal.x) +
  82.                                            abs(plane->normal.y) +
  83.                                            abs(plane->normal.z));
  84.             if (plane->normal * Vec3f(cellCenterPos.x, cellCenterPos.y, cellCenterPos.z) - plane->d < -r)
  85.                 return;
  86.         }
  87.     // Compute the distance to node; this is equal to the distance to
  88.     // the cellCenterPos of the node minus the boundingRadius of the node, scale * SQRT3.
  89.     float minDistance = (obsPosition - cellCenterPos).length() - scale * StarOctree::SQRT3;
  90.     // Process the objects in this node
  91.     float dimmest     = minDistance > 0 ? astro::appToAbsMag(limitingFactor, minDistance) : 1000;
  92.     for (unsigned int i=0; i<nObjects; ++i)
  93.     {
  94.         Star& obj = _firstObject[i];
  95.         if (obj.getAbsoluteMagnitude() < dimmest)
  96.         {
  97.             float distance    = obsPosition.distanceTo(obj.getPosition());
  98.             float appMag      = astro::absToAppMag(obj.getAbsoluteMagnitude(), distance);
  99.             
  100.             if (appMag < limitingFactor || (distance < MAX_STAR_ORBIT_RADIUS && obj.getOrbit()))
  101.                 processor.process(obj, distance, appMag);
  102.         }
  103.     }
  104.     // See if any of the objects in child nodes are potentially included
  105.     // that we need to recurse deeper.
  106.     if (minDistance <= 0 || astro::absToAppMag(exclusionFactor, minDistance) <= limitingFactor)
  107.     {
  108.         // Recurse into the child nodes
  109.         if (_children != NULL)
  110.         {
  111.             for (int i=0; i<8; ++i)
  112.             {
  113.                 _children[i]->processVisibleObjects(processor,
  114.                                                     obsPosition,
  115.                                                     frustumPlanes,
  116.                                                     limitingFactor,
  117.                                                     scale * 0.5f);
  118.             }
  119.         }
  120.     }
  121. }
  122. template<>
  123. void StarOctree::processCloseObjects(StarHandler&   processor,
  124.                                      const Point3f& obsPosition,
  125.                                      float          boundingRadius,
  126.                                      float          scale) const
  127. {
  128.     // Compute the distance to node; this is equal to the distance to
  129.     // the cellCenterPos of the node minus the boundingRadius of the node, scale * SQRT3.
  130.     float nodeDistance    = (obsPosition - cellCenterPos).length() - scale * StarOctree::SQRT3;
  131.     if (nodeDistance > boundingRadius)
  132.         return;
  133.     // At this point, we've determined that the cellCenterPos of the node is
  134.     // close enough that we must check individual objects for proximity.
  135.     // Compute distance squared to avoid having to sqrt for distance
  136.     // comparison.
  137.     float radiusSquared    = boundingRadius * boundingRadius;
  138.     // Check all the objects in the node.
  139.     for (unsigned int i = 0; i < nObjects; ++i)
  140.     {
  141.         Star& obj = _firstObject[i];
  142.         if (obsPosition.distanceToSquared(obj.getPosition()) < radiusSquared)
  143.         {
  144.             float distance    = obsPosition.distanceTo(obj.getPosition());
  145.             float appMag      = astro::absToAppMag(obj.getAbsoluteMagnitude(), distance);
  146.             processor.process(obj, distance, appMag);
  147.         }
  148.     }
  149.     // Recurse into the child nodes
  150.     if (_children != NULL)
  151.     {
  152.         for (int i = 0; i < 8; ++i)
  153.         {
  154.             _children[i]->processCloseObjects(processor,
  155.                                               obsPosition,
  156.                                               boundingRadius,
  157.                                               scale * 0.5f);
  158.         }
  159.     }
  160. }