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

OpenGL

开发平台:

Visual C++

  1. // frametree.cpp
  2. //
  3. // Reference frame tree
  4. //
  5. // Copyright (C) 2008, the Celestia Development Team
  6. // Initial version by Chris Laurel, claurel@gmail.com
  7. //
  8. // This program is free software; you can redistribute it and/or
  9. // modify it under the terms of the GNU General Public License
  10. // as published by the Free Software Foundation; either version 2
  11. // of the License, or (at your option) any later version.
  12. #include <algorithm>
  13. #include <cassert>
  14. #include "celengine/frametree.h"
  15. #include "celengine/timeline.h"
  16. #include "celengine/timelinephase.h"
  17. #include "celengine/frame.h"
  18. /* A FrameTree is hierarchy of solar system bodies organized according to
  19.  * the relationship of their reference frames. An object will appear in as
  20.  * a child in the tree of whatever object is the center of its orbit frame.
  21.  * Since an object may have several orbit frames in its timeline, the
  22.  * structure is a bit more complicated than a straightforward tree
  23.  * of Body objects. A Body has exactly a single parent in the frame tree
  24.  * at a given time, but may have many over it's lifespan. An object's
  25.  * timeline contains a list of timeline phases; each phase can point to
  26.  * a different parent. Thus, the timeline can be thought of as a list of
  27.  * parents.
  28.  *
  29.  * The FrameTree hiearchy is designed for fast visibility culling. There are
  30.  * two values stored in each node for this purpose: the bounding sphere 
  31.  * radius, and the maximum child object radius. The bounding sphere is large
  32.  * enough to contain the orbits of all child objects, as well as the child
  33.  * objects themselves. Change tracking is performed whenever the frame tree
  34.  * is modified: adding a node, removing a node, or changing the radius of an
  35.  * object will all cause the tree to be marked as changed.
  36.  */
  37. /*! Create a frame tree associated with a star.
  38.  */
  39. FrameTree::FrameTree(Star* star) :
  40.     starParent(star),
  41.     bodyParent(NULL),
  42.     defaultFrame(NULL)
  43. {
  44.     // Default frame for a star is J2000 ecliptical, centered
  45.     // on the star.
  46.     defaultFrame = new J2000EclipticFrame(Selection(star));
  47.     defaultFrame->addRef();
  48. }
  49. /*! Create a frame tree associated with a planet or other solar system body.
  50.  */
  51. FrameTree::FrameTree(Body* body) :
  52.     starParent(NULL),
  53.     bodyParent(body),
  54.     defaultFrame(NULL)
  55. {
  56.     // Default frame for a solar system body is the mean equatorial frame of the body.
  57.     defaultFrame = new BodyMeanEquatorFrame(Selection(body), Selection(body));
  58.     defaultFrame->addRef();
  59. }
  60. FrameTree::~FrameTree()
  61. {
  62.     defaultFrame->release();
  63. }
  64. /*! Return the default reference frame for the object a frame tree is associated
  65.  *  with.
  66.  */
  67. ReferenceFrame*
  68. FrameTree::getDefaultReferenceFrame() const
  69. {
  70.     return defaultFrame;
  71. }
  72. /*! Mark this node of the frame hierarchy as changed. The changed flag
  73.  *  is propagated up toward the root of the tree.
  74.  */
  75. void
  76. FrameTree::markChanged()
  77. {
  78.     if (!m_changed)
  79.     {
  80.         m_changed = true;
  81.         if (bodyParent != NULL)
  82.             bodyParent->markChanged();
  83.     }
  84. }
  85. /*! Mark this node of the frame hierarchy as updated. The changed flag
  86.  *  is marked false in this node and in all child nodes that
  87.  *  were marked changed.
  88.  */
  89. void
  90. FrameTree::markUpdated()
  91. {
  92.     if (m_changed)
  93.     {
  94.         m_changed = false;
  95.         for (vector<TimelinePhase*>::iterator iter = children.begin();
  96.              iter != children.end(); iter++)
  97.         {
  98.             (*iter)->body()->markUpdated();
  99.         }
  100.     }
  101. }
  102. /*! Recompute the bounding sphere for this tree and all subtrees marked
  103.  *  as having changed. The bounding sphere is large enough to accommodate
  104.  *  the orbits (and radii) of all child bodies. This method also recomputes
  105.  *  the maximum child radius, secondary illuminator status, and child
  106.  *  class mask.
  107.  */
  108. void
  109. FrameTree::recomputeBoundingSphere()
  110. {
  111.     if (m_changed)
  112.     {
  113.         m_boundingSphereRadius = 0.0;
  114.         m_maxChildRadius = 0.0;
  115.         m_containsSecondaryIlluminators = false;
  116.         m_childClassMask = 0;
  117.         for (vector<TimelinePhase*>::iterator iter = children.begin();
  118.              iter != children.end(); iter++)
  119.         {
  120.             TimelinePhase* phase = *iter;
  121.             double bodyRadius = phase->body()->getRadius();
  122.             double r = phase->body()->getCullingRadius() + phase->orbit()->getBoundingRadius();
  123.             m_maxChildRadius = max(m_maxChildRadius, bodyRadius);
  124.             m_containsSecondaryIlluminators = m_containsSecondaryIlluminators || phase->body()->isSecondaryIlluminator();
  125.             m_childClassMask |= phase->body()->getClassification();
  126.             FrameTree* tree = phase->body()->getFrameTree();
  127.             if (tree != NULL)
  128.             {
  129.                 tree->recomputeBoundingSphere();
  130.                 r += tree->m_boundingSphereRadius;
  131.                 m_maxChildRadius = max(m_maxChildRadius, tree->m_maxChildRadius);
  132.                 m_containsSecondaryIlluminators = m_containsSecondaryIlluminators || tree->containsSecondaryIlluminators();
  133.                 m_childClassMask |= tree->childClassMask();
  134.             }
  135.             m_boundingSphereRadius = max(m_boundingSphereRadius, r);
  136.         }
  137.     }
  138. }
  139. /*! Add a new phase to this tree.
  140.  */
  141. void
  142. FrameTree::addChild(TimelinePhase* phase)
  143. {
  144.     phase->addRef();
  145.     children.push_back(phase);
  146.     markChanged();
  147. }
  148. /*! Remove a phase from the tree. This method does nothing if the specified
  149.  *  phase doesn't exist in the tree.
  150.  */
  151. void
  152. FrameTree::removeChild(TimelinePhase* phase)
  153. {
  154.     vector<TimelinePhase*>::iterator iter = find(children.begin(), children.end(), phase);
  155.     if (iter != children.end())
  156.     {
  157.         (*iter)->release();
  158.         children.erase(iter);
  159.         markChanged();
  160.     }
  161. }
  162. /*! Return the child at the specified index. */
  163. TimelinePhase*
  164. FrameTree::getChild(unsigned int n) const
  165. {
  166.     return children[n];
  167. }
  168. /*! Get the number of immediate children of this tree. */
  169. unsigned int
  170. FrameTree::childCount() const
  171. {
  172.     return children.size();
  173. }