mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-04-24 04:58:59 -05:00
Feature/speck loader (#1585)
* Implement a shared speckfile loader * Apply new speck loader to RenderableBillboardsCloud, RenderablePlanesCloud, RenderablePoints
This commit is contained in:
@@ -52,21 +52,21 @@ namespace {
|
||||
constexpr const char* _loggerCat = "RenderableStars";
|
||||
|
||||
constexpr const std::array<const char*, 17> UniformNames = {
|
||||
"modelMatrix", "cameraUp", "cameraViewProjectionMatrix",
|
||||
"colorOption", "magnitudeExponent", "eyePosition", "psfParamConf",
|
||||
"lumCent", "radiusCent", "brightnessCent", "colorTexture",
|
||||
"alphaValue", "psfTexture", "otherDataTexture", "otherDataRange",
|
||||
"filterOutOfRange", "fixedColor"
|
||||
"modelMatrix", "cameraUp", "cameraViewProjectionMatrix", "colorOption",
|
||||
"magnitudeExponent", "eyePosition", "psfParamConf", "lumCent", "radiusCent",
|
||||
"brightnessCent", "colorTexture", "alphaValue", "psfTexture", "otherDataTexture",
|
||||
"otherDataRange", "filterOutOfRange", "fixedColor"
|
||||
};
|
||||
|
||||
constexpr int8_t CurrentCacheVersion = 3;
|
||||
|
||||
constexpr const int RenderOptionPointSpreadFunction = 0;
|
||||
constexpr const int RenderOptionTexture = 1;
|
||||
|
||||
constexpr const int PsfMethodSpencer = 0;
|
||||
constexpr const int PsfMethodMoffat = 1;
|
||||
|
||||
constexpr const int PsfTextureSize = 64;
|
||||
constexpr const int ConvolvedfTextureSize = 257;
|
||||
|
||||
constexpr double PARSEC = 0.308567756E17;
|
||||
|
||||
struct ColorVBOLayout {
|
||||
@@ -159,12 +159,6 @@ namespace {
|
||||
"or filtered away"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo EnableTestGridInfo = {
|
||||
"EnableTestGrid",
|
||||
"Enable Test Grid",
|
||||
"Set it to true for rendering the test grid."
|
||||
};
|
||||
|
||||
// Old Method
|
||||
constexpr openspace::properties::Property::PropertyInfo PsfTextureInfo = {
|
||||
"Texture",
|
||||
@@ -173,11 +167,11 @@ namespace {
|
||||
"stars."
|
||||
};
|
||||
|
||||
/*constexpr openspace::properties::Property::PropertyInfo ShapeTextureInfo = {
|
||||
"ShapeTexture",
|
||||
"Shape Texture to be convolved",
|
||||
"The path to the texture that should be used as the base shape for the stars."
|
||||
};*/
|
||||
//constexpr openspace::properties::Property::PropertyInfo ShapeTextureInfo = {
|
||||
// "ShapeTexture",
|
||||
// "Shape Texture to be convolved",
|
||||
// "The path to the texture that should be used as the base shape for the stars."
|
||||
//};
|
||||
|
||||
// PSF
|
||||
constexpr openspace::properties::Property::PropertyInfo MagnitudeExponentInfo = {
|
||||
@@ -344,17 +338,28 @@ namespace {
|
||||
// [[codegen::verbatim(MagnitudeExponentInfo.description)]]
|
||||
std::optional<float> magnitudeExponent;
|
||||
|
||||
// [[codegen::verbatim(EnableTestGridInfo.description)]]
|
||||
std::optional<bool> enableTestGrid;
|
||||
enum class RenderMethod {
|
||||
PSF,
|
||||
TextureBased [[codegen::key("Texture Based")]]
|
||||
};
|
||||
|
||||
// [[codegen::verbatim(RenderMethodOptionInfo.description)]]
|
||||
std::string renderMethod;
|
||||
RenderMethod renderMethod;
|
||||
|
||||
// [[codegen::verbatim(PsfTextureInfo.description)]]
|
||||
std::filesystem::path texture;
|
||||
|
||||
enum class SizeComposition {
|
||||
AppBrightness [[codegen::key("App Brightness")]],
|
||||
LumSize [[codegen::key("Lum and Size")]],
|
||||
LumSizeAppBrightness [[codegen::key("Lum, Size and App Brightness")]],
|
||||
AbsMagnitude [[codegen::key("Abs Magnitude")]],
|
||||
AppMagnitude [[codegen::key("App Magnitude")]],
|
||||
DistanceModulus [[codegen::key("Distance Modulus")]]
|
||||
};
|
||||
|
||||
// [[codegen::verbatim(SizeCompositionOptionInfo.description)]]
|
||||
std::optional<std::string> sizeComposition;
|
||||
std::optional<SizeComposition> sizeComposition;
|
||||
|
||||
// [[codegen::verbatim(FadeInDistancesInfo.description)]]
|
||||
std::optional<glm::dvec2> fadeInDistances;
|
||||
@@ -487,13 +492,6 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
_colorTextureFile->setCallback([this]() { _colorTextureIsDirty = true; });
|
||||
addProperty(_colorTexturePath);
|
||||
|
||||
/*_shapeTexturePath.onChange([&] { _shapeTextureIsDirty = true; });
|
||||
_shapeTextureFile->setCallback([&](const File&) {
|
||||
_shapeTextureIsDirty = true;
|
||||
});
|
||||
addProperty(_shapeTexturePath);*/
|
||||
|
||||
_enableTestGrid = p.enableTestGrid.value_or(_enableTestGrid);
|
||||
_queuedOtherData = p.otherData.value_or(_queuedOtherData);
|
||||
|
||||
_otherDataOption.onChange([&]() { _dataIsDirty = true; });
|
||||
@@ -517,10 +515,10 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
_renderingMethodOption.addOption(RenderOptionTexture, "Textured Based");
|
||||
addProperty(_renderingMethodOption);
|
||||
|
||||
if (p.renderMethod == "PSF") {
|
||||
if (p.renderMethod == Parameters::RenderMethod::PSF) {
|
||||
_renderingMethodOption = RenderOptionPointSpreadFunction;
|
||||
}
|
||||
else if (p.renderMethod == "Texture Based") {
|
||||
else {
|
||||
_renderingMethodOption = RenderOptionTexture;
|
||||
}
|
||||
|
||||
@@ -551,23 +549,25 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
|
||||
|
||||
if (p.sizeComposition.has_value()) {
|
||||
if (*p.sizeComposition == "App Brightness") {
|
||||
_psfMultiplyOption = 0;
|
||||
}
|
||||
else if (*p.sizeComposition == "Lum and Size") {
|
||||
_psfMultiplyOption = 1;
|
||||
}
|
||||
else if (*p.sizeComposition == "Lum, Size and App Brightness") {
|
||||
_psfMultiplyOption = 2;
|
||||
}
|
||||
else if (*p.sizeComposition == "Abs Magnitude") {
|
||||
_psfMultiplyOption = 3;
|
||||
}
|
||||
else if (*p.sizeComposition == "App Maginitude") {
|
||||
_psfMultiplyOption = 4;
|
||||
}
|
||||
else if (*p.sizeComposition == "Distance Modulus") {
|
||||
_psfMultiplyOption = 5;
|
||||
switch (*p.sizeComposition) {
|
||||
case Parameters::SizeComposition::AppBrightness:
|
||||
_psfMultiplyOption = 0;
|
||||
break;
|
||||
case Parameters::SizeComposition::LumSize:
|
||||
_psfMultiplyOption = 1;
|
||||
break;
|
||||
case Parameters::SizeComposition::LumSizeAppBrightness:
|
||||
_psfMultiplyOption = 2;
|
||||
break;
|
||||
case Parameters::SizeComposition::AbsMagnitude:
|
||||
_psfMultiplyOption = 3;
|
||||
break;
|
||||
case Parameters::SizeComposition::AppMagnitude:
|
||||
_psfMultiplyOption = 4;
|
||||
break;
|
||||
case Parameters::SizeComposition::DistanceModulus:
|
||||
_psfMultiplyOption = 5;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -632,13 +632,16 @@ void RenderableStars::initializeGL() {
|
||||
|
||||
loadData();
|
||||
|
||||
// We need to wait until after loading the data until we can see if the requested
|
||||
// data value actually exists or not. Once we determine the index, we no longer
|
||||
// need the value and can clear it
|
||||
if (!_queuedOtherData.empty()) {
|
||||
auto it = std::find(_dataNames.begin(), _dataNames.end(), _queuedOtherData);
|
||||
if (it == _dataNames.end()) {
|
||||
int idx = _dataset.index(_queuedOtherData);
|
||||
if (idx == -1) {
|
||||
LERROR(fmt::format("Could not find other data column {}", _queuedOtherData));
|
||||
}
|
||||
else {
|
||||
_otherDataOption = static_cast<int>(std::distance(_dataNames.begin(), it));
|
||||
_otherDataOption = idx;
|
||||
_queuedOtherData.clear();
|
||||
}
|
||||
}
|
||||
@@ -651,7 +654,7 @@ void RenderableStars::initializeGL() {
|
||||
glBindVertexArray(_psfVao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _psfVbo);
|
||||
|
||||
const GLfloat vertexData[] = {
|
||||
constexpr const std::array<GLfloat, 24> VertexData = {
|
||||
//x y s t
|
||||
-1.f, -1.f, 0.f, 0.f,
|
||||
1.f, 1.f, 1.f, 1.f,
|
||||
@@ -661,15 +664,8 @@ void RenderableStars::initializeGL() {
|
||||
1.f, 1.f, 1.f, 1.f
|
||||
};
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(
|
||||
0,
|
||||
4,
|
||||
GL_FLOAT,
|
||||
GL_FALSE,
|
||||
sizeof(GLfloat) * 4,
|
||||
nullptr
|
||||
);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(VertexData), VertexData.data(), GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), nullptr);
|
||||
glEnableVertexAttribArray(0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
@@ -685,8 +681,8 @@ void RenderableStars::initializeGL() {
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGBA8,
|
||||
_psfTextureSize,
|
||||
_psfTextureSize,
|
||||
PsfTextureSize,
|
||||
PsfTextureSize,
|
||||
0,
|
||||
GL_RGBA,
|
||||
GL_BYTE,
|
||||
@@ -708,8 +704,8 @@ void RenderableStars::initializeGL() {
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGBA8,
|
||||
_convolvedfTextureSize,
|
||||
_convolvedfTextureSize,
|
||||
ConvolvedfTextureSize,
|
||||
ConvolvedfTextureSize,
|
||||
0,
|
||||
GL_RGBA,
|
||||
GL_BYTE,
|
||||
@@ -747,8 +743,7 @@ void RenderableStars::loadPSFTexture() {
|
||||
|
||||
if (_pointSpreadFunctionTexture) {
|
||||
LDEBUG(fmt::format(
|
||||
"Loaded texture from '{}'",
|
||||
absPath(_pointSpreadFunctionTexturePath)
|
||||
"Loaded texture from '{}'", absPath(_pointSpreadFunctionTexturePath)
|
||||
));
|
||||
_pointSpreadFunctionTexture->uploadTexture();
|
||||
}
|
||||
@@ -760,21 +755,13 @@ void RenderableStars::loadPSFTexture() {
|
||||
_pointSpreadFunctionTexturePath.value()
|
||||
);
|
||||
_pointSpreadFunctionFile->setCallback(
|
||||
[this]() { _pointSpreadFunctionTextureIsDirty = true; }
|
||||
[&]() { _pointSpreadFunctionTextureIsDirty = true; }
|
||||
);
|
||||
}
|
||||
_pointSpreadFunctionTextureIsDirty = false;
|
||||
|
||||
}
|
||||
|
||||
void RenderableStars::renderPSFToTexture() {
|
||||
// Saves current FBO first
|
||||
// GLint defaultFBO;
|
||||
// defaultFBO = global::renderEngine->openglStateCache().defaultFramebuffer();
|
||||
|
||||
// GLint m_viewport[4];
|
||||
// global::renderEngine.openglStateCache().viewPort(m_viewport);
|
||||
|
||||
// Creates the FBO for the calculations
|
||||
GLuint psfFBO;
|
||||
glGenFramebuffers(1, &psfFBO);
|
||||
@@ -783,9 +770,7 @@ void RenderableStars::renderPSFToTexture() {
|
||||
glDrawBuffers(1, drawBuffers);
|
||||
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _psfTexture, 0);
|
||||
|
||||
glViewport(0, 0, _psfTextureSize, _psfTextureSize);
|
||||
|
||||
glViewport(0, 0, PsfTextureSize, PsfTextureSize);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
std::unique_ptr<ghoul::opengl::ProgramObject> program =
|
||||
@@ -796,8 +781,8 @@ void RenderableStars::renderPSFToTexture() {
|
||||
);
|
||||
|
||||
program->activate();
|
||||
constexpr const float black[] = { 0.f, 0.f, 0.f, 0.f };
|
||||
glClearBufferfv(GL_COLOR, 0, black);
|
||||
constexpr const std::array<float, 4> Black = { 0.f, 0.f, 0.f, 0.f };
|
||||
glClearBufferfv(GL_COLOR, 0, Black.data());
|
||||
|
||||
program->setUniform("psfMethod", _psfMethodOption.value());
|
||||
program->setUniform("p0Param", _p0Param);
|
||||
@@ -871,7 +856,7 @@ void RenderableStars::renderPSFToTexture() {
|
||||
// m_viewport[2],
|
||||
// m_viewport[3]
|
||||
//);
|
||||
//glDeleteFramebuffers(1, &psfFBO);
|
||||
glDeleteFramebuffers(1, &psfFBO);
|
||||
//glDeleteFramebuffers(1, &convolveFBO);
|
||||
|
||||
// Restores OpenGL blending state
|
||||
@@ -879,7 +864,7 @@ void RenderableStars::renderPSFToTexture() {
|
||||
}
|
||||
|
||||
void RenderableStars::render(const RenderData& data, RendererTasks&) {
|
||||
if (_fullData.empty()) {
|
||||
if (_dataset.entries.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -979,7 +964,7 @@ void RenderableStars::render(const RenderData& data, RendererTasks&) {
|
||||
|
||||
|
||||
glBindVertexArray(_vao);
|
||||
const GLsizei nStars = static_cast<GLsizei>(_fullData.size() / _nValuesPerStar);
|
||||
const GLsizei nStars = static_cast<GLsizei>(_dataset.entries.size());
|
||||
glDrawArrays(GL_POINTS, 0, nStars);
|
||||
|
||||
glBindVertexArray(0);
|
||||
@@ -997,7 +982,7 @@ void RenderableStars::update(const UpdateData&) {
|
||||
_dataIsDirty = true;
|
||||
}
|
||||
|
||||
if (_fullData.empty()) {
|
||||
if (_dataset.entries.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1005,9 +990,7 @@ void RenderableStars::update(const UpdateData&) {
|
||||
const int value = _colorOption;
|
||||
LDEBUG("Regenerating data");
|
||||
|
||||
createDataSlice(ColorOption(value));
|
||||
|
||||
int size = static_cast<int>(_slicedData.size());
|
||||
std::vector<float> slice = createDataSlice(ColorOption(value));
|
||||
|
||||
if (_vao == 0) {
|
||||
glGenVertexArrays(1, &_vao);
|
||||
@@ -1019,8 +1002,8 @@ void RenderableStars::update(const UpdateData&) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
||||
glBufferData(
|
||||
GL_ARRAY_BUFFER,
|
||||
size * sizeof(GLfloat),
|
||||
_slicedData.data(),
|
||||
slice.size() * sizeof(GLfloat),
|
||||
slice.data(),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
|
||||
@@ -1030,8 +1013,8 @@ void RenderableStars::update(const UpdateData&) {
|
||||
"in_bvLumAbsMagAppMag"
|
||||
);
|
||||
|
||||
const size_t nStars = _fullData.size() / _nValuesPerStar;
|
||||
const size_t nValues = _slicedData.size() / nStars;
|
||||
const size_t nStars = _dataset.entries.size();
|
||||
const size_t nValues = slice.size() / nStars;
|
||||
|
||||
GLsizei stride = static_cast<GLsizei>(sizeof(GLfloat) * nValues);
|
||||
|
||||
@@ -1204,276 +1187,39 @@ void RenderableStars::update(const UpdateData&) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void RenderableStars::loadShapeTexture() {
|
||||
if (_shapeTextureIsDirty) {
|
||||
LDEBUG("Reloading Shape Texture");
|
||||
_shapeTexture = nullptr;
|
||||
if (_shapeTexturePath.value() != "") {
|
||||
_shapeTexture = ghoul::io::TextureReader::ref().loadTexture(
|
||||
absPath(_shapeTexturePath)
|
||||
);
|
||||
if (_shapeTexture) {
|
||||
LDEBUG(fmt::format(
|
||||
"Loaded texture from '{}'",
|
||||
absPath(_shapeTexturePath)
|
||||
));
|
||||
_shapeTexture->uploadTexture();
|
||||
}
|
||||
|
||||
_shapeTextureFile = std::make_unique<ghoul::filesystem::File>(
|
||||
_shapeTexturePath
|
||||
);
|
||||
_shapeTextureFile->setCallback(
|
||||
[&](const ghoul::filesystem::File&) { _shapeTextureIsDirty = true; }
|
||||
);
|
||||
}
|
||||
_shapeTextureIsDirty = false;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void RenderableStars::loadData() {
|
||||
std::filesystem::path file = absPath(_speckFile);
|
||||
if (!std::filesystem::is_regular_file(file)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_nValuesPerStar = 0;
|
||||
_slicedData.clear();
|
||||
_fullData.clear();
|
||||
_dataNames.clear();
|
||||
|
||||
std::string cachedFile = FileSys.cacheManager()->cachedFilename(file);
|
||||
bool hasCachedFile = std::filesystem::is_regular_file(cachedFile);
|
||||
if (hasCachedFile) {
|
||||
LINFO(fmt::format("Cached file '{}' used for Speck file {}",
|
||||
cachedFile, file
|
||||
));
|
||||
|
||||
bool success = loadCachedFile(cachedFile);
|
||||
if (success) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
FileSys.cacheManager()->removeCacheFile(file);
|
||||
// Intentional fall-through to the 'else' computation to generate the cache
|
||||
// file for the next run
|
||||
}
|
||||
}
|
||||
else {
|
||||
LINFO(fmt::format("Cache for Speck file {} not found", file));
|
||||
}
|
||||
LINFO(fmt::format("Loading Speck file {}", file));
|
||||
|
||||
readSpeckFile();
|
||||
|
||||
LINFO("Saving cache");
|
||||
saveCachedFile(cachedFile);
|
||||
}
|
||||
|
||||
void RenderableStars::readSpeckFile() {
|
||||
std::filesystem::path filename = _speckFile.value();
|
||||
std::ifstream file(filename);
|
||||
if (!file.good()) {
|
||||
LERROR(fmt::format("Failed to open Speck file {}", filename));
|
||||
_dataset = speck::data::loadFileWithCache(file);
|
||||
if (_dataset.entries.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The beginning of the speck file has a header that either contains comments
|
||||
// (signaled by a preceding '#') or information about the structure of the file
|
||||
// (signaled by the keywords 'datavar', 'texturevar', and 'texture')
|
||||
std::string line;
|
||||
while (true) {
|
||||
std::streampos position = file.tellg();
|
||||
std::getline(file, line, '\n');
|
||||
|
||||
if (line[0] == '#' || line.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.substr(0, 7) != "datavar" &&
|
||||
line.substr(0, 10) != "texturevar" &&
|
||||
line.substr(0, 7) != "texture")
|
||||
{
|
||||
// we read a line that doesn't belong to the header, so we have to jump back
|
||||
// before the beginning of the current line
|
||||
if (_enableTestGrid) {
|
||||
file.seekg(position - std::streamoff(8));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (line.substr(0, 7) == "datavar") {
|
||||
// datavar lines are structured as follows:
|
||||
// datavar # description
|
||||
// where # is the index of the data variable; so if we repeatedly overwrite
|
||||
// the 'nValues' variable with the latest index, we will end up with the total
|
||||
// number of values (+3 since X Y Z are not counted in the Speck file index)
|
||||
std::stringstream str(line);
|
||||
|
||||
std::string dummy;
|
||||
str >> dummy;
|
||||
str >> _nValuesPerStar;
|
||||
|
||||
std::string name;
|
||||
str >> name;
|
||||
_dataNames.push_back(name);
|
||||
|
||||
// +3 because the position x, y, z
|
||||
if (name == "lum") {
|
||||
_lumArrayPos = _nValuesPerStar + 3;
|
||||
}
|
||||
else if (name == "absmag") {
|
||||
_absMagArrayPos = _nValuesPerStar + 3;
|
||||
}
|
||||
else if (name == "appmag") {
|
||||
_appMagArrayPos = _nValuesPerStar + 3;
|
||||
}
|
||||
else if (name == "colorb_v") {
|
||||
_bvColorArrayPos = _nValuesPerStar + 3;
|
||||
}
|
||||
else if (name == "vx") {
|
||||
_velocityArrayPos = _nValuesPerStar + 3;
|
||||
}
|
||||
else if (name == "speed") {
|
||||
_speedArrayPos = _nValuesPerStar + 3;
|
||||
}
|
||||
_nValuesPerStar += 1; // We want the number, but the index is 0 based
|
||||
}
|
||||
std::vector<std::string> variableNames;
|
||||
variableNames.reserve(_dataset.variables.size());
|
||||
for (const speck::Dataset::Variable& v : _dataset.variables) {
|
||||
variableNames.push_back(v.name);
|
||||
}
|
||||
_otherDataOption.addOptions(variableNames);
|
||||
|
||||
_nValuesPerStar += 3; // X Y Z are not counted in the Speck file indices
|
||||
_otherDataOption.addOptions(_dataNames);
|
||||
|
||||
float minLumValue = std::numeric_limits<float>::max();
|
||||
float maxLumValue = std::numeric_limits<float>::min();
|
||||
|
||||
do {
|
||||
std::vector<float> values(_nValuesPerStar);
|
||||
std::stringstream str(line);
|
||||
|
||||
for (int i = 0; i < _nValuesPerStar; ++i) {
|
||||
str >> values[i];
|
||||
}
|
||||
|
||||
bool nullArray = true;
|
||||
for (float v : values) {
|
||||
if (v != 0.0) {
|
||||
nullArray = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
minLumValue = values[_lumArrayPos] < minLumValue ?
|
||||
values[_lumArrayPos] : minLumValue;
|
||||
maxLumValue = values[_lumArrayPos] > maxLumValue ?
|
||||
values[_lumArrayPos] : maxLumValue;
|
||||
if (!nullArray) {
|
||||
_fullData.insert(_fullData.end(), values.begin(), values.end());
|
||||
}
|
||||
|
||||
std::getline(file, line, '\n');
|
||||
|
||||
} while (!file.eof());
|
||||
|
||||
// Normalize Luminosity:
|
||||
for (size_t i = 0; i < _fullData.size(); i += _nValuesPerStar) {
|
||||
_fullData[i + _lumArrayPos] =
|
||||
(_fullData[i + _lumArrayPos] - minLumValue) / (maxLumValue - minLumValue);
|
||||
bool success = _dataset.normalizeVariable("lum");
|
||||
if (!success) {
|
||||
throw ghoul::RuntimeError("Could not find required variable 'luminosity'");
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderableStars::loadCachedFile(const std::string& file) {
|
||||
std::ifstream fileStream(file, std::ifstream::binary);
|
||||
if (fileStream.good()) {
|
||||
int8_t version = 0;
|
||||
fileStream.read(reinterpret_cast<char*>(&version), sizeof(int8_t));
|
||||
if (version != CurrentCacheVersion) {
|
||||
LINFO("The format of the cached file has changed: deleting old cache");
|
||||
fileStream.close();
|
||||
if (std::filesystem::is_regular_file(file)) {
|
||||
std::filesystem::remove(file);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t nValues = 0;
|
||||
fileStream.read(reinterpret_cast<char*>(&nValues), sizeof(int32_t));
|
||||
fileStream.read(reinterpret_cast<char*>(&_nValuesPerStar), sizeof(int32_t));
|
||||
|
||||
fileStream.read(reinterpret_cast<char*>(&_lumArrayPos), sizeof(int32_t));
|
||||
fileStream.read(reinterpret_cast<char*>(&_absMagArrayPos), sizeof(int32_t));
|
||||
fileStream.read(reinterpret_cast<char*>(&_appMagArrayPos), sizeof(int32_t));
|
||||
fileStream.read(reinterpret_cast<char*>(&_bvColorArrayPos), sizeof(int32_t));
|
||||
fileStream.read(reinterpret_cast<char*>(&_velocityArrayPos), sizeof(int32_t));
|
||||
fileStream.read(reinterpret_cast<char*>(&_speedArrayPos), sizeof(int32_t));
|
||||
|
||||
for (int i = 0; i < _nValuesPerStar - 3; ++i) {
|
||||
uint16_t len;
|
||||
fileStream.read(reinterpret_cast<char*>(&len), sizeof(uint16_t));
|
||||
std::vector<char> buffer(len);
|
||||
fileStream.read(buffer.data(), len);
|
||||
std::string value(buffer.begin(), buffer.end());
|
||||
_dataNames.push_back(value);
|
||||
}
|
||||
_otherDataOption.addOptions(_dataNames);
|
||||
|
||||
_fullData.resize(nValues);
|
||||
fileStream.read(reinterpret_cast<char*>(
|
||||
_fullData.data()),
|
||||
nValues * sizeof(_fullData[0])
|
||||
);
|
||||
|
||||
bool success = fileStream.good();
|
||||
return success;
|
||||
}
|
||||
else {
|
||||
LERROR(fmt::format("Error opening file '{}' for loading cache file", file));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableStars::saveCachedFile(const std::string& file) const {
|
||||
std::ofstream fileStream(file, std::ofstream::binary);
|
||||
|
||||
if (!fileStream.good()) {
|
||||
LERROR(fmt::format("Error opening file '{}' for save cache file", file));
|
||||
return;
|
||||
}
|
||||
|
||||
fileStream.write(
|
||||
reinterpret_cast<const char*>(&CurrentCacheVersion),
|
||||
sizeof(int8_t)
|
||||
);
|
||||
|
||||
int32_t nValues = static_cast<int32_t>(_fullData.size());
|
||||
if (nValues == 0) {
|
||||
throw ghoul::RuntimeError("Error writing cache: No values were loaded");
|
||||
}
|
||||
fileStream.write(reinterpret_cast<const char*>(&nValues), sizeof(int32_t));
|
||||
|
||||
int32_t nValuesPerStar = static_cast<int32_t>(_nValuesPerStar);
|
||||
fileStream.write(reinterpret_cast<const char*>(&nValuesPerStar), sizeof(int32_t));
|
||||
fileStream.write(reinterpret_cast<const char*>(&_lumArrayPos), sizeof(int32_t));
|
||||
fileStream.write(reinterpret_cast<const char*>(&_absMagArrayPos), sizeof(int32_t));
|
||||
fileStream.write(reinterpret_cast<const char*>(&_appMagArrayPos), sizeof(int32_t));
|
||||
fileStream.write(reinterpret_cast<const char*>(&_bvColorArrayPos), sizeof(int32_t));
|
||||
fileStream.write(reinterpret_cast<const char*>(&_velocityArrayPos), sizeof(int32_t));
|
||||
fileStream.write(reinterpret_cast<const char*>(&_speedArrayPos), sizeof(int32_t));
|
||||
|
||||
// -3 as we don't want to save the xyz values that are in the beginning of the file
|
||||
for (int i = 0; i < _nValuesPerStar - 3; ++i) {
|
||||
uint16_t len = static_cast<uint16_t>(_dataNames[i].size());
|
||||
fileStream.write(reinterpret_cast<const char*>(&len), sizeof(uint16_t));
|
||||
fileStream.write(_dataNames[i].c_str(), len);
|
||||
}
|
||||
|
||||
size_t nBytes = nValues * sizeof(_fullData[0]);
|
||||
fileStream.write(reinterpret_cast<const char*>(_fullData.data()), nBytes);
|
||||
}
|
||||
|
||||
void RenderableStars::createDataSlice(ColorOption option) {
|
||||
_slicedData.clear();
|
||||
std::vector<float> RenderableStars::createDataSlice(ColorOption option) {
|
||||
const int bvIdx = std::max(_dataset.index("colorb_v"), 0);
|
||||
const int lumIdx = std::max(_dataset.index("lum"), 0);
|
||||
const int absMagIdx = std::max(_dataset.index("absmag"), 0);
|
||||
const int appMagIdx = std::max(_dataset.index("appmag"), 0);
|
||||
const int vxIdx = std::max(_dataset.index("vx"), 0);
|
||||
const int vyIdx = std::max(_dataset.index("vy"), 0);
|
||||
const int vzIdx = std::max(_dataset.index("vz"), 0);
|
||||
const int speedIdx = std::max(_dataset.index("speed"), 0);
|
||||
|
||||
_otherDataRange = glm::vec2(
|
||||
std::numeric_limits<float>::max(),
|
||||
@@ -1482,18 +1228,12 @@ void RenderableStars::createDataSlice(ColorOption option) {
|
||||
|
||||
double maxRadius = 0.0;
|
||||
|
||||
for (size_t i = 0; i < _fullData.size(); i += _nValuesPerStar) {
|
||||
glm::dvec3 position = glm::dvec3(
|
||||
_fullData[i + 0],
|
||||
_fullData[i + 1],
|
||||
_fullData[i + 2]
|
||||
);
|
||||
position *= openspace::distanceconstants::Parsec;
|
||||
|
||||
const double r = glm::length(position);
|
||||
if (r > maxRadius) {
|
||||
maxRadius = r;
|
||||
}
|
||||
std::vector<float> result;
|
||||
// 7 for the default Color option of 3 positions + bv + lum + abs + app magnitude
|
||||
result.reserve(_dataset.entries.size() * 7);
|
||||
for (const speck::Dataset::Entry& e : _dataset.entries) {
|
||||
glm::dvec3 position = glm::dvec3(e.position) * distanceconstants::Parsec;
|
||||
maxRadius = std::max(maxRadius, glm::length(position));
|
||||
|
||||
switch (option) {
|
||||
case ColorOption::Color:
|
||||
@@ -1510,23 +1250,12 @@ void RenderableStars::createDataSlice(ColorOption option) {
|
||||
static_cast<float>(position[2])
|
||||
}};
|
||||
|
||||
if (_enableTestGrid) {
|
||||
float sunColor = 0.650f;
|
||||
layout.value.value = sunColor;// _fullData[i + 3];
|
||||
}
|
||||
else {
|
||||
layout.value.value = _fullData[i + _bvColorArrayPos];
|
||||
}
|
||||
|
||||
layout.value.luminance = _fullData[i + _lumArrayPos];
|
||||
layout.value.absoluteMagnitude = _fullData[i + _absMagArrayPos];
|
||||
layout.value.apparentMagnitude = _fullData[i + _appMagArrayPos];
|
||||
|
||||
_slicedData.insert(
|
||||
_slicedData.end(),
|
||||
layout.data.begin(),
|
||||
layout.data.end());
|
||||
layout.value.value = e.data[bvIdx];
|
||||
layout.value.luminance = e.data[lumIdx];
|
||||
layout.value.absoluteMagnitude = e.data[absMagIdx];
|
||||
layout.value.apparentMagnitude = e.data[appMagIdx];
|
||||
|
||||
result.insert(result.end(), layout.data.begin(), layout.data.end());
|
||||
break;
|
||||
}
|
||||
case ColorOption::Velocity:
|
||||
@@ -1542,20 +1271,16 @@ void RenderableStars::createDataSlice(ColorOption option) {
|
||||
static_cast<float>(position[2])
|
||||
}};
|
||||
|
||||
layout.value.value = _fullData[i + _bvColorArrayPos];
|
||||
layout.value.luminance = _fullData[i + _lumArrayPos];
|
||||
layout.value.absoluteMagnitude = _fullData[i + _absMagArrayPos];
|
||||
layout.value.apparentMagnitude = _fullData[i + _appMagArrayPos];
|
||||
layout.value.value = e.data[bvIdx];
|
||||
layout.value.luminance = e.data[lumIdx];
|
||||
layout.value.absoluteMagnitude = e.data[absMagIdx];
|
||||
layout.value.apparentMagnitude = e.data[appMagIdx];
|
||||
|
||||
layout.value.vx = _fullData[i + _velocityArrayPos];
|
||||
layout.value.vy = _fullData[i + _velocityArrayPos + 1];
|
||||
layout.value.vz = _fullData[i + _velocityArrayPos + 2];
|
||||
layout.value.vx = e.data[vxIdx];
|
||||
layout.value.vy = e.data[vyIdx];
|
||||
layout.value.vz = e.data[vzIdx];
|
||||
|
||||
_slicedData.insert(
|
||||
_slicedData.end(),
|
||||
layout.data.begin(),
|
||||
layout.data.end()
|
||||
);
|
||||
result.insert(result.end(), layout.data.begin(), layout.data.end());
|
||||
break;
|
||||
}
|
||||
case ColorOption::Speed:
|
||||
@@ -1571,18 +1296,13 @@ void RenderableStars::createDataSlice(ColorOption option) {
|
||||
static_cast<float>(position[2])
|
||||
}};
|
||||
|
||||
layout.value.value = _fullData[i + _bvColorArrayPos];
|
||||
layout.value.luminance = _fullData[i + _lumArrayPos];
|
||||
layout.value.absoluteMagnitude = _fullData[i + _absMagArrayPos];
|
||||
layout.value.apparentMagnitude = _fullData[i + _appMagArrayPos];
|
||||
layout.value.value = e.data[bvIdx];
|
||||
layout.value.luminance = e.data[lumIdx];
|
||||
layout.value.absoluteMagnitude = e.data[absMagIdx];
|
||||
layout.value.apparentMagnitude = e.data[appMagIdx];
|
||||
layout.value.speed = e.data[speedIdx];
|
||||
|
||||
layout.value.speed = _fullData[i + _speedArrayPos];
|
||||
|
||||
_slicedData.insert(
|
||||
_slicedData.end(),
|
||||
layout.data.begin(),
|
||||
layout.data.end()
|
||||
);
|
||||
result.insert(result.end(), layout.data.begin(), layout.data.end());
|
||||
break;
|
||||
}
|
||||
case ColorOption::OtherData:
|
||||
@@ -1600,37 +1320,32 @@ void RenderableStars::createDataSlice(ColorOption option) {
|
||||
|
||||
int index = _otherDataOption.value();
|
||||
// plus 3 because of the position
|
||||
layout.value.value = _fullData[i + index + 3];
|
||||
layout.value.value = e.data[index];
|
||||
|
||||
if (_staticFilterValue.has_value() &&
|
||||
layout.value.value == _staticFilterValue)
|
||||
if (_staticFilterValue.has_value() && e.data[index] == _staticFilterValue)
|
||||
{
|
||||
layout.value.value = _staticFilterReplacementValue;
|
||||
}
|
||||
|
||||
glm::vec2 range = _otherDataRange.value();
|
||||
glm::vec2 range = _otherDataRange;
|
||||
range.x = std::min(range.x, layout.value.value);
|
||||
range.y = std::max(range.y, layout.value.value);
|
||||
_otherDataRange = range;
|
||||
_otherDataRange.setMinValue(glm::vec2(range.x));
|
||||
_otherDataRange.setMaxValue(glm::vec2(range.y));
|
||||
|
||||
layout.value.luminance = _fullData[i + _lumArrayPos];
|
||||
layout.value.absoluteMagnitude = _fullData[i + _absMagArrayPos];
|
||||
layout.value.apparentMagnitude = _fullData[i + _appMagArrayPos];
|
||||
|
||||
_slicedData.insert(
|
||||
_slicedData.end(),
|
||||
layout.data.begin(),
|
||||
layout.data.end()
|
||||
);
|
||||
layout.value.luminance = e.data[lumIdx];
|
||||
layout.value.absoluteMagnitude = e.data[absMagIdx];
|
||||
layout.value.apparentMagnitude = e.data[appMagIdx];
|
||||
|
||||
result.insert(result.end(), layout.data.begin(), layout.data.end());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setBoundingSphere(maxRadius);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
Reference in New Issue
Block a user