mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-02-25 06:19:02 -06:00
REFACTOR: split renderablefieldlinessequence.cpp into two files and give propertiy variables a 'p' as prefix
This commit is contained in:
@@ -25,268 +25,19 @@
|
||||
#include <modules/fieldlinessequence/rendering/renderablefieldlinessequence.h>
|
||||
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/interaction/navigationhandler.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <ghoul/opengl/textureunit.h>
|
||||
|
||||
using std::string;
|
||||
|
||||
namespace {
|
||||
std::string _loggerCat = "RenderableFieldlinesSequence";
|
||||
|
||||
// ----- KEYS POSSIBLE IN MODFILE. EXPECTED DATA TYPE OF VALUE IN [BRACKETS] ----- //
|
||||
// ---------------------------- MANDATORY MODFILE KEYS ---------------------------- //
|
||||
const char* KEY_INPUT_FILE_TYPE = "InputFileType"; // [STRING]
|
||||
const char* KEY_SOURCE_FOLDER = "SourceFolder"; // [STRING]
|
||||
|
||||
// ---------------------------- OPTIONAL MODFILE KEYS ---------------------------- //
|
||||
const char* KEY_COLOR_TABLE_PATHS = "ColorTablePaths"; // [STRING ARRAY] Values should be paths to .txt files
|
||||
const char* KEY_COLOR_TABLE_RANGES = "ColorTableRanges";// [VEC2 ARRAY] Values should be paths to .txt files
|
||||
const char* KEY_OSLFS_LOAD_AT_RUNTIME = "LoadAtRuntime"; // [BOOLEAN] If value False => Load in initializing step and store in RAM
|
||||
|
||||
// ------------- POSSIBLE STRING VALUES FOR CORRESPONDING MODFILE KEY ------------- //
|
||||
const char* VALUE_INPUT_FILE_TYPE_CDF = "cdf";
|
||||
const char* VALUE_INPUT_FILE_TYPE_JSON = "json";
|
||||
const char* VALUE_INPUT_FILE_TYPE_OSFLS = "osfls";
|
||||
|
||||
static const openspace::properties::Property::PropertyInfo ColorMethodInfo = {
|
||||
"colorMethod", "Color Method", "Color lines uniformly or using color tables based on extra quantities like e.g. temperature or particle density."
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo ColorQuantityInfo = {
|
||||
"colorQuantity", "Quantity to Color By", "Quantity used to color lines if the \"By Quantity\" color method is selected."
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo ColorQuantityMinInfo = {
|
||||
"colorQuantityMin", "ColorTable Min Value", "Value to map to the lowest end of the color table."
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo ColorQuantityMaxInfo = {
|
||||
"colorQuantityMax", "ColorTable Max Value", "Value to map to the highest end of the color table."
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo ColorTablePathInfo = {
|
||||
"colorTablePath", "Path to Color Table", "Color Table/Transfer Function to use for \"By Quantity\" coloring."
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo ColorUniformInfo = {
|
||||
"uniform", "Uniform Line Color", "The uniform color of lines shown when \"Color Method\" is set to \"Uniform\"."
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo FlowColorInfo = {
|
||||
"color", "Color", "Color of particles."
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo EnableFlowInfo = {
|
||||
"Enable", "ON/OFF",
|
||||
"Toggles the rendering of moving particles along the lines. Can e.g. illustrate magnetic flow."
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo ReverseFlowInfo = {
|
||||
"reversed", "Reversed Flow", "Toggle to make the flow move in the opposite direction."
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo ParticleSizeInfo = {
|
||||
"particleSize", "Particle Size", "Size of the particles."
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo ParticleSpacingInfo = {
|
||||
"particleSpacing", "Particle Spacing", "Spacing inbetween particles."
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo FlowSpeedInfo = {
|
||||
"speed", "Speed", "Speed of the flow."
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo OriginButtonInfo = {
|
||||
"focusCameraOnParent", "Focus Camera", "Focus camera on parent."
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo TimeJumpButtonInfo = {
|
||||
"timeJumpToStart", "Jump to Start Time", "Performs a time jump to the start of the sequence."
|
||||
};
|
||||
|
||||
enum ColorMethod { UNIFORM = 0, BY_QUANTITY };
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary),
|
||||
_colorGroup({ "Color" }),
|
||||
_colorMethod(ColorMethodInfo, properties::OptionProperty::DisplayType::Radio),
|
||||
_colorQuantity(ColorQuantityInfo, properties::OptionProperty::DisplayType::Dropdown),
|
||||
_colorQuantityMin(ColorQuantityMinInfo),
|
||||
_colorQuantityMax(ColorQuantityMaxInfo),
|
||||
_colorTablePath(ColorTablePathInfo),
|
||||
_colorUniform(ColorUniformInfo, glm::vec4(0.75f, 0.5f, 0.0f, 0.5f),
|
||||
glm::vec4(0.f), glm::vec4(1.f)),
|
||||
_flowColor(FlowColorInfo, glm::vec4(0.8f, 0.7f, 0.0f, 0.6f),
|
||||
glm::vec4(0.f), glm::vec4(1.f)),
|
||||
_flowEnabled(EnableFlowInfo, true),
|
||||
_flowGroup({ "Flow" }),
|
||||
_flowParticleSize(ParticleSizeInfo, 5, 0, 500),
|
||||
_flowParticleSpacing(ParticleSpacingInfo, 60, 0, 500),
|
||||
_flowReversed(ReverseFlowInfo, false),
|
||||
_flowSpeed(FlowSpeedInfo, 20, 0, 1000),
|
||||
_focusOnOriginBtn(OriginButtonInfo),
|
||||
_jumpToStartBtn(TimeJumpButtonInfo) {
|
||||
|
||||
// Set the default color table, just in case user defined paths are corrupt!
|
||||
_transferFunction = std::make_shared<TransferFunction>(absPath(_colorTablePaths[0]));
|
||||
|
||||
if(!extractInfoFromDictionary(dictionary)) {
|
||||
_sourceFileType = INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableFieldlinesSequence::initialize() {
|
||||
switch (_sourceFileType) {
|
||||
case CDF:
|
||||
LERROR("CDF NOT YET IMPLEMENTED!");
|
||||
break;
|
||||
case JSON:
|
||||
LERROR("JSON NOT YET IMPLEMENTED!");
|
||||
break;
|
||||
case OSFLS:
|
||||
if (_isLoadingStatesAtRuntime) {
|
||||
extractTriggerTimesFromFileNames();
|
||||
FieldlinesState newState;
|
||||
bool loadedSuccessfully = newState.loadStateFromOsfls(_sourceFiles[0]);
|
||||
if (loadedSuccessfully) {
|
||||
_states.push_back(newState);
|
||||
_nStates = _startTimes.size();
|
||||
_activeStateIndex = 0;
|
||||
} else {
|
||||
LERROR("The provided .osfls files seem to be corrupt!");
|
||||
_sourceFileType = INVALID;
|
||||
}
|
||||
} else {
|
||||
// Load states into RAM!
|
||||
for (string filePath : _sourceFiles) {
|
||||
FieldlinesState newState;
|
||||
bool loadedSuccessfully = newState.loadStateFromOsfls(filePath);
|
||||
if (loadedSuccessfully) {
|
||||
_states.push_back(newState);
|
||||
_startTimes.push_back(newState.triggerTime());
|
||||
_nStates++;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// At this point there's at least one state loaded into memory!
|
||||
// No need to store source paths in memory if they are already in RAM!
|
||||
if (!_isLoadingStatesAtRuntime) {
|
||||
_sourceFiles.clear();
|
||||
}
|
||||
|
||||
computeSequenceEndTime();
|
||||
|
||||
// --------------------- HANDLE PROPERTIES --------------------- //
|
||||
// Add Property Groups
|
||||
addPropertySubOwner(_colorGroup);
|
||||
addPropertySubOwner(_flowGroup);
|
||||
|
||||
// Add non-grouped properties
|
||||
addProperty(_focusOnOriginBtn);
|
||||
addProperty(_jumpToStartBtn);
|
||||
|
||||
// Add Properties to the groups
|
||||
_colorGroup.addProperty(_colorMethod);
|
||||
_colorGroup.addProperty(_colorQuantity);
|
||||
_colorGroup.addProperty(_colorQuantityMin);
|
||||
_colorGroup.addProperty(_colorQuantityMax);
|
||||
_colorGroup.addProperty(_colorTablePath);
|
||||
_colorGroup.addProperty(_colorUniform);
|
||||
|
||||
_flowGroup.addProperty(_flowEnabled);
|
||||
_flowGroup.addProperty(_flowReversed);
|
||||
_flowGroup.addProperty(_flowColor);
|
||||
_flowGroup.addProperty(_flowParticleSize);
|
||||
_flowGroup.addProperty(_flowParticleSpacing);
|
||||
_flowGroup.addProperty(_flowSpeed);
|
||||
|
||||
// Add Options to OptionProperties
|
||||
_colorMethod.addOption(ColorMethod::UNIFORM, "Uniform");
|
||||
_colorMethod.addOption(ColorMethod::BY_QUANTITY, "By Quantity");
|
||||
|
||||
// Add option for each extra quantity. We assume that there are just as many names to
|
||||
// extra quantities as there are extra quantities. We also assume that all states in
|
||||
// the given sequence have the same extra quantities!
|
||||
const size_t N_EXTRA_QUANTITIES = _states[0].nExtraQuantities();
|
||||
auto EXTRA_VARIABLE_NAMES_VEC = _states[0].extraQuantityNames();
|
||||
for (size_t i = 0; i < N_EXTRA_QUANTITIES; ++i) {
|
||||
_colorQuantity.addOption(i, EXTRA_VARIABLE_NAMES_VEC[i]);
|
||||
}
|
||||
// Each quantity should have its own color table and color table range, no more, no less
|
||||
_colorTablePaths.resize(N_EXTRA_QUANTITIES, _colorTablePaths.back());
|
||||
_colorTableRanges.resize(N_EXTRA_QUANTITIES, _colorTableRanges.back());
|
||||
|
||||
// Add Property Callback Functions
|
||||
_colorQuantity.onChange([this] {
|
||||
LDEBUG("CHANGED COLORING QUANTITY");
|
||||
_shouldUpdateColorBuffer = true;
|
||||
_colorQuantityMin = std::to_string(_colorTableRanges[_colorQuantity].x);
|
||||
_colorQuantityMax = std::to_string(_colorTableRanges[_colorQuantity].y);
|
||||
_activeColorTable = &_colorTablePaths[_colorQuantity];
|
||||
_colorTablePath = *_activeColorTable;
|
||||
});
|
||||
|
||||
_colorTablePath.onChange([this] {
|
||||
// TOGGLE ACTIVE SHADER PROGRAM
|
||||
_transferFunction->setPath(_colorTablePath);
|
||||
*_activeColorTable = _colorTablePath;
|
||||
});
|
||||
|
||||
_colorQuantityMin.onChange([this] {
|
||||
LDEBUG("CHANGED MIN VALUE");
|
||||
// TODO CHECK IF VALID NUMBER!
|
||||
// _updateTransferFunctionMin = true;
|
||||
_colorTableRanges[_colorQuantity].x = std::stof(_colorQuantityMin);
|
||||
});
|
||||
|
||||
_colorQuantityMax.onChange([this] {
|
||||
LDEBUG("CHANGED MAX VALUE");
|
||||
// TODO CHECK IF VALID NUMBER!
|
||||
// _updateTransferFunctionMin = true;
|
||||
_colorTableRanges[_colorQuantity].y = std::stof(_colorQuantityMax);
|
||||
});
|
||||
|
||||
_focusOnOriginBtn.onChange([this] {
|
||||
LDEBUG("SET FOCUS NODE TO PARENT");
|
||||
// TODO CHECK IF VALID NUMBER!
|
||||
// _updateTransferFunctionMin = true;
|
||||
//OsEng.navigationHandler().setFocusNode();
|
||||
SceneGraphNode* node = OsEng.renderEngine().scene()->sceneGraphNode(_name);
|
||||
if (!node) {
|
||||
LWARNING("Could not find a node in scenegraph called '" << _name << "'");
|
||||
return;
|
||||
}
|
||||
OsEng.navigationHandler().setFocusNode(node->parent());
|
||||
OsEng.navigationHandler().resetCameraDirection();
|
||||
});
|
||||
|
||||
_jumpToStartBtn.onChange([this] {
|
||||
LDEBUG("Jump in time to start of sequence!");
|
||||
OsEng.timeManager().time().setTime(_startTimes[0]);
|
||||
});
|
||||
|
||||
// Setup shader program
|
||||
_shaderProgram = OsEng.renderEngine().buildRenderProgram(
|
||||
"FieldlinesSequence",
|
||||
"${MODULE_FIELDLINESSEQUENCE}/shaders/fieldlinessequence_vs.glsl",
|
||||
"${MODULE_FIELDLINESSEQUENCE}/shaders/fieldlinessequence_fs.glsl"
|
||||
);
|
||||
|
||||
if (!_shaderProgram) {
|
||||
LERROR("Shader program failed initialization!");
|
||||
_sourceFileType = INVALID;
|
||||
}
|
||||
|
||||
//------------------ Initialize OpenGL VBOs and VAOs-------------------------------//
|
||||
glGenVertexArrays(1, &_vertexArrayObject);
|
||||
glGenBuffers(1, &_vertexPositionBuffer);
|
||||
glGenBuffers(1, &_vertexColorBuffer);
|
||||
}
|
||||
|
||||
void RenderableFieldlinesSequence::deinitialize() {
|
||||
glDeleteVertexArrays(1, &_vertexArrayObject);
|
||||
_vertexArrayObject = 0;
|
||||
@@ -294,6 +45,9 @@ void RenderableFieldlinesSequence::deinitialize() {
|
||||
glDeleteBuffers(1, &_vertexPositionBuffer);
|
||||
_vertexPositionBuffer = 0;
|
||||
|
||||
glDeleteBuffers(1, &_vertexColorBuffer);
|
||||
_vertexColorBuffer = 0;
|
||||
|
||||
RenderEngine& renderEngine = OsEng.renderEngine();
|
||||
if (_shaderProgram) {
|
||||
renderEngine.removeRenderProgram(_shaderProgram);
|
||||
@@ -326,26 +80,25 @@ void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks&
|
||||
_shaderProgram->setUniform("modelViewProjection",
|
||||
data.camera.sgctInternal.projectionMatrix() * glm::mat4(MODEL_VIEW_MAT));
|
||||
|
||||
_shaderProgram->setUniform("colorMethod", _pColorMethod);
|
||||
_shaderProgram->setUniform("lineColor", _pColorUniform);
|
||||
|
||||
_shaderProgram->setUniform("colorMethod", _colorMethod);
|
||||
_shaderProgram->setUniform("lineColor", _colorUniform);
|
||||
|
||||
if (_colorMethod == ColorMethod::BY_QUANTITY) {
|
||||
if (_pColorMethod == ColorMethod::BY_QUANTITY) {
|
||||
ghoul::opengl::TextureUnit textureUnit;
|
||||
textureUnit.activate();
|
||||
_transferFunction->bind(); // Calls update internally
|
||||
_shaderProgram->setUniform("colorTable", textureUnit);
|
||||
_shaderProgram->setUniform("colorTableRange",
|
||||
_colorTableRanges[_colorQuantity]);
|
||||
_colorTableRanges[_pColorQuantity]);
|
||||
}
|
||||
|
||||
// Flow/Particles
|
||||
_shaderProgram->setUniform("usingParticles", _flowEnabled);
|
||||
_shaderProgram->setUniform("flowColor", _flowColor);
|
||||
_shaderProgram->setUniform("particleSize", _flowParticleSize);
|
||||
_shaderProgram->setUniform("particleSpeed", _flowSpeed);
|
||||
_shaderProgram->setUniform("particleSpacing", _flowParticleSpacing);
|
||||
_shaderProgram->setUniform("time", OsEng.runTime() * (_flowReversed ? -1 : 1));
|
||||
_shaderProgram->setUniform("flowColor", _pFlowColor);
|
||||
_shaderProgram->setUniform("usingParticles", _pFlowEnabled);
|
||||
_shaderProgram->setUniform("particleSize", _pFlowParticleSize);
|
||||
_shaderProgram->setUniform("particleSpacing", _pFlowParticleSpacing);
|
||||
_shaderProgram->setUniform("particleSpeed", _pFlowSpeed);
|
||||
_shaderProgram->setUniform("time", OsEng.runTime() * (_pFlowReversed ? -1 : 1));
|
||||
|
||||
glBindVertexArray(_vertexArrayObject);
|
||||
glMultiDrawArrays(
|
||||
@@ -377,7 +130,7 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) {
|
||||
|
||||
updateActiveTriggerTimeIndex(CURRENT_TIME);
|
||||
|
||||
if (_isLoadingStatesAtRuntime) {
|
||||
if (_loadingStatesDynamically) {
|
||||
_mustLoadNewStateFromDisk = true;
|
||||
} else {
|
||||
_needsUpdate = true;
|
||||
@@ -404,7 +157,7 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) {
|
||||
}
|
||||
|
||||
if (_needsUpdate || _newStateIsReady) {
|
||||
if (_isLoadingStatesAtRuntime) {
|
||||
if (_loadingStatesDynamically) {
|
||||
_states[0] = std::move(_newState);
|
||||
}
|
||||
|
||||
@@ -413,7 +166,7 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) {
|
||||
if (_states[_activeStateIndex].nExtraQuantities() > 0) {
|
||||
_shouldUpdateColorBuffer = true;
|
||||
} else {
|
||||
_colorMethod = ColorMethod::UNIFORM;
|
||||
_pColorMethod = ColorMethod::UNIFORM;
|
||||
}
|
||||
|
||||
// Everything is set and ready for rendering!
|
||||
@@ -437,7 +190,8 @@ void RenderableFieldlinesSequence::updateActiveTriggerTimeIndex(const double CUR
|
||||
auto iter = std::upper_bound(_startTimes.begin(), _startTimes.end(), CURRENT_TIME);
|
||||
if (iter != _startTimes.end()) {
|
||||
if ( iter != _startTimes.begin()) {
|
||||
_activeTriggerTimeIndex = std::distance(_startTimes.begin(), iter) - 1;
|
||||
_activeTriggerTimeIndex =
|
||||
static_cast<int>(std::distance(_startTimes.begin(), iter)) - 1;
|
||||
} else {
|
||||
_activeTriggerTimeIndex = 0;
|
||||
}
|
||||
@@ -485,7 +239,7 @@ void RenderableFieldlinesSequence::updateVertexColorBuffer() {
|
||||
|
||||
bool isSuccessful;
|
||||
const std::vector<float>& QUANTITY_VEC =
|
||||
_states[_activeStateIndex].extraQuantity(_colorQuantity, isSuccessful);
|
||||
_states[_activeStateIndex].extraQuantity(_pColorQuantity, isSuccessful);
|
||||
|
||||
if (isSuccessful) {
|
||||
glBufferData(GL_ARRAY_BUFFER, QUANTITY_VEC.size() * sizeof(float),
|
||||
@@ -498,150 +252,7 @@ void RenderableFieldlinesSequence::updateVertexColorBuffer() {
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderableFieldlinesSequence::extractInfoFromDictionary(
|
||||
const ghoul::Dictionary& dictionary) {
|
||||
|
||||
string name;
|
||||
dictionary.getValue(SceneGraphNode::KeyName, name);
|
||||
_name = name;
|
||||
name += ": ";
|
||||
|
||||
// ------------------- EXTRACT MANDATORY VALUES FROM DICTIONARY ------------------- //
|
||||
string inputFileTypeValue;
|
||||
if(!dictionary.getValue(KEY_INPUT_FILE_TYPE, inputFileTypeValue)) {
|
||||
LERROR(name << "The field " << string(KEY_INPUT_FILE_TYPE) << " is missing!");
|
||||
return false;
|
||||
} else {
|
||||
std::transform(inputFileTypeValue.begin(), inputFileTypeValue.end(),
|
||||
inputFileTypeValue.begin(), ::tolower);
|
||||
// Verify that the input type is correct
|
||||
if (inputFileTypeValue == VALUE_INPUT_FILE_TYPE_CDF) {
|
||||
_sourceFileType = CDF;
|
||||
} else if (inputFileTypeValue == VALUE_INPUT_FILE_TYPE_JSON) {
|
||||
_sourceFileType = JSON;
|
||||
} else if (inputFileTypeValue == VALUE_INPUT_FILE_TYPE_OSFLS) {
|
||||
_sourceFileType = OSFLS;
|
||||
} else {
|
||||
LERROR(name << inputFileTypeValue << " is not a recognised "
|
||||
<< KEY_INPUT_FILE_TYPE);
|
||||
_sourceFileType = INVALID;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
string sourceFolderPath;
|
||||
if(!dictionary.getValue(KEY_SOURCE_FOLDER, sourceFolderPath)) {
|
||||
LERROR(name << "The field " << string(KEY_SOURCE_FOLDER) << " is missing!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure that the source folder exists and then extract
|
||||
// the files with the same extension as <inputFileTypeValue>
|
||||
ghoul::filesystem::Directory sourceFolder(sourceFolderPath);
|
||||
if (FileSys.directoryExists(sourceFolder)) {
|
||||
// Extract all file paths from the provided folder (Non-recursively! Sorted!)
|
||||
_sourceFiles = sourceFolder.readFiles(ghoul::Boolean::No, ghoul::Boolean::Yes);
|
||||
|
||||
// Remove all files that don't have <inputFileTypeValue> as extension
|
||||
_sourceFiles.erase(std::remove_if(_sourceFiles.begin(), _sourceFiles.end(),
|
||||
[inputFileTypeValue] (string str) {
|
||||
const size_t EXT_LENGTH = inputFileTypeValue.length();
|
||||
string sub = str.substr(str.length() - EXT_LENGTH, EXT_LENGTH);
|
||||
std::transform(sub.begin(), sub.end(), sub.begin(), ::tolower);
|
||||
return sub != inputFileTypeValue;
|
||||
}), _sourceFiles.end());
|
||||
// Ensure that there are available and valid source files left
|
||||
if (_sourceFiles.empty()) {
|
||||
LERROR(name << sourceFolderPath << " contains no ." << inputFileTypeValue
|
||||
<< " files!");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
LERROR(name << "FieldlinesSequence" << sourceFolderPath
|
||||
<< " is not a valid directory!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extract optional info from modfile
|
||||
ghoul::Dictionary colorTablesPathsDictionary;
|
||||
if (dictionary.getValue(KEY_COLOR_TABLE_PATHS, colorTablesPathsDictionary)) {
|
||||
const size_t N_PROVIDED_PATHS = colorTablesPathsDictionary.size();
|
||||
if (N_PROVIDED_PATHS > 0) {
|
||||
// Clear the default! It is already specified in the transferFunction
|
||||
_colorTablePaths.clear();
|
||||
for (size_t i = 1; i <= N_PROVIDED_PATHS; ++i) {
|
||||
_colorTablePaths.push_back(
|
||||
colorTablesPathsDictionary.value<std::string>( std::to_string(i) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ghoul::Dictionary colorTablesRangesDictionary;
|
||||
if (dictionary.getValue(KEY_COLOR_TABLE_RANGES, colorTablesRangesDictionary)) {
|
||||
const size_t N_PROVIDED_RANGES = colorTablesRangesDictionary.size();
|
||||
for (size_t i = 1; i <= N_PROVIDED_RANGES; ++i) {
|
||||
_colorTableRanges.push_back(
|
||||
colorTablesRangesDictionary.value<glm::vec2>( std::to_string(i) ) );
|
||||
}
|
||||
} else {
|
||||
_colorTableRanges.push_back(glm::vec2(0, 1));
|
||||
}
|
||||
|
||||
// Extract info specific to each inputType
|
||||
switch (_sourceFileType) {
|
||||
case CDF:
|
||||
LERROR(name << "CDF NOT YET IMPLEMENTED!");
|
||||
break;
|
||||
case JSON:
|
||||
LERROR(name << "JSON NOT YET IMPLEMENTED!");
|
||||
break;
|
||||
case OSFLS: {
|
||||
bool shouldLoadInRealtime = false;
|
||||
if (dictionary.getValue(KEY_OSLFS_LOAD_AT_RUNTIME, shouldLoadInRealtime)) {
|
||||
_isLoadingStatesAtRuntime = shouldLoadInRealtime;
|
||||
} else {
|
||||
LWARNING(name << KEY_OSLFS_LOAD_AT_RUNTIME <<
|
||||
" isn't specified! OSFLS files will be loaded during runtime!");
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate expected end time.
|
||||
void RenderableFieldlinesSequence::computeSequenceEndTime() {
|
||||
if (_nStates > 1) {
|
||||
const double LAST_TRIGGER_TIME = _startTimes[_nStates - 1];
|
||||
const double SEQUENCE_DURATION = LAST_TRIGGER_TIME - _startTimes[0];
|
||||
const double AVERAGE_STATE_DURATION = SEQUENCE_DURATION / (static_cast<double>(_nStates) - 1.0);
|
||||
_sequenceEndTime = LAST_TRIGGER_TIME + AVERAGE_STATE_DURATION;
|
||||
} else {
|
||||
// If there's just one state it should never disappear!
|
||||
_sequenceEndTime = DBL_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
// Extract J2000 time from file names
|
||||
// Requires files to be named as such: 'YYYY-MM-DDTHH-MM-SS-XXX.osfls'
|
||||
void RenderableFieldlinesSequence::extractTriggerTimesFromFileNames() {
|
||||
const size_t FILENAME_SIZE = 23; // number of characters in filename (excluding '.osfls')
|
||||
const size_t EXT_SIZE = 6; // size(".osfls")
|
||||
|
||||
for (const std::string& FILEPATH : _sourceFiles) {
|
||||
const size_t STR_LENGTH = FILEPATH.size();
|
||||
// Extract the filename from the path (without extension)
|
||||
std::string timeString = FILEPATH.substr(STR_LENGTH - FILENAME_SIZE - EXT_SIZE,
|
||||
FILENAME_SIZE - 1);
|
||||
// Ensure the separators are correct
|
||||
timeString.replace( 4, 1, "-");
|
||||
timeString.replace( 7, 1, "-");
|
||||
timeString.replace(13, 1, ":");
|
||||
timeString.replace(16, 1, ":");
|
||||
timeString.replace(19, 1, ".");
|
||||
const double TRIGGER_TIME = Time::convertTime(timeString);
|
||||
_startTimes.push_back(TRIGGER_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
Reference in New Issue
Block a user