Add managers for galaxy/globular details to avoid destructor issues on exit
parent
c632aea62d
commit
fd9ea94377
|
@ -53,9 +53,6 @@ bool operator<(const Blob& b1, const Blob& b2)
|
||||||
|
|
||||||
using BlobVector = std::vector<Blob>;
|
using BlobVector = std::vector<Blob>;
|
||||||
|
|
||||||
} // end unnamed namespace
|
|
||||||
|
|
||||||
|
|
||||||
class GalacticForm
|
class GalacticForm
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -63,10 +60,6 @@ public:
|
||||||
Eigen::Vector3f scale;
|
Eigen::Vector3f scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
constexpr int width = 128;
|
constexpr int width = 128;
|
||||||
constexpr int height = 128;
|
constexpr int height = 128;
|
||||||
constexpr unsigned int GALAXY_POINTS = 3500;
|
constexpr unsigned int GALAXY_POINTS = 3500;
|
||||||
|
@ -78,11 +71,6 @@ constexpr float MAX_SPIRAL_THICKNESS = 0.06f;
|
||||||
|
|
||||||
bool formsInitialized = false;
|
bool formsInitialized = false;
|
||||||
|
|
||||||
constexpr std::size_t GalacticFormsReserve = 32;
|
|
||||||
|
|
||||||
std::vector<std::optional<GalacticForm>> galacticForms;
|
|
||||||
std::map<fs::path, std::size_t> customForms;
|
|
||||||
|
|
||||||
Texture* galaxyTex = nullptr;
|
Texture* galaxyTex = nullptr;
|
||||||
Texture* colorTex = nullptr;
|
Texture* colorTex = nullptr;
|
||||||
|
|
||||||
|
@ -258,7 +246,50 @@ std::optional<GalacticForm> buildGalacticForm(const fs::path& filename)
|
||||||
return galacticForm;
|
return galacticForm;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initializeForms()
|
class GalacticFormManager
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static constexpr std::size_t GalacticFormsReserve = 32;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GalacticFormManager()
|
||||||
|
{
|
||||||
|
initializeStandardForms();
|
||||||
|
}
|
||||||
|
|
||||||
|
const GalacticForm* getForm(std::size_t) const;
|
||||||
|
std::size_t getCustomForm(const fs::path& path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initializeStandardForms();
|
||||||
|
|
||||||
|
std::vector<std::optional<GalacticForm>> galacticForms{ };
|
||||||
|
std::map<fs::path, std::size_t> customForms{ };
|
||||||
|
};
|
||||||
|
|
||||||
|
const GalacticForm* GalacticFormManager::getForm(std::size_t form) const
|
||||||
|
{
|
||||||
|
assert(form < galacticForms.size());
|
||||||
|
return galacticForms[form].has_value()
|
||||||
|
? &*galacticForms[form]
|
||||||
|
: nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t GalacticFormManager::getCustomForm(const fs::path& path)
|
||||||
|
{
|
||||||
|
auto iter = customForms.find(path);
|
||||||
|
if (iter != customForms.end())
|
||||||
|
{
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t result = galacticForms.size();
|
||||||
|
customForms[path] = result;
|
||||||
|
galacticForms.push_back(buildGalacticForm(path));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GalacticFormManager::initializeStandardForms()
|
||||||
{
|
{
|
||||||
// Irregular Galaxies
|
// Irregular Galaxies
|
||||||
unsigned int galaxySize = GALAXY_POINTS, ip = 0;
|
unsigned int galaxySize = GALAXY_POINTS, ip = 0;
|
||||||
|
@ -290,14 +321,12 @@ void initializeForms()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GalacticForm& irregularForm = *galacticForms.emplace_back(std::in_place);
|
std::optional<GalacticForm>& irregularForm = galacticForms.emplace_back(std::in_place);
|
||||||
irregularForm.blobs = std::move(irregularPoints);
|
irregularForm->blobs = std::move(irregularPoints);
|
||||||
irregularForm.scale = Eigen::Vector3f::Constant(0.5f);
|
irregularForm->scale = Eigen::Vector3f::Constant(0.5f);
|
||||||
|
|
||||||
// Spiral Galaxies, 7 classical Hubble types
|
// Spiral Galaxies, 7 classical Hubble types
|
||||||
|
|
||||||
galacticForms.reserve(GalacticFormsReserve);
|
|
||||||
|
|
||||||
galacticForms.push_back(buildGalacticForm("models/S0.png"));
|
galacticForms.push_back(buildGalacticForm("models/S0.png"));
|
||||||
galacticForms.push_back(buildGalacticForm("models/Sa.png"));
|
galacticForms.push_back(buildGalacticForm("models/Sa.png"));
|
||||||
galacticForms.push_back(buildGalacticForm("models/Sb.png"));
|
galacticForms.push_back(buildGalacticForm("models/Sb.png"));
|
||||||
|
@ -317,34 +346,27 @@ void initializeForms()
|
||||||
|
|
||||||
// note the correct x,y-alignment of 'ell' scaling!!
|
// note the correct x,y-alignment of 'ell' scaling!!
|
||||||
// build all elliptical templates from rescaling E0
|
// build all elliptical templates from rescaling E0
|
||||||
|
std::optional<GalacticForm> ellipticalForm = buildGalacticForm("models/E0.png");
|
||||||
galacticForms.push_back(buildGalacticForm("models/E0.png"));
|
if (ellipticalForm.has_value())
|
||||||
if (!galacticForms.back().has_value()) { continue; }
|
|
||||||
|
|
||||||
GalacticForm& ellipticalForm = *galacticForms.back();
|
|
||||||
ellipticalForm.scale = Eigen::Vector3f(ell, ell, 1.0f);
|
|
||||||
|
|
||||||
for (Blob& blob : ellipticalForm.blobs)
|
|
||||||
{
|
{
|
||||||
blob.colorIndex = static_cast<unsigned int>(std::ceil(0.76f * static_cast<float>(blob.colorIndex)));
|
ellipticalForm->scale = Eigen::Vector3f(ell, ell, 1.0f);
|
||||||
|
|
||||||
|
for (Blob& blob : ellipticalForm->blobs)
|
||||||
|
{
|
||||||
|
blob.colorIndex = static_cast<unsigned int>(std::ceil(0.76f * static_cast<float>(blob.colorIndex)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
galacticForms.push_back(std::move(ellipticalForm));
|
||||||
}
|
}
|
||||||
|
|
||||||
formsInitialized = true;
|
formsInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t customForm(const fs::path& path)
|
GalacticFormManager* getGalacticFormManager()
|
||||||
{
|
{
|
||||||
auto iter = customForms.find(path);
|
static GalacticFormManager* galacticFormManager = new GalacticFormManager();
|
||||||
if (iter != customForms.end())
|
return galacticFormManager;
|
||||||
{
|
|
||||||
return iter->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t result = galacticForms.size();
|
|
||||||
customForms[path] = result;
|
|
||||||
galacticForms.push_back(buildGalacticForm(path));
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end unnamed namespace
|
} // end unnamed namespace
|
||||||
|
@ -378,16 +400,13 @@ void Galaxy::setType(const std::string& typeStr)
|
||||||
|
|
||||||
void Galaxy::setForm(const std::string& customTmpName)
|
void Galaxy::setForm(const std::string& customTmpName)
|
||||||
{
|
{
|
||||||
if (!formsInitialized)
|
|
||||||
initializeForms();
|
|
||||||
|
|
||||||
if (customTmpName.empty())
|
if (customTmpName.empty())
|
||||||
{
|
{
|
||||||
form = static_cast<std::size_t>(type);
|
form = static_cast<std::size_t>(type);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
form = customForm(fs::path("models") / customTmpName);
|
form = getGalacticFormManager()->getCustomForm(fs::path("models") / customTmpName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,22 +424,20 @@ bool Galaxy::pick(const Eigen::ParametrizedLine<double, 3>& ray,
|
||||||
double& distanceToPicker,
|
double& distanceToPicker,
|
||||||
double& cosAngleToBoundCenter) const
|
double& cosAngleToBoundCenter) const
|
||||||
{
|
{
|
||||||
if (!galacticForms[form].has_value() || !isVisible())
|
const GalacticForm* galacticForm = getGalacticFormManager()->getForm(form);
|
||||||
return false;
|
if (galacticForm == nullptr || !isVisible()) { return false; }
|
||||||
|
|
||||||
GalacticForm& galacticForm = *galacticForms[form];
|
|
||||||
|
|
||||||
// The ellipsoid should be slightly larger to compensate for the fact
|
// The ellipsoid should be slightly larger to compensate for the fact
|
||||||
// that blobs are considered points when galaxies are built, but have size
|
// that blobs are considered points when galaxies are built, but have size
|
||||||
// when they are drawn.
|
// when they are drawn.
|
||||||
float yscale = (type > GalaxyType::Irr && type < GalaxyType::E0)
|
float yscale = (type > GalaxyType::Irr && type < GalaxyType::E0)
|
||||||
? MAX_SPIRAL_THICKNESS
|
? MAX_SPIRAL_THICKNESS
|
||||||
: galacticForm.scale.y() + RADIUS_CORRECTION;
|
: galacticForm->scale.y() + RADIUS_CORRECTION;
|
||||||
Eigen::Vector3d ellipsoidAxes(getRadius()*(galacticForm.scale.x() + RADIUS_CORRECTION),
|
Eigen::Vector3d ellipsoidAxes(getRadius()*(galacticForm->scale.x() + RADIUS_CORRECTION),
|
||||||
getRadius()* yscale,
|
getRadius()* yscale,
|
||||||
getRadius()*(galacticForm.scale.z() + RADIUS_CORRECTION));
|
getRadius()*(galacticForm->scale.z() + RADIUS_CORRECTION));
|
||||||
|
|
||||||
Eigen::Matrix3d rotation = getOrientation().cast<double>().toRotationMatrix();
|
Eigen::Matrix3d rotation = getOrientation().cast<double>().toRotationMatrix();
|
||||||
|
|
||||||
return celmath::testIntersection(
|
return celmath::testIntersection(
|
||||||
celmath::transformRay(Eigen::ParametrizedLine<double, 3>(ray.origin() - getPosition(), ray.direction()),
|
celmath::transformRay(Eigen::ParametrizedLine<double, 3>(ray.origin() - getPosition(), ray.direction()),
|
||||||
rotation),
|
rotation),
|
||||||
|
@ -453,10 +470,8 @@ void Galaxy::render(const Eigen::Vector3f& offset,
|
||||||
const Matrices& ms,
|
const Matrices& ms,
|
||||||
Renderer* renderer)
|
Renderer* renderer)
|
||||||
{
|
{
|
||||||
if (!galacticForms[form].has_value())
|
const GalacticForm* galacticForm = getGalacticFormManager()->getForm(form);
|
||||||
return;
|
if (galacticForm == nullptr) { return; }
|
||||||
|
|
||||||
const GalacticForm& galacticForm = *galacticForms[form];
|
|
||||||
|
|
||||||
/* We'll first see if the galaxy's apparent size is big enough to
|
/* We'll first see if the galaxy's apparent size is big enough to
|
||||||
be noticeable on screen; if it's not we'll break right here,
|
be noticeable on screen; if it's not we'll break right here,
|
||||||
|
@ -507,7 +522,7 @@ void Galaxy::render(const Eigen::Vector3f& offset,
|
||||||
v3.head(3) = viewMat * Eigen::Vector3f(-1, 1, 0) * size;
|
v3.head(3) = viewMat * Eigen::Vector3f(-1, 1, 0) * size;
|
||||||
|
|
||||||
Eigen::Quaternionf orientation = getOrientation().conjugate();
|
Eigen::Quaternionf orientation = getOrientation().conjugate();
|
||||||
Eigen::Matrix3f mScale = galacticForm.scale.asDiagonal() * size;
|
Eigen::Matrix3f mScale = galacticForm->scale.asDiagonal() * size;
|
||||||
Eigen::Matrix3f mLinear = orientation.toRotationMatrix() * mScale;
|
Eigen::Matrix3f mLinear = orientation.toRotationMatrix() * mScale;
|
||||||
|
|
||||||
Eigen::Matrix4f m = Eigen::Matrix4f::Identity();
|
Eigen::Matrix4f m = Eigen::Matrix4f::Identity();
|
||||||
|
@ -516,7 +531,7 @@ void Galaxy::render(const Eigen::Vector3f& offset,
|
||||||
|
|
||||||
int pow2 = 1;
|
int pow2 = 1;
|
||||||
|
|
||||||
const BlobVector& points = galacticForm.blobs;
|
const BlobVector& points = galacticForm->blobs;
|
||||||
unsigned int nPoints = static_cast<unsigned int>(points.size() * std::clamp(getDetail(), 0.0f, 1.0f));
|
unsigned int nPoints = static_cast<unsigned int>(points.size() * std::clamp(getDetail(), 0.0f, 1.0f));
|
||||||
// corrections to avoid excessive brightening if viewed e.g. edge-on
|
// corrections to avoid excessive brightening if viewed e.g. edge-on
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,8 @@ struct GlobularForm
|
||||||
float radius_2d;
|
float radius_2d;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Blob> gblobs;
|
std::vector<Blob> gblobs{ };
|
||||||
Eigen::Vector3f scale;
|
Eigen::Vector3f scale{ };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -330,9 +330,60 @@ GlobularForm buildGlobularForm(float c)
|
||||||
return globularForm;
|
return globularForm;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<GlobularForm> initializeForms()
|
class GlobularInfoManager
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
GlobularInfoManager()
|
||||||
|
{
|
||||||
|
initializeForms();
|
||||||
|
centerTex.fill(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
const GlobularForm* getForm(unsigned int) const;
|
||||||
|
Texture* getCenterTex(unsigned int);
|
||||||
|
Texture* getGlobularTex();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initializeForms();
|
||||||
|
|
||||||
|
std::array<GlobularForm, GlobularBuckets> globularForms{ };
|
||||||
|
std::array<Texture*, GlobularBuckets> centerTex{ };
|
||||||
|
Texture* globularTex{ nullptr };
|
||||||
|
};
|
||||||
|
|
||||||
|
const GlobularForm* GlobularInfoManager::getForm(unsigned int form) const
|
||||||
|
{
|
||||||
|
assert(form < globularForms.size());
|
||||||
|
return &globularForms[form];
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture* GlobularInfoManager::getCenterTex(unsigned int form)
|
||||||
|
{
|
||||||
|
if(centerTex[form] == nullptr)
|
||||||
|
{
|
||||||
|
centerTex[form] = CreateProceduralTexture(cntrTexWidth, cntrTexHeight,
|
||||||
|
celestia::PixelFormat::RGBA,
|
||||||
|
centerCloudTexEval);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(centerTex[form] != nullptr);
|
||||||
|
return centerTex[form];
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture* GlobularInfoManager::getGlobularTex()
|
||||||
|
{
|
||||||
|
if (globularTex == nullptr)
|
||||||
|
{
|
||||||
|
globularTex = CreateProceduralTexture(starTexWidth, starTexHeight,
|
||||||
|
celestia::PixelFormat::RGBA,
|
||||||
|
globularTextureEval);
|
||||||
|
}
|
||||||
|
assert(globularTex != nullptr);
|
||||||
|
return globularTex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobularInfoManager::initializeForms()
|
||||||
|
{
|
||||||
// Build RGB color table, using hue, saturation, value as input.
|
// Build RGB color table, using hue, saturation, value as input.
|
||||||
// Hue in degrees.
|
// Hue in degrees.
|
||||||
|
|
||||||
|
@ -373,16 +424,17 @@ std::vector<GlobularForm> initializeForms()
|
||||||
}
|
}
|
||||||
// Define globularForms corresponding to 8 different bins of King concentration c
|
// Define globularForms corresponding to 8 different bins of King concentration c
|
||||||
|
|
||||||
std::vector<GlobularForm> globularForms;
|
for (unsigned int ic = 0; ic < GlobularBuckets; ++ic)
|
||||||
globularForms.reserve(GlobularBuckets);
|
|
||||||
|
|
||||||
for (unsigned int ic = 0; ic <= 7; ++ic)
|
|
||||||
{
|
{
|
||||||
float CBin = MinC + (static_cast<float>(ic) + 0.5f) * BinWidth;
|
float CBin = MinC + (static_cast<float>(ic) + 0.5f) * BinWidth;
|
||||||
globularForms.push_back(buildGlobularForm(CBin));
|
globularForms[ic] = buildGlobularForm(CBin);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return globularForms;
|
GlobularInfoManager* getGlobularInfoManager()
|
||||||
|
{
|
||||||
|
static GlobularInfoManager* globularInfoManager = new GlobularInfoManager();
|
||||||
|
return globularInfoManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end unnamed namespace
|
} // end unnamed namespace
|
||||||
|
@ -454,8 +506,7 @@ void Globular::setConcentration(const float conc)
|
||||||
c = conc;
|
c = conc;
|
||||||
// For saving time, account for the c dependence via 8 bins only,
|
// For saving time, account for the c dependence via 8 bins only,
|
||||||
|
|
||||||
static const std::vector<GlobularForm> globularForms = initializeForms();
|
form = getGlobularInfoManager()->getForm(cSlot(conc));
|
||||||
form = &globularForms[cSlot(conc)];
|
|
||||||
recomputeTidalRadius();
|
recomputeTidalRadius();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,19 +619,7 @@ void Globular::render(const Eigen::Vector3f& offset,
|
||||||
RRatio = std::pow(10.0f, CBin);
|
RRatio = std::pow(10.0f, CBin);
|
||||||
XI = 1.0f / std::sqrt(1.0f + RRatio * RRatio);
|
XI = 1.0f / std::sqrt(1.0f + RRatio * RRatio);
|
||||||
|
|
||||||
static Texture* centerTex[GlobularBuckets] = {nullptr};
|
GlobularInfoManager* globularInfoManager = getGlobularInfoManager();
|
||||||
if(centerTex[ic] == nullptr)
|
|
||||||
{
|
|
||||||
centerTex[ic] = CreateProceduralTexture(cntrTexWidth, cntrTexHeight,
|
|
||||||
celestia::PixelFormat::RGBA,
|
|
||||||
centerCloudTexEval);
|
|
||||||
}
|
|
||||||
assert(centerTex[ic] != nullptr);
|
|
||||||
|
|
||||||
static Texture* globularTex = CreateProceduralTexture(starTexWidth, starTexHeight,
|
|
||||||
celestia::PixelFormat::RGBA,
|
|
||||||
globularTextureEval);
|
|
||||||
assert(globularTex != nullptr);
|
|
||||||
|
|
||||||
renderer->enableBlending();
|
renderer->enableBlending();
|
||||||
renderer->setBlendingFactors(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
renderer->setBlendingFactors(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
@ -605,7 +644,7 @@ void Globular::render(const Eigen::Vector3f& offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
tidalProg->use();
|
tidalProg->use();
|
||||||
centerTex[ic]->bind();
|
globularInfoManager->getCenterTex(ic)->bind();
|
||||||
|
|
||||||
tidalProg->setMVPMatrices(*m.projection, *m.modelview);
|
tidalProg->setMVPMatrices(*m.projection, *m.modelview);
|
||||||
|
|
||||||
|
@ -630,7 +669,7 @@ void Globular::render(const Eigen::Vector3f& offset,
|
||||||
|
|
||||||
globProg->use();
|
globProg->use();
|
||||||
|
|
||||||
globularTex->bind();
|
globularInfoManager->getGlobularTex()->bind();
|
||||||
globProg->setMVPMatrices(*m.projection, *m.modelview);
|
globProg->setMVPMatrices(*m.projection, *m.modelview);
|
||||||
// TODO: model view matrix should not be reset here
|
// TODO: model view matrix should not be reset here
|
||||||
globProg->ModelViewMatrix = vecgl::translate(*m.modelview, offset);
|
globProg->ModelViewMatrix = vecgl::translate(*m.modelview, offset);
|
||||||
|
|
Loading…
Reference in New Issue