Merge remote-tracking branch 'origin/kameleon' into properties

This commit is contained in:
Alexander Bock
2014-05-02 16:59:50 +02:00
28 changed files with 806 additions and 105 deletions

View File

@@ -95,6 +95,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

@@ -1,7 +1,7 @@
<?xml version="1.0" ?>
<Cluster masterAddress="localhost">
<Settings>
<Display swapInterval="0" />
<Display swapInterval="1" />
</Settings>
<Node address="localhost" port="20401">
<Window fullScreen="false">

View File

@@ -71,7 +71,7 @@ public:
bool CalculateTemporalError();
int * Data() { return &data_[0]; }
unsigned int Size() { return data_.size(); }
size_t Size() { return data_.size(); }
// TODO support dimensions of differens sizes
unsigned int BrickDim() const { return xBrickDim_; }

View File

@@ -58,13 +58,19 @@ public:
void mouseScrollWheelCallback(int pos);
private:
glm::vec3 mapToTrackball(glm::vec2 mousePos);
void trackballRotate(int x, int y);
Camera *camera_;
Camera* camera_;
bool enabled_;
SceneGraphNode *node_;
double dt_;
glm::vec3 _lastTrackballPos;
bool _leftMouseButtonDown, _isMouseBeingPressedAndHeld;
// used for calling when updating and deallocation
std::vector<ExternalControl*> controllers_;
@@ -75,4 +81,4 @@ private:
} // namespace openspace
#endif
#endif

View File

