diff --git a/include/openspace/rendering/stars/renderableconstellationbounds.h b/include/openspace/rendering/stars/renderableconstellationbounds.h index 9e57b54618..1735e627f8 100644 --- a/include/openspace/rendering/stars/renderableconstellationbounds.h +++ b/include/openspace/rendering/stars/renderableconstellationbounds.h @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -43,12 +44,11 @@ namespace openspace { * Renderable configuration attributes: * File [string] (required): The file that contains the bounds and the * abbreviations for the different constellations + * ConstellationFile [string]: The file that contains the mapping between + * abbreviations and full names. If the file is omitted, the abbreviations are used as the + * full names. * ReferenceFrame [string]: The reference frame in which the points contained * in the File are stored in. Defaults to J2000 - * - * @TODO Add a method to load (and access) a table translating from abbreviations to - * full names ---abock - * @TODO Make it possible to only show a subset of constellation bounds ---abock */ class RenderableConstellationBounds : public Renderable { public: @@ -65,21 +65,40 @@ public: private: /// Stores the constellation bounds struct ConstellationBound { - std::string constellation; ///< The abbreviation of the constellation + std::string constellationAbbreviation; ///< The abbreviation of the constellation + std::string constellationFullName; + bool isEnabled; size_t startIndex; ///< The index of the first vertex describing the bounds size_t nVertices; ///< The number of vertices describing the bounds }; /** - * Loads the file specified in _filename and fills the + * Loads the file specified in _vertexFilename and fills the * _constellationBounds variable, as well as the * _vertexValues list. If this method fails, the content of either * destination is undefined. * \return true if the loading succeeded, false otherwise */ - bool loadFile(); + bool loadVertexFile(); - std::string _filename; ///< The filename containing the constellation bounds + /** + * Loads the file specified in _constellationFilename that contains the + * mapping between abbreviations and full names of constellations. + * \return true if the loading succeeded, false otherwise + */ + bool loadConstellationFile(); + + /// Fills the _constellationSelection property with all constellations + void fillSelectionProperty(); + + /** + * Callback method that gets triggered when _constellationSelection + * changes. + */ + void selectionPropertyHasChanged(); + + std::string _vertexFilename; ///< The filename containing the constellation bounds + std::string _constellationFilename; ///< The file containing constellation names ghoul::opengl::ProgramObject* _program; bool _programIsDirty; @@ -93,6 +112,9 @@ private: /// The radius of the celestial sphere onto which the bounds are drawn properties::FloatProperty _distance; + /// The property that stores all indices of constellations that should be drawn + properties::SelectionProperty _constellationSelection; + std::string _originReferenceFrame; ///< Reference frame in which bounds are defined /// Used to translate between the origin reference frame and the target frame diff --git a/openspace-data b/openspace-data index 20da238d5a..07ef85b86b 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit 20da238d5a5d903918e8346bff40f1ae9ac5ea59 +Subproject commit 07ef85b86b2a65dbce718055f56ddb23a588da3c diff --git a/src/rendering/stars/renderableconstellationbounds.cpp b/src/rendering/stars/renderableconstellationbounds.cpp index 6036bc3a34..7b96544164 100644 --- a/src/rendering/stars/renderableconstellationbounds.cpp +++ b/src/rendering/stars/renderableconstellationbounds.cpp @@ -25,19 +25,16 @@ #include #include - #include -#include - +#include #define _USE_MATH_DEFINES #include -#include - namespace { const std::string _loggerCat = "RenderableConstellationBounds"; - const std::string keyFile = "File"; + const std::string keyVertexFile = "File"; + const std::string keyConstellationFile = "ConstellationFile"; const std::string keyReferenceFrame = "ReferenceFrame"; const std::string defaultReferenceFrame = "J2000"; @@ -56,25 +53,33 @@ namespace openspace { RenderableConstellationBounds::RenderableConstellationBounds( const ghoul::Dictionary& dictionary) : Renderable(dictionary) - , _filename("") + , _vertexFilename("") + , _constellationFilename("") , _programIsDirty(false) , _distance("distance", "Distance to the celestial Sphere", 15.f, 0.f, 30.f) + , _constellationSelection("constellationSelection", "Constellation Selection") , _originReferenceFrame("") , _vao(0) , _vbo(0) { - bool success = dictionary.getValue(keyFile, _filename); + bool success = dictionary.getValue(keyVertexFile, _vertexFilename); if (!success) { LERROR("RenderableConstellationBounds did not contain a key '" << - keyFile << "'"); + keyVertexFile << "'"); } + dictionary.getValue(keyConstellationFile, _constellationFilename); + success = dictionary.getValue(keyReferenceFrame, _originReferenceFrame); if (!success) { _originReferenceFrame = defaultReferenceFrame; } addProperty(_distance); + addProperty(_constellationSelection); + _constellationSelection.onChange( + std::bind(&RenderableConstellationBounds::selectionPropertyHasChanged, this) + ); } bool RenderableConstellationBounds::initialize() { @@ -85,6 +90,14 @@ bool RenderableConstellationBounds::initialize() { return false; _program->setProgramObjectCallback([&](ghoul::opengl::ProgramObject*){ this->_programIsDirty = true; }); + bool loadSuccess = loadVertexFile(); + if (!loadSuccess) + return false; + loadSuccess = loadConstellationFile(); + if (!loadSuccess) + return false; + + fillSelectionProperty(); if (_vao == 0) { glGenVertexArrays(1, &_vao); @@ -95,10 +108,6 @@ bool RenderableConstellationBounds::initialize() { LDEBUG("Generating Vertex Buffer Object id '" << _vbo << "'"); } - bool loadSuccess = loadFile(); - if (!loadSuccess) - return false; - glBindVertexArray(_vao); glBindBuffer(GL_ARRAY_BUFFER, _vbo); glBufferData(GL_ARRAY_BUFFER, @@ -147,11 +156,14 @@ void RenderableConstellationBounds::render(const RenderData& data) { glBindVertexArray(_vao); for (auto bound : _constellationBounds) - glDrawArrays( - GL_LINE_STRIP, - static_cast(bound.startIndex), - static_cast(bound.nVertices) - ); + if (bound.isEnabled) { + glDrawArrays( + //GL_LINE_STRIP, + GL_LINE_LOOP, + static_cast(bound.startIndex), + static_cast(bound.nVertices) + ); + } glBindVertexArray(0); _program->deactivate(); } @@ -170,11 +182,11 @@ void RenderableConstellationBounds::update(const UpdateData& data) { ); } -bool RenderableConstellationBounds::loadFile() { - if (_filename.empty()) +bool RenderableConstellationBounds::loadVertexFile() { + if (_vertexFilename.empty()) return false; - std::string fileName = absPath(_filename); + std::string fileName = absPath(_vertexFilename); std::ifstream file(fileName); if (!file.good()) { LERROR("Could not open file '" << fileName << "' for reading"); @@ -182,7 +194,7 @@ bool RenderableConstellationBounds::loadFile() { } ConstellationBound currentBound; - currentBound.constellation = ""; + currentBound.constellationAbbreviation = ""; std::string currentLine; int currentLineNumber = 1; @@ -215,13 +227,15 @@ bool RenderableConstellationBounds::loadFile() { } // Did we arrive at a new constellation? - if (constellationName != currentBound.constellation) { + if (constellationName != currentBound.constellationAbbreviation) { // Store how many vertices we read during the active time of the constellation currentBound.nVertices = (_vertexValues.size() - currentBound.startIndex); // Store the constellation and start a new one _constellationBounds.push_back(currentBound); currentBound = ConstellationBound(); - currentBound.constellation = constellationName; + currentBound.isEnabled = true; + currentBound.constellationAbbreviation = constellationName; + currentBound.constellationFullName = constellationName; currentBound.startIndex = _vertexValues.size(); } @@ -250,7 +264,80 @@ bool RenderableConstellationBounds::loadFile() { // contain any valid values. So we have to remove it _constellationBounds.erase(_constellationBounds.begin()); + // And we still have the one value that was left when we exited the loop + currentBound.nVertices = (_vertexValues.size() - currentBound.startIndex); + _constellationBounds.push_back(currentBound); + return true; } +bool RenderableConstellationBounds::loadConstellationFile() { + if (_constellationFilename.empty()) + return true; + + std::string fileName = absPath(_constellationFilename); + std::ifstream file(fileName); + if (!file.good()) { + LERROR("Could not open file '" << fileName << "' for reading"); + return false; + } + + std::string line; + int index = 0; + while (file.good()) { + std::getline(file, line); + if (line.empty()) + continue; + + std::string abbreviation; + std::stringstream s(line); + s >> abbreviation; + + auto it = std::find_if(_constellationBounds.begin(), _constellationBounds.end(), + [abbreviation](const ConstellationBound& bound) { + return bound.constellationAbbreviation == abbreviation; + }); + if (it == _constellationBounds.end()) { + LERROR("Could not find constellation '" << abbreviation << "' in list"); + return false; + } + + // Update the constellations full name + s >> it->constellationFullName; + + ++index; + } + + return true; +} + +void RenderableConstellationBounds::fillSelectionProperty() { + // Each constellation is associated with its position in the array as this is unique + // and will be constant during the runtime + for (int i = 0 ; i < _constellationBounds.size(); ++i) { + const ConstellationBound& bound = _constellationBounds[i]; + _constellationSelection.addOption( { i, bound.constellationFullName } ); + + } +} + +void RenderableConstellationBounds::selectionPropertyHasChanged() { + const std::vector& values = _constellationSelection; + // If no values are selected (the default), we want to show all constellations + if (values.size() == 0) { + for (ConstellationBound& b : _constellationBounds) + b.isEnabled = true; + } + else { + // In the worst case, this algorithm runs with 2 * nConstellations, which is + // acceptable as the number of constellations is < 100 + // First disable all constellations + for (ConstellationBound& b : _constellationBounds) + b.isEnabled = false; + // then re-enable the ones for which we have indices + for (int value : values) + _constellationBounds[value].isEnabled = true; + } +} + } // namespace openspace