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

OpenGL

开发平台:

Visual C++

  1. //
  2. // C++ Implementation: dsooctree
  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/dsooctree.h>
  13. // The octree node into which a dso is placed is dependent on two properties:
  14. // its obsPosition and its luminosity--the fainter the dso, the deeper the node
  15. // in which it will reside.  Each node stores an absolute magnitude; no child
  16. // of the node is allowed contain a dso brighter than this value, making it
  17. // possible to determine quickly whether or not to cull subtrees.
  18. bool dsoAbsoluteMagnitudePredicate(DeepSkyObject* const & _dso, const float absMag)
  19. {
  20.     return _dso->getAbsoluteMagnitude() <= absMag;
  21. }
  22. bool dsoStraddlesNodesPredicate(const Point3d& cellCenterPos, DeepSkyObject* const & _dso, const float)
  23. {
  24.     //checks if this dso's radius straddles child nodes
  25.     float dsoRadius    = _dso->getBoundingSphereRadius();
  26.     Point3d dsoPos     = _dso->getPosition();
  27.     return abs(dsoPos.x - cellCenterPos.x) < dsoRadius    ||
  28.            abs(dsoPos.y - cellCenterPos.y) < dsoRadius    ||
  29.            abs(dsoPos.z - cellCenterPos.z) < dsoRadius;
  30. }
  31. double dsoAbsoluteMagnitudeDecayFunction(const double excludingFactor)
  32. {
  33.     return excludingFactor + 0.5f;
  34. }
  35. template <>
  36. DynamicDSOOctree* DynamicDSOOctree::getChild(DeepSkyObject* const & _obj, const Point3d& cellCenterPos)
  37. {
  38.     Point3d objPos    = _obj->getPosition();
  39.     int child = 0;
  40.     child     |= objPos.x < cellCenterPos.x ? 0 : XPos;
  41.     child     |= objPos.y < cellCenterPos.y ? 0 : YPos;
  42.     child     |= objPos.z < cellCenterPos.z ? 0 : ZPos;
  43.     return _children[child];
  44. }
  45. template<> unsigned int DynamicDSOOctree::SPLIT_THRESHOLD = 10;
  46. template<> DynamicDSOOctree::LimitingFactorPredicate*
  47.            DynamicDSOOctree::limitingFactorPredicate = dsoAbsoluteMagnitudePredicate;
  48. template<> DynamicDSOOctree::StraddlingPredicate*
  49.            DynamicDSOOctree::straddlingPredicate = dsoStraddlesNodesPredicate;
  50. template<> DynamicDSOOctree::ExclusionFactorDecayFunction*
  51.            DynamicDSOOctree::decayFunction = dsoAbsoluteMagnitudeDecayFunction;
  52. // total specialization of the StaticOctree template process*() methods for DSOs:
  53. template<>
  54. void DSOOctree::processVisibleObjects(DSOHandler&    processor,
  55.                                       const Point3d& obsPosition,
  56.                                       const Planed*  frustumPlanes,
  57.                                       float          limitingFactor,
  58.                                       double         scale) const
  59. {
  60.     // See if this node lies within the view frustum
  61.     // Test the cubic octree node against each one of the five
  62.     // planes that define the infinite view frustum.
  63.     for (int i = 0; i < 5; ++i)
  64.     {
  65.         const Planed* plane = frustumPlanes + i;
  66.         double  r     = scale * (abs(plane->normal.x) +
  67.                                  abs(plane->normal.y) +
  68.                                  abs(plane->normal.z));
  69.         if (plane->normal * Vec3d(cellCenterPos.x, cellCenterPos.y, cellCenterPos.z) - plane->d < -r)
  70.             return;
  71.     }
  72.     // Compute the distance to node; this is equal to the distance to
  73.     // the cellCenterPos of the node minus the boundingRadius of the node, scale * SQRT3.
  74.     double minDistance = (obsPosition - cellCenterPos).length() - scale * DSOOctree::SQRT3;
  75.     // Process the objects in this node
  76.     double dimmest     = minDistance > 0.0 ? astro::appToAbsMag((double) limitingFactor, minDistance) : 1000.0;
  77.     for (unsigned int i=0; i<nObjects; ++i)
  78.     {
  79.         DeepSkyObject* _obj = _firstObject[i];
  80.         float  absMag      = _obj->getAbsoluteMagnitude();
  81.         if (absMag < dimmest)
  82.         {
  83.             double distance    = obsPosition.distanceTo(_obj->getPosition()) - _obj->getBoundingSphereRadius();
  84.             float appMag = (float) ((distance >= 32.6167) ? astro::absToAppMag((double) absMag, distance) : absMag);
  85.             if ( appMag < limitingFactor)
  86.                 processor.process(_obj, distance, absMag);
  87.         }
  88.     }
  89.     // See if any of the objects in child nodes are potentially included
  90.     // that we need to recurse deeper.
  91.     if (minDistance <= 0.0 || astro::absToAppMag((double) exclusionFactor, minDistance) <= limitingFactor)
  92.         // Recurse into the child nodes
  93.         if (_children != NULL)
  94.             for (int i=0; i<8; ++i)
  95.             {
  96.                 _children[i]->processVisibleObjects(processor,
  97.                                                     obsPosition,
  98.                                                     frustumPlanes,
  99.                                                     limitingFactor,
  100.                                                     scale * 0.5f);
  101.             }
  102. }
  103. template<>
  104. void DSOOctree::processCloseObjects(DSOHandler&    processor,
  105.                                     const Point3d& obsPosition,
  106.                                     double         boundingRadius,
  107.                                     double         scale) const
  108. {
  109.     // Compute the distance to node; this is equal to the distance to
  110.     // the cellCenterPos of the node minus the boundingRadius of the node, scale * SQRT3.
  111.     double nodeDistance    = (obsPosition - cellCenterPos).length() - scale * DSOOctree::SQRT3;    //
  112.     if (nodeDistance > boundingRadius)
  113.         return;
  114.     // At this point, we've determined that the cellCenterPos of the node is
  115.     // close enough that we must check individual objects for proximity.
  116.     // Compute distance squared to avoid having to sqrt for distance
  117.     // comparison.
  118.     double radiusSquared    = boundingRadius * boundingRadius;    //
  119.     // Check all the objects in the node.
  120.     for (unsigned int i=0; i<nObjects; ++i)
  121.     {
  122.         DeepSkyObject* _obj = _firstObject[i];        //
  123.         if (obsPosition.distanceToSquared(_obj->getPosition()) < radiusSquared)    //
  124.         {
  125.             float  absMag      = _obj->getAbsoluteMagnitude();
  126.             double distance    = obsPosition.distanceTo(_obj->getPosition()) - _obj->getBoundingSphereRadius();
  127.             processor.process(_obj, distance, absMag);
  128.         }
  129.     }
  130.     // Recurse into the child nodes
  131.     if (_children != NULL)
  132.     {
  133.         for (int i = 0; i < 8; ++i)
  134.         {
  135.             _children[i]->processCloseObjects(processor,
  136.                                               obsPosition,
  137.                                               boundingRadius,
  138.                                               scale * 0.5f);
  139.         }
  140.     }
  141. }