diff --git a/src/celengine/globular.cpp b/src/celengine/globular.cpp index bbc2118f8..9dc6ec735 100644 --- a/src/celengine/globular.cpp +++ b/src/celengine/globular.cpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include @@ -33,7 +35,23 @@ namespace vecgl = celestia::vecgl; -namespace { + +struct GlobularForm +{ + struct Blob + { + Eigen::Vector3f position; + unsigned int colorIndex; + float radius_2d; + }; + + std::vector gblobs; + Eigen::Vector3f scale; +}; + + +namespace +{ constexpr const int cntrTexWidth = 512; constexpr const int cntrTexHeight = 512; @@ -49,7 +67,8 @@ constexpr const float LumiShape = 3.0f; // min/max c-values of globular cluster data constexpr const float MinC = 0.50f; constexpr const float MaxC = 2.58f; -constexpr const float BinWidth = (MaxC - MinC) / 8.0f + 0.02f; +constexpr std::size_t GlobularBuckets = 8; +constexpr const float BinWidth = (MaxC - MinC) / static_cast(GlobularBuckets) + 0.02f; // P1 determines the zoom level, where individual cluster stars start to appear. // The smaller P2 (< 1), the faster stars show up when resolution increases. @@ -61,32 +80,7 @@ constexpr const float RADIUS_CORRECTION = 0.025f; float CBin, RRatio, XI, Rr = 1.0f, Gg = 1.0f, Bb = 1.0f; -struct GBlob -{ - Eigen::Vector3f position; - unsigned int colorIndex; - float radius_2d; -}; - -} // end unnamed namespace - - -struct GlobularForm -{ - std::vector* gblobs; - Eigen::Vector3f scale; -}; - - -namespace -{ - -GlobularForm** globularForms = nullptr; -Texture* globularTex = nullptr; -Texture* centerTex[8] = {nullptr}; -bool formsInitialized = false; - -void GlobularTextureEval(float u, float v, float /*w*/, unsigned char *pixel) +void globularTextureEval(float u, float v, float /*w*/, unsigned char *pixel) { // use an exponential luminosity shape for the individual stars // giving sort of a halo for the brighter (i.e.bigger) stars. @@ -129,7 +123,7 @@ float relStarDensity(float eta) return ((std::log(rho2) + 4.0f * (1.0f - std::sqrt(rho2)) * Xi) / (rho2 - 1.0f) + XI2) / (1.0f - 2.0f * Xi + XI2); } -static void CenterCloudTexEval(float u, float v, float /*w*/, unsigned char *pixel) +void centerCloudTexEval(float u, float v, float /*w*/, unsigned char *pixel) { /*! For reasons of speed, calculate central "cloud" texture only for * 8 bins of King_1962 concentration, c = CBin, XI(CBin), RRatio(CBin). @@ -154,7 +148,7 @@ static void CenterCloudTexEval(float u, float v, float /*w*/, unsigned char *pix // Skyplane projected King_1962 profile (Eq.(14)), vanishes for eta = 1: // i.e. absolutely no globular stars for r > tidalRadius: - float profile_2d = (1.0f / std::sqrt(rho2) - 1.0f)/c2d + 1.0f ; + float profile_2d = (1.0f / std::sqrt(rho2) - 1.0f)/c2d + 1.0f; profile_2d = profile_2d * profile_2d; pixel[0] = 255; @@ -163,7 +157,10 @@ static void CenterCloudTexEval(float u, float v, float /*w*/, unsigned char *pix pixel[3] = static_cast(relStarDensity(eta) * profile_2d * 255.99f); } -void initGlobularData(celgl::VertexObject& vo, std::vector* points, GLint sizeLoc, GLint etaLoc) +void initGlobularData(celgl::VertexObject& vo, + const std::vector& points, + GLint sizeLoc, + GLint etaLoc) { struct GlobularVtx { @@ -173,7 +170,7 @@ void initGlobularData(celgl::VertexObject& vo, std::vector* points, GLint float eta; }; std::vector globularVtx; - globularVtx.reserve(4 + points->size()); + globularVtx.reserve(4 + points.size()); // Reuse the buffer for a tidal globularVtx.push_back({{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 0.0f, 0.0f}); @@ -188,7 +185,7 @@ void initGlobularData(celgl::VertexObject& vo, std::vector* points, GLint float starSize = 0.5f; std::size_t pow2 = 128; - for (std::size_t i = 0; i < points->size(); ++i) + for (std::size_t i = 0; i < points.size(); ++i) { /*! Note that the [axis,angle] input in globulars.dsc transforms the * 2d projected star distance r_2d in the globular frame to refer to the @@ -205,7 +202,7 @@ void initGlobularData(celgl::VertexObject& vo, std::vector* points, GLint starSize /= 1.25f; } - GBlob b = (*points)[i]; + const GlobularForm::Blob& b = points[i]; GlobularVtx vtx; vtx.starSize = starSize; vtx.position = b.position; @@ -229,10 +226,10 @@ void initGlobularData(celgl::VertexObject& vo, std::vector* points, GLint vo.setVertexAttribArray(etaLoc, 1, GL_FLOAT, false, sizeof(GlobularVtx), offsetof(GlobularVtx, eta)); } -GlobularForm* buildGlobularForms(float c) +GlobularForm buildGlobularForm(float c) { - GBlob b{}; - std::vector* globularPoints = new std::vector; + GlobularForm::Blob b{}; + std::vector globularPoints; float rRatio = std::pow(10.0f, c); // = r_t / r_c float prob; @@ -318,7 +315,7 @@ GlobularForm* buildGlobularForms(float c) b.colorIndex = static_cast(Z * 254); - globularPoints->push_back(b); + globularPoints.push_back(b); i++; } } @@ -326,14 +323,14 @@ GlobularForm* buildGlobularForms(float c) // Check for efficiency of sprite-star generation => close to 100 %! //cout << "c = "<< c <<" i = " << i - 1 <<" k = " << k - 1 << " Efficiency: " << 100.0f * i / (float)k<<"%" << endl; - auto* globularForm = new GlobularForm(); - globularForm->gblobs = globularPoints; - globularForm->scale = Eigen::Vector3f::Ones(); + GlobularForm globularForm; + globularForm.gblobs = std::move(globularPoints); + globularForm.scale = Eigen::Vector3f::Ones(); return globularForm; } -void InitializeForms() +std::vector initializeForms() { // Build RGB color table, using hue, saturation, value as input. @@ -372,22 +369,25 @@ void InitializeForms() / static_cast(i_width)) + 1.0f); DeepSkyObject::hsv2rgb(&Rr, &Gg, &Bb, hue, sat, 0.85f); - colorTable[i] = Color(Rr, Gg, Bb); + colorTable[i] = Color(Rr, Gg, Bb); } // Define globularForms corresponding to 8 different bins of King concentration c - globularForms = new GlobularForm*[8]; + std::vector globularForms; + globularForms.reserve(GlobularBuckets); for (unsigned int ic = 0; ic <= 7; ++ic) { float CBin = MinC + (static_cast(ic) + 0.5f) * BinWidth; - globularForms[ic] = buildGlobularForms(CBin); + globularForms.push_back(buildGlobularForm(CBin)); } - formsInitialized = true; + + return globularForms; } } // end unnamed namespace + Globular::Globular() { recomputeTidalRadius(); @@ -452,12 +452,10 @@ float Globular::getConcentration() const void Globular::setConcentration(const float conc) { c = conc; - if (!formsInitialized) - InitializeForms(); - // For saving time, account for the c dependence via 8 bins only, - form = globularForms[cSlot(conc)]; + static const std::vector globularForms = initializeForms(); + form = &globularForms[cSlot(conc)]; recomputeTidalRadius(); } @@ -503,7 +501,7 @@ bool Globular::load(AssociativeArray* params, const fs::path& resPath) return false; if (params->getNumber("Detail", detail)) - setDetail((float) detail); + setDetail(static_cast(detail)); double coreRadius; if (params->getAngle("CoreRadius", coreRadius, 1.0 / MINUTES_PER_DEG)) @@ -570,20 +568,18 @@ void Globular::render(const Eigen::Vector3f& offset, RRatio = std::pow(10.0f, CBin); XI = 1.0f / std::sqrt(1.0f + RRatio * RRatio); + static Texture* centerTex[GlobularBuckets] = {nullptr}; if(centerTex[ic] == nullptr) { centerTex[ic] = CreateProceduralTexture(cntrTexWidth, cntrTexHeight, celestia::PixelFormat::RGBA, - CenterCloudTexEval); + centerCloudTexEval); } assert(centerTex[ic] != nullptr); - if (globularTex == nullptr) - { - globularTex = CreateProceduralTexture(starTexWidth, starTexHeight, - celestia::PixelFormat::RGBA, - GlobularTextureEval); - } + static Texture* globularTex = CreateProceduralTexture(starTexWidth, starTexHeight, + celestia::PixelFormat::RGBA, + globularTextureEval); assert(globularTex != nullptr); renderer->enableBlending(); @@ -628,7 +624,7 @@ void Globular::render(const Eigen::Vector3f& offset, * or when distance from globular center decreases. */ - GLsizei count = static_cast(form->gblobs->size() * std::clamp(getDetail(), 0.0f, 1.0f)); + GLsizei count = static_cast(form->gblobs.size() * std::clamp(getDetail(), 0.0f, 1.0f)); float t = std::pow(2.0f, 1.0f + std::log2(minimumFeatureSize / brightness) / std::log2(1.0f/1.25f)); count = std::min(count, static_cast(std::clamp(t, 128.0f, static_cast(std::max(count, 128))))); diff --git a/src/celengine/globular.h b/src/celengine/globular.h index 3ce7aaebd..fd6f0fad8 100644 --- a/src/celengine/globular.h +++ b/src/celengine/globular.h @@ -39,10 +39,10 @@ class Globular : public DeepSkyObject void setType(const std::string&) override; std::string getDescription() const override; float getDetail() const; - void setDetail(float); + void setDetail(float); float getCoreRadius() const; - void setCoreRadius(const float); - void setConcentration(const float); + void setCoreRadius(float); + void setConcentration(float); float getConcentration() const; float getHalfMassRadius() const override; unsigned int cSlot(float) const; @@ -71,11 +71,11 @@ class Globular : public DeepSkyObject void recomputeTidalRadius(); - float detail{ 1.0f }; - GlobularForm* form{ nullptr }; - float r_c{ R_c_ref }; - float c{ C_ref }; - float tidalRadius{ 0.0f }; + float detail{ 1.0f }; + const GlobularForm* form{ nullptr }; + float r_c{ R_c_ref }; + float c{ C_ref }; + float tidalRadius{ 0.0f }; celgl::VertexObject vo{ GL_ARRAY_BUFFER, 0, GL_STATIC_DRAW }; };