00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <celengine/staroctree.h>
00014
00015
00016
00017
00018
00019
00020
00021
00022 bool starAbsoluteMagnitudePredicate(const Star& star, const float absMag)
00023 {
00024 return star.getAbsoluteMagnitude() <= absMag;
00025 }
00026
00027
00028 bool starOrbitStraddlesNodesPredicate(const Point3f& cellCenterPos, const Star& star, const float absMag)
00029 {
00030
00031 float orbitalRadius = star.getOrbitalRadius();
00032 if (orbitalRadius == 0.0f)
00033 return false;
00034
00035 Point3f starPos = star.getPosition();
00036
00037 return abs(starPos.x - cellCenterPos.x) < orbitalRadius ||
00038 abs(starPos.y - cellCenterPos.y) < orbitalRadius ||
00039 abs(starPos.z - cellCenterPos.z) < orbitalRadius;
00040 }
00041
00042
00043 float starAbsoluteMagnitudeDecayFunction(const float excludingFactor)
00044 {
00045 return astro::lumToAbsMag(astro::absMagToLum(excludingFactor) / 4.0f);
00046 }
00047
00048
00049 template<>
00050 DynamicStarOctree* DynamicStarOctree::getChild(const Star& obj,
00051 const Point3f& cellCenterPos)
00052 {
00053 Point3f objPos = obj.getPosition();
00054
00055 int child = 0;
00056 child |= objPos.x < cellCenterPos.x ? 0 : XPos;
00057 child |= objPos.y < cellCenterPos.y ? 0 : YPos;
00058 child |= objPos.z < cellCenterPos.z ? 0 : ZPos;
00059
00060 return _children[child];
00061 }
00062
00063
00064
00065
00066
00067 template<> unsigned int DynamicStarOctree::SPLIT_THRESHOLD = 75;
00068 template<> DynamicStarOctree::LimitingFactorPredicate*
00069 DynamicStarOctree::limitingFactorPredicate = starAbsoluteMagnitudePredicate;
00070 template<> DynamicStarOctree::StraddlingPredicate*
00071 DynamicStarOctree::straddlingPredicate = starOrbitStraddlesNodesPredicate;
00072 template<> DynamicStarOctree::ExclusionFactorDecayFunction*
00073 DynamicStarOctree::decayFunction = starAbsoluteMagnitudeDecayFunction;
00074
00075
00076
00077 template<>
00078 void StarOctree::processVisibleObjects(StarHandler& processor,
00079 const Point3f& obsPosition,
00080 const Planef* frustumPlanes,
00081 float limitingFactor,
00082 float scale) const
00083 {
00084
00085
00086
00087
00088 for (int i=0; i<5; ++i)
00089 {
00090 const Planef* plane = frustumPlanes + i;
00091 float r = scale * (abs(plane->normal.x) +
00092 abs(plane->normal.y) +
00093 abs(plane->normal.z));
00094
00095 if (plane->normal * Vec3f(cellCenterPos.x, cellCenterPos.y, cellCenterPos.z) - plane->d < -r)
00096 return;
00097 }
00098
00099
00100
00101 float minDistance = (obsPosition - cellCenterPos).length() - scale * StarOctree::SQRT3;
00102
00103
00104 float dimmest = minDistance > 0 ? astro::appToAbsMag(limitingFactor, minDistance) : 1000;
00105
00106 for (unsigned int i=0; i<nObjects; ++i)
00107 {
00108 Star& obj = _firstObject[i];
00109
00110 if (obj.getAbsoluteMagnitude() < dimmest)
00111 {
00112 float distance = obsPosition.distanceTo(obj.getPosition());
00113 float appMag = astro::absToAppMag(obj.getAbsoluteMagnitude(), distance);
00114
00115 if (appMag < limitingFactor)
00116 processor.process(obj, distance, appMag);
00117 }
00118 }
00119
00120
00121
00122 if (minDistance <= 0 || astro::absToAppMag(exclusionFactor, minDistance) <= limitingFactor)
00123
00124 if (_children != NULL)
00125 for (int i=0; i<8; ++i)
00126 {
00127 _children[i]->processVisibleObjects(processor,
00128 obsPosition,
00129 frustumPlanes,
00130 limitingFactor,
00131 scale * 0.5f);
00132 }
00133 }
00134
00135
00136 template<>
00137 void StarOctree::processCloseObjects(StarHandler& processor,
00138 const Point3f& obsPosition,
00139 float boundingRadius,
00140 float scale) const
00141 {
00142
00143
00144 float nodeDistance = (obsPosition - cellCenterPos).length() - scale * StarOctree::SQRT3;
00145
00146 if (nodeDistance > boundingRadius)
00147 return;
00148
00149
00150
00151
00152
00153
00154 float radiusSquared = boundingRadius * boundingRadius;
00155
00156
00157 for (unsigned int i = 0; i < nObjects; ++i)
00158 {
00159 Star& obj = _firstObject[i];
00160
00161 if (obsPosition.distanceToSquared(obj.getPosition()) < radiusSquared)
00162 {
00163 float distance = obsPosition.distanceTo(obj.getPosition());
00164 float appMag = astro::absToAppMag(obj.getAbsoluteMagnitude(), distance);
00165
00166 processor.process(obj, distance, appMag);
00167 }
00168 }
00169
00170
00171 if (_children != NULL)
00172 {
00173 for (int i = 0; i < 8; ++i)
00174 {
00175 _children[i]->processCloseObjects(processor,
00176 obsPosition,
00177 boundingRadius,
00178 scale * 0.5f);
00179 }
00180 }
00181 }