Added working CDF data loading

- RenderableVolume can now load .raw and .cdf data to ghoul Texture
- KameleonWrapper included for easy interaction with Kameleon
- openspace-data updated with support for BATSRUS model
- CMakeLists.txt updated with settings to Kamelon library

- ext/kameleon not included due to Kameleon is currently being ported to
git. Waiting to add it as submodule to avoid duplication of files.
This commit is contained in:
Jonas Strandstedt
2014-04-24 10:32:01 -04:00
parent 199bb52d5d
commit d84d48d15b
8 changed files with 261 additions and 17 deletions

View File

@@ -92,6 +92,15 @@ if(OPENCL_FOUND)
set(GHOUL_DEPENDENCIES ${GHOUL_DEPENDENCIES} ${OPENCL_LIBRARIES})
endif(OPENCL_FOUND)
# Kameleon
option(KAMELEON_LIBRARY_ONLY "Build with Kameleon as library only" ON)
option(BUILD_SHARED_LIBS "Build Shared Libraries" ON)
set(KAMELEON_ROOT_DIR ${OPENSPACE_EXT_DIR}/kameleon)
set(KAMELEON_INCLUDES ${KAMELEON_ROOT_DIR}/src)
add_subdirectory(${KAMELEON_ROOT_DIR})
include_directories(${KAMELEON_INCLUDES})
set(DEPENDENT_LIBS ${DEPENDENT_LIBS} ccmc)
if (APPLE)
include_directories(/Developer/Headers/FlatCarbon)
find_library(CARBON_LIBRARY Carbon)

View File

@@ -44,6 +44,7 @@ public:
protected:
std::string findPath(const std::string& path);
ghoul::opengl::Texture* loadVolume(const std::string& filepath, const ghoul::Dictionary& hintsDictionary);
ghoul::RawVolumeReader::ReadHints readHints(const ghoul::Dictionary& dictionary);
ghoul::opengl::Texture* loadTransferFunction(const std::string& filepath);

View File

@@ -37,7 +37,6 @@
#include <ghoul/opencl/clcommandqueue.h>
#include <ghoul/opencl/clprogram.h>
#include <ghoul/opencl/clkernel.h>
#include <ghoul/io/rawvolumereader.h>
#include <ghoul/filesystem/file.h>
#ifdef __APPLE__
@@ -75,7 +74,7 @@ private:
// Volumes
std::vector<std::string> _volumePaths;
std::vector<ghoul::RawVolumeReader::ReadHints> _volumeHints;
std::vector<ghoul::Dictionary> _volumeHints;
// Textures
ghoul::opengl::Texture* _output;
@@ -105,7 +104,6 @@ private:
std::mutex* _textureLock;
ghoul::opengl::ProgramObject *_quadProgram;
sgct_utils::SGCTBox* _boundingBox;
GLuint _screenQuad;
VolumeRaycasterBox* _colorBoxRenderer;

View File

@@ -0,0 +1,57 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 *
* *
* 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 KAMELEONWRAPPER_H_
#define KAMELEONWRAPPER_H_
#include <glm/glm.hpp>
#include <glm/gtx/std_based_type.hpp>
namespace ccmc {
class Model;
class Interpolator;
}
namespace openspace {
class KameleonWrapper {
public:
enum class Model {
ENLIL, // Heliosphere
BATSRUS // Magnetosphere
};
KameleonWrapper(const std::string& filename, Model model);
~KameleonWrapper();
float* getUniformSampledValues(const std::string& var, glm::size3_t outDimensions);
private:
ccmc::Model* _model;
ccmc::Interpolator* _interpolator;
};
} // namespace openspace
#endif // KAMELEONWRAPPER_H_

View File

