Merge branch 'master' into feature/DU

This commit is contained in:
Jonathas Costa
2017-10-04 09:36:37 -04:00
77 changed files with 1635 additions and 224 deletions

View File

@@ -31,12 +31,15 @@
#include <ghoul/io/texture/texturereaderdevil.h>
#include <ghoul/io/texture/texturereaderfreeimage.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/filesystem/directory.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/logging/consolelog.h>
#include <ghoul/ghoul.h>
#include <ghoul/cmdparser/commandlineparser.h>
#include <ghoul/cmdparser/singlecommand.h>
#include <openspace/scripting/scriptengine.h>
#include <openspace/rendering/renderable.h>
#include <openspace/util/progressbar.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/configurationmanager.h>
@@ -62,10 +65,54 @@ void initTextureReaders() {
#endif // GHOUL_USE_FREEIMAGE
}
void performTasks(const std::string& path) {
using namespace openspace;
TaskLoader taskLoader;
std::vector<std::unique_ptr<Task>> tasks = taskLoader.tasksFromFile(path);
size_t nTasks = tasks.size();
if (nTasks == 1) {
LINFO("Task queue has 1 item");
}
else {
LINFO("Task queue has " << tasks.size() << " items");
}
for (size_t i = 0; i < tasks.size(); i++) {
Task& task = *tasks[i].get();
LINFO("Performing task " << (i + 1) << " out of " << tasks.size() << ": " << task.description());
ProgressBar progressBar(100);
auto onProgress = [&progressBar](float progress) {
progressBar.print(progress * 100);
};
task.perform(onProgress);
}
std::cout << "Done performing tasks." << std::endl;
}
int main(int argc, char** argv) {
using namespace openspace;
ghoul::initialize();
ghoul::logging::LogManager::initialize(
ghoul::logging::LogLevel::Debug,
ghoul::logging::LogManager::ImmediateFlush::Yes
);
LogMgr.addLog(std::make_unique< ghoul::logging::ConsoleLog>());
LDEBUG("Initialize FileSystem");
ghoul::filesystem::Directory launchDirectory = FileSys.currentDirectory();
#ifdef __APPLE__
ghoul::filesystem::File app(argv[0]);
std::string dirName = app.directoryName();
LINFO("Setting starting directory to '" << dirName << "'");
FileSys.setCurrentDirectory(dirName);
#endif
initTextureReaders();
FactoryManager::initialize();
@@ -98,34 +145,49 @@ int main(int argc, char** argv) {
ModuleEngine moduleEngine;
moduleEngine.initialize();
std::string tasksPath;
configuration.getValue(ConfigurationManager::KeyConfigTask, tasksPath);
LINFO("Initialization done.");
TaskLoader taskLoader;
std::vector<std::unique_ptr<Task>> tasks = taskLoader.tasksFromFile(tasksPath);
size_t nTasks = tasks.size();
if (nTasks == 1) {
LINFO("Task queue has 1 item");
} else {
LINFO("Task queue has " << tasks.size() << " items");
// Parse commandline arguments
std::vector<std::string> args(argv, argv + argc);
ghoul::cmdparser::CommandlineParser commandlineParser(
"OpenSpace TaskRunner",
ghoul::cmdparser::CommandlineParser::AllowUnknownCommands::Yes
);
std::string tasksPath = "";
commandlineParser.addCommand(
std::make_unique<ghoul::cmdparser::SingleCommand<std::string>>(
&tasksPath,
"--task",
"-t",
"Provides the path to a task file to execute"
)
);
commandlineParser.setCommandLine(args);
commandlineParser.execute();
FileSys.setCurrentDirectory(launchDirectory);
if (tasksPath != "") {
performTasks(tasksPath);
return 0;
}
for (size_t i = 0; i < tasks.size(); i++) {
Task& task = *tasks[i].get();
LINFO("Performing task " << (i+1) << " out of " << tasks.size() << ": " << task.description());
ProgressBar progressBar(100);
auto onProgress = [&progressBar](float progress) {
progressBar.print(progress * 100);
};
task.perform(onProgress);
// If no task file was specified in as argument, run in CLI mode.
std::string tasksRoot;
if (configuration.getValue(ConfigurationManager::KeyConfigTasksRoot, tasksRoot)) {
LINFO("Task root: " << tasksRoot);
FileSys.setCurrentDirectory(ghoul::filesystem::Directory(absPath(tasksRoot)));
}
std::cout << "Done performing tasks." << std::endl;
std::cout << "TASK >";
while (std::cin >> tasksPath) {
performTasks(tasksPath);
std::cout << "TASK >";
}
std::cin.get();
return 0;
};

View File

@@ -69,8 +69,8 @@ public:
static const std::string KeyFactoryDocumentation;
/// The key that stores the location of the scene file that is initially loaded
static const std::string KeyConfigScene;
/// The key that stores the location of the tasks file that is initially loaded
static const std::string KeyConfigTask;
/// The key that stores the location of the tasks files
static const std::string KeyConfigTasksRoot;
/// The key that stores the subdirectory containing a list of all startup scripts to
/// be executed on application start before the scene file is loaded
static const std::string KeyStartupScript;

View File

@@ -46,7 +46,6 @@ namespace ghoul::opengl {
namespace openspace {
class RenderableVolume;
class Camera;
class Scene;

View File

@@ -22,15 +22,15 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___CONCURRENT_JOB_MANAGER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___CONCURRENT_JOB_MANAGER___H__
#ifndef __OPENSPACE_CORE___CONCURRENT_JOB_MANAGER___H__
#define __OPENSPACE_CORE___CONCURRENT_JOB_MANAGER___H__
#include <modules/globebrowsing/other/concurrentqueue.h>
#include <modules/globebrowsing/other/threadpool.h>
#include <openspace/util/concurrentqueue.h>
#include <openspace/util/threadpool.h>
#include <mutex>
namespace openspace::globebrowsing {
namespace openspace {
// Templated abstract base class representing a job to be done.
// Client code derive from this class and implement the virtual execute() method
@@ -66,8 +66,8 @@ private:
ThreadPool threadPool;
};
} // namespace openspace::globebrowsing
} // namespace openspace
#include "concurrentjobmanager.inl"
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___CONCURRENT_JOB_MANAGER___H__
#endif // __OPENSPACE_CORE___CONCURRENT_JOB_MANAGER___H__

View File

@@ -24,7 +24,7 @@
#include <ghoul/misc/assert.h>
namespace openspace::globebrowsing {
namespace openspace {
template<typename P>
Job<P>::Job() {}
@@ -63,4 +63,4 @@ size_t ConcurrentJobManager<P>::numFinishedJobs() const {
return _finishedJobs.size();
}
} // namespace openspace::globebrowsing
} // namespace openspace

View File

@@ -22,14 +22,14 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___CONCURRENT_QUEUE___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___CONCURRENT_QUEUE___H__
#ifndef __OPENSPACE_CORE___CONCURRENT_QUEUE___H__
#define __OPENSPACE_CORE___CONCURRENT_QUEUE___H__
#include <condition_variable>
#include <mutex>
#include <queue>
namespace openspace::globebrowsing {
namespace openspace {
/**
* Templated thread-safe queue based on std::thread and std::queue
@@ -53,8 +53,8 @@ private:
mutable std::condition_variable _cond;
};
} // namespace openspace::globebrowsing
} // namespace openspace
#include "concurrentqueue.inl"
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___CONCURRENT_QUEUE___H__
#endif // __OPENSPACE_CORE___CONCURRENT_QUEUE___H__

View File

@@ -22,7 +22,7 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
namespace openspace::globebrowsing {
namespace openspace {
template <typename T>
T ConcurrentQueue<T>::pop() {
@@ -70,4 +70,4 @@ size_t ConcurrentQueue<T>::size() const {
return s;
}
} // namespace openspace::globebrowsing
} // namespace openspace

View File

@@ -22,8 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___THREAD_POOL___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___THREAD_POOL___H__
#ifndef __OPENSPACE_CORE___THREAD_POOL___H__
#define __OPENSPACE_CORE___THREAD_POOL___H__
#include <condition_variable>
#include <functional>
@@ -35,7 +35,7 @@
// Implementatin based on http://progsch.net/wordpress/?p=81
namespace openspace::globebrowsing {
namespace openspace {
class ThreadPool;
@@ -69,6 +69,6 @@ private:
bool stop;
};
} // namespace openspace::globebrowsing
} // namespace openspace
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___THREAD_POOL___H__
#endif // __OPENSPACE_CORE___THREAD_POOL___H__

View File

@@ -42,8 +42,11 @@ public:
void removeKeyframesBefore(double timestamp);
void removeKeyframesAfter(double timestamp);
void clearKeyframes();
void setTimeNextFrame(Time t);
size_t nKeyframes() const;
private:
bool _shouldSetTime;
Time _timeNextFrame;
Timeline<Time> _timeline;
SyncData<Time> _currentTime;
void consumeKeyframes(double dt);

View File

@@ -59,19 +59,14 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/meshes/skirtedgrid.h
${CMAKE_CURRENT_SOURCE_DIR}/meshes/trianglesoup.h
${CMAKE_CURRENT_SOURCE_DIR}/other/concurrentjobmanager.h
${CMAKE_CURRENT_SOURCE_DIR}/other/concurrentjobmanager.inl
${CMAKE_CURRENT_SOURCE_DIR}/other/prioritizingconcurrentjobmanager.h
${CMAKE_CURRENT_SOURCE_DIR}/other/prioritizingconcurrentjobmanager.inl
${CMAKE_CURRENT_SOURCE_DIR}/other/concurrentqueue.h
${CMAKE_CURRENT_SOURCE_DIR}/other/concurrentqueue.inl
${CMAKE_CURRENT_SOURCE_DIR}/other/distanceswitch.h
${CMAKE_CURRENT_SOURCE_DIR}/other/pixelbuffer.h
${CMAKE_CURRENT_SOURCE_DIR}/other/pixelbuffercontainer.h
${CMAKE_CURRENT_SOURCE_DIR}/other/pixelbuffercontainer.inl
${CMAKE_CURRENT_SOURCE_DIR}/other/statscollector.h
${CMAKE_CURRENT_SOURCE_DIR}/other/statscollector.inl
${CMAKE_CURRENT_SOURCE_DIR}/other/threadpool.h
${CMAKE_CURRENT_SOURCE_DIR}/other/lruthreadpool.h
${CMAKE_CURRENT_SOURCE_DIR}/other/lruthreadpool.inl
@@ -157,7 +152,6 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/other/distanceswitch.cpp
${CMAKE_CURRENT_SOURCE_DIR}/other/pixelbuffer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/other/statscollector.cpp
${CMAKE_CURRENT_SOURCE_DIR}/other/threadpool.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/chunkrenderer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/layershadermanager.cpp

View File

@@ -123,6 +123,15 @@ namespace openspace {
GlobeBrowsingModule::GlobeBrowsingModule() : OpenSpaceModule(Name) {}
void GlobeBrowsingModule::internalInitialize() {
// TODO: Remove dependency on OsEng.
// Instead, make this class implement an interface that OsEng depends on.
// Do not try to register module callbacks if OsEng does not exist,
// for example in the TaskRunner.
if (!OpenSpaceEngine::isCreated()) {
return;
}
using namespace globebrowsing;
// Initialize
@@ -232,6 +241,7 @@ scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
"Get geographic coordinates of the camera poosition in latitude, "
"longitude, and altitude"
},
#ifdef GLOBEBROWSING_USE_GDAL
{
"loadWMSCapabilities",
&globebrowsing::luascriptfunctions::loadWMSCapabilities,
@@ -259,6 +269,7 @@ scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
"component of the returned table can be used in the 'FilePath' argument "
"for a call to the 'addLayer' function to add the value to a globe."
}
#endif // GLOBEBROWSING_USE_GDAL
},
{
"${MODULE_GLOBEBROWSING}/scripts/layer_support.lua"

View File

@@ -204,6 +204,7 @@ int getGeoPosition(lua_State* L) {
return 3;
}
#ifdef GLOBEBROWSING_USE_GDAL
int loadWMSCapabilities(lua_State* L) {
int nArguments = lua_gettop(L);
@@ -220,8 +221,6 @@ int loadWMSCapabilities(lua_State* L) {
std::move(globe),
std::move(url)
);
return 0;
}
int removeWMSServer(lua_State* L) {
@@ -266,5 +265,7 @@ int capabilities(lua_State* L) {
return 1;
}
#endif // GLOBEBROWSING_USE_GDAL
} // namespace openspace::globebrowsing::luascriptfunctions

View File

@@ -25,9 +25,10 @@
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___PRIORITIZING_CONCURRENT_JOB_MANAGER___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___PRIORITIZING_CONCURRENT_JOB_MANAGER___H__
#include <modules/globebrowsing/other/concurrentqueue.h>
#include <modules/globebrowsing/other/lruthreadpool.h>
#include <modules/globebrowsing/other/concurrentjobmanager.h>
#include <openspace/util/concurrentjobmanager.h>
#include <openspace/util/concurrentqueue.h>
#include <mutex>

View File

@@ -25,8 +25,8 @@
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILELOADJOB___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILELOADJOB___H__
#include <modules/globebrowsing/other/concurrentjobmanager.h>
#include <modules/globebrowsing/tile/tile.h>
#include <openspace/util/concurrentjobmanager.h>
namespace openspace::globebrowsing {

View File

@@ -67,7 +67,9 @@ public:
//protected:
GuiHelpComponent _help;
GuiFilePathComponent _filePath;
#ifdef GLOBEBROWSING_USE_GDAL
GuiGlobeBrowsingComponent _globeBrowsing;
#endif // GLOBEBROWSING_USE_GDAL
GuiOriginComponent _origin;
GuiPerformanceComponent _performance;
GuiPropertyComponent _globalProperty;

View File

@@ -22,6 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifdef GLOBEBROWSING_USE_GDAL
#ifndef __OPENSPACE_MODULE_IMGUI___GUIGLOBEBROWSINGCOMPONENT___H__
#define __OPENSPACE_MODULE_IMGUI___GUIGLOBEBROWSINGCOMPONENT___H__
@@ -49,3 +51,5 @@ private:
#endif // __OPENSPACE_MODULE_IMGUI___GUIGLOBEBROWSINGCOMPONENT___H__
#endif // GLOBEBROWSING_USE_GDAL

View File

@@ -242,7 +242,9 @@ GUI::GUI()
addPropertySubOwner(_property);
addPropertySubOwner(_screenSpaceProperty);
addPropertySubOwner(_virtualProperty);
#ifdef GLOBEBROWSING_USE_GDAL
addPropertySubOwner(_globeBrowsing);
#endif // GLOBEBROWSING_USE_GDAL
addPropertySubOwner(_filePath);
addPropertySubOwner(_time);
#ifdef OPENSPACE_MODULE_ISWA_ENABLED
@@ -330,7 +332,9 @@ void GUI::initialize() {
_globalProperty.setHasRegularProperties(true);
_virtualProperty.initialize();
_filePath.initialize();
#ifdef GLOBEBROWSING_USE_GDAL
_globeBrowsing.initialize();
#endif // GLOBEBROWSING_USE_GDAL
_performance.initialize();
_help.initialize();
_parallel.initialize();
@@ -352,7 +356,9 @@ void GUI::deinitialize() {
_screenSpaceProperty.deinitialize();
_virtualProperty.deinitialize();
_filePath.deinitialize();
#ifdef GLOBEBROWSING_USE_GDAL
_globeBrowsing.deinitialize();
#endif // GLOBEBROWSING_USE_GDAL
_property.deinitialize();
delete iniFileBuffer;
@@ -427,8 +433,10 @@ void GUI::initializeGL() {
_screenSpaceProperty.initializeGL();
_globalProperty.initializeGL();
_performance.initializeGL();
_help.initializeGL();
_help.initializeGL();
#ifdef GLOBEBROWSING_USE_GDAL
_globeBrowsing.initializeGL();
#endif // GLOBEBROWSING_USE_GDAL
_filePath.initializeGL();
_parallel.initializeGL();
#ifdef OPENSPACE_MODULE_ISWA_ENABLED
@@ -459,7 +467,9 @@ void GUI::deinitializeGL() {
_performance.deinitializeGL();
_globalProperty.deinitializeGL();
_screenSpaceProperty.deinitializeGL();
#ifdef GLOBEBROWSING_USE_GDAL
_globeBrowsing.deinitializeGL();
#endif // GLOBEBROWSING_USE_GDAL
_filePath.deinitializeGL();
_property.deinitializeGL();
}
@@ -520,9 +530,11 @@ void GUI::endFrame() {
_filePath.render();
}
#ifdef GLOBEBROWSING_USE_GDAL
if (_globeBrowsing.isEnabled()) {
_globeBrowsing.render();
}
#endif // GLOBEBROWSING_USE_GDAL
}
ImGui::Render();
@@ -622,9 +634,11 @@ void GUI::render() {
ImGui::Checkbox("File Paths", &filePath);
_filePath.setEnabled(filePath);
#ifdef GLOBEBROWSING_USE_GDAL
bool globeBrowsing = _globeBrowsing.isEnabled();
ImGui::Checkbox("GlobeBrowsing", &globeBrowsing);
_globeBrowsing.setEnabled(globeBrowsing);
#endif // GLOBEBROWSING_USE_GDAL
#ifdef OPENSPACE_MODULE_ISWA_ENABLED
bool iswa = _iswa.isEnabled();

View File

@@ -22,6 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifdef GLOBEBROWSING_USE_GDAL
#include <modules/imgui/include/guiglobebrowsingcomponent.h>
#include <modules/imgui/include/imgui_include.h>
@@ -332,3 +334,5 @@ void GuiGlobeBrowsingComponent::render() {
}
} // namespace openspace::gui
#endif // GLOBEBROWSING_USE_GDAL

View File

@@ -28,17 +28,17 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/kameleonvolumereader.h
${CMAKE_CURRENT_SOURCE_DIR}/kameleonvolumereader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablekameleonvolume.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/kameleonvolumeraycaster.h
${CMAKE_CURRENT_SOURCE_DIR}/tasks/kameleondocumentationtask.h
${CMAKE_CURRENT_SOURCE_DIR}/tasks/kameleonmetadatatojsontask.h
${CMAKE_CURRENT_SOURCE_DIR}/tasks/kameleonvolumetorawtask.h
)
source_group("Header Files" FILES ${HEADER_FILES})
set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablekameleonvolume.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/kameleonvolumeraycaster.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tasks/kameleondocumentationtask.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tasks/kameleonmetadatatojsontask.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tasks/kameleonvolumetorawtask.cpp
)
source_group("Source Files" FILES ${SOURCE_FILES})

View File

@@ -32,9 +32,13 @@
#include <modules/kameleonvolume/rendering/renderablekameleonvolume.h>
#include <modules/kameleonvolume/tasks/kameleonmetadatatojsontask.h>
#include <modules/kameleonvolume/tasks/kameleondocumentationtask.h>
#include <modules/kameleonvolume/tasks/kameleonvolumetorawtask.h>
namespace openspace {
using namespace kameleonvolume;
KameleonVolumeModule::KameleonVolumeModule() : OpenSpaceModule(Name) {}
void KameleonVolumeModule::internalInitialize() {
@@ -46,6 +50,7 @@ void KameleonVolumeModule::internalInitialize() {
ghoul_assert(fTask, "No task factory existed");
fTask->registerClass<KameleonMetadataToJsonTask>("KameleonMetadataToJsonTask");
fTask->registerClass<KameleonDocumentationTask>("KameleonDocumentationTask");
fTask->registerClass<KameleonVolumeToRawTask>("KameleonVolumeToRawTask");
}
std::vector<documentation::Documentation> KameleonVolumeModule::documentations() const {

View File

@@ -48,36 +48,66 @@ namespace {
} // namespace
namespace openspace {
namespace kameleonvolume {
KameleonVolumeReader::KameleonVolumeReader(const std::string& path)
: _path(path)
{
if (!FileSys.fileExists(path)) {
LERROR(_path << "does not exist");
return;
LERROR(_path << " does not exist");
throw ghoul::FileNotFoundError(_path);
}
long status = _kameleon.open(_path);
if (status != ccmc::FileReader::OK) {
LERROR("Failed to open file " << _path << " with kameleon");
LERROR("Failed to open file " << _path << " with Kameleon");
throw ghoul::RuntimeError("Failed to open file: " + _path + " with Kameleon");
return;
}
_model = _kameleon.model;
// Possibly use a kameleon interpolator instead of a model interpolator?
_interpolator = std::unique_ptr<ccmc::Interpolator>(_model->createNewInterpolator());
}
std::unique_ptr<RawVolume<float>> KameleonVolumeReader::readFloatVolume(
std::unique_ptr<volume::RawVolume<float>> KameleonVolumeReader::readFloatVolume(
const glm::uvec3 & dimensions,
const std::string & variable,
const glm::vec3 & lowerDomainBound,
const glm::vec3 & upperDomainBound) const
{
float min, max;
return readFloatVolume(dimensions, variable, lowerDomainBound, upperDomainBound, min, max);
}
std::unique_ptr<volume::RawVolume<float>> KameleonVolumeReader::readFloatVolume(
const glm::uvec3 & dimensions,
const std::string & variable,
const glm::vec3 & lowerBound,
const glm::vec3 & upperBound) const
const glm::vec3 & upperBound,
float& minValue,
float& maxValue) const
{
auto volume = std::make_unique<RawVolume<float>>(dimensions);
minValue = FLT_MAX;
maxValue = FLT_MIN;
auto volume = std::make_unique<volume::RawVolume<float>>(dimensions);
const glm::vec3 dims = volume->dimensions();
const glm::vec3 diff = upperBound - lowerBound;
_model->loadVariable(variable);
auto interpolate =
[this](const std::string& variable, glm::vec3 volumeCoords) {
return _interpolator->interpolate(
variable,
volumeCoords[0],
volumeCoords[1],
volumeCoords[2]);
};
auto sample = [this, &variable, &interpolate](glm::vec3 volumeCoords) {
return interpolate(variable, volumeCoords);
};
float* data = volume->data();
for (size_t index = 0; index < volume->nCells(); index++) {
@@ -85,11 +115,14 @@ std::unique_ptr<RawVolume<float>> KameleonVolumeReader::readFloatVolume(
glm::vec3 coordsZeroToOne = coords / dims;
glm::vec3 volumeCoords = lowerBound + diff * coordsZeroToOne;
data[index] = _interpolator->interpolate(
variable,
static_cast<float>(volumeCoords[0]),
static_cast<float>(volumeCoords[1]),
static_cast<float>(volumeCoords[2]));
data[index] = sample(volumeCoords);
if (data[index] < minValue) {
minValue = data[index];
}
if (data[index] > maxValue) {
maxValue = data[index];
}
}
return volume;
@@ -205,12 +238,80 @@ ghoul::Dictionary KameleonVolumeReader::readMetaData() const {
};
}
float KameleonVolumeReader::minValue(const std::string & variable) const {
std::string KameleonVolumeReader::simulationStart() const {
std::string startTime;
if (_model->doesAttributeExist("start_time")){
startTime =
_model->getGlobalAttribute("start_time").getAttributeString();
} else if (_model->doesAttributeExist("tim_rundate_cal")) {
startTime =
_model->getGlobalAttribute("tim_rundate_cal").getAttributeString();
size_t numChars = startTime.length();
if (numChars < 19) {
// Fall through to add the required characters
switch (numChars) {
case 10 : // YYYY-MM-DD => YYYY-MM-DDTHH
startTime += "T00";
[[fallthrough]];
case 13 : // YYYY-MM-DDTHH => YYYY-MM-DDTHH:
startTime += ":";
[[fallthrough]];
case 14 : // YYYY-MM-DDTHH: => YYYY-MM-DDTHH:MM
startTime += "00";
[[fallthrough]];
case 16 : // YYYY-MM-DDTHH:MM => YYYY-MM-DDTHH:MM:
startTime += ":";
[[fallthrough]];
case 17 : // YYYY-MM-DDTHH:MM: => YYYY-MM-DDTHH:MM:SS
startTime += "00";
break;
default :
break;
}
}
} else if (_model->doesAttributeExist("tim_obsdate_cal")) {
startTime =
_model->getGlobalAttribute("tim_obsdate_cal").getAttributeString();
} else if (_model->doesAttributeExist("tim_crstart_cal")) {
startTime =
_model->getGlobalAttribute("tim_crstart_cal").getAttributeString();
}
if (startTime.length() == 19) {
startTime += ".000Z";
}
return startTime;
}
float KameleonVolumeReader::elapsedTime() const {
if (_model->doesAttributeExist("elapsed_time_in_seconds")) {
return _model->getGlobalAttribute("elapsed_time_in_seconds").getAttributeFloat();
} else if (_model->doesAttributeExist("time_physical_time")) {
return _model->getGlobalAttribute("time_physical_time").getAttributeFloat();
}
return 0;
}
std::string KameleonVolumeReader::simulationEnd() const {
return _model->getGlobalAttribute("end_time").getAttributeString();
}
std::string KameleonVolumeReader::time() const {
double start =
ccmc::Time(simulationStart()).getEpoch();
// Get elapsed time in seconds and convert to milliseconds.
double elapsed = elapsedTime() * 1000;
return ccmc::Time(start + elapsed).toString();
}
double KameleonVolumeReader::minValue(const std::string & variable) const {
return _model->getVariableAttribute(variable, "actual_min").getAttributeFloat();
}
float KameleonVolumeReader::maxValue(const std::string & variable) const {
double KameleonVolumeReader::maxValue(const std::string & variable) const {
return _model->getVariableAttribute(variable, "actual_max").getAttributeFloat();
}
} // namepace kameleonvolume
} // namespace openspace

View File

@@ -47,23 +47,37 @@
namespace ccmc { class Model; }
namespace openspace {
namespace kameleonvolume {
class KameleonVolumeReader {
public:
KameleonVolumeReader(const std::string& path);
//KameleonMetaData readMetaData();
std::unique_ptr<RawVolume<float>> readFloatVolume(
std::unique_ptr<volume::RawVolume<float>> readFloatVolume(
const glm::uvec3& dimensions,
const std::string& variable,
const glm::vec3& lowerDomainBound,
const glm::vec3& upperDomainBound) const;
std::unique_ptr<volume::RawVolume<float>> readFloatVolume(
const glm::uvec3& dimensions,
const std::string& variable,
const glm::vec3& lowerBound,
const glm::vec3& upperBound) const;
const glm::vec3& upperBound,
float& minValue,
float& maxValue) const;
ghoul::Dictionary readMetaData() const;
float minValue(const std::string& variable) const;
float maxValue(const std::string& variable) const;
std::string time() const;
std::string simulationStart() const;
std::string simulationEnd() const;
float elapsedTime() const;
double minValue(const std::string& variable) const;
double maxValue(const std::string& variable) const;
std::vector<std::string> gridVariableNames() const;
std::vector<std::string> gridUnits() const;
std::vector<std::string> variableNames() const;
std::vector<std::string> variableAttributeNames() const;
std::vector<std::string> globalAttributeNames() const;
@@ -77,6 +91,7 @@ private:
};
} // namespace kameleonvolume
} // namespace openspace
#endif // __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONVOLUMEREADER___H__

View File

@@ -133,6 +133,7 @@ namespace {
} // namespace
namespace openspace {
namespace kameleonvolume {
RenderableKameleonVolume::RenderableKameleonVolume(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
@@ -226,7 +227,7 @@ RenderableKameleonVolume::RenderableKameleonVolume(const ghoul::Dictionary& dict
ghoul::Dictionary clipPlanesDictionary;
dictionary.getValue(KeyClipPlanes, clipPlanesDictionary);
_clipPlanes = std::make_shared<VolumeClipPlanes>(clipPlanesDictionary);
_clipPlanes = std::make_shared<volume::VolumeClipPlanes>(clipPlanesDictionary);
_clipPlanes->setName("clipPlanes");
bool cache;
@@ -234,14 +235,14 @@ RenderableKameleonVolume::RenderableKameleonVolume(const ghoul::Dictionary& dict
_cache = cache;
}
_gridType.addOption(static_cast<int>(VolumeGridType::Cartesian), "Cartesian grid");
_gridType.addOption(static_cast<int>(VolumeGridType::Spherical), "Spherical grid");
_gridType.setValue(static_cast<int>(VolumeGridType::Cartesian));
_gridType.addOption(static_cast<int>(volume::VolumeGridType::Cartesian), "Cartesian grid");
_gridType.addOption(static_cast<int>(volume::VolumeGridType::Spherical), "Spherical grid");
_gridType.setValue(static_cast<int>(volume::VolumeGridType::Cartesian));
std::string gridType;
if (dictionary.getValue(KeyGridType, gridType)) {
if (gridType == ValueSphericalGridType) {
_gridType.setValue(static_cast<int>(VolumeGridType::Spherical));
_gridType.setValue(static_cast<int>(volume::VolumeGridType::Spherical));
} else {
_autoGridType = true;
}
@@ -256,15 +257,15 @@ void RenderableKameleonVolume::initialize() {
_volumeTexture->uploadTexture();
_transferFunction->update();
_raycaster = std::make_unique<KameleonVolumeRaycaster>(_volumeTexture, _transferFunction, _clipPlanes);
_raycaster = std::make_unique<volume::BasicVolumeRaycaster>(_volumeTexture, _transferFunction, _clipPlanes);
_raycaster->setStepSize(_stepSize);
_gridType.onChange([this] {
_raycaster->setStepSize(_stepSize);
});
_raycaster->setGridType(static_cast<VolumeGridType>(_gridType.value()));
_raycaster->setGridType(static_cast<volume::VolumeGridType>(_gridType.value()));
_gridType.onChange([this] {
_raycaster->setGridType(static_cast<VolumeGridType>(_gridType.value()));
_raycaster->setGridType(static_cast<volume::VolumeGridType>(_gridType.value()));
});
updateRaycasterModelTransform();
@@ -372,7 +373,7 @@ void RenderableKameleonVolume::loadFromPath(const std::string& path) {
}
void RenderableKameleonVolume::loadRaw(const std::string& path) {
RawVolumeReader<float> reader(path, _dimensions);
volume::RawVolumeReader<float> reader(path, _dimensions);
_rawVolume = reader.read();
updateTextureFromVolume();
}
@@ -401,10 +402,10 @@ void RenderableKameleonVolume::loadCdf(const std::string& path) {
if (variables.size() == 3 && _autoGridType) {
if (variables[0] == "r" && variables[0] == "theta" && variables[0] == "phi") {
_gridType.setValue(static_cast<int>(VolumeGridType::Spherical));
_gridType.setValue(static_cast<int>(volume::VolumeGridType::Spherical));
}
else {
_gridType.setValue(static_cast<int>(VolumeGridType::Cartesian));
_gridType.setValue(static_cast<int>(volume::VolumeGridType::Cartesian));
}
}
@@ -414,7 +415,7 @@ void RenderableKameleonVolume::loadCdf(const std::string& path) {
}
void RenderableKameleonVolume::updateTextureFromVolume() {
_normalizedVolume = std::make_unique<RawVolume<GLfloat>>(_dimensions);
_normalizedVolume = std::make_unique<volume::RawVolume<GLfloat>>(_dimensions);
float* in = _rawVolume->data();
GLfloat* out = _normalizedVolume->data();
float min = _lowerValueBound;
@@ -438,7 +439,7 @@ void RenderableKameleonVolume::updateTextureFromVolume() {
}
void RenderableKameleonVolume::storeRaw(const std::string& path) {
RawVolumeWriter<float> writer(path);
volume::RawVolumeWriter<float> writer(path);
writer.write(*_rawVolume);
}
@@ -464,3 +465,4 @@ void RenderableKameleonVolume::render(const RenderData& data, RendererTasks& tas
}
}
}

View File

@@ -29,21 +29,21 @@
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/util/boxgeometry.h>
#include <openspace/util/blockplaneintersectiongeometry.h>
#include <openspace/rendering/renderable.h>
#include <openspace/rendering/transferfunction.h>
#include <modules/kameleon/include/kameleonwrapper.h>
#include <modules/volume/rawvolume.h>
#include <modules/kameleonvolume/rendering/kameleonvolumeraycaster.h>
#include <modules/volume/rendering/basicvolumeraycaster.h>
#include <modules/volume/rendering/volumeclipplanes.h>
namespace openspace {
struct RenderData;
namespace kameleonvolume {
class RenderableKameleonVolume : public Renderable {
public:
RenderableKameleonVolume(const ghoul::Dictionary& dictionary);
@@ -81,7 +81,7 @@ private:
properties::OptionProperty _gridType;
bool _autoGridType;
std::shared_ptr<VolumeClipPlanes> _clipPlanes;
std::shared_ptr<volume::VolumeClipPlanes> _clipPlanes;
properties::FloatProperty _stepSize;
properties::StringProperty _sourcePath;
@@ -89,14 +89,15 @@ private:
properties::BoolProperty _cache;
std::unique_ptr<RawVolume<float>> _rawVolume;
std::unique_ptr<RawVolume<GLfloat>> _normalizedVolume;
std::unique_ptr<KameleonVolumeRaycaster> _raycaster;
std::unique_ptr<volume::RawVolume<float>> _rawVolume;
std::unique_ptr<volume::RawVolume<GLfloat>> _normalizedVolume;
std::unique_ptr<volume::BasicVolumeRaycaster> _raycaster;
std::shared_ptr<ghoul::opengl::Texture> _volumeTexture;
std::shared_ptr<TransferFunction> _transferFunction;
};
} // namespace kameleonvolume
} // namespace openspace
#endif // __OPENSPACE_MODULE_KAMELEONVOLUME___RENDERABLEKAMELEONVOLUME___H__

View File

@@ -46,6 +46,7 @@ namespace {
} // namespace
namespace openspace {
namespace kameleonvolume {
KameleonDocumentationTask::KameleonDocumentationTask(const ghoul::Dictionary& dictionary) {
openspace::documentation::testSpecificationAndThrow(
@@ -164,4 +165,5 @@ documentation::Documentation KameleonDocumentationTask::documentation() {
};
}
} // namespace kameleonvolume
} // namespace openspace

View File

@@ -30,6 +30,7 @@
#include <string>
namespace openspace {
namespace kameleonvolume {
class KameleonDocumentationTask : public Task {
public:
@@ -43,6 +44,7 @@ private:
std::string _outputPath;
};
} // namespace kameleonvolume
} // namespace openspace
#endif // __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONDOCUMENTATIONTASK___H__

View File

@@ -39,6 +39,7 @@ namespace {
} // namespace
namespace openspace {
namespace kameleonvolume {
KameleonMetadataToJsonTask::KameleonMetadataToJsonTask(
const ghoul::Dictionary& dictionary)
@@ -98,4 +99,5 @@ documentation::Documentation KameleonMetadataToJsonTask::documentation() {
};
}
} // namespace kameleonvolume
} // namespace openspace

View File

@@ -30,6 +30,7 @@
#include <string>
namespace openspace {
namespace kameleonvolume {
class KameleonMetadataToJsonTask : public Task {
public:
@@ -43,6 +44,7 @@ private:
std::string _outputPath;
};
} // namespace kameleonvolume
} // namespace openspace
#endif // __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONMETADATATOJSONTASK___H__

View File

@@ -0,0 +1,207 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/kameleonvolume/tasks/kameleonvolumetorawtask.h>
#include <modules/kameleonvolume/kameleonvolumereader.h>
#include <modules/volume/rawvolume.h>
#include <modules/volume/rawvolumewriter.h>
#include <openspace/documentation/verifier.h>
#include <ghoul/misc/dictionaryjsonformatter.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/dictionaryluaformatter.h>
#include <fstream>
namespace {
const char* KeyInput = "Input";
const char* KeyRawVolumeOutput = "RawVolumeOutput";
const char* KeyDictionaryOutput = "DictionaryOutput";
const char* KeyDimensions = "Dimensions";
const char* KeyVariable = "Variable";
const char* KeyTime = "Time";
const char* KeyLowerDomainBound = "LowerDomainBound";
const char* KeyUpperDomainBound = "UpperDomainBound";
const char* KeyMinValue = "MinValue";
const char* KeyMaxValue = "MaxValue";
const char* _loggerCat = "KameleonVolumeToRawTask";
} // namespace
namespace openspace {
namespace kameleonvolume {
KameleonVolumeToRawTask::KameleonVolumeToRawTask(const ghoul::Dictionary& dictionary)
: _autoDomainBounds(false)
{
openspace::documentation::testSpecificationAndThrow(
documentation(),
dictionary,
"KameleonVolumeToRawTask"
);
_inputPath = absPath(dictionary.value<std::string>(KeyInput));
_rawVolumeOutputPath = absPath(dictionary.value<std::string>(KeyRawVolumeOutput));
_dictionaryOutputPath = absPath(dictionary.value<std::string>(KeyDictionaryOutput));
_variable = dictionary.value<std::string>(KeyVariable);
_dimensions = glm::uvec3(dictionary.value<glm::vec3>(KeyDimensions));
if (!dictionary.getValue<glm::vec3>(KeyLowerDomainBound, _lowerDomainBound)) {
_autoDomainBounds = true;
}
if (!dictionary.getValue<glm::vec3>(KeyUpperDomainBound, _upperDomainBound)) {
_autoDomainBounds = true;
}
}
std::string KameleonVolumeToRawTask::description() {
return "Extract volumetric data from cdf-file " + _inputPath + "." +
"Write raw volume data into " + _rawVolumeOutputPath +
" and dictionary with metadata to " + _dictionaryOutputPath;
}
void KameleonVolumeToRawTask::perform(const Task::ProgressCallback& progressCallback) {
KameleonVolumeReader reader(_inputPath);
std::vector<std::string> variables = reader.gridVariableNames();
if (variables.size() == 3 && _autoDomainBounds) {
_lowerDomainBound = glm::vec3(
reader.minValue(variables[0]),
reader.minValue(variables[1]),
reader.minValue(variables[2]));
_upperDomainBound = glm::vec3(
reader.maxValue(variables[0]),
reader.maxValue(variables[1]),
reader.maxValue(variables[2]));
}
std::unique_ptr<volume::RawVolume<float>> rawVolume = reader.readFloatVolume(
_dimensions,
_variable,
_lowerDomainBound,
_upperDomainBound);
progressCallback(0.5f);
volume::RawVolumeWriter<float> writer(_rawVolumeOutputPath);
writer.write(*rawVolume);
progressCallback(0.9f);
ghoul::Dictionary inputMetadata = reader.readMetaData();
ghoul::Dictionary outputMetadata;
std::string time = reader.time();
// Do not include time offset in time string
if (time.back() == 'Z') {
time.pop_back();
}
outputMetadata.setValue<std::string>(KeyTime, time);
outputMetadata.setValue<glm::vec3>(KeyDimensions, _dimensions);
outputMetadata.setValue<glm::vec3>(KeyLowerDomainBound, _lowerDomainBound);
outputMetadata.setValue<glm::vec3>(KeyUpperDomainBound, _upperDomainBound);
outputMetadata.setValue<float>(KeyMinValue, reader.minValue(_variable));
outputMetadata.setValue<float>(KeyMaxValue, reader.maxValue(_variable));
ghoul::DictionaryLuaFormatter formatter;
std::string metadataString = formatter.format(outputMetadata);
std::fstream f(_dictionaryOutputPath, std::ios::out);
f << "return " << metadataString;
f.close();
progressCallback(1.0f);
}
documentation::Documentation KameleonVolumeToRawTask::documentation() {
using namespace documentation;
return {
"KameleonVolumeToRawTask",
"kameleon_metadata_to_json_task",
{
{
"Type",
new StringEqualVerifier("KameleonVolumeToRawTask"),
Optional::No,
"The type of this task",
},
{
KeyInput,
new StringAnnotationVerifier("A file path to a cdf file"),
Optional::No,
"The cdf file to extract data from",
},
{
KeyRawVolumeOutput,
new StringAnnotationVerifier("A valid filepath"),
Optional::No,
"The raw volume file to export data to",
},
{
KeyDictionaryOutput,
new StringAnnotationVerifier("A valid filepath"),
Optional::No,
"The lua dictionary file to export metadata to",
},
{
KeyVariable,
new StringAnnotationVerifier("A valid kameleon variable"),
Optional::No,
"The variable name to read from the kameleon dataset",
},
{
KeyDimensions,
new DoubleVector3Verifier,
Optional::No,
"A vector representing the number of cells in each dimension",
},
{
KeyLowerDomainBound,
new DoubleVector3Verifier,
Optional::Yes,
"A vector representing the lower bound of the domain, "
"in the native kameleon grid units",
},
{
KeyUpperDomainBound,
new DoubleVector3Verifier,
Optional::Yes,
"A vector representing the lower bound of the domain, "
"in the native kameleon grid units",
}
}
};
}
} // namespace kameleonvolume
} // namespace openspace

View File

@@ -0,0 +1,59 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONVOLUMETORAWTASK___H__
#define __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONVOLUMETORAWTASK___H__
#include <openspace/util/task.h>
#include <glm/glm.hpp>
#include <string>
namespace openspace {
namespace kameleonvolume {
class KameleonVolumeToRawTask : public Task {
public:
KameleonVolumeToRawTask(const ghoul::Dictionary& dictionary);
std::string description() override;
void perform(const Task::ProgressCallback& progressCallback) override;
static documentation::Documentation documentation();
private:
std::string _inputPath;
std::string _rawVolumeOutputPath;
std::string _dictionaryOutputPath;
std::string _variable;
glm::uvec3 _dimensions;
bool _autoDomainBounds;
glm::vec3 _lowerDomainBound;
glm::vec3 _upperDomainBound;
};
} // namespace kameleon
} // namespace openspace
#endif // __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONMETADATATORAWTASK___H__

View File

@@ -44,12 +44,11 @@ RenderableToyVolume::RenderableToyVolume(const ghoul::Dictionary& dictionary)
, _rotation({ "Rotation", "Euler rotation", "" }, glm::vec3(0.f, 0.f, 0.f), glm::vec3(0), glm::vec3(6.28f)) // @TODO Missing documentation
, _color({ "Color", "Color", "" }, glm::vec4(1.f, 0.f, 0.f, 0.1f), glm::vec4(0.f), glm::vec4(1.f)) // @TODO Missing documentation
{
float stepSize;
int scalingExponent;
float stepSize, scalingExponent;
glm::vec3 scaling, translation, rotation;
glm::vec4 color;
if (dictionary.getValue("ScalingExponent", scalingExponent)) {
_scalingExponent = scalingExponent;
_scalingExponent = static_cast<int>(scalingExponent);
}
if (dictionary.getValue("Scaling", scaling)) {
_scaling = scaling;

View File

@@ -39,6 +39,8 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/volumesampler.h
${CMAKE_CURRENT_SOURCE_DIR}/volumesampler.inl
${CMAKE_CURRENT_SOURCE_DIR}/volumeutils.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderabletimevaryingvolume.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/basicvolumeraycaster.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/volumeclipplane.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/volumeclipplanes.h
)
@@ -50,7 +52,10 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rawvolumewriter.inl
${CMAKE_CURRENT_SOURCE_DIR}/textureslicevolumereader.inl
${CMAKE_CURRENT_SOURCE_DIR}/volumesampler.inl
${CMAKE_CURRENT_SOURCE_DIR}/volumegridtype.cpp
${CMAKE_CURRENT_SOURCE_DIR}/volumeutils.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderabletimevaryingvolume.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/basicvolumeraycaster.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/volumeclipplane.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/volumeclipplanes.cpp
)

View File

@@ -30,6 +30,7 @@
#include <iterator>
namespace openspace {
namespace volume {
template <typename ValueType>
class LinearLruCache {
@@ -86,6 +87,7 @@ private:
size_t _capacity;
};
} // namespace volume
} // namespace openspace
#endif // __OPENSPACE_MODULE_VOLUME___LINEARLRUCACHE___H__

View File

@@ -30,6 +30,7 @@
#include <iterator>
namespace openspace {
namespace volume {
template <typename KeyType, typename ValueType, template<typename...> class ContainerType>
class LruCache {
@@ -85,6 +86,7 @@ private:
size_t _capacity;
};
} // namespace volume
} // namespace openspace
#endif // __OPENSPACE_MODULE_VOLUME___LRUCACHE___H__

View File

@@ -30,6 +30,7 @@
#include <vector>
namespace openspace {
namespace volume {
template <typename Type>
class RawVolume {
@@ -54,6 +55,7 @@ private:
std::vector<VoxelType> _data;
};
} // namespace volume
} // namespace openspace
#include "rawvolume.inl"

View File

@@ -26,6 +26,7 @@
#include "rawvolume.h"
namespace openspace {
namespace volume {
template <typename VoxelType>
RawVolume<VoxelType>::RawVolume(const glm::uvec3& dimensions)
@@ -57,7 +58,7 @@ size_t RawVolume<VoxelType>::nCells() const
template <typename VoxelType>
VoxelType RawVolume<VoxelType>::get(const glm::uvec3& coordinates) const {
return get(coordsToIndex(coordinates, dimensions()));
return get(coordsToIndex(coordinates));
}
template <typename VoxelType>
@@ -67,7 +68,7 @@ VoxelType RawVolume<VoxelType>::get(size_t index) const {
template <typename VoxelType>
void RawVolume<VoxelType>::set(const glm::uvec3& coordinates, const VoxelType& value) {
return set(coordsToIndex(coordinates, dimensions()), value);
return set(coordsToIndex(coordinates), value);
}
template <typename VoxelType>
@@ -87,12 +88,12 @@ void RawVolume<VoxelType>::forEachVoxel(
template <typename VoxelType>
size_t RawVolume<VoxelType>::coordsToIndex(const glm::uvec3& cartesian) const {
return volumeutils::coordsToIndex(cartesian, dimensions());
return volume::coordsToIndex(cartesian, dimensions());
}
template <typename VoxelType>
glm::uvec3 RawVolume<VoxelType>::indexToCoords(size_t linear) const {
return volumeutils::indexToCoords(linear, dimensions());
return volume::indexToCoords(linear, dimensions());
}
template <typename VoxelType>
@@ -105,5 +106,5 @@ const VoxelType* RawVolume<VoxelType>::data() const {
return _data.data();
}
}
} // namespace volume
} // namespace openspace

View File

@@ -29,6 +29,7 @@
#include <modules/volume/rawvolume.h>
namespace openspace {
namespace volume {
template <typename Type>
class RawVolumeReader {
@@ -51,6 +52,7 @@ private:
std::string _path;
};
} // namespace volume
} // namespace openspace
#include "rawvolumereader.inl"

View File

@@ -25,6 +25,7 @@
#include <fstream>
namespace openspace {
namespace volume {
template <typename VoxelType>
RawVolumeReader<VoxelType>::RawVolumeReader(const std::string& path,
@@ -69,12 +70,12 @@ VoxelType RawVolumeReader<VoxelType>::get(size_t index) const {
template <typename VoxelType>
size_t RawVolumeReader<VoxelType>::coordsToIndex(const glm::uvec3& cartesian) const {
return volumeutils::coordsToIndex(cartesian, dimensions());
return coordsToIndex(cartesian, dimensions());
}
template <typename VoxelType>
glm::uvec3 RawVolumeReader<VoxelType>::indexToCoords(size_t linear) const {
return volumeutils::indexToCoords(linear, dimensions());
return indexToCoords(linear, dimensions());
}
@@ -95,4 +96,5 @@ std::unique_ptr<RawVolume<VoxelType>> RawVolumeReader<VoxelType>::read() {
return volume;
}
} // namepsace volume
} // namespace openspace

View File

@@ -30,6 +30,7 @@
#include <modules/volume/rawvolume.h>
namespace openspace {
namespace volume {
template <typename VoxelType>
class RawVolumeWriter {
@@ -51,6 +52,7 @@ private:
size_t _bufferSize;
};
} // namespace volume
} // namespace openspace
#include "rawvolumewriter.inl"

View File

@@ -26,6 +26,7 @@
#include <modules/volume/volumeutils.h>
namespace openspace {
namespace volume {
template <typename VoxelType>
RawVolumeWriter<VoxelType>::RawVolumeWriter(std::string path, size_t bufferSize)
@@ -35,12 +36,12 @@ RawVolumeWriter<VoxelType>::RawVolumeWriter(std::string path, size_t bufferSize)
template <typename VoxelType>
size_t RawVolumeWriter<VoxelType>::coordsToIndex(const glm::uvec3& cartesian) const {
return volumeutils::coordsToIndex(cartesian, dimensions());
return coordsToIndex(cartesian, dimensions());
}
template <typename VoxelType>
glm::ivec3 RawVolumeWriter<VoxelType>::indexToCoords(size_t linear) const {
return volumeutils::indexToCoords(linear, dimensions());
return indexToCoords(linear, dimensions());
}
template <typename VoxelType>
@@ -96,4 +97,5 @@ void RawVolumeWriter<VoxelType>::write(const RawVolume<VoxelType>& volume) {
file.close();
}
} // namespace volume
} // namespace openspace

View File

@@ -22,7 +22,7 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/kameleonvolume/rendering/kameleonvolumeraycaster.h>
#include <modules/volume/rendering/basicvolumeraycaster.h>
#include <ghoul/glm.h>
#include <ghoul/opengl/ghoul_gl.h>
@@ -32,44 +32,44 @@
#include <openspace/util/powerscaledcoordinate.h>
#include <openspace/util/updatestructures.h>
#include <openspace/rendering/renderable.h>
#include <modules/kameleonvolume/rendering/renderablekameleonvolume.h>
namespace {
const char* GlslRaycastPath = "${MODULES}/kameleonvolume/shaders/raycast.glsl";
const char* GlslHelperPath = "${MODULES}/kameleonvolume/shaders/helper.glsl";
const char* GlslBoundsVsPath = "${MODULES}/kameleonvolume/shaders/boundsvs.glsl";
const char* GlslBoundsFsPath = "${MODULES}/kameleonvolume/shaders/boundsfs.glsl";
} // namespace
const char* GlslRaycastPath = "${MODULE_VOLUME}/shaders/raycast.glsl";
const char* GlslHelperPath = "${MODULE_VOLUME}/shaders/helper.glsl";
const char* GlslBoundsVsPath = "${MODULE_VOLUME}/shaders/boundsvs.glsl";
const char* GlslBoundsFsPath = "${MODULE_VOLUME}/shaders/boundsfs.glsl";
}
namespace openspace {
namespace volume {
KameleonVolumeRaycaster::KameleonVolumeRaycaster(
std::shared_ptr<ghoul::opengl::Texture> texture,
std::shared_ptr<TransferFunction> transferFunction,
std::shared_ptr<VolumeClipPlanes> clipPlanes)
: _clipPlanes(clipPlanes)
, _volumeTexture(texture)
BasicVolumeRaycaster::BasicVolumeRaycaster(
std::shared_ptr<ghoul::opengl::Texture> volumeTexture,
std::shared_ptr<TransferFunction> transferFunction,
std::shared_ptr<VolumeClipPlanes> clipPlanes)
: _volumeTexture(volumeTexture)
, _transferFunction(transferFunction)
, _clipPlanes(clipPlanes)
, _boundingBox(glm::vec3(1.0))
, _opacity(20.0)
, _rNormalization(0.0)
, _rUpperBound(1.0)
, _valueRemapping(0.0, 1.0)
{}
KameleonVolumeRaycaster::~KameleonVolumeRaycaster() {}
void KameleonVolumeRaycaster::initialize() {
BasicVolumeRaycaster::~BasicVolumeRaycaster() {}
void BasicVolumeRaycaster::initialize() {
_boundingBox.initialize();
}
void KameleonVolumeRaycaster::deinitialize() {
}
void BasicVolumeRaycaster::deinitialize() {}
void KameleonVolumeRaycaster::renderEntryPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) {
glm::dmat4 modelTransform =
glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * // Translation
glm::dmat4(data.modelTransform.rotation) * // Spice rotation
glm::dmat4(glm::scale(glm::dmat4(_modelTransform), glm::dvec3(data.modelTransform.scale)));
glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() * modelTransform;
program.setUniform("modelViewTransform", glm::mat4(modelViewTransform));
void BasicVolumeRaycaster::renderEntryPoints(
const RenderData& data,
ghoul::opengl::ProgramObject& program)
{
program.setUniform("modelViewTransform", glm::mat4(modelViewTransform(data)));
program.setUniform("projectionTransform", data.camera.projectionMatrix());
// Cull back face
@@ -79,15 +79,23 @@ void KameleonVolumeRaycaster::renderEntryPoints(const RenderData& data, ghoul::o
// Render bounding geometry
_boundingBox.render();
}
void KameleonVolumeRaycaster::renderExitPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) {
glm::dmat4 BasicVolumeRaycaster::modelViewTransform(const RenderData& data) {
glm::dmat4 modelTransform =
glm::translate(glm::dmat4(1.0), data.modelTransform.translation) *
glm::dmat4(data.modelTransform.rotation) *
glm::dmat4(glm::scale(glm::dmat4(_modelTransform), glm::dvec3(data.modelTransform.scale)));
glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() * modelTransform;
glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)) *
glm::dmat4(_modelTransform);
program.setUniform("modelViewTransform", glm::mat4(modelViewTransform));
return data.camera.combinedViewMatrix() * modelTransform;
}
void BasicVolumeRaycaster::renderExitPoints(
const RenderData& data,
ghoul::opengl::ProgramObject& program)
{
program.setUniform("modelViewTransform", glm::mat4(modelViewTransform(data)));
program.setUniform("projectionTransform", data.camera.projectionMatrix());
// Cull front face
@@ -101,7 +109,14 @@ void KameleonVolumeRaycaster::renderExitPoints(const RenderData& data, ghoul::op
glCullFace(GL_BACK);
}
void KameleonVolumeRaycaster::preRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) {
void BasicVolumeRaycaster::preRaycast(
const RaycastData& data,
ghoul::opengl::ProgramObject& program)
{
if (!_volumeTexture || !_transferFunction) {
return;
}
std::string stepSizeUniformName = "maxStepSize" + std::to_string(data.id);
program.setUniform(stepSizeUniformName, _stepSize);
@@ -126,56 +141,110 @@ void KameleonVolumeRaycaster::preRaycast(const RaycastData& data, ghoul::opengl:
program.setUniform("nClips_" + id, nClips);
program.setUniform("clipNormals_" + id, clipNormals.data(), nClips);
program.setUniform("clipOffsets_" + id, clipOffsets.data(), nClips);
program.setUniform("opacity_" + id, _opacity);
program.setUniform("rNormalization_" + id, _rNormalization);
program.setUniform("rUpperBound_" + id, _rUpperBound);
program.setUniform("valueRemapping_" + id, _valueRemapping);
}
void KameleonVolumeRaycaster::postRaycast(const RaycastData&,
ghoul::opengl::ProgramObject&)
void BasicVolumeRaycaster::postRaycast(const RaycastData&, ghoul::opengl::ProgramObject&)
{
// For example: release texture units
_textureUnit = nullptr;
_tfUnit = nullptr;
}
bool KameleonVolumeRaycaster::cameraIsInside(const RenderData & data, glm::vec3 & localPosition)
{
glm::dmat4 modelTransform =
glm::translate(glm::dmat4(1.0), data.modelTransform.translation) *
glm::dmat4(data.modelTransform.rotation) *
glm::dmat4(glm::scale(glm::dmat4(_modelTransform), glm::dvec3(data.modelTransform.scale)));
glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() * modelTransform;
glm::vec4 modelPos = glm::inverse(modelViewTransform) * glm::vec4(0.0, 0.0, 0.0, 1.0);
bool BasicVolumeRaycaster::cameraIsInside(
const RenderData & data,
glm::vec3 & localPosition)
{
glm::vec4 modelPos =
glm::inverse(modelViewTransform(data)) * glm::vec4(0.0, 0.0, 0.0, 1.0);
localPosition = (glm::vec3(modelPos) + glm::vec3(0.5));
return (localPosition.x > 0 && localPosition.y > 0 && localPosition.z > 0 && localPosition.x < 1 && localPosition.y < 1 && localPosition.z < 1);
return (localPosition.x > 0 && localPosition.x < 1 &&
localPosition.y > 0 && localPosition.y < 1 &&
localPosition.z > 0 && localPosition.z < 1);
}
std::string KameleonVolumeRaycaster::getBoundsVsPath() const {
std::string BasicVolumeRaycaster::getBoundsVsPath() const {
return GlslBoundsVsPath;
}
std::string KameleonVolumeRaycaster::getBoundsFsPath() const {
std::string BasicVolumeRaycaster::getBoundsFsPath() const {
return GlslBoundsFsPath;
}
std::string KameleonVolumeRaycaster::getRaycastPath() const {
std::string BasicVolumeRaycaster::getRaycastPath() const {
return GlslRaycastPath;
}
std::string KameleonVolumeRaycaster::getHelperPath() const {
std::string BasicVolumeRaycaster::getHelperPath() const {
return GlslHelperPath;
}
void KameleonVolumeRaycaster::setStepSize(float stepSize) {
void BasicVolumeRaycaster::setTransferFunction(
std::shared_ptr<TransferFunction> transferFunction)
{
_transferFunction = transferFunction;
}
void BasicVolumeRaycaster::setVolumeTexture(
std::shared_ptr<ghoul::opengl::Texture> volumeTexture)
{
_volumeTexture = volumeTexture;
}
std::shared_ptr<ghoul::opengl::Texture> BasicVolumeRaycaster::volumeTexture() const {
return _volumeTexture;
}
void BasicVolumeRaycaster::setStepSize(float stepSize) {
_stepSize = stepSize;
}
void KameleonVolumeRaycaster::setGridType(VolumeGridType gridType) {
void BasicVolumeRaycaster::setOpacity(float opacity) {
_opacity = opacity;
}
float BasicVolumeRaycaster::opacity() const {
return _opacity;
}
void BasicVolumeRaycaster::setRNormalization(float rNormalization) {
_rNormalization = rNormalization;
}
float BasicVolumeRaycaster::rNormalization() const {
return _rNormalization;
}
void BasicVolumeRaycaster::setRUpperBound(float rUpperBound) {
_rUpperBound = rUpperBound;
}
float BasicVolumeRaycaster::rUpperBound() const {
return _rUpperBound;
}
void BasicVolumeRaycaster::setValueRemapping(float mapZeroTo, float mapOneTo) {
_valueRemapping = glm::vec2(mapZeroTo, mapOneTo);
}
VolumeGridType BasicVolumeRaycaster::gridType() const {
return _gridType;
}
void BasicVolumeRaycaster::setGridType(VolumeGridType gridType) {
_gridType = gridType;
}
void KameleonVolumeRaycaster::setModelTransform(const glm::mat4 & transform) {
void BasicVolumeRaycaster::setModelTransform(const glm::mat4 & transform) {
_modelTransform = transform;
}
}
} // namespace volume
} // namespace openspace

View File

@@ -22,8 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONVOLUMERAYCASTER___H__
#define __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONVOLUMERAYCASTER___H__
#ifndef __OPENSPACE_MODULE_VOLUME___BASICVOLUMERAYCASTER___H__
#define __OPENSPACE_MODULE_VOLUME___BASICVOLUMERAYCASTER___H__
#include <string>
#include <vector>
@@ -50,16 +50,18 @@ namespace openspace {
struct RenderData;
struct RaycastData;
class KameleonVolumeRaycaster : public VolumeRaycaster {
namespace volume {
class BasicVolumeRaycaster : public VolumeRaycaster {
public:
KameleonVolumeRaycaster(
BasicVolumeRaycaster(
std::shared_ptr<ghoul::opengl::Texture> texture,
std::shared_ptr<TransferFunction> transferFunction,
std::shared_ptr<VolumeClipPlanes> clipPlanes);
virtual ~KameleonVolumeRaycaster();
virtual ~BasicVolumeRaycaster();
void initialize();
void deinitialize();
void renderEntryPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) override;
void renderExitPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) override;
void preRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) override;
@@ -71,23 +73,42 @@ public:
std::string getRaycastPath() const override;
std::string getHelperPath() const override;
void setVolumeTexture(std::shared_ptr<ghoul::opengl::Texture> texture);
std::shared_ptr<ghoul::opengl::Texture> volumeTexture() const;
void setTransferFunction(std::shared_ptr<TransferFunction> transferFunction);
void setStepSize(float stepSize);
float opacity() const;
void setOpacity(float opacity);
float rNormalization() const;
void setRNormalization(float rNormalization);
float rUpperBound() const;
void setRUpperBound(float rNormalization);
void setValueRemapping(float mapZeroTo, float mapOneTo);
VolumeGridType gridType() const;
void setGridType(VolumeGridType gridType);
void setModelTransform(const glm::mat4& transform);
private:
glm::dmat4 modelViewTransform(const RenderData& data);
std::shared_ptr<VolumeClipPlanes> _clipPlanes;
std::shared_ptr<ghoul::opengl::Texture> _volumeTexture;
std::shared_ptr<TransferFunction> _transferFunction;
BoxGeometry _boundingBox;
VolumeGridType _gridType;
glm::mat4 _modelTransform;
float _opacity;
float _rNormalization;
float _rUpperBound;
glm::vec2 _valueRemapping;
std::unique_ptr<ghoul::opengl::TextureUnit> _tfUnit;
std::unique_ptr<ghoul::opengl::TextureUnit> _textureUnit;
float _stepSize;
};
} // namespace volume
} // namespace openspace
#endif // __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONVOLUMERAYCASTER___H__
#endif // __OPENSPACE_MODULE_VOLUME___BASICVOLUMERAYCASTER___H__

View File

@@ -0,0 +1,473 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/volume/rendering/renderabletimevaryingvolume.h>
#include <modules/volume/rawvolumereader.h>
#include <modules/volume/rawvolume.h>
#include <openspace/rendering/renderable.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/rendering/raycastermanager.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/util/timemanager.h>
#include <openspace/util/time.h>
#include <ghoul/glm.h>
#include <ghoul/opengl/ghoul_gl.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/filesystem/cachemanager.h>
#include <ghoul/logging/logmanager.h>
#include <glm/gtc/matrix_transform.hpp>
namespace {
const char* _loggerCat = "RenderableTimeVaryingVolume";
}
namespace {
const char* KeyDimensions = "Dimensions";
const char* KeyStepSize = "StepSize";
const char* KeyTransferFunction = "TransferFunction";
const char* KeySourceDirectory = "SourceDirectory";
const char* KeyLowerDomainBound = "LowerDomainBound";
const char* KeyUpperDomainBound = "UpperDomainBound";
const char* KeyLowerValueBound = "LowerValueBound";
const char* KeyUpperValueBound = "UpperValueBound";
const char* KeyClipPlanes = "ClipPlanes";
const char* KeySecondsBefore = "SecondsBefore";
const char* KeySecondsAfter = "SecondsAfter";
const char* KeyGridType = "GridType";
const char* KeyMinValue = "MinValue";
const char* KeyMaxValue = "MaxValue";
const char* KeyTime = "Time";
const float SecondsInOneDay = 60 * 60 * 24;
}
namespace openspace {
namespace volume {
RenderableTimeVaryingVolume::RenderableTimeVaryingVolume(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _clipPlanes(nullptr)
, _stepSize({ "stepSize", "Step Size", "" }, 0.02, 0.01, 1)
, _gridType({ "gridType", "Grid Type", "" }, properties::OptionProperty::DisplayType::Dropdown)
, _secondsBefore({ "secondsBefore", "Seconds before", "" }, 0.0, 0.01, SecondsInOneDay)
, _secondsAfter({ "secondsAfter", "Seconds after", "" }, 0.0, 0.01, SecondsInOneDay)
, _sourceDirectory({ "sourceDirectory", "Source Directory", "" })
, _transferFunctionPath({"transferFunctionPath", "Transfer Function Path", "" })
, _triggerTimeJump({"triggerTimeJump", "Jump", "" })
, _jumpToTimestep({"jumpToTimestep", "Jump to timestep", "" }, 0, 0, 256)
, _currentTimestep({"currentTimestep", "Current timestep", "" }, 0, 0, 256)
, _opacity({"opacity", "Opacity", "" }, 10.0f, 0.0f, 50.0f)
, _rNormalization({"rNormalization", "Radius normalization", "" }, 0.0f, 0.0f, 2.0f)
, _rUpperBound({"rUpperBound", "Radius upper bound", "" }, 1.0f, 0.0f, 2.0f)
, _lowerValueBound({"lowerValueBound", "Lower value bound", "" }, 0.0f, 0.0f, 1000000.0f)
, _upperValueBound({"upperValueBound", "Upper value bound", "" }, 0.0f, 0.0f, 1000000.0f)
, _raycaster(nullptr)
, _transferFunction(nullptr)
{
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"RenderableTimeVaryingVolume"
);
_sourceDirectory = absPath(dictionary.value<std::string>(KeySourceDirectory));
_transferFunctionPath = absPath(dictionary.value<std::string>(KeyTransferFunction));
_lowerValueBound = dictionary.value<float>(KeyLowerValueBound);
_upperValueBound = dictionary.value<float>(KeyUpperValueBound);
_transferFunction = std::make_shared<TransferFunction>(_transferFunctionPath);
_gridType.addOption(static_cast<int>(volume::VolumeGridType::Cartesian), "Cartesian grid");
_gridType.addOption(static_cast<int>(volume::VolumeGridType::Spherical), "Spherical grid");
_gridType.setValue(static_cast<int>(volume::VolumeGridType::Cartesian));
if (dictionary.hasValue<float>(KeySecondsBefore)) {
_secondsBefore = dictionary.value<float>(KeySecondsBefore);
}
_secondsAfter = dictionary.value<float>(KeySecondsAfter);
ghoul::Dictionary clipPlanesDictionary;
dictionary.getValue(KeyClipPlanes, clipPlanesDictionary);
_clipPlanes = std::make_shared<volume::VolumeClipPlanes>(clipPlanesDictionary);
_clipPlanes->setName("clipPlanes");
if (dictionary.hasValue<std::string>(KeyGridType)) {
VolumeGridType gridType = volume::parseGridType(dictionary.value<std::string>(KeyGridType));
_gridType = (gridType == VolumeGridType::Spherical) ? 1 : 0;
}
}
RenderableTimeVaryingVolume::~RenderableTimeVaryingVolume() {}
void RenderableTimeVaryingVolume::initialize() {
using RawPath = ghoul::filesystem::Directory::RawPath;
ghoul::filesystem::Directory sequenceDir(_sourceDirectory, RawPath::Yes);
if (!FileSys.directoryExists(sequenceDir)) {
LERROR("Could not load sequence directory '" << sequenceDir.path() << "'");
return;
}
using Recursive = ghoul::filesystem::Directory::Recursive;
using Sort = ghoul::filesystem::Directory::Sort;
std::vector<std::string> sequencePaths = sequenceDir.read(Recursive::Yes, Sort::No);
for (auto path : sequencePaths) {
ghoul::filesystem::File currentFile(path);
std::string extension = currentFile.fileExtension();
if (extension == "dictionary") {
loadTimestepMetadata(path);
}
}
// TODO: defer loading of data to later. (separate thread or at least not when loading)
for (auto& p : _volumeTimesteps) {
Timestep& t = p.second;
std::string path = FileSys.pathByAppendingComponent(_sourceDirectory, t.baseName) + ".rawvolume";
RawVolumeReader<float> reader(path, t.dimensions);
t.rawVolume = reader.read();
float min = t.minValue;
float diff = t.maxValue - t.minValue;
float *data = t.rawVolume->data();
for (size_t i = 0; i < t.rawVolume->nCells(); ++i) {
data[i] = glm::clamp((data[i] - min) / diff, 0.0f, 1.0f);
}
// TODO: handle normalization properly for different timesteps + transfer function
t.texture = std::make_shared<ghoul::opengl::Texture>(
t.dimensions,
ghoul::opengl::Texture::Format::Red,
GL_RED,
GL_FLOAT,
ghoul::opengl::Texture::FilterMode::Linear,
ghoul::opengl::Texture::WrappingMode::Clamp
);
t.texture->setPixelData(reinterpret_cast<void*>(data), ghoul::opengl::Texture::TakeOwnership::No);
t.texture->uploadTexture();
}
_clipPlanes->initialize();
_transferFunction->update();
_raycaster = std::make_unique<volume::BasicVolumeRaycaster>(nullptr, _transferFunction, _clipPlanes);
_raycaster->initialize();
OsEng.renderEngine().raycasterManager().attachRaycaster(*_raycaster.get());
auto onChange = [&](bool enabled) {
if (enabled) {
OsEng.renderEngine().raycasterManager().attachRaycaster(*_raycaster.get());
} else {
OsEng.renderEngine().raycasterManager().detachRaycaster(*_raycaster.get());
}
};
onEnabledChange(onChange);
_triggerTimeJump.onChange([this] () {
jumpToTimestep(_jumpToTimestep);
});
_jumpToTimestep.onChange([this] () {
jumpToTimestep(_jumpToTimestep);
});
const int lastTimestep = (_volumeTimesteps.size() > 0) ? (_volumeTimesteps.size() - 1) : 0;
_currentTimestep.setMaxValue(lastTimestep);
_jumpToTimestep.setMaxValue(lastTimestep);
addProperty(_stepSize);
addProperty(_transferFunctionPath);
addProperty(_sourceDirectory);
addPropertySubOwner(_clipPlanes.get());
addProperty(_triggerTimeJump);
addProperty(_jumpToTimestep);
addProperty(_currentTimestep);
addProperty(_opacity);
addProperty(_rNormalization);
addProperty(_rUpperBound);
addProperty(_lowerValueBound);
addProperty(_upperValueBound);
_raycaster->setGridType((_gridType.value() == 1) ? VolumeGridType::Spherical : VolumeGridType::Cartesian);
_gridType.onChange([this] {
_raycaster->setGridType((_gridType.value() == 1) ? VolumeGridType::Spherical : VolumeGridType::Cartesian);
});
}
void RenderableTimeVaryingVolume::loadTimestepMetadata(const std::string& path) {
ghoul::Dictionary dictionary = ghoul::lua::loadDictionaryFromFile(path);
try {
documentation::testSpecificationAndThrow(TimestepDocumentation(), dictionary, "TimeVaryingVolumeTimestep");
} catch (const documentation::SpecificationError& e) {
LERROR(e.message << e.component);
return;
}
Timestep t;
t.baseName = ghoul::filesystem::File(path).baseName();
t.dimensions = dictionary.value<glm::vec3>(KeyDimensions);
t.lowerDomainBound = dictionary.value<glm::vec3>(KeyLowerDomainBound);
t.upperDomainBound = dictionary.value<glm::vec3>(KeyUpperDomainBound);
t.minValue = dictionary.value<float>(KeyMinValue);
t.maxValue = dictionary.value<float>(KeyMaxValue);
std::string timeString = dictionary.value<std::string>(KeyTime);
t.time = Time::convertTime(timeString);
t.inRam = false;
t.onGpu = false;
_volumeTimesteps[t.time] = std::move(t);
}
RenderableTimeVaryingVolume::Timestep* RenderableTimeVaryingVolume::currentTimestep() {
if (_volumeTimesteps.size() == 0) {
return nullptr;
}
double currentTime = OsEng.timeManager().time().j2000Seconds();
// Get the first item with time > currentTime
auto currentTimestepIt = _volumeTimesteps.upper_bound(currentTime);
if (currentTimestepIt == _volumeTimesteps.end()) {
// No such timestep was found: show last timestep if it is within the time margin.
RenderableTimeVaryingVolume::Timestep* lastTimestep = &(_volumeTimesteps.rbegin()->second);
double threshold = lastTimestep->time + static_cast<double>(_secondsAfter);
return currentTime < threshold ? lastTimestep : nullptr;
}
if (currentTimestepIt == _volumeTimesteps.begin()) {
// No such timestep was found: show first timestep if it is within the time margin.
RenderableTimeVaryingVolume::Timestep* firstTimestep = &(_volumeTimesteps.begin()->second);
double threshold = firstTimestep->time - static_cast<double>(_secondsBefore);
return currentTime >= threshold ? firstTimestep : nullptr;
}
// Get the last item with time <= currentTime
currentTimestepIt--;
return &(currentTimestepIt->second);
}
int RenderableTimeVaryingVolume::timestepIndex(const RenderableTimeVaryingVolume::Timestep* t) const {
if (!t) {
return -1;
}
int index = 0;
for (auto& it : _volumeTimesteps) {
if (&(it.second) == t) {
return index;
}
++index;
}
return -1;
}
RenderableTimeVaryingVolume::Timestep* RenderableTimeVaryingVolume::timestepFromIndex(int target) {
if (target < 0) target = 0;
int index = 0;
for (auto& it : _volumeTimesteps) {
if (index == target) {
return &(it.second);
}
++index;
}
return nullptr;
}
void RenderableTimeVaryingVolume::jumpToTimestep(int target) {
Timestep* t = timestepFromIndex(target);
if (!t) {
return;
}
OsEng.timeManager().setTimeNextFrame(t->time);
}
void RenderableTimeVaryingVolume::update(const UpdateData& data) {
if (_raycaster) {
Timestep* t = currentTimestep();
_currentTimestep = timestepIndex(t);
if (t && t->texture) {
if (_raycaster->gridType() == volume::VolumeGridType::Cartesian) {
glm::dvec3 scale = t->upperDomainBound - t->lowerDomainBound;
glm::dvec3 translation = (t->lowerDomainBound + t->upperDomainBound) * 0.5f;
glm::dmat4 modelTransform = glm::translate(glm::dmat4(1.0), translation);
glm::dmat4 scaleMatrix = glm::scale(glm::dmat4(1.0), scale);
modelTransform = modelTransform * scaleMatrix;
_raycaster->setModelTransform(glm::mat4(modelTransform));
} else {
_raycaster->setModelTransform(
glm::scale(
glm::dmat4(1.0),
glm::dvec3(t->upperDomainBound[0])
)
);
}
_raycaster->setVolumeTexture(t->texture);
// Remap volume value to that TF value 0 is sampled for lowerValueBound, and 1 is sampled for upperLowerBound.
// This means that volume values = 0 need to be remapped to how localMin relates to the global range.
float zeroMap = (t->minValue - _lowerValueBound) / (_upperValueBound - _lowerValueBound);
// Volume values = 1 are mapped to how localMax relates to the global range.
float oneMap = (t->maxValue - _lowerValueBound) / (_upperValueBound - _lowerValueBound);
_raycaster->setValueRemapping(zeroMap, oneMap);
} else {
_raycaster->setVolumeTexture(nullptr);
}
_raycaster->setStepSize(_stepSize);
_raycaster->setOpacity(_opacity);
_raycaster->setRNormalization(_rNormalization);
_raycaster->setRUpperBound(_rUpperBound);
}
}
void RenderableTimeVaryingVolume::render(const RenderData& data, RendererTasks& tasks) {
if (_raycaster && _raycaster->volumeTexture()) {
tasks.raycasterTasks.push_back({ _raycaster.get(), data });
}
}
bool RenderableTimeVaryingVolume::isReady() const {
return true;
}
void RenderableTimeVaryingVolume::deinitialize() {
if (_raycaster) {
OsEng.renderEngine().raycasterManager().detachRaycaster(*_raycaster.get());
_raycaster = nullptr;
}
}
documentation::Documentation RenderableTimeVaryingVolume::Documentation() {
using namespace documentation;
return {
"RenderableTimevaryingVolume",
"volume_renderable_timevaryingvolume",
{
{
KeySourceDirectory,
new StringVerifier,
Optional::No,
"Specifies the path to load timesteps from"
},
{
KeyTransferFunction,
new StringVerifier,
Optional::No,
"Specifies the transfer function file path",
},
{
KeyLowerValueBound,
new DoubleVerifier,
Optional::No,
"Specifies the lower value bound."
"This number will be mapped to 0 before uploadin to the GPU.",
},
{
KeyUpperValueBound,
new DoubleVerifier,
Optional::No,
"Specifies the lower value bound."
"This number will be mapped to 0 before uploadin to the GPU."
},
{
KeyGridType,
new StringInListVerifier({"Cartesian", "Spherical"}),
Optional::Yes,
"Specifies the grid type"
},
{
KeySecondsBefore,
new DoubleVerifier,
Optional::Yes,
"Specifies the number of seconds to show the the first timestep before its actual time."
"The default value is 0.",
},
{
KeySecondsAfter,
new DoubleVerifier,
Optional::No,
"Specifies the number of seconds to show the the last timestep after its actual time",
},
}
};
}
documentation::Documentation RenderableTimeVaryingVolume::TimestepDocumentation() {
using namespace documentation;
return {
"TimevaryingVolumeTimestep",
"volume_timevaryingvolumetimestep",
{
{
KeyLowerDomainBound,
new Vector3Verifier<float>,
Optional::No,
"Specifies the lower domain bounds in the model coordinate system",
},
{
KeyUpperDomainBound,
new Vector3Verifier<float>,
Optional::No,
"Specifies the upper domain bounds in the model coordinate system",
},
{
KeyDimensions,
new Vector3Verifier<float>,
Optional::No,
"Specifies the number of grid cells in each dimension",
},
{
KeyTime,
new StringVerifier,
Optional::No,
"Specifies the time on the format YYYY-MM-DDTHH:MM:SS.000Z",
},
{
KeyMinValue,
new DoubleVerifier,
Optional::No,
"Specifies the minimum value stored in the volume"
},
{
KeyMaxValue,
new DoubleVerifier,
Optional::No,
"Specifies the maximum value stored in the volume"
}
}
};
}
} // namespace volume
} // namespace openspace

View File

@@ -0,0 +1,109 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_VOLUME___RENDERABLEKAMELEONVOLUME___H__
#define __OPENSPACE_MODULE_VOLUME___RENDERABLEKAMELEONVOLUME___H__
#include <openspace/rendering/renderable.h>
#include <modules/volume/rawvolume.h>
#include <modules/volume/rendering/basicvolumeraycaster.h>
#include <modules/volume/rendering/volumeclipplanes.h>
#include <openspace/properties/vectorproperty.h>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/rendering/transferfunction.h>
#include <openspace/util/boxgeometry.h>
namespace openspace {
struct RenderData;
namespace volume {
class RenderableTimeVaryingVolume : public Renderable {
public:
RenderableTimeVaryingVolume(const ghoul::Dictionary& dictionary);
~RenderableTimeVaryingVolume();
void initialize() override;
void deinitialize() override;
bool isReady() const override;
void render(const RenderData& data, RendererTasks& tasks) override;
void update(const UpdateData& data) override;
static documentation::Documentation Documentation();
static documentation::Documentation TimestepDocumentation();
private:
struct Timestep {
std::string baseName;
double time;
float minValue;
float maxValue;
glm::uvec3 dimensions;
glm::vec3 lowerDomainBound;
glm::vec3 upperDomainBound;
bool inRam;
bool onGpu;
std::unique_ptr<RawVolume<float>> rawVolume;
std::shared_ptr<ghoul::opengl::Texture> texture;
};
Timestep* currentTimestep();
int timestepIndex(const Timestep* t) const;
Timestep* timestepFromIndex(int index);
void jumpToTimestep(int i);
void loadTimestepMetadata(const std::string& path);
properties::OptionProperty _gridType;
std::shared_ptr<VolumeClipPlanes> _clipPlanes;
properties::FloatProperty _stepSize;
properties::FloatProperty _opacity;
properties::FloatProperty _rNormalization;
properties::FloatProperty _rUpperBound;
properties::FloatProperty _secondsBefore;
properties::FloatProperty _secondsAfter;
properties::StringProperty _sourceDirectory;
properties::StringProperty _transferFunctionPath;
properties::FloatProperty _lowerValueBound;
properties::FloatProperty _upperValueBound;
properties::TriggerProperty _triggerTimeJump;
properties::IntProperty _jumpToTimestep;
properties::IntProperty _currentTimestep;
std::map<double, Timestep> _volumeTimesteps;
std::unique_ptr<BasicVolumeRaycaster> _raycaster;
std::shared_ptr<TransferFunction> _transferFunction;
};
} // namespace volume
} // namespace openspace
#endif // __OPENSPACE_MODULE_KAMELEONVOLUME___RENDERABLEKAMELEONVOLUME___H__

View File

@@ -1,4 +1,3 @@
/*****************************************************************************************
* *
* OpenSpace *
@@ -28,6 +27,7 @@
namespace openspace {
namespace volume {
VolumeClipPlane::VolumeClipPlane(const ghoul::Dictionary& dictionary)
: properties::PropertyOwner({ "" }) // @TODO Missing name
@@ -66,4 +66,5 @@ glm::vec2 VolumeClipPlane::offsets() {
return _offsets;
}
} // namespace volume
} // namespace openspace

View File

@@ -31,6 +31,7 @@
namespace ghoul { class Dictionary; }
namespace openspace {
namespace volume {
class VolumeClipPlane : public properties::PropertyOwner {
public:
@@ -45,6 +46,7 @@ private:
};
} // namespace openspace
} // namespace volume
} // namespace openspace
#endif // __OPENSPACE_MODULE_VOLUME___VOLUMECLIPPLANE___H__

View File

@@ -28,6 +28,7 @@
namespace openspace {
namespace volume {
VolumeClipPlanes::VolumeClipPlanes(const ghoul::Dictionary& dictionary)
: properties::PropertyOwner({ "" }) // @TODO Missing name
@@ -70,4 +71,5 @@ std::vector<glm::vec2> VolumeClipPlanes::offsets() {
return offsets;
}
} // namespace volume
} // namespace openspace

View File

@@ -36,6 +36,7 @@
namespace ghoul { class Dictionary; }
namespace openspace {
namespace volume {
class VolumeClipPlanes : public properties::PropertyOwner {
public:
@@ -51,6 +52,7 @@ private:
std::vector<std::shared_ptr<VolumeClipPlane>> _clipPlanes;
};
} // namespace openspace
} // namepsace volume
} // namespace openspace
#endif // __OPENSPACE_MODULE_VOLUME___VOLUMECLIPPLANES___H__

View File

@@ -22,20 +22,21 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#define KAMELEON_PI 3.14159265358979323846 /* pi */
#define KAMELEON_SQRT1_3 0.57735026919 /* 1/sqrt(3) */
#define VOLUME_PI 3.14159265358979323846 /* pi */
#define VOLUME_SQRT1_3 0.57735026919 /* 1/sqrt(3) */
vec3 kameleon_cartesianToSpherical(vec3 zeroToOneCoords) {
vec3 volume_cartesianToSpherical(vec3 zeroToOneCoords) {
// Put cartesian in [-1..1] range first
vec3 cartesian = vec3(-1.0,-1.0,-1.0) + zeroToOneCoords * 2.0f;
float r = length(cartesian);
float theta = 0.0;
float phi = 0.0;
if (r != 0.0) {
theta = acos(cartesian.z / r) / KAMELEON_PI;
phi = (KAMELEON_PI + atan(cartesian.y, cartesian.x)) / (2.0 * KAMELEON_PI );
theta = acos(cartesian.z / r) / VOLUME_PI;
phi = (VOLUME_PI + atan(cartesian.y, cartesian.x)) / (2.0 * VOLUME_PI );
}
return vec3(r * KAMELEON_SQRT1_3, theta, phi);
return vec3(r * VOLUME_SQRT1_3, theta, phi);
}

View File

@@ -31,6 +31,20 @@ uniform int nClips_#{id};
uniform vec3 clipNormals_#{id}[8];
uniform vec2 clipOffsets_#{id}[8];
uniform float opacity_#{id} = 10.0;
// Value remapping:
// Linearly remap volume values of zero to x and one to y
// before using the values to sample the transfer function.
uniform vec2 valueRemapping_#{id} = vec2(0.0, 1.0);
// Normalization factor x for radius r [0, 1].
// value *= 1/(r^x)
// only working for volumes given in spherical coordianates.
// Applied after any linear value remapping.
uniform float rNormalization_#{id} = 0.0;
uniform float rUpperBound_#{id} = 1.0;
void sample#{id}(vec3 samplePos, vec3 dir, inout vec3 accumulatedColor,
inout vec3 accumulatedAlpha, inout float stepSize)
@@ -38,7 +52,7 @@ void sample#{id}(vec3 samplePos, vec3 dir, inout vec3 accumulatedColor,
vec3 transformedPos = samplePos;
if (gridType_#{id} == 1) {
transformedPos = kameleon_cartesianToSpherical(samplePos);
transformedPos = volume_cartesianToSpherical(samplePos);
}
float clipAlpha = 1.0;
@@ -52,14 +66,23 @@ void sample#{id}(vec3 samplePos, vec3 dir, inout vec3 accumulatedColor,
clipAlpha *= smoothstep(clipBegin, clipEnd, dot(centerToPos, clipNormal));
}
clipAlpha *= 1.0 - smoothstep(rUpperBound_#{id} - 0.01, rUpperBound_#{id} + 0.01, transformedPos.x);
if (clipAlpha > 0) {
float val = texture(volumeTexture_#{id}, transformedPos).r;
val = mix(valueRemapping_#{id}.x, valueRemapping_#{id}.y, val);
if (rNormalization_#{id} > 0 && gridType_#{id} == 1) {
val *= pow(transformedPos.x, rNormalization_#{id});
}
vec4 color = texture(transferFunction_#{id}, val);
vec3 backColor = color.rgb;
vec3 backAlpha = color.aaa;
backColor *= stepSize * clipAlpha;
backAlpha *= stepSize * clipAlpha;
backColor *= stepSize*opacity_#{id} * clipAlpha;
backAlpha *= stepSize*opacity_#{id} * clipAlpha;
backColor = clamp(backColor, 0.0, 1.0);
backAlpha = clamp(backAlpha, 0.0, 1.0);

View File

@@ -34,6 +34,7 @@
#include <unordered_map>
namespace openspace {
namespace volume {
template <typename Type>
class TextureSliceVolumeReader {
@@ -53,6 +54,7 @@ private:
bool _initialized;
};
} // namespace volume
} // namespace openspace
#include "textureslicevolumereader.inl"

View File

@@ -25,6 +25,7 @@
#include <ghoul/io/texture/texturereader.h>
namespace openspace {
namespace volume {
template <typename VoxelType>
VoxelType TextureSliceVolumeReader<VoxelType>::get(const glm::ivec3& coordinates) const {
@@ -81,4 +82,5 @@ ghoul::opengl::Texture& TextureSliceVolumeReader<VoxelType>::getSlice(int sliceI
return *_cache.get(sliceIndex).get();
}
} // namespace volume
} // namespace openspace

View File

@@ -0,0 +1,48 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/volume/volumegridtype.h>
#include <string>
namespace openspace {
namespace volume {
VolumeGridType parseGridType(const std::string& gridType) {
if (gridType == "Cartesian") {
return VolumeGridType::Cartesian;
}
if (gridType == "Spherical") {
return VolumeGridType::Spherical;
}
throw InvalidGridTypeError(gridType);
}
InvalidGridTypeError::InvalidGridTypeError(std::string gt)
: RuntimeError("Invalid grid type: '" + gt + "'")
, gridType(std::move(gt))
{}
} // namespace volume
} // namespace openspace

View File

@@ -25,13 +25,24 @@
#ifndef __OPENSPACE_MODULE_VOLUME___VOLUMEGRIDTYPE_H__
#define __OPENSPACE_MODULE_VOLUME___VOLUMEGRIDTYPE_H__
#include <ghoul/misc/exception.h>
namespace openspace {
namespace volume {
enum class VolumeGridType : int {
Cartesian = 0,
Spherical = 1
};
struct InvalidGridTypeError : public ghoul::RuntimeError {
explicit InvalidGridTypeError(std::string gridType);
std::string gridType;
};
VolumeGridType parseGridType(const std::string& gridType);
} // namespace volume
} // namespace openspace
#endif // __OPENSPACE_MODULE_VOLUME___VOLUMEGRIDTYPE_H__

View File

@@ -23,6 +23,7 @@
****************************************************************************************/
#include <modules/volume/volumemodule.h>
#include <modules/volume/rendering/renderabletimevaryingvolume.h>
#include <openspace/rendering/renderable.h>
#include <openspace/util/factorymanager.h>
@@ -31,6 +32,14 @@
namespace openspace {
VolumeModule::VolumeModule() : OpenSpaceModule(Name) {}
using namespace volume;
VolumeModule::VolumeModule() : OpenSpaceModule(Name) {}
void VolumeModule::internalInitialize() {
auto fRenderable = FactoryManager::ref().factory<Renderable>();
ghoul_assert(fRenderable, "No renderable factory existed");
fRenderable->registerClass<RenderableTimeVaryingVolume>("RenderableTimeVaryingVolume");
}
} // namespace openspace

View File

@@ -33,6 +33,7 @@ class VolumeModule : public OpenSpaceModule {
public:
constexpr static const char* Name = "Volume";
void internalInitialize() override;
VolumeModule();
};

View File

@@ -26,6 +26,7 @@
#define __OPENSPACE_MODULE_VOLUME___VOLUMESAMPLER___H__
namespace openspace {
namespace volume {
template <typename VolumeType>
class VolumeSampler {
@@ -40,6 +41,7 @@ private:
const VolumeType* _volume;
};
} // namespace volume
} // namespace openspace
#include "volumesampler.inl"

View File

@@ -23,6 +23,7 @@
****************************************************************************************/
namespace openspace {
namespace volume {
template <typename VolumeType>
VolumeSampler<VolumeType>::VolumeSampler(const VolumeType& volume, const glm::vec3& filterSize) {
@@ -78,4 +79,5 @@ typename VolumeType::VoxelType VolumeSampler<VolumeType>::sample(const glm::vec3
return value;
}
} // namespace volume
} // namespace openspace

View File

@@ -24,8 +24,9 @@
#include "volumeutils.h"
namespace openspace::volumeutils {
namespace openspace {
namespace volume {
size_t coordsToIndex(const glm::uvec3& coords, const glm::uvec3& dims) {
size_t w = dims.x;
size_t h = dims.y;
@@ -48,5 +49,6 @@ glm::uvec3 indexToCoords(size_t index, const glm::uvec3& dims) {
return glm::uvec3(x, y, z);
}
} // namespace openspace::volumeutils
} // namespace volume
} // namespace openspace

View File

@@ -27,11 +27,13 @@
#include <ghoul/glm.h>
namespace openspace::volumeutils {
namespace openspace {
namespace volume {
size_t coordsToIndex(const glm::uvec3& coords, const glm::uvec3& dimensions);
glm::uvec3 indexToCoords(size_t index, const glm::uvec3& dimensions);
} // namespace openspace::volumeutils
} // namespace volume
} // namespace openspace
#endif // __OPENSPACE_MODULE_VOLUME___VOLUMEUTILS___H__

View File

@@ -35,14 +35,13 @@ return {
-- Scene = "${SCENE}/rosetta.scene",
-- Scene = "${SCENE}/osirisrex.scene",
Task = "${TASKS}/default.task",
TasksRoot = "${OPENSPACE_DATA}/tasks",
Paths = {
SCRIPTS = "${BASE_PATH}/scripts",
SHADERS = "${BASE_PATH}/shaders",
OPENSPACE_DATA = "${BASE_PATH}/data",
SCENE = "${OPENSPACE_DATA}/scene",
TASKS = "${OPENSPACE_DATA}/tasks",
SPICE = "${OPENSPACE_DATA}/spice",
MODULES = "${BASE_PATH}/modules",
TESTDIR = "${BASE_PATH}/tests",

View File

@@ -159,6 +159,7 @@ set(OPENSPACE_SOURCE
${OPENSPACE_BASE_DIR}/src/util/histogram.cpp
${OPENSPACE_BASE_DIR}/src/util/task.cpp
${OPENSPACE_BASE_DIR}/src/util/taskloader.cpp
${OPENSPACE_BASE_DIR}/src/util/threadpool.cpp
${OPENSPACE_BASE_DIR}/src/util/time.cpp
${OPENSPACE_BASE_DIR}/src/util/timeline.cpp
${OPENSPACE_BASE_DIR}/src/util/timemanager.cpp
@@ -296,6 +297,10 @@ set(OPENSPACE_HEADER
${OPENSPACE_BASE_DIR}/include/openspace/util/blockplaneintersectiongeometry.h
${OPENSPACE_BASE_DIR}/include/openspace/util/boxgeometry.h
${OPENSPACE_BASE_DIR}/include/openspace/util/camera.h
${OPENSPACE_BASE_DIR}/include/openspace/util/concurrentjobmanager.h
${OPENSPACE_BASE_DIR}/include/openspace/util/concurrentjobmanager.inl
${OPENSPACE_BASE_DIR}/include/openspace/util/concurrentqueue.h
${OPENSPACE_BASE_DIR}/include/openspace/util/concurrentqueue.inl
${OPENSPACE_BASE_DIR}/include/openspace/util/factorymanager.h
${OPENSPACE_BASE_DIR}/include/openspace/util/factorymanager.inl
${OPENSPACE_BASE_DIR}/include/openspace/util/keys.h
@@ -318,6 +323,7 @@ set(OPENSPACE_HEADER
${OPENSPACE_BASE_DIR}/include/openspace/util/timerange.h
${OPENSPACE_BASE_DIR}/include/openspace/util/updatestructures.h
${OPENSPACE_BASE_DIR}/include/openspace/util/transformationmanager.h
${OPENSPACE_BASE_DIR}/include/openspace/util/threadpool.h
${OPENSPACE_BASE_DIR}/include/openspace/util/histogram.h
${OPENSPACE_BASE_DIR}/include/openspace/util/gpudata.h
)

View File

@@ -59,7 +59,7 @@ const string ConfigurationManager::KeyKeyboardShortcuts = "KeyboardShortcuts";
const string ConfigurationManager::KeyDocumentation = "Documentation";
const string ConfigurationManager::KeyFactoryDocumentation = "FactoryDocumentation";
const string ConfigurationManager::KeyConfigScene = "Scene";
const string ConfigurationManager::KeyConfigTask = "Task";
const string ConfigurationManager::KeyConfigTasksRoot = "TasksRoot";
const string ConfigurationManager::KeyLogging = "Logging";
const string ConfigurationManager::PartLogDir = "LogDir";

View File

@@ -1,4 +1,4 @@
/*****************************************************************************************
/*****************************************************************************************
* *
* OpenSpace *
* *
@@ -53,7 +53,7 @@ documentation::Documentation ConfigurationManager::Documentation() {
"the Scene documentation."
},
{
ConfigurationManager::KeyConfigTask,
ConfigurationManager::KeyConfigTasksRoot,
new StringAnnotationVerifier(
"A valid task file as described in the Task documentation"
),

View File

@@ -216,8 +216,8 @@ bool Renderable::isEnabled() const {
}
void Renderable::onEnabledChange(std::function<void(bool)> callback) {
_enabled.onChange([&] () {
callback(isEnabled());
_enabled.onChange([this, c{ std::move(callback) }]() {
c(isEnabled());
});
}

View File

@@ -109,8 +109,7 @@ void TransferFunction::setTextureFromTxt() {
in.open(_filepath.c_str());
if (!in.is_open()) {
LERROR("Could not open file " << _filepath);
return;
throw ghoul::FileNotFoundError(_filepath);
}
int width = 512;

View File

@@ -46,7 +46,7 @@ std::vector<std::unique_ptr<Task>> TaskLoader::tasksFromDictionary(const ghoul::
std::string taskName;
ghoul::Dictionary subTask;
if (tasksDictionary.getValue(key, taskName)) {
std::string path = "${TASKS}/" + taskName + ".task";
std::string path = taskName + ".task";
std::vector<std::unique_ptr<Task>> subTasks = tasksFromFile(path);
std::move(subTasks.begin(), subTasks.end(), std::back_inserter(tasks));
} else if (tasksDictionary.getValue(key, subTask)) {
@@ -75,10 +75,10 @@ std::vector<std::unique_ptr<Task>> TaskLoader::tasksFromFile(const std::string&
ghoul::lua::loadDictionaryFromFile(
absTasksFile,
tasksDictionary
);
} catch (...) {
);
} catch (const ghoul::RuntimeError& e) {
LERROR("Could not load tasks file '" << absTasksFile << "'. " <<
"Lua parse error");
"Lua error: " << e.message << ": " << e.component);
return std::vector<std::unique_ptr<Task>>();
}
return tasksFromDictionary(tasksDictionary);

View File

@@ -22,9 +22,9 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/globebrowsing/other/threadpool.h>
#include <openspace/util/threadpool.h>
namespace openspace::globebrowsing {
namespace openspace {
Worker::Worker(ThreadPool& pool) : pool(pool) {}
@@ -103,4 +103,4 @@ void ThreadPool::clearTasks() {
} // release lock
}
} // namespace openspace::globebrowsing
} // namespace openspace

View File

@@ -34,7 +34,10 @@ using datamessagestructures::TimeKeyframe;
void TimeManager::preSynchronization(double dt) {
// double now = OsEng.runTime();
removeKeyframesBefore(_latestConsumedTimestamp);
if (_timeline.nKeyframes() == 0) {
if (_shouldSetTime) {
time().setTime(_timeNextFrame.j2000Seconds());
_shouldSetTime = false;
} else if (_timeline.nKeyframes() == 0) {
time().advanceTime(dt);
} else {
consumeKeyframes(dt);
@@ -141,6 +144,11 @@ void TimeManager::clearKeyframes() {
_timeline.clearKeyframes();
}
void TimeManager::setTimeNextFrame(Time t) {
_shouldSetTime = true;
_timeNextFrame = t;
}
size_t TimeManager::nKeyframes() const {
return _timeline.nKeyframes();
}

View File

@@ -38,7 +38,7 @@ function (handle_applications)
get_application_attribute_default(${app_dir} is_default_application)
if (${is_default_application})
set(OPENSPACE_APPLICATION_${upper_app} ON CACHE BOOL "Build ${app} application" FORCE)
option(OPENSPACE_APPLICATION_${upper_app} "Build ${app} application" ${is_default_application})
endif ()
if (OPENSPACE_APPLICATION_${upper_app})

View File

@@ -139,7 +139,7 @@ function (set_openspace_compile_settings project)
"-Wredundant-move"
"-Wreorder"
"-Wsemicolon-before-method-body"
"-Wshadow-field"
# "-Wshadow-field"
"-Wshadow-field-in-constructor"
# "-Wshadow-all" Add this again once the Properties don't throw warnings --abock
"-Wshift-sign-overflow"

View File

@@ -81,6 +81,10 @@
//#include <test_iswamanager.inl>
#endif
#ifdef OPENSPACE_MODULE_VOLUME_ENABLED
#include <test_rawvolumeio.inl>
#endif
#include <test_scriptscheduler.inl>
#include <test_documentation.inl>

View File

@@ -22,7 +22,11 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/globebrowsing/other/concurrentjobmanager.h>
#include "gtest/gtest.h"
#include <openspace/util/concurrentjobmanager.h>
#include <ghoul/misc/threadpool.h>
#define _USE_MATH_DEFINES
@@ -31,7 +35,7 @@
class ConcurrentJobManagerTest : public testing::Test {};
struct TestJob : public openspace::globebrowsing::Job<int> {
struct TestJob : public openspace::Job<int> {
TestJob(int jobExecutingTime)
: _jobExecutingTime(jobExecutingTime)
{}
@@ -56,8 +60,8 @@ private:
TEST_F(ConcurrentJobManagerTest, Basic) {
using namespace openspace::globebrowsing;
using namespace openspace;
ConcurrentJobManager<int> jobManager(ThreadPool(1));
auto testJob1 = std::shared_ptr<TestJob>(new TestJob(20));
@@ -97,7 +101,7 @@ struct VerboseProduct {
};
struct VerboseJob : public openspace::globebrowsing::Job<VerboseProduct>{
struct VerboseJob : public openspace::Job<VerboseProduct>{
VerboseJob(int jobExecutingTime)
: _jobExecutingTime(jobExecutingTime) {
std::cout << "VerboseTestJob constructor" << std::endl;
@@ -124,7 +128,7 @@ struct VerboseJob : public openspace::globebrowsing::Job<VerboseProduct>{
};
TEST_F(ConcurrentJobManagerTest, JobCreation) {
using namespace openspace::globebrowsing;
using namespace openspace;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));

View File

@@ -22,7 +22,9 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/globebrowsing/other/concurrentqueue.h>
#include "gtest/gtest.h"
#include <openspace/util/concurrentqueue.h>
#define _USE_MATH_DEFINES
#include <math.h>
@@ -31,7 +33,7 @@
class ConcurrentQueueTest : public testing::Test {};
TEST_F(ConcurrentQueueTest, Basic) {
using namespace openspace::globebrowsing;
using namespace openspace;
ConcurrentQueue<int> q1;
q1.push(4);

View File

@@ -0,0 +1,93 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include "gtest/gtest.h"
#include <openspace/util/timeline.h>
#include <openspace/util/time.h>
#include <modules/volume/rawvolume.h>
#include <modules/volume/rawvolumereader.h>
#include <modules/volume/rawvolumewriter.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/glm.h>
using namespace openspace;
class RawVolumeIoTest : public testing::Test {};
TEST_F(RawVolumeIoTest, TinyInputOutput) {
using namespace volume;
glm::uvec3 dims{ 1, 1, 1 };
float value = 0.5;
RawVolume<float> vol(dims);
vol.set({ 0, 0, 0 }, value);
ASSERT_EQ(vol.get({ 0, 0, 0 }), value);
std::string volumePath = absPath("${TESTDIR}/tinyvolume.rawvolume");
// Write the 1x1x1 volume to disk
RawVolumeWriter<float> writer(volumePath);
writer.write(vol);
// Read the 1x1x1 volume and make sure the value is the same.
RawVolumeReader<float> reader(volumePath, dims);
std::unique_ptr<RawVolume<float>> storedVolume = reader.read();
ASSERT_EQ(storedVolume->get({ 0, 0, 0 }), value);
}
TEST_F(RawVolumeIoTest, BasicInputOutput) {
using namespace volume;
glm::uvec3 dims{ 2, 4, 8 };
auto value = [dims](glm::uvec3 v) {
return v.z * 8 * 4 + v.y * 4 + v.x;
};
RawVolume<float> vol(dims);
vol.forEachVoxel([&vol, &value](glm::uvec3 x, float v) {
vol.set(x, value(x));
});
vol.forEachVoxel([&value](glm::uvec3 x, float v) {
ASSERT_EQ(v, value(x));
});
std::string volumePath = absPath("${TESTDIR}/basicvolume.rawvolume");
// Write the 2x4x8 volume to disk
RawVolumeWriter<float> writer(volumePath);
writer.write(vol);
// Read the 2x4x8 volume and make sure the value is the same.
RawVolumeReader<float> reader(volumePath, dims);
std::unique_ptr<RawVolume<float>> storedVolume = reader.read();
vol.forEachVoxel([&value](glm::uvec3 x, float v) {
ASSERT_EQ(v, value(x));
});
}