frametree.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:6k
- // frametree.cpp
- //
- // Reference frame tree
- //
- // Copyright (C) 2008, the Celestia Development Team
- // Initial version by Chris Laurel, claurel@gmail.com
- //
- // This program is free software; you can redistribute it and/or
- // modify it under the terms of the GNU General Public License
- // as published by the Free Software Foundation; either version 2
- // of the License, or (at your option) any later version.
- #include <algorithm>
- #include <cassert>
- #include "celengine/frametree.h"
- #include "celengine/timeline.h"
- #include "celengine/timelinephase.h"
- #include "celengine/frame.h"
- /* A FrameTree is hierarchy of solar system bodies organized according to
- * the relationship of their reference frames. An object will appear in as
- * a child in the tree of whatever object is the center of its orbit frame.
- * Since an object may have several orbit frames in its timeline, the
- * structure is a bit more complicated than a straightforward tree
- * of Body objects. A Body has exactly a single parent in the frame tree
- * at a given time, but may have many over it's lifespan. An object's
- * timeline contains a list of timeline phases; each phase can point to
- * a different parent. Thus, the timeline can be thought of as a list of
- * parents.
- *
- * The FrameTree hiearchy is designed for fast visibility culling. There are
- * two values stored in each node for this purpose: the bounding sphere
- * radius, and the maximum child object radius. The bounding sphere is large
- * enough to contain the orbits of all child objects, as well as the child
- * objects themselves. Change tracking is performed whenever the frame tree
- * is modified: adding a node, removing a node, or changing the radius of an
- * object will all cause the tree to be marked as changed.
- */
- /*! Create a frame tree associated with a star.
- */
- FrameTree::FrameTree(Star* star) :
- starParent(star),
- bodyParent(NULL),
- defaultFrame(NULL)
- {
- // Default frame for a star is J2000 ecliptical, centered
- // on the star.
- defaultFrame = new J2000EclipticFrame(Selection(star));
- defaultFrame->addRef();
- }
- /*! Create a frame tree associated with a planet or other solar system body.
- */
- FrameTree::FrameTree(Body* body) :
- starParent(NULL),
- bodyParent(body),
- defaultFrame(NULL)
- {
- // Default frame for a solar system body is the mean equatorial frame of the body.
- defaultFrame = new BodyMeanEquatorFrame(Selection(body), Selection(body));
- defaultFrame->addRef();
- }
- FrameTree::~FrameTree()
- {
- defaultFrame->release();
- }
- /*! Return the default reference frame for the object a frame tree is associated
- * with.
- */
- ReferenceFrame*
- FrameTree::getDefaultReferenceFrame() const
- {
- return defaultFrame;
- }
- /*! Mark this node of the frame hierarchy as changed. The changed flag
- * is propagated up toward the root of the tree.
- */
- void
- FrameTree::markChanged()
- {
- if (!m_changed)
- {
- m_changed = true;
- if (bodyParent != NULL)
- bodyParent->markChanged();
- }
- }
- /*! Mark this node of the frame hierarchy as updated. The changed flag
- * is marked false in this node and in all child nodes that
- * were marked changed.
- */
- void
- FrameTree::markUpdated()
- {
- if (m_changed)
- {
- m_changed = false;
- for (vector<TimelinePhase*>::iterator iter = children.begin();
- iter != children.end(); iter++)
- {
- (*iter)->body()->markUpdated();
- }
- }
- }
- /*! Recompute the bounding sphere for this tree and all subtrees marked
- * as having changed. The bounding sphere is large enough to accommodate
- * the orbits (and radii) of all child bodies. This method also recomputes
- * the maximum child radius, secondary illuminator status, and child
- * class mask.
- */
- void
- FrameTree::recomputeBoundingSphere()
- {
- if (m_changed)
- {
- m_boundingSphereRadius = 0.0;
- m_maxChildRadius = 0.0;
- m_containsSecondaryIlluminators = false;
- m_childClassMask = 0;
- for (vector<TimelinePhase*>::iterator iter = children.begin();
- iter != children.end(); iter++)
- {
- TimelinePhase* phase = *iter;
- double bodyRadius = phase->body()->getRadius();
- double r = phase->body()->getCullingRadius() + phase->orbit()->getBoundingRadius();
- m_maxChildRadius = max(m_maxChildRadius, bodyRadius);
- m_containsSecondaryIlluminators = m_containsSecondaryIlluminators || phase->body()->isSecondaryIlluminator();
- m_childClassMask |= phase->body()->getClassification();
- FrameTree* tree = phase->body()->getFrameTree();
- if (tree != NULL)
- {
- tree->recomputeBoundingSphere();
- r += tree->m_boundingSphereRadius;
- m_maxChildRadius = max(m_maxChildRadius, tree->m_maxChildRadius);
- m_containsSecondaryIlluminators = m_containsSecondaryIlluminators || tree->containsSecondaryIlluminators();
- m_childClassMask |= tree->childClassMask();
- }
- m_boundingSphereRadius = max(m_boundingSphereRadius, r);
- }
- }
- }
- /*! Add a new phase to this tree.
- */
- void
- FrameTree::addChild(TimelinePhase* phase)
- {
- phase->addRef();
- children.push_back(phase);
- markChanged();
- }
- /*! Remove a phase from the tree. This method does nothing if the specified
- * phase doesn't exist in the tree.
- */
- void
- FrameTree::removeChild(TimelinePhase* phase)
- {
- vector<TimelinePhase*>::iterator iter = find(children.begin(), children.end(), phase);
- if (iter != children.end())
- {
- (*iter)->release();
- children.erase(iter);
- markChanged();
- }
- }
- /*! Return the child at the specified index. */
- TimelinePhase*
- FrameTree::getChild(unsigned int n) const
- {
- return children[n];
- }
- /*! Get the number of immediate children of this tree. */
- unsigned int
- FrameTree::childCount() const
- {
- return children.size();
- }