@@ -24,6 +24,7 @@
#ifndef INTERFACE_H_
#define INTERFACE_H_
#include <openspace/engine/openspaceengine.h>
#include <boost/property_tree/ptree.hpp>
#include <openspace/engine/openspaceengine.h>
@@ -31,7 +32,6 @@
namespace openspace {
class Interface {
struct Node {
std::string _key;
std::string _value;
@@ -62,6 +62,7 @@ public:
void callback(const char * receivedChars);
private:
void handleNodes();
void loadIntoNodes(const boost::property_tree::ptree& tree, std::string parent = "", const int depth = 0);

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

@@ -43,6 +43,10 @@
#define SGCT_WINDOWS_INCLUDE
#include <sgct.h>
namespace sgct_utils {
class SGCTBox;
}
//#include <vector>
//#include <string>
#ifdef __APPLE__

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;
@@ -98,6 +97,8 @@ private:
ghoul::opencl::CLWorkSize* _ws;
ghoul::filesystem::File* _kernelSourceFile;
std::vector<std::pair<ghoul::opencl::CLProgram::Option, bool> > _kernelOptions;
std::vector<std::string> _kernelIncludes;
std::vector<std::pair<std::string,std::string> > _kernelDefinitions;
bool _programUpdateOnSave;
// mutexes to prevent inconsistencies
@@ -105,10 +106,10 @@ private:
std::mutex* _textureLock;
ghoul::opengl::ProgramObject *_quadProgram;
sgct_utils::SGCTBox* _boundingBox;
GLuint _screenQuad;
VolumeRaycasterBox* _colorBoxRenderer;
glm::vec3 _boxScaling;
};

View File

@@ -44,6 +44,10 @@
#include <mutex>
#endif
namespace sgct_utils {
class SGCTBox;
}
namespace openspace {
class RenderableVolumeGL: public RenderableVolume {

View File

@@ -25,13 +25,18 @@
#ifndef VOLUMERAYCASTERBOX_H_
#define VOLUMERAYCASTERBOX_H_
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/framebufferobject.h>
#include <ghoul/opengl/texture.h>
// forward declare private objects
namespace sgct_utils {
class SGCTBox;
}
namespace ghoul {
namespace opengl {
class FramebufferObject;
class ProgramObject;
}
}
namespace openspace {
@@ -40,7 +45,7 @@ public:
VolumeRaycasterBox();
~VolumeRaycasterBox();
bool initialize();
void render(glm::mat4 MVP);
void render(const glm::mat4& MVP);
ghoul::opengl::Texture* backFace();
ghoul::opengl::Texture* frontFace();
@@ -56,5 +61,5 @@ private:
glm::size2_t _dimensions;
};
} /* namespace openspace */
#endif /* VOLUMERAYCASTERBOX_H_ */
} // namespace openspace
#endif // VOLUMERAYCASTERBOX_H_

View File

@@ -0,0 +1,58 @@
/*****************************************************************************************
* *
* 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;
Model _type;
ccmc::Interpolator* _interpolator;
};
} // namespace openspace
#endif // KAMELEONWRAPPER_H_

View File

@@ -0,0 +1,28 @@
float3 CartesianToSpherical(float3 _cartesian);
float intensityNormalizer(float intensity, float iMin, float iMax);
float3 CartesianToSpherical(float3 _cartesian) {
// Put cartesian in [-1..1] range first
_cartesian = (float3)(-1.0) + 2.0f* _cartesian;
float r = length(_cartesian);
float theta, phi;
if (r == 0.0) {
theta = phi = 0.0;
} else {
theta = acospi(_cartesian.z/r);
phi = (M_PI + atan2(_cartesian.y, _cartesian.x)) / (2.0*M_PI);
}
r = r / native_sqrt(3.0f);
// Sampler ignores w component
return (float3)(r, theta, phi);
}
float intensityNormalizer(float intensity, float iMin, float iMax) {
float i = clamp(intensity, iMin, iMax);
i = (i - iMin) / (iMax - iMin);
return clamp(i, 0.0f, 1.0f);
}

View File

@@ -0,0 +1,104 @@
#define EARLY_RAY_TERMINATION_OPACITY 0.95
void raySetup(float3 first, float3 last, float3 dimension, float3* rayDirection, float* tIncr, float* tEnd);
bool earlyRayTermination(float4* color, float maxOpacity);
#define RC_DEFINE_TEXTUE_COORDINATES(coords) \
int2 coords = (int2)(get_global_id(0), get_global_id(1))
#define RC_DEFINE_VOLUME3D_DIMENSIONS(dimension, volume) \
float3 dimension; \
{ \
int4 idim = get_image_dim(volume); \
dimension = (float3)(idim.x,idim.y,idim.z); \
}
//#define RC_DEFINE_VARIABLES(dimension, intCoords)
/***
* Calculates the direction of the ray and returns the number
* of steps and the direction.
***/
void raySetup(float3 first, float3 last, float3 dimension, float3* rayDirection, float* tIncr, float* tEnd) {
float samplingRate_ = 1.0f;
*rayDirection = last - first;
*tEnd = length(*rayDirection);
*rayDirection = normalize(*rayDirection);
*tIncr = 1.0/(samplingRate_*length((*rayDirection)*dimension));
}
/***
* Applies early ray termination. The current opacity is compared to
* the maximum opacity. In case it is greater, the opacity is set to
* 1.0 and true is returned, otherwise false is returned.
***/
bool earlyRayTermination(float4* color, float maxOpacity) {
if ((*color).a >= maxOpacity) {
(*color).a = 1.0f;
return true;
} else {
return false;
}
}
#define RC_EARLY_RAY_TERMINATION(opacity, maxOpacity, finished) \
finished = earlyRayTermination(&opacity, maxOpacity)
#define RC_BEGIN_LOOP_FOR \
for (int loop=0; !finished && loop<RAYCASTING_LOOP_COUNT; ++loop) {
#define RC_END_LOOP_BRACES }
/***
* The beginning of a typical raycasting loop.
*/
#define RC_BEGIN_LOOP \
bool finished = false; \
float t = 0.0f; \
int RAYCASTING_LOOP_COUNT = tEnd / tIncr; \
RC_BEGIN_LOOP_FOR
/***
* The end of a typical raycasting loop. If adaptive sampling
* is used for rendering bricked volumes, t is increased by a
* multiple of tIncr, thereby skipping several samples.
*/
#ifdef ADAPTIVE_SAMPLING
#define RC_END_LOOP(result) \
RC_EARLY_RAY_TERMINATION(result, EARLY_RAY_TERMINATION_OPACITY, finished); \
t += (tIncr * float(numberOfSkippedSamples)); \
finished = finished || (t > tEnd); \
RC_END_LOOP_BRACES
#else
#define RC_END_LOOP(result) \
RC_EARLY_RAY_TERMINATION(result, EARLY_RAY_TERMINATION_OPACITY, finished); \
t += tIncr; \
finished = finished || (t > tEnd); \
RC_END_LOOP_BRACES
#endif
/**
* In order to keep the shaders as free as possible from dealing
* with bricking and adaptive sampling, these defines can be placed
* before and after the compositing function calls to enable adaptive
* sampling when bricking is used. For normal datasets these defines
* will have no impact at all.
*/
#ifdef ADAPTIVE_SAMPLING
#define RC_BEGIN_COMPOSITING \
for (int i=0; i<numberOfSkippedSamples; i++) {
#else
#define RC_BEGIN_COMPOSITING
#endif
#ifdef ADAPTIVE_SAMPLING
#define RC_END_COMPOSITING \
}
#else
#define RC_END_COMPOSITING
#endif

View File

@@ -10,4 +10,5 @@ return {
CONFIG = "${BASE_PATH}/config"
},
sgctConfig = "${SGCT}/single.xml",
--sgctConfig = "${SGCT}/single_sbs_stereo.xml",
}

View File

@@ -35,8 +35,6 @@
#include <openspace/util//spice.h>
#include <openspace/util/factorymanager.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/logging/consolelog.h>
@@ -45,7 +43,6 @@
#include <ghoul/lua/lua_helper.h>
#include <ghoul/cmdparser/commandlineparser.h>
#include <ghoul/cmdparser/commandlinecommand.h>
#include <ghoul/opencl/clcontext.h>
#include <ghoul/opencl/clprogram.h>
#include <ghoul/opencl/clkernel.h>
@@ -215,6 +212,12 @@ bool OpenSpaceEngine::isInitialized() {
bool OpenSpaceEngine::initialize() {
// clear the screen so the user don't have to see old buffer contents from the graphics card
glClearColor(0,0,0,0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLFWwindow* win = sgct::Engine::instance()->getActiveWindowPtr()->getWindowHandle();
glfwSwapBuffers(win);
// Register the filepaths from static function enables easy testing
//registerFilePaths();
_context.createContextFromGLContext();
@@ -244,8 +247,6 @@ bool OpenSpaceEngine::initialize() {
DeviceIdentifier::init();
DeviceIdentifier::ref().scanDevices();
_engine->_interactionHandler->connectDevices();
//_flare = new Flare();
return true;
}
@@ -282,8 +283,6 @@ void OpenSpaceEngine::preSynchronization() {
_interactionHandler->update(dt);
_interactionHandler->lockControls();
//_flare->preSync();
}
}
@@ -292,28 +291,24 @@ void OpenSpaceEngine::postSynchronizationPreDraw() {
}
void OpenSpaceEngine::render() {
//_flare->render();
_renderEngine->render();
}
void OpenSpaceEngine::postDraw() {
if (sgct::Engine::instance()->isMaster()) {
_interactionHandler->unlockControls();
//_flare->postDraw();
}
}
void OpenSpaceEngine::keyboardCallback(int key, int action) {
if (sgct::Engine::instance()->isMaster()) {
_interactionHandler->keyboardCallback(key, action);
//_flare->keyboard(key, action);
}
}
void OpenSpaceEngine::mouseButtonCallback(int key, int action) {
if (sgct::Engine::instance()->isMaster()) {
_interactionHandler->mouseButtonCallback(key, action);
//_flare->mouse(key, action);
}
}
@@ -326,11 +321,9 @@ void OpenSpaceEngine::mouseScrollWheelCallback(int pos) {
}
void OpenSpaceEngine::encode() {
//_flare->encode();
}
void OpenSpaceEngine::decode() {
//_flare->decode();
}
} // namespace openspace

View File

@@ -11,6 +11,8 @@
#include <ghoul/filesystem/filesystem.h>
#include <sgct.h>
#include <string>
#include <cstdlib>
#include <vector>

View File

@@ -1,15 +1,20 @@
// open space includes
#include <ghoul/logging/logmanager.h>
#include <openspace/interaction/interactionhandler.h>
#include <openspace/interaction/deviceidentifier.h>
#include <openspace/interaction/externalcontrol/randomexternalcontrol.h>
#include <openspace/interaction/externalcontrol/joystickexternalcontrol.h>
#include <openspace/query/query.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/util/psc.h>
#include <glm/gtx/vector_angle.hpp>
// std includes
#include <cassert>
std::string _loggerCat = "InteractionHandler";
namespace openspace {
InteractionHandler::InteractionHandler() {
@@ -19,11 +24,13 @@ InteractionHandler::InteractionHandler() {
enabled_ = true;
node_ = nullptr;
dt_ = 0.0;
_lastTrackballPos = glm::vec3(0.5);
_leftMouseButtonDown = false;
_isMouseBeingPressedAndHeld = false;
}
InteractionHandler::~InteractionHandler() {
for (size_t i = 0; i < controllers_.size(); ++i)
{
for (size_t i = 0; i < controllers_.size(); ++i) {
delete controllers_[i];
}
}
@@ -225,6 +232,75 @@ double InteractionHandler::getDt() {
return dt_;
}
glm::vec3 InteractionHandler::mapToTrackball(glm::vec2 mousePos) {
const float RADIUS = 0.5; // Sphere radius
glm::vec3 out = glm::vec3(mousePos.x-0.5, -1.0*(mousePos.y-0.5), 0);
// Mapping according to Holroyds trackball
// Piece-wise sphere + hyperbolic sheet
if (out.x*out.x + out.y*out.y <= RADIUS*RADIUS/2.0) {
//Spherical Region
out.z = RADIUS*RADIUS - (out.x*out.x + out.y*out.y);
out.z = out.z > 0.0 ? sqrtf(out.z) : 0.0;
} else { //Hyperbolic Region - for smooth z values
out.z = (RADIUS*RADIUS)/(2.0*sqrt(out.x*out.x + out.y*out.y));
}
return glm::normalize(out);
}
void InteractionHandler::trackballRotate(int x, int y) {
// Normalize mouse coordinates to [0,1]
float width = sgct::Engine::instance()->getActiveXResolution();
float height = sgct::Engine::instance()->getActiveYResolution();
glm::vec2 mousePos = glm::vec2((float)x/width, (float)y/height);
mousePos[1] = 0.5;
glm::vec3 curTrackballPos = mapToTrackball(mousePos);
// LDEBUG(mousePos.x << ", " << mousePos.y << " = " << curTrackballPos.x << ", " << curTrackballPos.y << ", " << curTrackballPos.z);
// Disable movement on the first click for extra smoothness
if (!_isMouseBeingPressedAndHeld) {
_lastTrackballPos = curTrackballPos;
_isMouseBeingPressedAndHeld = true;
}
if (curTrackballPos != _lastTrackballPos) {
// calculate rotation angle (in radians), rotation axis and quaternion
float rotationAngle = glm::angle(curTrackballPos, _lastTrackballPos);
rotationAngle *= getDt()*100.0f;
glm::vec3 rotationAxis = glm::cross(_lastTrackballPos, curTrackballPos);
rotationAxis = glm::normalize(rotationAxis);
glm::quat quaternion = glm::angleAxis(rotationAngle, rotationAxis);
// -----------------------------------------------------------------
orbit(glm::inverse(quaternion));
camera_->rotate(quaternion);
// camera_->compileViewRotationMatrix();
/*
psc nodePos = node_->getWorldPosition();
psc camPos = camera_->getPosition();
glm::mat4 transMatrix = glm::translate(glm::mat4(1.0), nodePos.getVec3f()-camPos.getVec3f());
glm::mat4 transBackMatrix = glm::translate(glm::mat4(1.0), camPos.getVec3f()-nodePos.getVec3f());
glm::vec4 translated = transMatrix*glm::vec4(camPos.getVec3f(), 1.0);
glm::vec4 postRot = glm::rotate(quaternion, translated);
glm::vec4 newCamPos = transBackMatrix*glm::vec4(postRot.x, postRot.y, postRot.z, 1.0);
camera_->setPosition(psc::CreatePSC(newCamPos.x, newCamPos.y, newCamPos.z));
camera_->rotate(glm::inverse(quaternion));
camera_->compileViewRotationMatrix();
*/
// node_->calculateBoundingSphere();
// glm::vec3 camPos = *sgct::Engine::instance()->getUserPtr()->getPosPtr();
// sgct::Engine::instance()->getUserPtr()->setOrientation(quaternion.w, quaternion.x, quaternion.y, quaternion.z);
// sgct::Engine::instance()->getUserPtr()->setPos(glm::rotate(quaternion, camPos));
_lastTrackballPos = curTrackballPos;
}
}
void InteractionHandler::keyboardCallback(int key, int action) {
// TODO package in script
const double speed = 2.75;
@@ -270,11 +346,11 @@ void InteractionHandler::keyboardCallback(int key, int action) {
rotate(rot);
}
if (key == 'R') {
pss dist(-speed * dt, 8.0);
pss dist(-speed * dt, 0.0);
distance(dist);
}
if (key == 'F') {
pss dist(speed * dt, 8.0);
pss dist(speed * dt, 0.0);
distance(dist);
}
/*
@@ -309,9 +385,18 @@ void InteractionHandler::mouseButtonCallback(int key, int action) {
//if(mouseControl_ != nullptr) {
// mouseControl_->mouseButtonCallback(key,action);
//}
if (key == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
_leftMouseButtonDown = true;
else if (key == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE) {
_leftMouseButtonDown = false;
_isMouseBeingPressedAndHeld = false;
}
}
void InteractionHandler::mousePositionCallback(int x, int y) {
if (_leftMouseButtonDown)
trackballRotate(x,y);
//if(mouseControl_ != nullptr) {
// mouseControl_->mousePosCallback(x,y);
//}
@@ -324,4 +409,4 @@ void InteractionHandler::mouseScrollWheelCallback(int pos) {
}
} // namespace openspace
} // namespace openspace

View File

@@ -23,20 +23,21 @@
****************************************************************************************/
#include <openspace/interface/interface.h>
/*
#include <sgct.h>
#include <boost/property_tree/json_parser.hpp>
#include <boost/foreach.hpp>
#include <algorithm>
*/
namespace openspace {
Interface::Interface(OpenSpaceEngine* engine) : _engine(engine) {}
Interface::~Interface() {}
void Interface::callback(const char* receivedChars) {
/*
std::cout << receivedChars;
boost::property_tree::ptree pt;
@@ -47,26 +48,25 @@ void Interface::callback(const char* receivedChars) {
loadIntoNodes(pt);
handleNodes(); // Issue commands
_nodes.clear(); // Clean up after commands are issued
*/
}
void Interface::handleNodes() {
/*
for (int i = 0; i < _nodes.size(); ++i) {
Node node = _nodes.at(i);
if (node == "stats") {
sgct::Engine::instance()->setDisplayInfoVisibility(atoi(node._value.c_str()));
} else if (node == "graph") {
sgct::Engine::instance()->setStatsGraphVisibility(atoi(node._value.c_str()));
} /*else if (node == "renderer") {
if (strcmp(node._value.c_str(), "volumeraycaster") == 0)
_engine->setRenderer(OpenSpaceEngine::Renderers::VolumeRaycaster);
else if (strcmp(node._value.c_str(), "flare") == 0)
_engine->setRenderer(OpenSpaceEngine::Renderers::Flare);
}*/
}
}
*/
}
// http://duck-wrath.blogspot.com/2012/02/how-to-recursive-parse.html
void Interface::loadIntoNodes(const boost::property_tree::ptree& tree, std::string parent, const int depth) {
/*
BOOST_FOREACH( boost::property_tree::ptree::value_type const&v, tree.get_child("") ) {
boost::property_tree::ptree subtree = v.second;
std::string value = v.second.data();
@@ -88,6 +88,7 @@ void Interface::loadIntoNodes(const boost::property_tree::ptree& tree, std::stri
// recursive go down the hierarchy
loadIntoNodes(subtree,key,depth+1);
}
*/
}
} // namespace openspace

View File

@@ -115,8 +115,8 @@ void RenderablePlanet::render(const Camera *camera, const psc &thisPosition) {
// scale the planet to appropriate size since the planet is a unit sphere
glm::mat4 transform = glm::mat4(1);
transform = glm::rotate(transform, 4.1f*static_cast<float>(sgct::Engine::instance()->getTime()), glm::vec3(0.0f, 1.0f, 0.0f));
// transform = glm::rotate(transform, 4.1f*static_cast<float>(sgct::Engine::instance()->getTime()), glm::vec3(0.0f, 1.0f, 0.0f));
// setup the data to the shader
programObject_->setUniform("ViewProjection", camera->getViewProjectionMatrix());
programObject_->setUniform("ModelTransform", transform);
@@ -142,4 +142,4 @@ void RenderablePlanet::update() {
}
} // namespace openspace
} // namespace openspace

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,8 +228,8 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string
}
// check if not a txt based texture
if ( ! hasEnding(filepath, ".txt")) {
return ghoul::opengl::loadTexture(f);;
if ( ! hasExtension(filepath, "txt")) {
return ghoul::opengl::loadTexture(f);
}
// it is a txt based texture

View File

@@ -30,6 +30,8 @@
#include <ghoul/opengl/texturereader.h>
#include <ghoul/filesystem/filesystem.h>
#include <sgct.h>
#include <algorithm>
namespace {

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>
@@ -63,7 +64,8 @@ RenderableVolumeExpert::RenderableVolumeExpert(const ghoul::Dictionary& dictiona
RenderableVolume(dictionary),
_output(nullptr),
_clBackTexture(0), _clFrontTexture(0), _clOutput(0),
_kernelSourceFile(nullptr), _programUpdateOnSave(false), _colorBoxRenderer(nullptr) {
_kernelSourceFile(nullptr), _programUpdateOnSave(false), _colorBoxRenderer(nullptr),
_boxScaling(1.0,1.0,1.0) {
_kernelLock = new std::mutex;
_textureLock = new std::mutex;
@@ -85,10 +87,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);
}
}
}
@@ -161,6 +162,30 @@ RenderableVolumeExpert::RenderableVolumeExpert(const ghoul::Dictionary& dictiona
}
}
}
ghoul::Dictionary includeDictionary;
if (kernelDictionary.hasKey("Includes") && kernelDictionary.getValue("Includes", includeDictionary)) {
auto keys = includeDictionary.keys();
for(auto key: keys) {
std::string includePath;
if(includeDictionary.getValue(key, includePath)) {
if(FileSys.directoryExists(includePath)) {
_kernelIncludes.push_back(absPath(includePath));
}
}
}
}
ghoul::Dictionary defineDictionary;
if (kernelDictionary.hasKey("Definitions") && kernelDictionary.getValue("Definitions", defineDictionary)) {
auto keys = defineDictionary.keys();
for(auto key: keys) {
std::string defintion;
if(defineDictionary.getValue(key, defintion)) {
_kernelDefinitions.push_back(std::make_pair(key, defintion));
}
}
}
}
}
if (kernelPath != "") {
@@ -168,6 +193,24 @@ RenderableVolumeExpert::RenderableVolumeExpert(const ghoul::Dictionary& dictiona
}
_colorBoxRenderer = new VolumeRaycasterBox();
double tempValue;
if(dictionary.hasKey("BoxScaling.1") && dictionary.getValue("BoxScaling.1", tempValue)) {
if(tempValue > 0.0) {
_boxScaling[0] = tempValue;
}
}
if(dictionary.hasKey("BoxScaling.2") && dictionary.getValue("BoxScaling.2", tempValue)) {
if(tempValue > 0.0) {
_boxScaling[1] = tempValue;
}
}
if(dictionary.hasKey("BoxScaling.3") && dictionary.getValue("BoxScaling.3", tempValue)) {
if(tempValue > 0.0) {
_boxScaling[2] = tempValue;
}
}
setBoundingSphere(pss::CreatePSS(_boxScaling.length()));
}
RenderableVolumeExpert::~RenderableVolumeExpert() {
@@ -204,13 +247,16 @@ 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();
LDEBUG("Creating CL texture from GL texture with path '" << _volumePaths.at(i) << "'");
cl_mem volumeTexture = _context.createTextureFromGLTexture(CL_MEM_READ_ONLY, *volume);
_volumes.push_back(volume);
_clVolumes.push_back(volumeTexture);
}
}
// ------ SETUP GEOMETRY ----------------
@@ -252,6 +298,7 @@ bool RenderableVolumeExpert::initialize() {
_colorBoxRenderer->initialize();
glm::size2_t dimensions = _colorBoxRenderer->dimensions();
ghoul::opengl::Texture* backTexture = _colorBoxRenderer->backFace();
ghoul::opengl::Texture* frontTexture = _colorBoxRenderer->frontFace();
_output = new ghoul::opengl::Texture(glm::size3_t(dimensions[0],dimensions[1],1));
@@ -267,7 +314,7 @@ bool RenderableVolumeExpert::initialize() {
// Compile kernels
safeKernelCompilation();
// create work group
size_t local_x = 32;
size_t local_y = 32;
while (local_x > 1) {
@@ -281,7 +328,6 @@ bool RenderableVolumeExpert::initialize() {
local_y /= 2;
}
_ws = new ghoul::opencl::CLWorkSize({dimensions[0],dimensions[1]}, {local_x,local_y});
return true;
}
@@ -296,18 +342,21 @@ void RenderableVolumeExpert::render(const Camera *camera, const psc &thisPositio
if( ! _kernel.isValidKernel())
return;
float speed = 50.0f;
float time = sgct::Engine::getTime();
glm::mat4 transform = camera->getViewProjectionMatrix();
psc camPos = camera->getPosition();
psc relative = thisPosition-camPos;
double factor = pow(10.0,relative[3]);
glm::mat4 camTransform = camera->getViewRotationMatrix();
double factor = pow(10.0,thisPosition[3]);
transform = glm::translate(transform, glm::vec3(thisPosition[0]*factor, thisPosition[1]*factor, thisPosition[2]*factor));
transform = glm::rotate(transform, time*speed, glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 transform = camera->getViewProjectionMatrix();
transform = transform*camTransform;
transform = glm::translate(transform, glm::vec3(relative[0]*factor, relative[1]*factor, relative[2]*factor));
transform = glm::scale(transform, _boxScaling);
_colorBoxRenderer->render(transform);
_textureLock->lock();
_kernelLock->lock();
// tell opengl to finish everything before opencl takes ownerhip (uses) the textures
glFinish();
// Aquire GL objects
@@ -330,8 +379,12 @@ void RenderableVolumeExpert::render(const Camera *camera, const psc &thisPositio
_quadProgram->activate();
glActiveTexture(GL_TEXTURE0);
_output->bind();
glClearColor(0.0f, 0.0f, 0.0f, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// enable blending
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
glBindVertexArray(_screenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
@@ -339,6 +392,11 @@ void RenderableVolumeExpert::render(const Camera *camera, const psc &thisPositio
_kernelLock->unlock();
_textureLock->unlock();
// disable blending
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glBlendFunc(GL_ONE, GL_ZERO);
_quadProgram->deactivate();
}
@@ -353,6 +411,14 @@ void RenderableVolumeExpert::safeKernelCompilation() {
for(auto option: _kernelOptions) {
tmpProgram.setOption(option.first, option.second);
}
for(auto defintion: _kernelDefinitions) {
tmpProgram.addDefinition(defintion.first, defintion.second);
}
// add the include directories
tmpProgram.addIncludeDirectory(_kernelIncludes);
if(tmpProgram.build()) {
ghoul::opencl::CLKernel tmpKernel = tmpProgram.createKernel("volumeraycaster");
if(tmpKernel.isValidKernel()) {
@@ -384,7 +450,6 @@ void RenderableVolumeExpert::safeKernelCompilation() {
if(argumentError)
return;
tmpKernel.setArgument(0, &_clFrontTexture);
tmpKernel.setArgument(1, &_clBackTexture);
tmpKernel.setArgument(2, &_clOutput);
@@ -429,24 +494,24 @@ void RenderableVolumeExpert::safeUpdateTexture(const ghoul::filesystem::File& fi
// create the new texture
ghoul::opengl::Texture* newTexture = loadTransferFunction(file.path());
if(newTexture) {
// upload the new texture and create a cl memory
newTexture->uploadTexture();
cl_mem clNewTexture = _context.createTextureFromGLTexture(CL_MEM_READ_ONLY, *newTexture);
// check if opencl memory is unsuccessfull
if(clNewTexture == 0) {
delete newTexture;
return;
}
// everything is ok, critical point to replace current texture pointers
// everything seems ok, critical point to replace current texture pointers
_textureLock->lock();
// deallocate current texture
delete _transferFunctions.at(fileID);
clReleaseMemObject(_clTransferFunctions.at(fileID));
delete _transferFunctions.at(fileID);
// set the new texture
_transferFunctions.at(fileID) = newTexture;

View File

@@ -31,6 +31,8 @@
#include <ghoul/opencl/clworksize.h>
#include <ghoul/filesystem/filesystem.h>
#include <sgct.h>
#include <algorithm>
namespace {

View File

@@ -27,6 +27,8 @@
#include <openspace/engine/openspaceengine.h>
#include <sgct.h>
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/framebufferobject.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/filesystem/filesystem.h>
@@ -39,29 +41,25 @@ using namespace ghoul::opengl;
namespace openspace {
VolumeRaycasterBox::VolumeRaycasterBox() {
VolumeRaycasterBox::VolumeRaycasterBox(): _fbo(nullptr), _backTexture(nullptr),
_frontTexture(nullptr), _boxProgram(nullptr), _boundingBox(nullptr) {
}
VolumeRaycasterBox::~VolumeRaycasterBox() {}
VolumeRaycasterBox::~VolumeRaycasterBox() {
if(_boundingBox)
delete _boundingBox;
if(_fbo) {
_fbo->detachAll(); // maybe not needed
delete _fbo;
}
}
bool VolumeRaycasterBox::initialize() {
_boundingBox = new sgct_utils::SGCTBox(1.0f, sgct_utils::SGCTBox::Regular);
// ------ SETUP SHADER -----------------
_boxProgram = new ProgramObject("RaycastBoxProgram");
/*
ShaderObject* vertexShader = new ShaderObject(ShaderObject::ShaderTypeVertex,
absPath("${BASE_PATH}/shaders/exitpoints.vert"));
ShaderObject* fragmentShader = new ShaderObject(ShaderObject::ShaderTypeFragment,
absPath("${BASE_PATH}/shaders/exitpoints.frag"));
_boxProgram->attachObject(vertexShader);
_boxProgram->attachObject(fragmentShader);
_boxProgram->compileShaderObjects();
_boxProgram->linkProgramObject();
*/
OsEng.configurationManager().getValue("RaycastProgram", _boxProgram);
_MVPLocation = _boxProgram->uniformLocation("modelViewProjection");
@@ -69,49 +67,68 @@ bool VolumeRaycasterBox::initialize() {
_fbo = new FramebufferObject();
_fbo->activate();
// changed from getActiveXResolution to getCurrentViewportPixelCoords because
// if there are more viewports in the same screen.
//size_t x = sgct::Engine::instance()->getActiveXResolution();
//size_t y = sgct::Engine::instance()->getActiveYResolution();
int x1, xSize, y1, ySize;
sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewportPixelCoords(x1, y1, xSize, ySize);
size_t x = xSize;
size_t y = ySize;
size_t x = sgct::Engine::instance()->getActiveXResolution();
size_t y = sgct::Engine::instance()->getActiveYResolution();
_dimensions = glm::size2_t(x, y);
_backTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1));
_frontTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1));
_backTexture = new Texture(glm::size3_t(x,y,1));
_frontTexture = new Texture(glm::size3_t(x,y,1));
_backTexture->uploadTexture();
_frontTexture->uploadTexture();
_fbo->attachTexture(_backTexture, GL_COLOR_ATTACHMENT0);
_fbo->attachTexture(_frontTexture, GL_COLOR_ATTACHMENT1);
_fbo->deactivate();
return true;
}
void VolumeRaycasterBox::render(glm::mat4 MVP) {
GLuint activeFBO = ghoul::opengl::FramebufferObject::getActiveObject(); // Save SGCTs main FBO
void VolumeRaycasterBox::render(const glm::mat4& MVP) {
GLuint activeFBO = FramebufferObject::getActiveObject(); // Save SGCTs main FBO
_fbo->activate();
_boxProgram->activate();
_boxProgram->setUniform(_MVPLocation, MVP);
sgct_core::Frustum::FrustumMode mode = sgct::Engine::instance()->
getActiveWindowPtr()->
getCurrentViewport()->
getEye();
// oh god why..?
if(mode == sgct_core::Frustum::FrustumMode::Mono ||
mode == sgct_core::Frustum::FrustumMode::StereoLeftEye) {
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
}
// make sure GL_CULL_FACE is enabled (it should be)
glEnable(GL_CULL_FACE);
// Draw backface
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glClearColor(0.2f, 0.2f, 0.2f, 0);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
_boundingBox->draw();
glDisable(GL_CULL_FACE);
// Draw frontface
// Draw frontface (now the normal cull face is is set)
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.2f, 0.2f, 0.2f, 0);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
_boundingBox->draw();
glDisable(GL_CULL_FACE);
_boxProgram->deactivate();
_fbo->deactivate();
// rebind the previous FBO
glBindFramebuffer(GL_FRAMEBUFFER, activeFBO);
}

View File

@@ -171,7 +171,7 @@ bool SceneGraph::initialize() {
// TODO: Set scaling dependent on the position and distance
// set position for camera
psc cameraPosition = positionNode->getPosition();
cameraPosition += psc(0.0,0.0,1.0,2.0);
cameraPosition += psc(0.0,0.0,2.0,0.0);
c->setPosition(cameraPosition);
c->setCameraDirection(glm::vec3(0,0,-1));
c->setScaling(glm::vec2(1.0,0.0));

View File

@@ -44,6 +44,7 @@ const glm::mat4 & Camera::getViewRotationMatrix() const {
void Camera::compileViewRotationMatrix() {
// convert from quaternion to rotationmatrix using glm
viewRotationMatrix_ = glm::mat4_cast(viewRotation_);
// the camera matrix needs to be rotated inverse to the world

View File

@@ -0,0 +1,248 @@
/*****************************************************************************************
* *
* 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>
#define _USE_MATH_DEFINES
#include <math.h>
#include <iomanip>
namespace openspace {
std::string _loggerCat = "KameleonWrapper";
KameleonWrapper::KameleonWrapper(const std::string& filename, Model model): _type(model) {
switch (_type) {
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("No valid model type provided!");
}
}
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);
assert(_type == Model::ENLIL || _type == Model::BATSRUS);
LINFO("Loading CDF data");
int size = outDimensions.x*outDimensions.y*outDimensions.z;
float* data = new float[size];
// get the grid system string
std::string gridSystem = _model->getGlobalAttribute("grid_system_1").getAttributeString();
// remove leading and trailing brackets
gridSystem = gridSystem.substr(1,gridSystem.length()-2);
// remove all whitespaces
gridSystem.erase(remove_if(gridSystem.begin(), gridSystem.end(), isspace), gridSystem.end());
// replace all comma signs with whitespaces
std::replace( gridSystem.begin(), gridSystem.end(), ',', ' ');
// tokenize
std::istringstream iss(gridSystem);
std::vector<std::string> tokens{std::istream_iterator<std::string>{iss},std::istream_iterator<std::string>{}};
// validate
if (tokens.size() != 3) {
LERROR("Something went wrong");
delete[] data;
return 0;
}
std::string v_x = tokens.at(0), v_y = tokens.at(1), v_z = tokens.at(2);
/*
for(auto t: tokens)
LDEBUG("t: " << t);
*/
/*
LERROR("getVariableAttributeNames");
std::vector<std::string> attributeNames = _model->getVariableAttributeNames();
for(auto name : attributeNames)
LDEBUG(name);
*/
//_model->getVa
//auto fan = std::find(attributeNames.begin(), attributeNames.end(), "");
//KameleonWrapper (Debug) grid_system_1
//KameleonWrapper (Debug) grid_1_type
LDEBUG("Using coordinate system: " << v_x << ", " << v_y << ", " << v_z);
float xMin = _model->getVariableAttribute(v_x, "actual_min").getAttributeFloat();
float xMax = _model->getVariableAttribute(v_x, "actual_max").getAttributeFloat();
float yMin = _model->getVariableAttribute(v_y, "actual_min").getAttributeFloat();
float yMax = _model->getVariableAttribute(v_y, "actual_max").getAttributeFloat();
float zMin = _model->getVariableAttribute(v_z, "actual_min").getAttributeFloat();
float zMax = _model->getVariableAttribute(v_z, "actual_max").getAttributeFloat();
float varMin = _model->getVariableAttribute(var, "actual_min").getAttributeFloat();
float varMax = _model->getVariableAttribute(var, "actual_max").getAttributeFloat();
float stepX = (xMax-xMin)/(static_cast<float>(outDimensions.x));
float stepY = (yMax-yMin)/(static_cast<float>(outDimensions.y));
float stepZ = (zMax-zMin)/(static_cast<float>(outDimensions.z));
LDEBUG(v_x << "Min: " << xMin);
LDEBUG(v_x << "Max: " << xMax);
LDEBUG(v_y << "Min: " << yMin);
LDEBUG(v_y << "Max: " << yMax);
LDEBUG(v_z << "Min: " << zMin);
LDEBUG(v_z << "Max: " << zMax);
LDEBUG(var << "Min: " << varMin);
LDEBUG(var << "Max: " << varMax);
int barWidth = 70;
int lastiProgress = -1;
for (int x = 0; x < outDimensions.x; ++x) {
float progress = static_cast<float>(x) / static_cast<float>(outDimensions.x-1);
int iprogress = static_cast<int>(progress*100.0f);
if (iprogress != lastiProgress) {
int pos = barWidth * progress;
int eqWidth = pos+1;
int spWidth = barWidth - pos + 2;
std::cout << "[" << std::setfill('=') << std::setw(eqWidth)
<< ">" << std::setfill(' ') << std::setw(spWidth)
<< "] " << iprogress << " % \r" << std::flush;
}
lastiProgress = iprogress;
for (int y = 0; y < outDimensions.y; ++y) {
for (int z = 0; z < outDimensions.z; ++z) {
int index = x + y*outDimensions.x + z*outDimensions.x*outDimensions.y;
if(_type == Model::BATSRUS) {
float xPos = xMin + stepX*x;
float yPos = yMin + stepY*y;
float zPos = zMin + stepZ*z;
// get interpolated data value for (xPos, yPos, zPos)
float value = _interpolator->interpolate(var, xPos, yPos, zPos);
// scale to [0,1]
data[index] = (value-varMin)/(varMax-varMin);
} else if (_type == Model::ENLIL) {
//LDEBUG("data: " << theval);
// Calculate array index
//unsigned int index = r + theta*xDim_ + phi*xDim_*yDim_;
// Put r in the [0..sqrt(3)] range
float rNorm = sqrt(3.0)*(float)x/(float)(outDimensions.x-1);
// Put theta in the [0..PI] range
float thetaNorm = M_PI*(float)y/(float)(outDimensions.y-1);
// Put phi in the [0..2PI] range
float phiNorm = 2.0*M_PI*(float)z/(float)(outDimensions.z-1);
// Go to physical coordinates before sampling
float rPh = xMin + rNorm*(xMax-xMin);
float thetaPh = thetaNorm;
//phi range needs to be mapped to the slightly different
// model range to avoid gaps in the data
// Subtract a small term to avoid rounding errors when comparing
// to phiMax.
float phiPh = zMin + phiNorm/(2.0*M_PI)*(zMax-zMin-0.000001);
// Hardcoded variables (rho or rho - rho_back)
// TODO Don't hardcode, make more flexible
float varValue = 0.f;//, rho_back = 0.f, diff = 0.f;
// See if sample point is inside domain
if (rPh < xMin || rPh > xMax || thetaPh < yMin ||
thetaPh > yMax || phiPh < zMin || phiPh > zMax) {
if (phiPh > zMax) {
std::cout << "Warning: There might be a gap in the data\n";
}
// Leave values at zero if outside domain
} else { // if inside
// ENLIL CDF specific hacks!
// Convert from meters to AU for interpolator
rPh /= ccmc::constants::AU_in_meters;
// Convert from colatitude [0, pi] rad to latitude [-90, 90] degrees
thetaPh = -thetaPh*180.f/M_PI+90.f;
// Convert from [0, 2pi] rad to [0, 360] degrees
phiPh = phiPh*180.f/M_PI;
// Sample
varValue = _interpolator->interpolate(var, rPh, thetaPh, phiPh);
//rho_back = _interpolator->interpolate("rho-back",rPh,thetaPh,phiPh);
// Calculate difference (or just rho)
//diff = rho;
//diff = rho - rho_back;
// Clamp to 0
//if (diff < 0.f) diff = 0.f;
}
//if(var < 0.0f) var = 0.0f;
//data[index] = var;
data[index] = (varValue-varMin)/(varMax-varMin);
//LDEBUG("varValue:" << varValue);
//LDEBUG("data[index]:" << data[index]);
//data[index] = var;
//data[index] = diff;
}
}
}
}
std::cout << std::endl;
LINFO("Done!");
return data;
}
} // namespace openspace