1010
1111#include < celengine/dsodb.h>
1212#include < celengine/deepskyobj.h>
13- #include < celmath/geomutil.h>
14- #include < celmath/vecgl.h>
15- #include " glsupport.h"
13+ #include < celrender/galaxyrenderer.h>
14+ #include < celrender/globularrenderer.h>
15+ #include < celrender/nebularenderer.h>
16+ #include < celrender/openclusterrenderer.h>
1617#include " render.h"
17-
1818#include " dsorenderer.h"
1919
20- using namespace Eigen ;
21- using namespace celestia ;
22- using namespace celmath ;
2320
21+ namespace
22+ {
2423// The parameter 'enhance' adjusts the DSO brightness as viewed from "inside"
25- // (e.g. MilkyWay as seen from Earth). It provides an enhanced apparent core
24+ // (e.g. MilkyWay as seen from Earth). It provides an enhanced apparent core
2625// brightness appMag ~ absMag - enhance. 'enhance' thus serves to uniformly
2726// enhance the too low sprite luminosity at close distance.
28- constexpr const double enhance = 4.0 ;
29- constexpr const double pc10 = 32.6167 ; // 10 parsecs
30- static const float CubeCornerToCenterDistance = sqrt(3 .0f );
27+ constexpr double enhance = 4.0 ;
28+ constexpr double pc10 = 32.6167 ; // 10 parsecs
29+ constexpr float CubeCornerToCenterDistance = 1 .7320508075688772f ;
30+
31+ enum class DeepSkyObjectType
32+ {
33+ Galaxy,
34+ Globular,
35+ Nebula,
36+ OpenCluster
37+ };
38+
39+ DeepSkyObjectType
40+ GetDSOType (const DeepSkyObject* dso)
41+ {
42+ if (!strcmp (dso->getObjTypeName (), " galaxy" ))
43+ return DeepSkyObjectType::Galaxy;
44+
45+ if (!strcmp (dso->getObjTypeName (), " globular" ))
46+ return DeepSkyObjectType::Globular;
47+
48+ if (!strcmp (dso->getObjTypeName (), " nebula" ))
49+ return DeepSkyObjectType::Nebula;
50+
51+ if (!strcmp (dso->getObjTypeName (), " opencluster" ))
52+ return DeepSkyObjectType::OpenCluster;
53+ }
54+
55+ float
56+ brightness (float avgAbsMag, float absMag, float appMag, float brightnessCorr, float faintestMag)
57+ {
58+ // Input: display looks satisfactory for 0.2 < brightness < O(1.0)
59+ // Ansatz: brightness = a - b * appMag(distanceToDSO), emulating eye sensitivity...
60+ // determine a,b such that
61+ // a - b * absMag = absMag / avgAbsMag ~ 1; a - b * faintestMag = 0.2.
62+ // The 2nd eq. guarantees that the faintest galaxies are still visible.
63+
64+ float r = absMag / avgAbsMag;
65+ float b = r - (r - 0 .2f ) * (absMag - appMag) / (absMag - faintestMag);
66+
67+ // obviously, brightness(appMag = absMag) = r and
68+ // brightness(appMag = faintestMag) = 0.2, as desired.
69+
70+ return std::max (0 .0f , b * brightnessCorr);
71+ }
72+
73+ } // anonymous namespace
3174
3275DSORenderer::DSORenderer () :
3376 ObjectRenderer<DeepSkyObject*, double>(DSO_OCTREE_ROOT_SIZE)
@@ -41,15 +84,15 @@ void DSORenderer::process(DeepSkyObject* const &dso,
4184 if (distanceToDSO > distanceLimit || !dso->isVisible ())
4285 return ;
4386
44- Vector3f relPos = (dso->getPosition () - obsPos).cast <float >();
45- Vector3f center = orientationMatrixT * relPos;
87+ Eigen:: Vector3f relPos = (dso->getPosition () - obsPos).cast <float >();
88+ Eigen:: Vector3f center = orientationMatrixT * relPos;
4689
4790 // Test the object's bounding sphere against the view frustum. If we
4891 // avoid this stage, overcrowded octree cells may hit performance badly:
4992 // each object (even if it's not visible) would be sent to the OpenGL
5093 // pipeline.
5194 double dsoRadius = dso->getBoundingSphereRadius ();
52- if (frustum.testSphere (center, (float ) dsoRadius) == Frustum::Outside)
95+ if (frustum.testSphere (center, (float ) dsoRadius) == celmath:: Frustum::Outside)
5396 return ;
5497
5598 float appMag;
@@ -62,59 +105,45 @@ void DSORenderer::process(DeepSkyObject* const &dso,
62105 {
63106 dsosProcessed++;
64107
65- // Input: display looks satisfactory for 0.2 < brightness < O(1.0)
66- // Ansatz: brightness = a - b * appMag(distanceToDSO), emulating eye sensitivity...
67- // determine a,b such that
68- // a - b * absMag = absMag / avgAbsMag ~ 1; a - b * faintestMag = 0.2.
69- // The 2nd eq. guarantees that the faintest galaxies are still visible.
70-
71- if (!strcmp (dso->getObjTypeName (), " globular" ))
72- avgAbsMag = -6 .86f ; // average over 150 globulars in globulars.dsc.
73- else if (!strcmp (dso->getObjTypeName (), " galaxy" ))
74- avgAbsMag = -19 .04f ; // average over 10937 galaxies in galaxies.dsc.
75-
76- float r = absMag / avgAbsMag;
77- float brightness = r - (r - 0 .2f ) * (absMag - appMag) / (absMag - faintestMag);
78-
79- // obviously, brightness(appMag = absMag) = r and
80- // brightness(appMag = faintestMag) = 0.2, as desired.
81-
82- brightness *= 2 .3f * (faintestMag - 4 .75f ) / renderer->getFaintestAM45deg ();
83-
84- if (brightness < 0 )
85- brightness = 0 ;
86-
87- Matrix4f mv = celmath::translate (renderer->getModelViewMatrix (), relPos);
88- Matrix4f pr;
89-
108+ float nearZ = 0 .0f , farZ = 0 .0f ;
90109 if (dsoRadius < 1000.0 )
91110 {
92111 // Small objects may be prone to clipping; give them special
93112 // handling. We don't want to always set the projection
94113 // matrix, since that could be expensive with large galaxy
95114 // catalogs.
96- auto nearZ = (float )(distanceToDSO / 2 );
97- auto farZ = (float )(distanceToDSO + dsoRadius * 2 * CubeCornerToCenterDistance);
98- if (nearZ < dsoRadius * 0.001 )
115+ nearZ = static_cast <float >(distanceToDSO / 2.0 );
116+ farZ = static_cast <float >(distanceToDSO + dsoRadius * 2.0 * CubeCornerToCenterDistance);
117+ auto minZ = static_cast <float >(dsoRadius * 0.001 );
118+ if (nearZ < minZ)
99119 {
100- nearZ = ( float )(dsoRadius * 0.001 ) ;
120+ nearZ = minZ ;
101121 farZ = nearZ * 10000 .0f ;
102122 }
103-
104- float t = renderer->getAspectRatio ();
105- if (renderer->getProjectionMode () == Renderer::ProjectionMode::FisheyeMode)
106- pr = Ortho (-t, t, -1 .0f , 1 .0f , nearZ, farZ);
107- else
108- pr = Perspective (fov, t, nearZ, farZ);
109123 }
110- else
124+
125+ float b = 2 .3f * (faintestMag - 4 .75f ) / renderer->getFaintestAM45deg (); // brightnesCorr
126+ switch (GetDSOType (dso))
111127 {
112- pr = renderer->getProjectionMatrix ();
128+ case DeepSkyObjectType::Galaxy:
129+ // -19.04f == average over 10937 galaxies in galaxies.dsc.
130+ b = brightness (-19 .04f , absMag, appMag, b, faintestMag);
131+ galaxyRenderer->add (reinterpret_cast <Galaxy*>(dso), relPos, b, nearZ, farZ);
132+ break ;
133+ case DeepSkyObjectType::Globular:
134+ // -6.86f == average over 150 globulars in globulars.dsc.
135+ b = brightness (-6 .86f , absMag, appMag, b, faintestMag);
136+ globularRenderer->add (reinterpret_cast <Globular*>(dso), relPos, b, nearZ, farZ);
137+ break ;
138+ case DeepSkyObjectType::Nebula:
139+ b = brightness (avgAbsMag, absMag, appMag, b, faintestMag);
140+ nebulaRenderer->add (reinterpret_cast <Nebula*>(dso), relPos, b, nearZ, farZ);
141+ break ;
142+ case DeepSkyObjectType::OpenCluster:
143+ b = brightness (avgAbsMag, absMag, appMag, b, faintestMag);
144+ openClusterRenderer->add (reinterpret_cast <OpenCluster*>(dso), relPos, b, nearZ, farZ);
145+ break ;
113146 }
114-
115- dso->render (relPos, observer->getOrientationf (), brightness,
116- pixelSize, { &pr, &mv }, renderer);
117-
118147 } // renderFlags check
119148
120149 // Only render those labels that are in front of the camera:
@@ -169,9 +198,7 @@ void DSORenderer::process(DeepSkyObject* const &dso,
169198 if (appMagEff < labelThresholdMag)
170199 {
171200 // introduce distance dependent label transparency.
172- float distr = step * (labelThresholdMag - appMagEff) / labelThresholdMag;
173- if (distr > 1 .0f )
174- distr = 1 .0f ;
201+ float distr = std::min (1 .0f , step * (labelThresholdMag - appMagEff) / labelThresholdMag);
175202 labelColor.alpha (distr * labelColor.alpha ());
176203
177204 renderer->addBackgroundAnnotation (rep,
0 commit comments