Celestia

Форк
0
/
frametree.cpp 
189 строк · 5.6 Кб
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

13
#include <algorithm>
14
#include <cassert>
15
#include "celengine/frametree.h"
16
#include "celengine/timeline.h"
17
#include "celengine/timelinephase.h"
18
#include "celengine/frame.h"
19
#include <celengine/star.h>
20
#include <celengine/location.h>
21
#include <celengine/deepskyobj.h>
22

23
/* A FrameTree is hierarchy of solar system bodies organized according to
24
 * the relationship of their reference frames. An object will appear in as
25
 * a child in the tree of whatever object is the center of its orbit frame.
26
 * Since an object may have several orbit frames in its timeline, the
27
 * structure is a bit more complicated than a straightforward tree
28
 * of Body objects. A Body has exactly a single parent in the frame tree
29
 * at a given time, but may have many over it's lifespan. An object's
30
 * timeline contains a list of timeline phases; each phase can point to
31
 * a different parent. Thus, the timeline can be thought of as a list of
32
 * parents.
33
 *
34
 * The FrameTree hiearchy is designed for fast visibility culling. There are
35
 * two values stored in each node for this purpose: the bounding sphere
36
 * radius, and the maximum child object radius. The bounding sphere is large
37
 * enough to contain the orbits of all child objects, as well as the child
38
 * objects themselves. Change tracking is performed whenever the frame tree
39
 * is modified: adding a node, removing a node, or changing the radius of an
40
 * object will all cause the tree to be marked as changed.
41
 */
42

43
using namespace std;
44

45
/*! Create a frame tree associated with a star.
46
 */
47
FrameTree::FrameTree(Star* star) :
48
    starParent(star),
49
    bodyParent(nullptr),
50
    m_changed(true),
51
    // Default frame for a star is J2000 ecliptical, centered
52
    // on the star.
53
    defaultFrame(new J2000EclipticFrame(Selection(star)))
54
{
55
}
56

57

58
/*! Create a frame tree associated with a planet or other solar system body.
59
 */
60
FrameTree::FrameTree(Body* body) :
61
    starParent(nullptr),
62
    bodyParent(body),
63
    m_changed(true),
64
    // Default frame for a solar system body is the mean equatorial frame of the body.
65
    defaultFrame(new BodyMeanEquatorFrame(Selection(body), Selection(body)))
66
{
67
}
68

69

70
/*! Return the default reference frame for the object a frame tree is associated
71
 *  with.
72
 */
73
const ReferenceFrame::SharedConstPtr&
74
FrameTree::getDefaultReferenceFrame() const
75
{
76
    return defaultFrame;
77
}
78

79

80
/*! Mark this node of the frame hierarchy as changed. The changed flag
81
 *  is propagated up toward the root of the tree.
82
 */
83
void
84
FrameTree::markChanged()
85
{
86
    if (!m_changed)
87
    {
88
        m_changed = true;
89
        if (bodyParent != nullptr)
90
            bodyParent->markChanged();
91
    }
92
}
93

94

95
/*! Mark this node of the frame hierarchy as updated. The changed flag
96
 *  is marked false in this node and in all child nodes that
97
 *  were marked changed.
98
 */
99
void
100
FrameTree::markUpdated()
101
{
102
    if (m_changed)
103
    {
104
        m_changed = false;
105
        for (const auto &child : children)
106
            child->body()->markUpdated();
107
    }
108
}
109

110

111
/*! Recompute the bounding sphere for this tree and all subtrees marked
112
 *  as having changed. The bounding sphere is large enough to accommodate
113
 *  the orbits (and radii) of all child bodies. This method also recomputes
114
 *  the maximum child radius, secondary illuminator status, and child
115
 *  class mask.
116
 */
117
void
118
FrameTree::recomputeBoundingSphere()
119
{
120
    if (m_changed)
121
    {
122
        m_boundingSphereRadius = 0.0;
123
        m_maxChildRadius = 0.0;
124
        m_containsSecondaryIlluminators = false;
125
        m_childClassMask = BodyClassification::EmptyMask;
126

127
        for (const auto &phase : children)
128
        {
129
            double bodyRadius = phase->body()->getRadius();
130
            double r = phase->body()->getCullingRadius() + phase->orbit()->getBoundingRadius();
131
            m_maxChildRadius = max(m_maxChildRadius, bodyRadius);
132
            m_containsSecondaryIlluminators = m_containsSecondaryIlluminators || phase->body()->isSecondaryIlluminator();
133
            m_childClassMask |= phase->body()->getClassification();
134

135
            FrameTree* tree = phase->body()->getFrameTree();
136
            if (tree != nullptr)
137
            {
138
                tree->recomputeBoundingSphere();
139
                r += tree->m_boundingSphereRadius;
140
                m_maxChildRadius = max(m_maxChildRadius, tree->m_maxChildRadius);
141
                m_containsSecondaryIlluminators = m_containsSecondaryIlluminators || tree->containsSecondaryIlluminators();
142
                m_childClassMask |= tree->childClassMask();
143
            }
144

145
            m_boundingSphereRadius = max(m_boundingSphereRadius, r);
146
        }
147
    }
148
}
149

150

151
/*! Add a new phase to this tree.
152
 */
153
void
154
FrameTree::addChild(const TimelinePhase::SharedConstPtr &phase)
155
{
156
    children.push_back(phase);
157
    markChanged();
158
}
159

160

161
/*! Remove a phase from the tree. This method does nothing if the specified
162
 *  phase doesn't exist in the tree.
163
 */
164
void
165
FrameTree::removeChild(const TimelinePhase::SharedConstPtr &phase)
166
{
167
    auto iter = find(children.begin(), children.end(), phase);
168
    if (iter != children.end())
169
    {
170
        children.erase(iter);
171
        markChanged();
172
    }
173
}
174

175

176
/*! Return the child at the specified index. */
177
const TimelinePhase*
178
FrameTree::getChild(unsigned int n) const
179
{
180
    return children[n].get();
181
}
182

183

184
/*! Get the number of immediate children of this tree. */
185
unsigned int
186
FrameTree::childCount() const
187
{
188
    return children.size();
189
}
190

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.