@@ -29,6 +29,8 @@
#include <ghoul/filesystem/filesystem.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/util/kameleonwrapper.h>
#include <sgct.h>
#include <iostream>
@@ -41,10 +43,11 @@
namespace {
std::string _loggerCat = "RenderableVolume";
bool hasEnding (std::string const &fullString, std::string const &ending)
bool hasExtension (std::string const &filepath, std::string const &extension)
{
if (fullString.length() >= ending.length()) {
return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
std::string ending = "." + extension;
if (filepath.length() > ending.length()) {
return (0 == filepath.compare (filepath.length() - ending.length(), ending.length(), ending));
} else {
return false;
}
@@ -96,6 +99,66 @@ std::string RenderableVolume::findPath(const std::string& path) {
return "";
}
ghoul::opengl::Texture* RenderableVolume::loadVolume(const std::string& filepath, const ghoul::Dictionary& hintsDictionary) {
if( ! FileSys.fileExists(filepath)) {
LWARNING("Could not load volume, could not find '" << filepath << "'");
return nullptr;
}
if(hasExtension(filepath, "raw")) {
ghoul::RawVolumeReader::ReadHints hints = readHints(hintsDictionary);
ghoul::RawVolumeReader rawReader(hints);
return rawReader.read(filepath);
} else if(hasExtension(filepath, "cdf")) {
std::string modelString;
if (hintsDictionary.hasKey("Model") && hintsDictionary.getValue("Model", modelString)) {
KameleonWrapper::Model model;
if (modelString == "BATSRUS") {
model = KameleonWrapper::Model::BATSRUS;
} else if (modelString == "ENLIL") {
model = KameleonWrapper::Model::ENLIL;
} else {
LWARNING("Hints does not specify a valid 'Model'");
return nullptr;
}
std::string variableString;
if (hintsDictionary.hasKey("Variable") && hintsDictionary.getValue("Variable", variableString)) {
glm::size3_t dimensions(1,1,1);
double tempValue;
if (hintsDictionary.hasKey("Dimensions.1") && hintsDictionary.getValue("Dimensions.1", tempValue)) {
int intVal = static_cast<int>(tempValue);
if(intVal > 0)
dimensions[0] = intVal;
}
if (hintsDictionary.hasKey("Dimensions.2") && hintsDictionary.getValue("Dimensions.2", tempValue)) {
int intVal = static_cast<int>(tempValue);
if(intVal > 0)
dimensions[1] = intVal;
}
if (hintsDictionary.hasKey("Dimensions.3") && hintsDictionary.getValue("Dimensions.3", tempValue)) {
int intVal = static_cast<int>(tempValue);
if(intVal > 0)
dimensions[2] = intVal;
}
KameleonWrapper kw(filepath, model);
float* data = kw.getUniformSampledValues(variableString, dimensions);
return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT);
} else {
LWARNING("Hints does not specify a 'Variable'");
}
}
LWARNING("Hints does not specify a 'Model'");
} else {
LWARNING("No valid file extension.");
}
return nullptr;
}
ghoul::RawVolumeReader::ReadHints RenderableVolume::readHints(const ghoul::Dictionary& dictionary) {
ghoul::RawVolumeReader::ReadHints hints;
hints._dimensions = glm::ivec3(1, 1, 1);
@@ -165,7 +228,7 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string
}
// check if not a txt based texture
if ( ! hasEnding(filepath, ".txt")) {
if ( ! hasExtension(filepath, "txt")) {
return ghoul::opengl::loadTexture(f);
}

View File

@@ -30,6 +30,7 @@
#include <ghoul/opengl/texturereader.h>
#include <ghoul/opencl/clworksize.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/io/rawvolumereader.h>
#include <algorithm>
@@ -85,10 +86,9 @@ RenderableVolumeExpert::RenderableVolumeExpert(const ghoul::Dictionary& dictiona
ghoul::Dictionary hintsDictionary;
if(volume.hasKey("Hints"))
volume.getValue("Hints", hintsDictionary);
ghoul::RawVolumeReader::ReadHints hints = readHints(hintsDictionary);
_volumePaths.push_back(file);
_volumeHints.push_back(hints);
_volumeHints.push_back(hintsDictionary);
}
}
}
@@ -204,13 +204,15 @@ bool RenderableVolumeExpert::initialize() {
}
for (int i = 0; i < _volumePaths.size(); ++i) {
ghoul::RawVolumeReader rawReader(_volumeHints.at(i));
ghoul::opengl::Texture* volume = rawReader.read(_volumePaths.at(i));
volume->uploadTexture();
cl_mem volumeTexture = _context.createTextureFromGLTexture(CL_MEM_READ_ONLY, *volume);
_volumes.push_back(volume);
_clVolumes.push_back(volumeTexture);
ghoul::opengl::Texture* volume = loadVolume(_volumePaths.at(i), _volumeHints.at(i));
if(volume) {
volume->uploadTexture();
cl_mem volumeTexture = _context.createTextureFromGLTexture(CL_MEM_READ_ONLY, *volume);
_volumes.push_back(volume);
_clVolumes.push_back(volumeTexture);
}
}
// ------ SETUP GEOMETRY ----------------

View File

@@ -0,0 +1,114 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 *
* *
* 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 <ghoul/logging/logmanager.h>
#include <openspace/util/kameleonwrapper.h>
#include <ccmc/Model.h>
#include <ccmc/Interpolator.h>
#include <ccmc/BATSRUS.h>
#include <ccmc/ENLIL.h>
namespace openspace {
std::string _loggerCat = "KameleonWrapper";
KameleonWrapper::KameleonWrapper(const std::string& filename, Model model) {
switch (model) {
case Model::BATSRUS:
_model = new ccmc::BATSRUS();
if(!_model) LERROR("BATSRUS:Failed to create model instance");
if (_model->open(filename) != ccmc::FileReader::OK)
LERROR("BATSRUS:Failed to open "+filename);
_interpolator = _model->createNewInterpolator();
if (!_interpolator) LERROR("BATSRUS:Failed to create interpolator");
break;
case Model::ENLIL:
_model = new ccmc::ENLIL();
if(!_model) LERROR("Failed to create model instance");
if (_model->open(filename) != ccmc::FileReader::OK)
LERROR("Failed to open "+filename);
_interpolator = _model->createNewInterpolator();
if (!_interpolator) LERROR("Failed to create interpolator");
break;
default:
LERROR("Only the BATSRUS model is supported for now. Sorry.");
}
}
KameleonWrapper::~KameleonWrapper() {
delete _model;
delete _interpolator;
}
float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::size3_t outDimensions) {
assert(_model && _interpolator);
assert(outDimensions.x > 0 && outDimensions.y > 0 && outDimensions.z > 0);
LDEBUG("getUniformSampledValues");
int size = outDimensions.x*outDimensions.y*outDimensions.z;
float* data = new float[size];
// TODO Check which coordinate system the model use. Currently assumes {x,y,z}
float xMin = _model->getVariableAttribute("x", "actual_min").getAttributeFloat();
float xMax = _model->getVariableAttribute("x", "actual_max").getAttributeFloat();
float yMin = _model->getVariableAttribute("y", "actual_min").getAttributeFloat();
float yMax = _model->getVariableAttribute("y", "actual_max").getAttributeFloat();
float zMin = _model->getVariableAttribute("z", "actual_min").getAttributeFloat();
float zMax = _model->getVariableAttribute("z", "actual_max").getAttributeFloat();
float varMin = _model->getVariableAttribute(var, "actual_min").getAttributeFloat();
float varMax = _model->getVariableAttribute(var, "actual_max").getAttributeFloat();
float stepX = (xMax-xMin)/((float)outDimensions.x-1.0);
float stepY = (yMax-yMin)/((float)outDimensions.y-1.0);
float stepZ = (zMax-zMin)/((float)outDimensions.z-1.0);
// Temporary hack to keep data proportions correct, will give a lot of empty
// voxels in y and z. TODO Add spacing/voxel dimensions
float step = std::max(stepX, stepY);
step = std::max(step, stepZ);
for (int x = 0; x < outDimensions.x; ++x) {
unsigned int progress = (unsigned int)(((float)x/(float)outDimensions.x)*100.f);
if (progress % 10 == 0) {
std::cout << "Getting data from kameleon: "<< progress << "% \r" << std::flush;
}
for (int y = 0; y < outDimensions.y; ++y) {
for (int z = 0; z < outDimensions.z; ++z) {
float xPos = xMin + step*x;
float yPos = yMin + step*y;
float zPos = zMin + step*z;
int index = x + y*outDimensions.x + z*outDimensions.x*outDimensions.y;
// get interpolated data value for (xPos, yPos, zPos) and scale to [0,1]
data[index] = (_interpolator->interpolate(var, xPos, yPos, zPos)-varMin)/(varMax-varMin);
}
}
}
return data;
}
} // namespace openspace