Merge branch 'develop' into stars

Conflicts:
	include/openspace/util/constants.h
	shaders/pscstandard_fs.glsl
	shaders/pscstandard_vs.glsl
	src/interaction/interactionhandler.cpp
	src/main.cpp
	src/rendering/renderengine.cpp
	src/scenegraph/scenegraph.cpp
	src/scenegraph/scenegraphnode.cpp
	src/util/factorymanager.cpp
This commit is contained in:
Jonas Strandstedt
2014-09-24 15:39:22 +02:00
135 changed files with 10844 additions and 3182 deletions

View File

@@ -34,6 +34,12 @@ file(GLOB CONFIGURATION_HEADER ${HEADER_ROOT_DIR}/openspace/configuration/*.h)
set(OPENSPACE_HEADER ${OPENSPACE_HEADER} ${CONFIGURATION_HEADER})
source_group(Configuration FILES ${CONFIGURATION_SOURCE} ${CONFIGURATION_HEADER})
file(GLOB ABUFFER_SOURCE ${SOURCE_ROOT_DIR}/abuffer/*.cpp)
set(OPENSPACE_SOURCE ${OPENSPACE_SOURCE} ${ABUFFER_SOURCE})
file(GLOB ABUFFER_HEADER ${HEADER_ROOT_DIR}/openspace/abuffer/*.h)
set(OPENSPACE_HEADER ${OPENSPACE_HEADER} ${ABUFFER_HEADER})
source_group(ABuffer FILES ${ABUFFER_SOURCE} ${ABUFFER_HEADER})
file(GLOB ENGINE_SOURCE ${SOURCE_ROOT_DIR}/engine/*.cpp)
set(OPENSPACE_SOURCE ${OPENSPACE_SOURCE} ${ENGINE_SOURCE})
file(GLOB ENGINE_HEADER ${HEADER_ROOT_DIR}/openspace/engine/*.h)
@@ -90,6 +96,12 @@ file(GLOB SCENEGRAPH_HEADER ${HEADER_ROOT_DIR}/openspace/scenegraph/*.h ${HEADER
set(OPENSPACE_HEADER ${OPENSPACE_HEADER} ${SCENEGRAPH_HEADER})
source_group(SceneGraph FILES ${SCENEGRAPH_SOURCE} ${SCENEGRAPH_HEADER})
file(GLOB SCRIPTING_SOURCE ${SOURCE_ROOT_DIR}/scripting/*.cpp)
set(OPENSPACE_SOURCE ${OPENSPACE_SOURCE} ${SCRIPTING_SOURCE})
file(GLOB SCRIPTING_HEADER ${HEADER_ROOT_DIR}/openspace/scripting/*.h)
set(OPENSPACE_HEADER ${OPENSPACE_HEADER} ${SCRIPTING_HEADER})
source_group(Scripting FILES ${SCRIPTING_SOURCE} ${SCRIPTING_HEADER})
file(GLOB UTIL_SOURCE ${SOURCE_ROOT_DIR}/util/*.cpp)
set(OPENSPACE_SOURCE ${OPENSPACE_SOURCE} ${UTIL_SOURCE})
file(GLOB UTIL_HEADER ${HEADER_ROOT_DIR}/openspace/util/*.h)
@@ -136,5 +148,23 @@ include_directories("${HEADER_ROOT_DIR}")
add_executable(OpenSpace ${SOURCE_ROOT_DIR}/main.cpp ${OPENSPACE_HEADER} ${OPENSPACE_SOURCE})
target_link_libraries(OpenSpace ${DEPENDENT_LIBS})
if (WIN32)
if (CMAKE_CL_64)
set(OPENSPACE_DLL_LIBS ${OPENSPACE_DLL_LIBS} ${GHOUL_ROOT_DIR}/ext/il/lib/win64/DevIL.dll)
set(OPENSPACE_DLL_LIBS ${OPENSPACE_DLL_LIBS} ${GHOUL_ROOT_DIR}/ext/il/lib/win64/ILU.dll)
set(OPENSPACE_DLL_LIBS ${OPENSPACE_DLL_LIBS} ${GHOUL_ROOT_DIR}/ext/il/lib/win64/ILUT.dll)
else (CMAKE_CL_64)
set(OPENSPACE_DLL_LIBS ${OPENSPACE_DLL_LIBS} ${GHOUL_ROOT_DIR}/ext/il/lib/win32/DevIL.dll)
set(OPENSPACE_DLL_LIBS ${OPENSPACE_DLL_LIBS} ${GHOUL_ROOT_DIR}/ext/il/lib/win32/ILU.dll)
set(OPENSPACE_DLL_LIBS ${OPENSPACE_DLL_LIBS} ${GHOUL_ROOT_DIR}/ext/il/lib/win32/ILUT.dll)
endif (CMAKE_CL_64)
foreach( file_i ${OPENSPACE_DLL_LIBS})
add_custom_command(TARGET OpenSpace POST_BUILD # Adds a post-build event to MyTest
COMMAND ${CMAKE_COMMAND} -E copy_if_different # which executes "cmake - E copy_if_different..."
"${file_i}" # <--this is in-file
$<TARGET_FILE_DIR:OpenSpace>)
endforeach( file_i )
endif(WIN32)
add_subdirectory(tests)

379
src/abuffer/abuffer.cpp Normal file
View File

@@ -0,0 +1,379 @@
/*****************************************************************************************
* *
* 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 <openspace/abuffer/abuffer.h>
#include <openspace/engine/openspaceengine.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <sgct.h>
#include <iostream>
#include <fstream>
#include <string>
namespace {
std::string _loggerCat = "ABuffer";
std::string padGeneratedString(const std::string& content) {
std::string _content_ = "// GENERATED CONTENT\n" + content + "\n// END GENERATED CONTENT";
return _content_;
}
}
namespace openspace {
ABuffer::ABuffer(): _validShader(true) {
int x1, xSize, y1, ySize;
sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewportPixelCoords(x1, y1, xSize, ySize);
_width = xSize;
_height = ySize;
_totalPixels = _width * _height;
const std::string fragmentShaderSourcePath = absPath("${SHADERS}/ABuffer/abufferResolveFragment.glsl");
_fragmentShaderFile = new ghoul::filesystem::File(fragmentShaderSourcePath, true);
_fragmentShaderPath = fragmentShaderSourcePath.substr(0, fragmentShaderSourcePath.length()-4) + "gglsl";
}
ABuffer::~ABuffer() {
if(_fragmentShaderFile)
delete _fragmentShaderFile;
if(_resolveShader)
delete _resolveShader;
for(auto file: _samplerFiles) {
delete file;
}
for(auto file: _shaderFiles) {
delete file;
}
}
bool ABuffer::initializeABuffer() {
// ============================
// SHADERS
// ============================
auto shaderCallback = [this](const ghoul::filesystem::File& file) {
_validShader = false;
};
_fragmentShaderFile->setCallback(shaderCallback);
// Development functionality to update shader for changes in several files
auto addFunc = [this, shaderCallback](const std::string& path) {
ghoul::filesystem::File* f = new ghoul::filesystem::File(path, false);
f->setCallback(shaderCallback);
_shaderFiles.push_back(f);
};
addFunc("${SHADERS}/ABuffer/abufferSort.hglsl");
addFunc("${SHADERS}/ABuffer/abufferAddToBuffer.hglsl");
addFunc("${SHADERS}/ABuffer/abufferStruct.hglsl");
addFunc("${SHADERS}/PowerScaling/powerScaling_fs.hglsl");
addFunc("${SHADERS}/PowerScaling/powerScaling_vs.hglsl");
_resolveShader = nullptr;
generateShaderSource();
updateShader();
// ============================
// GEOMETRY (quad)
// ============================
const GLfloat size = 1.0f;
const GLfloat vertex_data[] = { // square of two triangles (sigh)
// x y z w s t
-size, -size, 0.0f, 1.0f,
size, size, 0.0f, 1.0f,
-size, size, 0.0f, 1.0f,
-size, -size, 0.0f, 1.0f,
size, -size, 0.0f, 1.0f,
size, size, 0.0f, 1.0f,
};
GLuint vertexPositionBuffer;
glGenVertexArrays(1, &_screenQuad); // generate array
glBindVertexArray(_screenQuad); // bind array
glGenBuffers(1, &vertexPositionBuffer); // generate buffer
glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*4, reinterpret_cast<void*>(0));
glEnableVertexAttribArray(0);
return true;
}
void ABuffer::resolve() {
if( ! _validShader) {
_validShader = true;
generateShaderSource();
updateShader();
}
if(_resolveShader) {
_resolveShader->activate();
int startAt = 0;
for(int i = 0; i < _volumes.size(); ++i) {
glActiveTexture(GL_TEXTURE0 + i);
_volumes.at(i).second->bind();
startAt = i + 1;
}
for(int i = 0; i < _transferFunctions.size(); ++i) {
glActiveTexture(GL_TEXTURE0 + startAt + i);
_transferFunctions.at(i).second->bind();
}
// Decrease stepsize in volumes if right click is pressed
// TODO: Let the interactionhandler handle this
int val = sgct::Engine::getMouseButton(0, SGCT_MOUSE_BUTTON_RIGHT);
float volumeStepFactor = (val) ? 0.2: 1.0;
if(volumeStepFactor != _volumeStepFactor) {
_volumeStepFactor = volumeStepFactor;
_resolveShader->setUniform("volumeStepFactor", _volumeStepFactor);
}
glBindVertexArray(_screenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
_resolveShader->deactivate();
}
}
void ABuffer::addVolume(const std::string& tag,ghoul::opengl::Texture* volume) {
_volumes.push_back(std::make_pair(tag, volume));
}
void ABuffer::addTransferFunction(const std::string& tag,ghoul::opengl::Texture* transferFunction) {
_transferFunctions.push_back(std::make_pair(tag, transferFunction));
}
int ABuffer::addSamplerfile(const std::string& filename) {
if( ! FileSys.fileExists(filename))
return -1;
auto fileCallback = [this](const ghoul::filesystem::File& file) {
_validShader = false;
};
ghoul::filesystem::File* file = new ghoul::filesystem::File(filename);
file->setCallback(fileCallback);
_samplerFiles.push_back(file);
_samplers.push_back("");
// ID is one more than "actual" position since ID=0 is considered geometry
//return 1 << (_samplers.size()-1);
return _samplers.size();
}
bool ABuffer::updateShader() {
using ghoul::opengl::ShaderObject;
using ghoul::opengl::ProgramObject;
ShaderCreator sc = OsEng.shaderBuilder();
ghoul::opengl::ProgramObject* resolveShader = sc.buildShader("ABuffer resolve", absPath("${SHADERS}/ABuffer/abufferResolveVertex.glsl"), _fragmentShaderPath);
if( ! resolveShader) {
LERROR("Resolve shader not updated");
return false;
}
int startAt = 0;
for(int i = 0; i < _volumes.size(); ++i) {
resolveShader->setUniform(_volumes.at(i).first, i);
startAt = i + 1;
}
for(int i = 0; i < _transferFunctions.size(); ++i) {
resolveShader->setUniform(_transferFunctions.at(i).first, startAt + i);
}
if(_resolveShader)
delete _resolveShader;
_resolveShader = resolveShader;
LDEBUG("Successfully updated shader!");
return true;
}
void ABuffer::generateShaderSource() {
for(int i = 0; i < _samplerFiles.size(); ++i) {
std::string line, source = "";
std::ifstream samplerFile(_samplerFiles.at(i)->path());
if(samplerFile.is_open()) {
while(std::getline(samplerFile, line)) {
source += line + "\n";
}
}
samplerFile.close();
_samplers.at(i) = source;
}
std::string line, source = "";
std::ifstream fragmentShaderFile(_fragmentShaderFile->path());
if(fragmentShaderFile.is_open()) {
while(std::getline(fragmentShaderFile, line)) {
if(line == "#pragma openspace insert HEADERS") {
line = padGeneratedString(openspaceHeaders());
} else if(line == "#pragma openspace insert SAMPLERCALLS") {
line = padGeneratedString(openspaceSamplerCalls());
} else if(line == "#pragma openspace insert SAMPLERS") {
line = padGeneratedString(openspaceSamplers());
} else if(line == "#pragma openspace insert SETTINGS") {
line = padGeneratedString(settings());
} else if(line == "#pragma openspace insert TRANSFERFUNC") {
line = padGeneratedString(openspaceTransferFunction());
}
source += line + "\n";
}
}
fragmentShaderFile.close();
std::ofstream fragmentShaderOut(_fragmentShaderPath);
fragmentShaderOut << source;
fragmentShaderOut.close();
}
std::string ABuffer::openspaceHeaders() {
std::string headers;
headers += "#define MAX_VOLUMES " + std::to_string(_samplers.size()) + "\n";
headers += "#define MAX_TF " + std::to_string(_transferFunctions.size()) + "\n";
for (int i = 0; i < _volumes.size(); ++i) {
headers += "uniform sampler3D " + _volumes.at(i).first + ";\n";
}
for (int i = 0; i < _transferFunctions.size(); ++i) {
headers += "uniform sampler1D " + _transferFunctions.at(i).first + ";\n";
}
for (int i = 0; i < _samplers.size(); ++i) {
auto found = _samplers.at(i).find_first_of('{');
if(found!=std::string::npos) {
headers += _samplers.at(i).substr(0, found) + ";\n";
}
}
if(_volumes.size() < 1)
return headers;
size_t maxLoop = 0;
headers += "const vec3 volume_dim[] = {\n";
for (int i = 0; i < _volumes.size(); ++i) {
glm::size3_t size = _volumes.at(i).second->dimensions();
for(int k = 0; k < 3; ++k)
maxLoop = glm::max(maxLoop, size[k]);
headers += " vec3(" + std::to_string(size[0]) + ".0," + std::to_string(size[1]) + ".0,"
+ std::to_string(size[2]) + ".0),\n";
}
headers += "};\n";
headers += "#define LOOP_LIMIT " + std::to_string(maxLoop) + "\n";
headers += "float volumeStepSize[] = {\n";
for (int i = 0; i < _volumes.size(); ++i) {
glm::size3_t size = _volumes.at(i).second->dimensions();
headers += " stepSize,\n";
}
headers += "};\n";
headers += "float volumeStepSizeOriginal[] = {\n";
for (int i = 0; i < _volumes.size(); ++i) {
glm::size3_t size = _volumes.at(i).second->dimensions();
headers += " stepSize,\n";
}
headers += "};\n";
return headers;
}
std::string ABuffer::openspaceSamplerCalls() {
std::string samplercalls;
for (int i = 0; i < _samplers.size(); ++i) {
auto found1 = _samplers.at(i).find_first_not_of("vec4 ");
auto found2 = _samplers.at(i).find_first_of("(",found1);
if(found1 != std::string::npos && found2 != std::string::npos) {
std::string functionName = _samplers.at(i).substr(found1, found2 - found1);
samplercalls += "#ifndef SKIP_VOLUME_"+std::to_string(i)+"\n";
samplercalls += "if((currentVolumeBitmask & (1 << " + std::to_string(i) + ")) == "+std::to_string(1 << i)+") {\n";
samplercalls += " vec4 c = " + functionName + "(final_color,volume_position[" + std::to_string(i) + "]);\n";
// samplercalls += " if(c.a < 0.1) { \n";
// samplercalls += " if( volumeStepSize[" + std::to_string(i) + "] < 16.0*volumeStepSizeOriginal[" + std::to_string(i) + "]) \n";
// samplercalls += " volumeStepSize[" + std::to_string(i) + "] *= 2.0; \n";
// samplercalls += " } else {\n";
// samplercalls += " //volume_position[" + std::to_string(i) + "] -= volume_direction[" + std::to_string(i) + "]*volumeStepSize[" + std::to_string(i) + "];\n";
// samplercalls += " volumeStepSize[" + std::to_string(i) + "] = volumeStepSizeOriginal[" + std::to_string(i) + "]; \n";
// samplercalls += " //c = " + functionName + "(final_color,volume_position[" + std::to_string(i) + "]);\n";
// samplercalls += " } \n";
// samplercalls += " if(c.a > EPSILON)\n";
samplercalls += " blendStep(final_color, c, volumeStepSize[" + std::to_string(i) + "]);\n";
// samplercalls += " blendStep(final_color, c, stepSize);\n";
// samplercalls += " float aaa = volume_length[i]/myMaxSteps;\n";
samplercalls += " volume_position[" + std::to_string(i) + "] += volume_direction[" + std::to_string(i) + "]*volumeStepSize[" + std::to_string(i) + "];\n";
// float aaa = ray[v].w/myMaxSteps;
// pos[v] += vec4(ray[v].xyz*vec3(aaa),aaa);
// samplercalls += " volume_position[" + std::to_string(i) + "] += volume_direction[" + std::to_string(i) + "]*volumeStepSize[" + std::to_string(i) + "];\n";
samplercalls += "}\n";
samplercalls += "#endif\n";
}
}
return samplercalls;
}
std::string ABuffer::openspaceSamplers() {
std::string samplers;
for (int i = 0; i < _samplers.size(); ++i) {
samplers += _samplers.at(i) + "\n";
}
return samplers;
}
std::string ABuffer::openspaceTransferFunction() {
std::string tf;
tf += "float showfunc_size = 20.0;\n";
tf += "float SCREEN_HEIGHTf = float(SCREEN_HEIGHT);\n";
tf += "float SCREEN_WIDTHf = float(SCREEN_WIDTH);\n";
for(int i = 0; i < _transferFunctions.size(); ++i) {
tf += "if( gl_FragCoord.y > SCREEN_HEIGHTf-showfunc_size*"+std::to_string(i+1)+
" && gl_FragCoord.y < SCREEN_HEIGHTf-showfunc_size*"+std::to_string(i)+") {\n";
tf += " float normalizedIntensity = gl_FragCoord.x / (SCREEN_WIDTHf-1) ;\n";
tf += " vec4 tfc = texture("+ _transferFunctions.at(i).first +", normalizedIntensity);\n";
tf += " final_color = tfc;\n";
tf += " float cmpf = SCREEN_HEIGHTf-showfunc_size*"+std::to_string(i+1)+" + tfc.a*showfunc_size;\n";
tf += " if(gl_FragCoord.y > cmpf) {\n";
tf += " final_color = vec4(0,0,0,0);\n";
tf += " } else {\n";
tf += " final_color.a = 1.0;\n";
tf += " }\n";
tf += "} else if(ceil(gl_FragCoord.y) == SCREEN_HEIGHTf - showfunc_size*"+std::to_string(i+1)+") {\n";
tf += " const float intensity = 0.4;\n";
tf += " final_color = vec4(intensity,intensity,intensity,1.0);\n";
tf += "}\n";
}
return tf;
}
} // openspace

View File

@@ -0,0 +1,124 @@
/*****************************************************************************************
* *
* 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 <openspace/abuffer/abufferSingleLinked.h>
#include <openspace/engine/openspaceengine.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <iostream>
#include <fstream>
#include <string>
#define MAX_LAYERS 10
namespace {
std::string _loggerCat = "ABufferSingleLinked";
}
namespace openspace {
ABufferSingleLinked::ABufferSingleLinked(): _data(0), _anchorPointerTexture(0),
_anchorPointerTextureInitializer(0), _atomicCounterBuffer(0), _fragmentBuffer(0),
_fragmentTexture(0)
{}
ABufferSingleLinked::~ABufferSingleLinked() {
if(_data != 0)
delete _data;
glDeleteTextures(1,&_anchorPointerTexture);
glDeleteTextures(1,&_fragmentTexture);
glDeleteBuffers(1,&_anchorPointerTextureInitializer);
glDeleteBuffers(1,&_atomicCounterBuffer);
glDeleteBuffers(1,&_anchorPointerTextureInitializer);
}
bool ABufferSingleLinked::initialize() {
// ============================
// BUFFERS
// ============================
glGenTextures(1, &_anchorPointerTexture);
glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
glGenBuffers(1, &_anchorPointerTextureInitializer);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer);
glBufferData(GL_PIXEL_UNPACK_BUFFER, _totalPixels * sizeof(GLuint), NULL, GL_STATIC_DRAW);
_data = (GLuint*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
memset(_data, 0x00, _totalPixels * sizeof(GLuint));
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glGenBuffers(1, &_atomicCounterBuffer);
glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, _atomicCounterBuffer);
glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_COPY);
glGenBuffers(1, &_fragmentBuffer);
glBindBuffer(GL_TEXTURE_BUFFER, _fragmentBuffer);
glBufferData(GL_TEXTURE_BUFFER, MAX_LAYERS*_totalPixels*sizeof(GLfloat)*4, NULL, GL_DYNAMIC_COPY);
glGenTextures(1, &_fragmentTexture);
glBindTexture(GL_TEXTURE_BUFFER, _fragmentTexture);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, _fragmentBuffer);
glBindTexture(GL_TEXTURE_BUFFER, 0);
glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI);
return initializeABuffer();
}
void ABufferSingleLinked::clear() {
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer);
glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
static const GLuint zero = 1;
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, _atomicCounterBuffer);
glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(zero), &zero);
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, 0);
}
void ABufferSingleLinked::preRender() {
// Bind head-pointer image for read-write
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, _atomicCounterBuffer);
glBindImageTexture(0, _anchorPointerTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
}
void ABufferSingleLinked::postRender() {
}
std::string ABufferSingleLinked::settings() {
return R"()";
}
} // openspace

View File

@@ -0,0 +1,124 @@
/*****************************************************************************************
* *
* 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 <openspace/abuffer/abufferdynamic.h>
#include <openspace/engine/openspaceengine.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <iostream>
#include <fstream>
#include <string>
#define MAX_LAYERS 10
namespace {
std::string _loggerCat = "ABufferDynamic";
}
namespace openspace {
ABufferDynamic::ABufferDynamic(): _data(0), _anchorPointerTexture(0),
_anchorPointerTextureInitializer(0), _atomicCounterBuffer(0), _fragmentBuffer(0),
_fragmentTexture(0)
{}
ABufferDynamic::~ABufferDynamic() {
if(_data != 0)
delete _data;
glDeleteTextures(1,&_anchorPointerTexture);
glDeleteTextures(1,&_fragmentTexture);
glDeleteBuffers(1,&_anchorPointerTextureInitializer);
glDeleteBuffers(1,&_atomicCounterBuffer);
glDeleteBuffers(1,&_anchorPointerTextureInitializer);
}
bool ABufferDynamic::initialize() {
// ============================
// BUFFERS
// ============================
glGenTextures(1, &_anchorPointerTexture);
glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
glGenBuffers(1, &_anchorPointerTextureInitializer);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer);
glBufferData(GL_PIXEL_UNPACK_BUFFER, _totalPixels * sizeof(GLuint), NULL, GL_STATIC_DRAW);
_data = (GLuint*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
memset(_data, 0x00, _totalPixels * sizeof(GLuint));
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glGenBuffers(1, &_atomicCounterBuffer);
glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, _atomicCounterBuffer);
glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_COPY);
glGenBuffers(1, &_fragmentBuffer);
glBindBuffer(GL_TEXTURE_BUFFER, _fragmentBuffer);
glBufferData(GL_TEXTURE_BUFFER, MAX_LAYERS*_totalPixels*sizeof(GLfloat)*4, NULL, GL_DYNAMIC_COPY);
glGenTextures(1, &_fragmentTexture);
glBindTexture(GL_TEXTURE_BUFFER, _fragmentTexture);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, _fragmentBuffer);
glBindTexture(GL_TEXTURE_BUFFER, 0);
glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI);
return initializeABuffer();
}
void ABufferDynamic::clear() {
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer);
glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
static const GLuint zero = 1;
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, _atomicCounterBuffer);
glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(zero), &zero);
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, 0);
}
void ABufferDynamic::preRender() {
// Bind head-pointer image for read-write
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, _atomicCounterBuffer);
glBindImageTexture(0, _anchorPointerTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
}
void ABufferDynamic::postRender() {
}
std::string ABufferDynamic::settings() {
return R"(#define ABUFFER_SINGLE_LINKED)";
}
} // openspace

View File

@@ -0,0 +1,137 @@
/*****************************************************************************************
* *
* 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 <openspace/abuffer/abufferfixed.h>
#include <openspace/engine/openspaceengine.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <iostream>
#include <fstream>
#include <string>
#define MAX_LAYERS 32
namespace {
std::string _loggerCat = "ABufferFixed";
}
namespace openspace {
ABufferFixed::ABufferFixed(): _data(0), _anchorPointerTexture(0),
_anchorPointerTextureInitializer(0), _atomicCounterBuffer(0), _fragmentBuffer(0),
_fragmentTexture(0)
{}
ABufferFixed::~ABufferFixed() {
if(_data != 0)
delete _data;
glDeleteTextures(1,&_anchorPointerTexture);
glDeleteTextures(1,&_fragmentTexture);
// glDeleteTextures(1,&_atomicCounterTexture);
glDeleteBuffers(1,&_anchorPointerTextureInitializer);
// glDeleteBuffers(1,&_atomicCounterBuffer);
glDeleteBuffers(1,&_anchorPointerTextureInitializer);
}
bool ABufferFixed::initialize() {
// ============================
// BUFFERS
// ============================
glGenTextures(1, &_anchorPointerTexture);
glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
glGenBuffers(1, &_anchorPointerTextureInitializer);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer);
glBufferData(GL_PIXEL_UNPACK_BUFFER, _totalPixels * sizeof(GLuint), NULL, GL_STATIC_DRAW);
_data = (GLuint*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
memset(_data, 0x00, _totalPixels * sizeof(GLuint));
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
// glGenBuffers(1, &_atomicCounterBuffer);
// glBindBuffer(GL_TEXTURE_BUFFER, _atomicCounterBuffer);
// glBufferData(GL_TEXTURE_BUFFER, _totalPixels*sizeof(GLuint), NULL, GL_DYNAMIC_COPY);
// glGenTextures(1, &_atomicCounterTexture);
// glBindTexture(GL_TEXTURE_2D, _atomicCounterTexture);
// glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, _atomicCounterBuffer);
// glBindTexture(GL_TEXTURE_BUFFER, 0);
glGenBuffers(1, &_fragmentBuffer);
glBindBuffer(GL_TEXTURE_BUFFER, _fragmentBuffer);
glBufferData(GL_TEXTURE_BUFFER, MAX_LAYERS*_totalPixels*sizeof(GLfloat)*4, NULL, GL_DYNAMIC_COPY);
glGenTextures(1, &_fragmentTexture);
glBindTexture(GL_TEXTURE_BUFFER, _fragmentTexture);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, _fragmentBuffer);
glBindTexture(GL_TEXTURE_BUFFER, 0);
glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI);
return initializeABuffer();
}
void ABufferFixed::clear() {
// Bind texture initializer
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer);
// clear _anchorPointerTexture
glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
// // clear _atomicCounterTexture
// glBindTexture(GL_TEXTURE_2D, _atomicCounterTexture);
// glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
// reset GL_PIXEL_UNPACK_BUFFER
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
void ABufferFixed::preRender() {
// Bind head-pointer image for read-write
glBindImageTexture(0, _anchorPointerTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI);
// glBindImageTexture(2, _atomicCounterTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
}
void ABufferFixed::postRender() {
}
std::string ABufferFixed::settings() {
return R"()";
}
} // openspace

View File

@@ -31,10 +31,12 @@
#include <openspace/interaction/deviceidentifier.h>
#include <openspace/interaction/interactionhandler.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scripting/scriptengine.h>
#include <openspace/util/time.h>
#include <openspace/util/spice.h>
#include <openspace/util/factorymanager.h>
#include <openspace/util/constants.h>
#include <openspace/util/spicemanager.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
@@ -43,42 +45,59 @@
#include <ghoul/lua/ghoul_lua.h>
#include <ghoul/lua/lua_helper.h>
#include <ghoul/cmdparser/commandlineparser.h>
#include <ghoul/cmdparser/commandlinecommand.h>
#include <ghoul/cmdparser/singlecommand.h>
using namespace ghoul::filesystem;
using namespace ghoul::logging;
using namespace openspace::scripting;
namespace {
const std::string _loggerCat = "OpenSpaceEngine";
const std::string _configurationFile = "openspace.cfg";
const std::string _basePathToken = "${BASE_PATH}";
const std::string _sgctDefaultConfigFile = "${SGCT}/single.xml";
const std::string _sgctConfigArgumentCommand = "-config";
struct {
std::string configurationName;
} commandlineArgumentPlaceholders;
}
using namespace ghoul::cmdparser;
namespace openspace {
OpenSpaceEngine* OpenSpaceEngine::_engine = nullptr;
OpenSpaceEngine::OpenSpaceEngine()
: _configurationManager(nullptr)
, _interactionHandler(nullptr)
, _renderEngine(nullptr)
//, _scriptEngine(nullptr)
OpenSpaceEngine::OpenSpaceEngine(std::string programName)
: _configurationManager(new ghoul::Dictionary)
, _interactionHandler(new InteractionHandler)
, _renderEngine(new RenderEngine)
, _scriptEngine(new ScriptEngine)
, _commandlineParser(new CommandlineParser(programName, true))
{
}
OpenSpaceEngine::~OpenSpaceEngine()
{
delete _configurationManager;
_configurationManager = nullptr;
delete _interactionHandler;
_interactionHandler = nullptr;
delete _renderEngine;
_renderEngine = nullptr;
delete _scriptEngine;
_scriptEngine = nullptr;
delete _commandlineParser;
_commandlineParser = nullptr;
// TODO deallocate script engine when starting to use it
// delete _scriptEngine;
SpiceManager::deinitialize();
Spice::deinit();
Time::deinit();
Time::deinitialize();
DeviceIdentifier::deinit();
FileSystem::deinitialize();
LogManager::deinitialize();
}
@@ -87,6 +106,18 @@ OpenSpaceEngine& OpenSpaceEngine::ref()
assert(_engine);
return *_engine;
}
bool OpenSpaceEngine::gatherCommandlineArguments()
{
// TODO: Get commandline arguments from all modules
CommandlineCommand* configurationFileCommand = new SingleCommand<std::string>(
&commandlineArgumentPlaceholders.configurationName, "-config", "-c",
"Provides the path to the OpenSpace configuration file");
_commandlineParser->addCommand(configurationFileCommand);
return true;
}
void OpenSpaceEngine::registerPathsFromDictionary(const ghoul::Dictionary& dictionary)
{
@@ -97,10 +128,12 @@ void OpenSpaceEngine::registerPathsFromDictionary(const ghoul::Dictionary& dicti
const std::string fullKey
= ghoul::filesystem::FileSystem::TokenOpeningBraces + key
+ ghoul::filesystem::FileSystem::TokenClosingBraces;
LDEBUG(fullKey << ": " << p);
LDEBUG("Registering path " << fullKey << ": " << p);
bool override = (_basePathToken == fullKey);
if (override)
LINFO("Overriding base path with '" << p << "'");
FileSys.registerPathToken(fullKey, p, override);
}
}
@@ -118,7 +151,6 @@ bool OpenSpaceEngine::registerBasePathFromConfigurationFile(const std::string& f
if (last == std::string::npos)
return false;
std::string basePath = absolutePath.substr(0, last);
FileSys.registerPathToken(_basePathToken, basePath);
@@ -128,88 +160,117 @@ bool OpenSpaceEngine::registerBasePathFromConfigurationFile(const std::string& f
bool OpenSpaceEngine::findConfiguration(std::string& filename)
{
if (!filename.empty())
return FileSys.fileExists(filename);
else {
std::string currentDirectory = FileSys.absolutePath(FileSys.currentDirectory());
size_t occurrences = std::count(currentDirectory.begin(), currentDirectory.end(),
ghoul::filesystem::FileSystem::PathSeparator);
std::string currentDirectory = FileSys.absolutePath(FileSys.currentDirectory());
size_t occurrences = std::count(currentDirectory.begin(), currentDirectory.end(),
ghoul::filesystem::FileSystem::PathSeparator);
std::string cfgname = _configurationFile;
std::string cfgname = _configurationFile;
bool cfgFileFound = false;
for (size_t i = 0; i < occurrences; ++i) {
if (i > 0)
cfgname = "../" + cfgname;
if (FileSys.fileExists(cfgname)) {
cfgFileFound = true;
break;
}
bool cfgFileFound = false;
for (size_t i = 0; i < occurrences; ++i) {
if (i > 0)
cfgname = "../" + cfgname;
if (FileSys.fileExists(cfgname)) {
cfgFileFound = true;
break;
}
if (!cfgFileFound)
return false;
filename = cfgname;
return true;
}
if (!cfgFileFound)
return false;
filename = cfgname;
return true;
}
void OpenSpaceEngine::create(int argc, char** argv,
bool OpenSpaceEngine::create(int argc, char** argv,
std::vector<std::string>& sgctArguments)
{
// TODO custom assert (ticket #5)
assert(_engine == nullptr);
// initialize ghoul logging
// initialize Ghoul logging
LogManager::initialize(LogManager::LogLevel::Debug, true);
LogMgr.addLog(new ConsoleLog);
// TODO change so initialize is not called in the create function
// Initialize FileSystem
ghoul::filesystem::FileSystem::initialize();
// TODO parse arguments if filename is specified, if not use default
std::string configurationFilePath = "";
LDEBUG("Finding configuration");
if (!OpenSpaceEngine::findConfiguration(configurationFilePath)) {
LFATAL("Could not find OpenSpace configuration file!");
assert(false);
// Sanity check of values
if (argc < 1) {
LFATAL("No arguments were passed to the function");
return false;
}
// create other objects
LDEBUG("Creating OpenSpaceEngine");
_engine = new OpenSpaceEngine(std::string(argv[0]));
// Query modules for commandline arguments
const bool gatherSuccess = _engine->gatherCommandlineArguments();
if (!gatherSuccess)
return false;
LINFO(FileSys.absolutePath(configurationFilePath));
// create objects
_engine = new OpenSpaceEngine;
_engine->_renderEngine = new RenderEngine;
_engine->_interactionHandler = new InteractionHandler;
_engine->_configurationManager = new ghoul::Dictionary;
// Parse commandline arguments
std::vector<std::string> remainingArguments;
_engine->_commandlineParser->setCommandLine(argc, argv, &sgctArguments);
const bool executeSuccess = _engine->_commandlineParser->execute();
if (!executeSuccess)
return false;
// Find configuration
std::string configurationFilePath = commandlineArgumentPlaceholders.configurationName;
if (configurationFilePath.empty()) {
LDEBUG("Finding configuration");
const bool findConfigurationSuccess = OpenSpaceEngine::findConfiguration(configurationFilePath);
if (!findConfigurationSuccess) {
LFATAL("Could not find OpenSpace configuration file!");
return false;
}
}
LINFO("Configuration Path: '" << FileSys.absolutePath(configurationFilePath) << "'");
// Registering base path
LDEBUG("Registering base path");
if (!OpenSpaceEngine::registerBasePathFromConfigurationFile(configurationFilePath)) {
LFATAL("Could not register base path");
assert(false);
return false;
}
ghoul::Dictionary& configuration = *(_engine->_configurationManager);
// Loading configuration from disk
LDEBUG("Loading configuration from disk");
ghoul::Dictionary& configuration = _engine->configurationManager();
ghoul::lua::loadDictionaryFromFile(configurationFilePath, configuration);
if (configuration.hasKey(constants::openspaceengine::keyPaths)) {
ghoul::Dictionary pathsDictionary;
if (configuration.getValue(constants::openspaceengine::keyPaths, pathsDictionary))
OpenSpaceEngine::registerPathsFromDictionary(pathsDictionary);
ghoul::Dictionary pathsDictionary;
const bool success = configuration.getValueSafe(constants::openspaceengine::keyPaths, pathsDictionary);
if (success)
OpenSpaceEngine::registerPathsFromDictionary(pathsDictionary);
else {
LFATAL("Configuration file does not contain paths token '" << constants::openspaceengine::keyPaths << "'");
return false;
}
std::string sgctConfigurationPath = _sgctDefaultConfigFile;
if (configuration.hasKey(constants::openspaceengine::keyConfigSgct))
configuration.getValue(constants::openspaceengine::keyConfigSgct, sgctConfigurationPath);
sgctArguments.push_back(argv[0]);
sgctArguments.push_back("-config");
sgctArguments.push_back(absPath(sgctConfigurationPath));
for (int i = 1; i < argc; ++i)
sgctArguments.push_back(argv[i]);
// Determining SGCT configuration file
LDEBUG("Determining SGCT configuration file");
std::string sgctConfigurationPath = _sgctDefaultConfigFile;
configuration.getValueSafe(constants::openspaceengine::keyConfigSgct,
sgctConfigurationPath);
// Prepend the outgoing sgctArguments with the program name
// as well as the configuration file that sgct is supposed to use
sgctArguments.insert(sgctArguments.begin(), argv[0]);
sgctArguments.insert(sgctArguments.begin() + 1, _sgctConfigArgumentCommand);
sgctArguments.insert(sgctArguments.begin() + 2, absPath(sgctConfigurationPath));
return true;
}
void OpenSpaceEngine::destroy()
@@ -230,14 +291,25 @@ bool OpenSpaceEngine::initialize()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLFWwindow* win = sgct::Engine::instance()->getActiveWindowPtr()->getWindowHandle();
glfwSwapBuffers(win);
//int samples = sqrt(sgct::Engine::instance()->getActiveWindowPtr()->getNumberOfAASamples());
//LDEBUG("samples: " << samples);
int x1, xSize, y1, ySize;
sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewportPixelCoords(x1, y1, xSize, ySize);
std::string sourceHeader = "";
sourceHeader += "#define SCREEN_WIDTH " + std::to_string(xSize) + "\n";
sourceHeader += "#define SCREEN_HEIGHT " + std::to_string(ySize) + "\n";
sourceHeader += "#define ABUFFER_SINGLE_LINKED " + std::to_string(ABUFFER_SINGLE_LINKED) + "\n";
sourceHeader += "#define ABUFFER_FIXED " + std::to_string(ABUFFER_FIXED) + "\n";
sourceHeader += "#define ABUFFER_DYNAMIC " + std::to_string(ABUFFER_DYNAMIC) + "\n";
sourceHeader += "#define ABUFFER_IMPLEMENTATION " + std::to_string(ABUFFER_IMPLEMENTATION) + "\n";
_shaderBuilder.createSourceFile(true);
_shaderBuilder.sourceFileHeader(sourceHeader);
// Register the filepaths from static function enables easy testing
// registerFilePaths();
_context.createContextFromGLContext();
// initialize the configurationmanager with the default configuration
//_configurationManager->loadConfiguration(absPath("${SCRIPTS}/DefaultConfig.lua"));
// Detect and log OpenCL and OpenGL versions and available devices
ghoul::systemcapabilities::SystemCapabilities::initialize();
SysCap.addComponent(new ghoul::systemcapabilities::CPUCapabilitiesComponent);
@@ -246,34 +318,48 @@ bool OpenSpaceEngine::initialize()
SysCap.detectCapabilities();
SysCap.logCapabilities();
std::string timeKernel;
OsEng.configurationManager().getValueSafe(constants::openspaceengine::keyConfigTimekernel, timeKernel);
// initialize OpenSpace helpers
Time::init();
SpiceManager::initialize();
Time::initialize(timeKernel);
Spice::init();
Spice::ref().loadDefaultKernels();
FactoryManager::initialize();
scriptEngine().initialize();
// Register Lua script functions
LDEBUG("Registering Lua libraries");
scriptEngine().addLibrary(SceneGraph::luaLibrary());
scriptEngine().addLibrary(Time::luaLibrary());
// Load scenegraph
SceneGraph* sceneGraph = new SceneGraph;
_renderEngine->setSceneGraph(sceneGraph);
if (!OsEng.configurationManager().hasValue<std::string>(
constants::openspaceengine::keyConfigScene)) {
LFATAL("Configuration needs to point to the scene file");
std::string sceneDescriptionPath;
bool success = OsEng.configurationManager().getValueSafe(
constants::openspaceengine::keyConfigScene, sceneDescriptionPath);
if (!success) {
LFATAL("The configuration does not contain a scene file under key '" <<
constants::openspaceengine::keyConfigScene << "'");
return false;
}
std::string sceneDescriptionPath;
bool success = _configurationManager->getValue(
constants::openspaceengine::keyConfigScene, sceneDescriptionPath);
if (!FileSys.fileExists(sceneDescriptionPath)) {
LFATAL("Could not find '" << sceneDescriptionPath << "'");
if (!FileSys.fileExists(sceneDescriptionPath)) {
LFATAL("Could not find scene description '" << sceneDescriptionPath << "'");
return false;
}
std::string scenePath;
success = _configurationManager->getValue(constants::openspaceengine::keyPathScene, scenePath);
success = _configurationManager->getValueSafe(
constants::openspaceengine::keyPathScene, scenePath);
if (!success) {
LFATAL("Could not find SCENEPATH key in configuration file");
LFATAL("Could not find key '" << constants::openspaceengine::keyPathScene <<
"' in configuration file '" << sceneDescriptionPath << "'");
return false;
}
@@ -281,7 +367,6 @@ bool OpenSpaceEngine::initialize()
_renderEngine->initialize();
sceneGraph->loadScene(sceneDescriptionPath, scenePath);
sceneGraph->initialize();
_renderEngine->setSceneGraph(sceneGraph);
#ifdef FLARE_ONLY
_flare = new Flare();
@@ -293,13 +378,42 @@ bool OpenSpaceEngine::initialize()
DeviceIdentifier::ref().scanDevices();
_engine->_interactionHandler->connectDevices();
// Run start up scripts
//using ghoul::Dictionary;
//using constants::openspaceengine::keyStartupScript;
ghoul::Dictionary scripts;
success = _engine->configurationManager().getValueSafe(
constants::openspaceengine::keyStartupScript, scripts);
if (success) {
for (size_t i = 0; i < scripts.size(); ++i) {
std::stringstream stream;
// Dictionary-size is 0-based; script numbers are 1-based
stream << (i + 1);
const std::string& key = stream.str();
const bool hasKey = scripts.hasKeyAndValue<std::string>(key);
if (!hasKey) {
LERROR("The startup scripts have to be declared in a simple array format");
break;
}
std::string scriptPath;
scripts.getValue(key, scriptPath);
std::string&& absoluteScriptPath = absPath(scriptPath);
_engine->scriptEngine().runScriptFile(absoluteScriptPath);
}
}
#ifdef OPENSPACE_VIDEO_EXPORT
LINFO("OpenSpace compiled with video export; press Print Screen to start/stop recording");
#endif
return true;
}
ghoul::Dictionary& OpenSpaceEngine::configurationManager()
{
// TODO custom assert (ticket #5)
assert(_configurationManager != nullptr);
assert(_configurationManager);
return *_configurationManager;
}
@@ -311,17 +425,31 @@ ghoul::opencl::CLContext& OpenSpaceEngine::clContext()
InteractionHandler& OpenSpaceEngine::interactionHandler()
{
// TODO custom assert (ticket #5)
assert(_configurationManager != nullptr);
assert(_interactionHandler);
return *_interactionHandler;
}
RenderEngine& OpenSpaceEngine::renderEngine()
{
// TODO custom assert (ticket #5)
assert(_configurationManager != nullptr);
assert(_renderEngine);
return *_renderEngine;
}
ScriptEngine& OpenSpaceEngine::scriptEngine()
{
// TODO custom assert (ticket #5)
assert(_scriptEngine);
return *_scriptEngine;
}
ShaderCreator& OpenSpaceEngine::shaderBuilder()
{
// TODO custom assert (ticket #5)
return _shaderBuilder;
}
bool OpenSpaceEngine::initializeGL()
{
return _renderEngine->initializeGL();
@@ -338,6 +466,8 @@ void OpenSpaceEngine::preSynchronization()
_interactionHandler->update(dt);
_interactionHandler->lockControls();
Time::ref().advanceTime(dt);
}
#ifdef FLARE_ONLY
_flare->preSync();
@@ -366,6 +496,17 @@ void OpenSpaceEngine::postDraw()
if (sgct::Engine::instance()->isMaster()) {
_interactionHandler->unlockControls();
}
#ifdef OPENSPACE_VIDEO_EXPORT
float speed = 0.01;
glm::vec3 euler(0.0, speed, 0.0);
glm::quat rot = glm::quat(euler);
glm::vec3 euler2(0.0, -speed, 0.0);
glm::quat rot2 = glm::quat(euler2);
_interactionHandler->orbit(rot);
_interactionHandler->rotate(rot2);
if(_doVideoExport)
sgct::Engine::instance()->takeScreenshot();
#endif
#ifdef FLARE_ONLY
_flare->postDraw();
#endif
@@ -376,6 +517,12 @@ void OpenSpaceEngine::keyboardCallback(int key, int action)
if (sgct::Engine::instance()->isMaster()) {
_interactionHandler->keyboardCallback(key, action);
}
#ifdef OPENSPACE_VIDEO_EXPORT
// LDEBUG("key: " << key);
// LDEBUG("SGCT_KEY_PRINT_SCREEN: " << SGCT_KEY_PRINT_SCREEN);
if(action == SGCT_PRESS && key == SGCT_KEY_PRINT_SCREEN)
_doVideoExport = !_doVideoExport;
#endif
#ifdef FLARE_ONLY
_flare->keyboard(key, action);
#endif
@@ -431,4 +578,24 @@ void OpenSpaceEngine::decode()
#endif
}
void OpenSpaceEngine::externalControlCallback(const char* receivedChars,
int size, int clientId)
{
if (size == 0)
return;
// The first byte determines the type of message
const char type = receivedChars[0];
switch (type) {
case '0': // LuaScript
{
std::string script = std::string(receivedChars + 1);
LINFO("Received Lua Script: '" << script << "'");
_scriptEngine->runScript(script);
}
}
}
} // namespace openspace

View File

@@ -2,6 +2,7 @@
* Author: Victor Sand (victor.sand@gmail.com)
*
*/
//#include <ghoul/opengl/ghoul_gl.h>
#include <openspace/flare/CLProgram.h>
#include <openspace/flare/CLManager.h>
@@ -248,14 +249,13 @@ bool CLProgram::ReleaseBuffer(unsigned int _argNr) {
bool CLProgram::PrepareProgram() {
//ghoulFinishGL();
/*
#ifdef __APPLE__
//#ifdef __APPLE__
//glFlushRenderAPPLE();
glFinish();
// glFinish();
//glFlush();
#else
*/
//#else
glFinish();
// Let OpenCL take control of the shared GL textures
@@ -341,15 +341,13 @@ bool CLProgram::FinishProgram() {
LERROR("Failed to finish program");
return false;
}
/*
#else
error_ = clFinish(clManager_->commandQueues_[CLManager::EXECUTE]);
if (!clManager_->CheckSuccess(error_, "FinishProgram, clFinish")) {
ERROR("Failed to finish program");
return false;
}
#endif
*/
//#else
//error_ = clFinish(clManager_->commandQueues_[CLManager::EXECUTE]);
//if (!clManager_->CheckSuccess(error_, "FinishProgram, clFinish")) {
// ERROR("Failed to finish program");
// return false;
//}
//#endif
return true;
}

View File

@@ -27,13 +27,13 @@ using namespace osp;
Flare::Flare()
: Renderable(ghoul::Dictionary())
, _oldTime(0.f)
, _currentTime(0.f)
, _leftMouseButton(false)
, _currentMouseX(0)
, _currentMouseY(0)
, _lastMouseX(0)
, _lastMouseY(0)
, _oldTime(0.f)
, _currentTime(0.f)
{
setBoundingSphere(PowerScaledScalar::CreatePSS(sqrt(3.0f)));
}

View File

@@ -119,7 +119,7 @@ Camera * InteractionHandler::getCamera() const {
const psc InteractionHandler::getOrigin() const {
if(node_)
return node_->getWorldPosition();
return node_->worldPosition();
return psc();
}
@@ -155,7 +155,7 @@ void InteractionHandler::orbit(const glm::quat &rotation) {
// should be changed to something more dynamic =)
psc origin;
if(node_) {
origin = node_->getWorldPosition();
origin = node_->worldPosition();
}
psc relative_origin_coordinate = relative - origin;
@@ -173,19 +173,21 @@ void InteractionHandler::distance(const PowerScaledScalar &distance) {
lockControls();
psc relative = camera_->position();
psc origin;
if(node_) {
origin = node_->getWorldPosition();
}
const psc origin = (node_) ? node_->worldPosition() : psc();
psc relative_origin_coordinate = relative - origin;
glm::vec3 dir(relative_origin_coordinate.direction());
dir = dir * distance[0];
relative_origin_coordinate = dir;
const glm::vec3 dir(relative_origin_coordinate.direction());
glm:: vec3 newdir = dir * distance[0];
relative_origin_coordinate = newdir;
relative_origin_coordinate[3] = distance[1];
relative = relative + relative_origin_coordinate;
camera_->setPosition(relative);
relative_origin_coordinate = relative - origin;
newdir = relative_origin_coordinate.direction();
// update only if on the same side of the origin
if(glm::angle(newdir, dir) < 90.0f)
camera_->setPosition(relative);
unlockControls();
}
@@ -246,7 +248,7 @@ glm::vec3 InteractionHandler::mapToCamera(glm::vec3 trackballPos) {
//Get x,y,z axis vectors of current camera view
glm::vec3 currentViewYaxis = glm::normalize(camera_->lookUpVector());
psc viewDir = camera_->position() - node_->getWorldPosition();
psc viewDir = camera_->position() - node_->worldPosition();
glm::vec3 currentViewZaxis = glm::normalize(viewDir.vec3());
glm::vec3 currentViewXaxis = glm::normalize(glm::cross(currentViewYaxis, currentViewZaxis));
@@ -303,69 +305,63 @@ void InteractionHandler::keyboardCallback(int key, int action) {
// TODO package in script
const double speed = 2.75;
const double dt = getDt();
if (key == 'S') {
glm::vec3 euler(speed * dt* pow(10, 17), 0.0, 0.0);
glm::quat rot = glm::quat(euler);
orbit(rot);
}
if (key == 'W') {
glm::vec3 euler(-speed * dt* pow(10, 17), 0.0, 0.0);
glm::quat rot = glm::quat(euler);
orbit(rot);
}
if (key == 'A') {
glm::vec3 euler(0.0, -speed * dt, 0.0);
glm::quat rot = glm::quat(euler);
orbit(rot);
}
if (key == 'D') {
glm::vec3 euler(0.0, speed * dt, 0.0);
glm::quat rot = glm::quat(euler);
orbit(rot);
}
if (key == 262) {
glm::vec3 euler(0.0, speed * dt, 0.0);
glm::quat rot = glm::quat(euler);
rotate(rot);
}
if (key == 263) {
glm::vec3 euler(0.0, -speed * dt, 0.0);
glm::quat rot = glm::quat(euler);
rotate(rot);
}
if (key == 264) {
glm::vec3 euler(speed * dt, 0.0, 0.0);
glm::quat rot = glm::quat(euler);
rotate(rot);
}
if (key == 265) {
glm::vec3 euler(-speed * dt, 0.0, 0.0);
glm::quat rot = glm::quat(euler);
rotate(rot);
}
if (key == 'R') {
PowerScaledScalar dist(-speed * dt, 0.0);
distance(dist);
}
if (key == 'F') {
PowerScaledScalar dist(speed * dt, 0.0);
distance(dist);
}
if (key == 'T') {
PowerScaledScalar dist(-speed * dt, 8.0);
distance(dist);
}
if (key == 'G') {
PowerScaledScalar dist(speed * dt, 8.0);
distance(dist);
}
if (key == 'Y') {
PowerScaledScalar dist(-speed * dt, 18.0);
distance(dist);
}
if (key == 'H') {
PowerScaledScalar dist(speed * dt, 18.0);
distance(dist);
if(action == SGCT_PRESS || action == SGCT_REPEAT) {
if (key == SGCT_KEY_S) {
glm::vec3 euler(speed * dt, 0.0, 0.0);
glm::quat rot = glm::quat(euler);
orbit(rot);
}
if (key == SGCT_KEY_W) {
glm::vec3 euler(-speed * dt, 0.0, 0.0);
glm::quat rot = glm::quat(euler);
orbit(rot);
}
if (key == SGCT_KEY_A) {
glm::vec3 euler(0.0, -speed * dt, 0.0);
glm::quat rot = glm::quat(euler);
orbit(rot);
}
if (key == SGCT_KEY_D) {
glm::vec3 euler(0.0, speed * dt, 0.0);
glm::quat rot = glm::quat(euler);
orbit(rot);
}
if (key == 262) {
glm::vec3 euler(0.0, speed * dt, 0.0);
glm::quat rot = glm::quat(euler);
rotate(rot);
}
if (key == 263) {
glm::vec3 euler(0.0, -speed * dt, 0.0);
glm::quat rot = glm::quat(euler);
rotate(rot);
}
if (key == 264) {
glm::vec3 euler(speed * dt, 0.0, 0.0);
glm::quat rot = glm::quat(euler);
rotate(rot);
}
if (key == 265) {
glm::vec3 euler(-speed * dt, 0.0, 0.0);
glm::quat rot = glm::quat(euler);
rotate(rot);
}
if (key == SGCT_KEY_R) {
PowerScaledScalar dist(-speed * dt, 0.0);
distance(dist);
}
if (key == SGCT_KEY_F) {
PowerScaledScalar dist(speed * dt, 0.0);
distance(dist);
}
if (key == SGCT_KEY_T) {
PowerScaledScalar dist(-speed * 100.0 * dt, 0.0);
distance(dist);
}
if (key == SGCT_KEY_G) {
PowerScaledScalar dist(speed * 100.0 * dt, 0.0);
distance(dist);
}
}
/*
if (key == '1') {
@@ -393,15 +389,23 @@ void InteractionHandler::keyboardCallback(int key, int action) {
getCamera()->setCameraDirection(glm::vec3(0.0, 0.0, -1.0));
}
*/
// std::pair <std::multimap<int,std::function<void(void)> >::iterator, std::multimap<int , std::function<void(void)> >::iterator> ret;
if(action == SGCT_PRESS) {
auto ret = _keyCallbacks.equal_range(key);
for (auto it=ret.first; it!=ret.second; ++it)
it->second();
}
}
void InteractionHandler::mouseButtonCallback(int key, int action) {
//if(mouseControl_ != nullptr) {
// mouseControl_->mouseButtonCallback(key,action);
//}
if (key == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
if (key == SGCT_MOUSE_BUTTON_LEFT && action == SGCT_PRESS)
_leftMouseButtonDown = true;
else if (key == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE) {
else if (key == SGCT_MOUSE_BUTTON_LEFT && action == SGCT_RELEASE) {
_leftMouseButtonDown = false;
_isMouseBeingPressedAndHeld = false;
}
@@ -420,7 +424,21 @@ void InteractionHandler::mouseScrollWheelCallback(int pos) {
//if(mouseControl_ != nullptr) {
// mouseControl_->mouseScrollCallback(pos);
//}
const double speed = 4.75;
const double dt = getDt();
if(pos < 0) {
PowerScaledScalar dist(speed * dt, 0.0);
distance(dist);
} else if(pos > 0) {
PowerScaledScalar dist(-speed * dt, 0.0);
distance(dist);
}
}
void InteractionHandler::addKeyCallback(int key, std::function<void(void)> f) {
//std::map<int, std::vector<std::function<void(void)> > > _keyCallbacks;
_keyCallbacks.insert(std::make_pair(key, f));
}
} // namespace openspace

View File

@@ -33,7 +33,7 @@
*/
namespace openspace {
Interface::Interface(OpenSpaceEngine* engine) : _engine(engine) {}
Interface::Interface(OpenSpaceEngine* ) {}
Interface::~Interface() {}
void Interface::callback(const char* receivedChars) {

View File

@@ -22,23 +22,20 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
// open space includes
#include <openspace/engine/openspaceengine.h>
#include <openspace/interface/interface.h>
// sgct includes
#include <sgct.h>
sgct::Engine* _sgctEngine;
openspace::Interface* _interface;
// function pointer declarations
void mainInitFunc(void);
void mainPreSyncFunc(void);
void mainPostSyncPreDrawFunc(void);
void mainRenderFunc(void);
void mainPostDrawFunc(void);
void mainInitFunc();
void mainPreSyncFunc();
void mainPostSyncPreDrawFunc();
void mainRenderFunc();
void mainPostDrawFunc();
void mainKeyboardCallback(int key, int action);
void mainMouseButtonCallback(int key, int action);
void mainMousePosCallback(double x, double y);
@@ -47,27 +44,30 @@ void mainEncodeFun();
void mainDecodeFun();
void mainExternalControlCallback(const char * receivedChars, int size, int clientId);
namespace {
const std::string _loggerCat = "main";
}
int main(int argc, char** argv)
{
// create the OpenSpace engine and get arguments for the sgct engine
std::vector<std::string> sgctArguments;
openspace::OpenSpaceEngine::create(argc, argv, sgctArguments);
const bool success = openspace::OpenSpaceEngine::create(argc, argv, sgctArguments);
if (!success)
return EXIT_FAILURE;
// create sgct engine c arguments
int newArgc = static_cast<int>(sgctArguments.size());
char** newArgv = new char* [newArgc];
for (int i = 0; i < newArgc; ++i) {
// newArgv[i] = new char[sgctArguments.at(i).length()];
// std::strcpy(newArgv[i], sgctArguments.at(i).c_str());
char** newArgv = new char*[newArgc];
for (int i = 0; i < newArgc; ++i)
newArgv[i] = const_cast<char*>(sgctArguments.at(i).c_str());
}
LDEBUG("Creating SGCT Engine");
_sgctEngine = new sgct::Engine(newArgc, newArgv);
// deallocate sgct c arguments
for (int i = 0; i < newArgc; ++i) {
// delete newArgv[i];
}
for (int i = 0; i < newArgc; ++i)
delete newArgv[i];
delete[] newArgv;
// Bind functions
@@ -87,11 +87,11 @@ int main(int argc, char** argv)
sgct::SharedData::instance()->setEncodeFunction(mainEncodeFun);
sgct::SharedData::instance()->setDecodeFunction(mainDecodeFun);
// init the interface which will handle callbacks from an external gui
_interface = new openspace::Interface(&OsEng);
// try to open a window
if (!_sgctEngine->init(sgct::Engine::OpenGL_4_3_Core_Profile)) {
LDEBUG("Initialize SGCT Engine");
const bool initSuccess = _sgctEngine->init(sgct::Engine::OpenGL_4_3_Core_Profile);
if (!initSuccess) {
LFATAL("Initializing failed");
// could not open a window, deallocates and exits
delete _sgctEngine;
openspace::OpenSpaceEngine::destroy();
@@ -99,47 +99,52 @@ int main(int argc, char** argv)
}
// Main loop
LDEBUG("Starting rendering loop");
_sgctEngine->render();
LDEBUG("Destroying OpenSpaceEngine");
openspace::OpenSpaceEngine::destroy();
// Clean up (de-allocate)
LDEBUG("Destroying SGCT Engine");
delete _sgctEngine;
// Exit program
exit(EXIT_SUCCESS);
exit(EXIT_SUCCESS);
}
void mainExternalControlCallback(const char* receivedChars, int size, int clientId)
{
if (_sgctEngine->isMaster())
_interface->callback(receivedChars);
}
void mainInitFunc(void)
void mainInitFunc()
{
OsEng.initialize();
OsEng.initializeGL();
}
void mainPreSyncFunc(void)
void mainPreSyncFunc()
{
OsEng.preSynchronization();
}
void mainPostSyncPreDrawFunc(void)
void mainPostSyncPreDrawFunc()
{
OsEng.postSynchronizationPreDraw();
}
void mainRenderFunc(void)
void mainRenderFunc()
{
OsEng.render();
}
void mainPostDrawFunc(void)
void mainPostDrawFunc()
{
OsEng.postDraw();
}
void mainExternalControlCallback(const char* receivedChars, int size, int clientId)
{
if (_sgctEngine->isMaster())
OsEng.externalControlCallback(receivedChars, size, clientId);
}
void mainKeyboardCallback(int key, int action)
{
if (_sgctEngine->isMaster())
@@ -159,11 +164,11 @@ void mainMousePosCallback(double x, double y)
OsEng.mousePositionCallback(static_cast<int>(x), static_cast<int>(y));
}
void mainMouseScrollCallback(double pos, double /*pos2*/)
void mainMouseScrollCallback(double posX, double posY)
{
// TODO use float instead
if (_sgctEngine->isMaster())
OsEng.mouseScrollWheelCallback(static_cast<int>(pos));
OsEng.mouseScrollWheelCallback(static_cast<int>(posY));
}
void mainEncodeFun()

View File

@@ -31,144 +31,167 @@ using std::numeric_limits;
namespace openspace {
namespace properties {
#define DEFAULT_FROM_LUA_LAMBDA(__TYPE__) \
[](lua_State * state, bool& success) -> __TYPE__ { \
__TYPE__ result; \
int number = 1; \
for (__TYPE__::size_type i = 0; i < __TYPE__::row_size(); ++i) { \
for (__TYPE__::size_type j = 0; j < __TYPE__::col_size(); ++j) { \
lua_getfield(state, -1, std::to_string(number).c_str()); \
if (lua_isnumber(state, -1) != 1) { \
success = false; \
return __TYPE__(0); \
} else { \
result[i][j] \
= static_cast<__TYPE__::value_type>(lua_tonumber(state, -1)); \
lua_pop(state, 1); \
++number; \
} \
} \
} \
success = true; \
return result; \
}
#define DEFAULT_TO_LUA_LAMBDA(__TYPE__) \
[](lua_State * state, __TYPE__ value) -> bool { \
lua_newtable(state); \
int number = 1; \
for (__TYPE__::size_type i = 0; i < __TYPE__::row_size(); ++i) { \
for (__TYPE__::size_type j = 0; j < __TYPE__::col_size(); ++j) { \
lua_pushnumber(state, static_cast<lua_Number>(value[i][j])); \
lua_setfield(state, -2, std::to_string(number).c_str()); \
++number; \
} \
} \
return true; \
}
REGISTER_NUMERICALPROPERTY_SOURCE(Mat2Property, glm::mat2x2, glm::mat2x2(0),
glm::mat2x2(numeric_limits<float>::lowest()),
glm::mat2x2(numeric_limits<float>::max()), glm::mat2x2(0.01f));
glm::mat2x2(numeric_limits<float>::lowest()),
glm::mat2x2(numeric_limits<float>::max()),
glm::mat2x2(0.01f),
DEFAULT_FROM_LUA_LAMBDA(glm::mat2x2),
DEFAULT_TO_LUA_LAMBDA(glm::mat2x2), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(Mat2x3Property, glm::mat2x3, glm::mat2x3(0),
glm::mat2x3(numeric_limits<float>::lowest()),
glm::mat2x3(numeric_limits<float>::max()), glm::mat2x3(0.01f));
glm::mat2x3(numeric_limits<float>::lowest()),
glm::mat2x3(numeric_limits<float>::max()),
glm::mat2x3(0.01f),
DEFAULT_FROM_LUA_LAMBDA(glm::mat2x3),
DEFAULT_TO_LUA_LAMBDA(glm::mat2x3), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(Mat2x4Property, glm::mat2x4, glm::mat2x4(0),
glm::mat2x4(numeric_limits<float>::lowest()),
glm::mat2x4(numeric_limits<float>::max()), glm::mat2x4(0.01f));
glm::mat2x4(numeric_limits<float>::lowest()),
glm::mat2x4(numeric_limits<float>::max()),
glm::mat2x4(0.01f),
DEFAULT_FROM_LUA_LAMBDA(glm::mat2x4),
DEFAULT_TO_LUA_LAMBDA(glm::mat2x4), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(Mat3x2Property, glm::mat3x2, glm::mat3x2(0),
glm::mat3x2(numeric_limits<float>::lowest()),
glm::mat3x2(numeric_limits<float>::max()), glm::mat3x2(0.01f));
glm::mat3x2(numeric_limits<float>::lowest()),
glm::mat3x2(numeric_limits<float>::max()),
glm::mat3x2(0.01f),
DEFAULT_FROM_LUA_LAMBDA(glm::mat3x2),
DEFAULT_TO_LUA_LAMBDA(glm::mat3x2), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(Mat3Property, glm::mat3x3, glm::mat3x3(0),
glm::mat3x3(numeric_limits<float>::lowest()),
glm::mat3x3(numeric_limits<float>::max()), glm::mat3x3(0.01f));
glm::mat3x3(numeric_limits<float>::lowest()),
glm::mat3x3(numeric_limits<float>::max()),
glm::mat3x3(0.01f),
DEFAULT_FROM_LUA_LAMBDA(glm::mat3x3),
DEFAULT_TO_LUA_LAMBDA(glm::mat3x3), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(Mat3x4Property, glm::mat3x4, glm::mat3x4(0),
glm::mat3x4(numeric_limits<float>::lowest()),
glm::mat3x4(numeric_limits<float>::max()), glm::mat3x4(0.01f));
glm::mat3x4(numeric_limits<float>::lowest()),
glm::mat3x4(numeric_limits<float>::max()),
glm::mat3x4(0.01f),
DEFAULT_FROM_LUA_LAMBDA(glm::mat3x4),
DEFAULT_TO_LUA_LAMBDA(glm::mat3x4), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(Mat4x2Property, glm::mat4x2, glm::mat4x2(0),
glm::mat4x2(numeric_limits<float>::lowest()),
glm::mat4x2(numeric_limits<float>::max()), glm::mat4x2(0.01f));
glm::mat4x2(numeric_limits<float>::lowest()),
glm::mat4x2(numeric_limits<float>::max()),
glm::mat4x2(0.01f),
DEFAULT_FROM_LUA_LAMBDA(glm::mat4x2),
DEFAULT_TO_LUA_LAMBDA(glm::mat4x2), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(Mat4x3Property, glm::mat4x3, glm::mat4x3(0),
glm::mat4x3(numeric_limits<float>::lowest()),
glm::mat4x3(numeric_limits<float>::max()), glm::mat4x3(0.01f));
glm::mat4x3(numeric_limits<float>::lowest()),
glm::mat4x3(numeric_limits<float>::max()),
glm::mat4x3(0.01f),
DEFAULT_FROM_LUA_LAMBDA(glm::mat4x3),
DEFAULT_TO_LUA_LAMBDA(glm::mat4x3), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(Mat4Property, glm::mat4x4, glm::mat4x4(0),
glm::mat4x4(numeric_limits<float>::lowest()),
glm::mat4x4(numeric_limits<float>::max()), glm::mat4x4(0.01f));
glm::mat4x4(numeric_limits<float>::lowest()),
glm::mat4x4(numeric_limits<float>::max()),
glm::mat4x4(0.01f),
DEFAULT_FROM_LUA_LAMBDA(glm::mat4x4),
DEFAULT_TO_LUA_LAMBDA(glm::mat4x4), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(DMat2Property, glm::dmat2x2, glm::dmat2x2(0),
glm::dmat2x2(numeric_limits<double>::lowest()),
glm::dmat2x2(numeric_limits<double>::max()), glm::dmat2x2(0.01));
glm::dmat2x2(numeric_limits<double>::lowest()),
glm::dmat2x2(numeric_limits<double>::max()),
glm::dmat2x2(0.01),
DEFAULT_FROM_LUA_LAMBDA(glm::dmat2x2),
DEFAULT_TO_LUA_LAMBDA(glm::dmat2x2), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(DMat2x3Property, glm::dmat2x3, glm::dmat2x3(0),
glm::dmat2x3(numeric_limits<double>::lowest()),
glm::dmat2x3(numeric_limits<double>::max()), glm::dmat2x3(0.01));
glm::dmat2x3(numeric_limits<double>::lowest()),
glm::dmat2x3(numeric_limits<double>::max()),
glm::dmat2x3(0.01),
DEFAULT_FROM_LUA_LAMBDA(glm::dmat2x3),
DEFAULT_TO_LUA_LAMBDA(glm::dmat2x3), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(DMat2x4Property, glm::dmat2x4, glm::dmat2x4(0),
glm::dmat2x4(numeric_limits<double>::lowest()),
glm::dmat2x4(numeric_limits<double>::max()), glm::dmat2x4(0.01));
glm::dmat2x4(numeric_limits<double>::lowest()),
glm::dmat2x4(numeric_limits<double>::max()),
glm::dmat2x4(0.01),
DEFAULT_FROM_LUA_LAMBDA(glm::dmat2x4),
DEFAULT_TO_LUA_LAMBDA(glm::dmat2x4), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(DMat3x2Property, glm::dmat3x2, glm::dmat3x2(0),
glm::dmat3x2(numeric_limits<double>::lowest()),
glm::dmat3x2(numeric_limits<double>::max()), glm::dmat3x2(0.01));
glm::dmat3x2(numeric_limits<double>::lowest()),
glm::dmat3x2(numeric_limits<double>::max()),
glm::dmat3x2(0.01),
DEFAULT_FROM_LUA_LAMBDA(glm::dmat3x2),
DEFAULT_TO_LUA_LAMBDA(glm::dmat3x2), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(DMat3Property, glm::dmat3x3, glm::dmat3x3(0),
glm::dmat3x3(numeric_limits<double>::lowest()),
glm::dmat3x3(numeric_limits<double>::max()), glm::dmat3x3(0.01));
glm::dmat3x3(numeric_limits<double>::lowest()),
glm::dmat3x3(numeric_limits<double>::max()),
glm::dmat3x3(0.01),
DEFAULT_FROM_LUA_LAMBDA(glm::dmat3x3),
DEFAULT_TO_LUA_LAMBDA(glm::dmat3x3), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(DMat3x4Property, glm::dmat3x4, glm::dmat3x4(0),
glm::dmat3x4(numeric_limits<double>::lowest()),
glm::dmat3x4(numeric_limits<double>::max()), glm::dmat3x4(0.01));
glm::dmat3x4(numeric_limits<double>::lowest()),
glm::dmat3x4(numeric_limits<double>::max()),
glm::dmat3x4(0.01),
DEFAULT_FROM_LUA_LAMBDA(glm::dmat3x4),
DEFAULT_TO_LUA_LAMBDA(glm::dmat3x4), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(DMat4x2Property, glm::dmat4x2, glm::dmat4x2(0),
glm::dmat4x2(numeric_limits<double>::lowest()),
glm::dmat4x2(numeric_limits<double>::max()), glm::dmat4x2(0.01));
glm::dmat4x2(numeric_limits<double>::lowest()),
glm::dmat4x2(numeric_limits<double>::max()),
glm::dmat4x2(0.01),
DEFAULT_FROM_LUA_LAMBDA(glm::dmat4x2),
DEFAULT_TO_LUA_LAMBDA(glm::dmat4x2), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(DMat4x3Property, glm::dmat4x3, glm::dmat4x3(0),
glm::dmat4x3(numeric_limits<double>::lowest()),
glm::dmat4x3(numeric_limits<double>::max()), glm::dmat4x3(0.01));
glm::dmat4x3(numeric_limits<double>::lowest()),
glm::dmat4x3(numeric_limits<double>::max()),
glm::dmat4x3(0.01),
DEFAULT_FROM_LUA_LAMBDA(glm::dmat4x3),
DEFAULT_TO_LUA_LAMBDA(glm::dmat4x3), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(DMat4Property, glm::dmat4x4, glm::dmat4x4(0),
glm::dmat4x4(numeric_limits<double>::lowest()),
glm::dmat4x4(numeric_limits<double>::max()), glm::dmat4x4(0.01));
glm::dmat4x4(numeric_limits<double>::lowest()),
glm::dmat4x4(numeric_limits<double>::max()),
glm::dmat4x4(0.01),
DEFAULT_FROM_LUA_LAMBDA(glm::dmat4x4),
DEFAULT_TO_LUA_LAMBDA(glm::dmat4x4), LUA_TTABLE);
//REGISTER_NUMERICALPROPERTY_SOURCE(Vec2Property, glm::vec2, glm::vec2(0),
// glm::vec2(numeric_limits<float>::lowest()), glm::vec2(numeric_limits<float>::max()),
// glm::vec2(0.01f));
//REGISTER_NUMERICALPROPERTY_SOURCE(Vec3Property, glm::vec3, glm::vec3(0),
// glm::vec3(numeric_limits<float>::lowest()), glm::vec3(numeric_limits<float>::max()),
// glm::vec3(0.01f));
//REGISTER_NUMERICALPROPERTY_SOURCE(Vec4Property, glm::vec4, glm::vec4(0),
// glm::vec4(numeric_limits<float>::lowest()), glm::vec4(numeric_limits<float>::max()),
// glm::vec4(0.01f));
//REGISTER_NUMERICALPROPERTY_SOURCE(DVec2Property, glm::dvec2, glm::dvec2(0),
// glm::dvec2(numeric_limits<double>::lowest()),
// glm::dvec2(numeric_limits<double>::max()), glm::dvec2(0.01));
//REGISTER_NUMERICALPROPERTY_SOURCE(DVec3Property, glm::dvec3, glm::dvec3(0),
// glm::dvec3(numeric_limits<double>::lowest()),
// glm::dvec3(numeric_limits<double>::max()), glm::dvec3(0.01));
//REGISTER_NUMERICALPROPERTY_SOURCE(DVec4Property, glm::dvec4, glm::dvec4(0),
// glm::dvec4(numeric_limits<double>::lowest()),
// glm::dvec4(numeric_limits<double>::max()), glm::dvec4(0.01));
//REGISTER_NUMERICALPROPERTY_SOURCE(IVec2Property, glm::ivec2, glm::ivec2(0),
// glm::ivec2(numeric_limits<int>::lowest()), glm::ivec2(numeric_limits<int>::max()),
// glm::ivec2(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(IVec3Property, glm::ivec3, glm::ivec3(0),
// glm::ivec3(numeric_limits<int>::lowest()), glm::ivec3(numeric_limits<int>::max()),
// glm::ivec3(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(IVec4Property, glm::ivec4, glm::ivec4(0),
// glm::ivec4(numeric_limits<int>::lowest()), glm::ivec4(numeric_limits<int>::max()),
// glm::ivec4(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(UVec2Property, glm::uvec2, glm::uvec2(0),
// glm::uvec2(numeric_limits<unsigned int>::lowest()),
// glm::uvec2(numeric_limits<unsigned int>::max()), glm::uvec2(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(UVec3Property, glm::uvec3, glm::uvec3(0),
// glm::uvec3(numeric_limits<unsigned int>::lowest()),
// glm::uvec3(numeric_limits<unsigned int>::max()), glm::uvec3(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(UVec4Property, glm::uvec4, glm::uvec4(0),
// glm::uvec4(numeric_limits<unsigned int>::lowest()),
// glm::uvec4(numeric_limits<unsigned int>::max()), glm::uvec4(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(CharProperty, char, char(0),
// numeric_limits<char>::min(), numeric_limits<char>::max(), char(1));
////REGISTER_NUMERICALPROPERTY_SOURCE(Char16Property, char16_t, char16_t(0),
//// numeric_limits<char16_t>::min(), numeric_limits<char16_t>::max(), char16_t(1));
////REGISTER_NUMERICALPROPERTY_SOURCE(Char32Property, char32_t, char32_t(0),
//// numeric_limits<char32_t>::min(), numeric_limits<char32_t>::max(), char32_t(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(WCharProperty, wchar_t, wchar_t(0),
// numeric_limits<wchar_t>::min(), numeric_limits<wchar_t>::max(), wchar_t(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(SignedCharProperty, signed char, signed char(0),
// numeric_limits<signed char>::min(), numeric_limits<signed char>::max(),
// signed char(0));
//REGISTER_NUMERICALPROPERTY_SOURCE(UCharProperty, unsigned char, unsigned char(0),
// numeric_limits<unsigned char>::min(), numeric_limits<unsigned char>::max(),
// unsigned char(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(ShortProperty, short, short(0),
// numeric_limits<short>::min(), numeric_limits<short>::max(), short(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(UShortProperty, unsigned short, unsigned short(0),
// numeric_limits<unsigned short>::min(), numeric_limits<unsigned short>::max(),
// unsigned short(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(IntProperty, int, int(0),
// numeric_limits<int>::min(), numeric_limits<int>::max(), int(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(UIntProperty, unsigned int, unsigned int(0),
// numeric_limits<unsigned int>::min(), numeric_limits<unsigned int>::max(),
// unsigned int(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(LongProperty, long, long(0),
// numeric_limits<long>::min(), numeric_limits<long>::max(), long(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(ULongProperty, unsigned long, unsigned long(0),
// numeric_limits<unsigned long>::min(), numeric_limits<unsigned long>::max(),
// unsigned long(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(LongLongProperty, long long, long long(0),
// numeric_limits<long long>::min(), numeric_limits<long long>::max(), long long(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(ULongLongProperty, unsigned long long,
// unsigned long long(1), numeric_limits<unsigned long long>::min(),
// numeric_limits<unsigned long long>::max(), unsigned long long(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(FloatProperty, float, 0.f,
// numeric_limits<float>::min(), numeric_limits<float>::max(), 0.01f);
//REGISTER_NUMERICALPROPERTY_SOURCE(DoubleProperty, double, 0.0,
// numeric_limits<double>::min(), numeric_limits<double>::max(), 0.01);
//REGISTER_NUMERICALPROPERTY_SOURCE(LongDoubleProperty, long double, long double(0),
// numeric_limits<long double>::min(), numeric_limits<long double>::max(),
// long double(0.01f));
} // namespace properties
} // namespace openspace
} // namespace properties
} // namespace openspace

View File

@@ -1,26 +0,0 @@
/*****************************************************************************************
* *
* 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 "openspace/properties/numericalproperty.h"

View File

@@ -24,13 +24,19 @@
#include "openspace/properties/property.h"
#include <ghoul/lua/ghoul_lua.h>
namespace openspace {
namespace properties {
namespace {
const std::string _loggerCat = "Property";
const std::string _metaDataKeyGuiName = "guiName";
const std::string _metaDataKeyGroup = "group";
const std::string _metaDataKeyVisible = "isVisible";
const std::string _metaDataKeyReadOnly = "isReadOnly";
const std::string _metaDataKeyViewPrefix = "view.";
}
const std::string Property::ViewOptions::Color = "color";
@@ -41,9 +47,14 @@ const std::string Property::ViewOptions::PowerScaledScalar = "powerScaledScalar"
Property::Property(std::string identifier, std::string guiName)
: _identifier(std::move(identifier))
, _guiName(std::move(guiName))
{
if (_identifier.empty())
LWARNING("Property identifier is empty");
if (guiName.empty())
LWARNING("Property GUI name is empty");
setVisible(true);
_metaData.setValue(_metaDataKeyGuiName, std::move(guiName));
}
Property::~Property() {}
@@ -56,14 +67,28 @@ boost::any Property::get() const {
return boost::any();
}
bool Property::getLua(lua_State* state) const {
return true;
}
void Property::set(boost::any value) {}
bool Property::setLua(lua_State* state) {
return true;
}
const std::type_info& Property::type() const {
return typeid(void);
}
int Property::typeLua() const {
return LUA_TNONE;
}
const std::string& Property::guiName() const {
return _guiName;
std::string result;
_metaData.getValueSafe(_metaDataKeyGuiName, result);
return std::move(result);
}
void Property::setGroupIdentifier(std::string groupId) {
@@ -71,8 +96,8 @@ void Property::setGroupIdentifier(std::string groupId) {
}
std::string Property::groupIdentifier() const {
std::string result = "";
_metaData.getValue(_metaDataKeyGroup, result);
std::string result;
_metaData.getValueSafe(_metaDataKeyGroup, result);
return std::move(result);
}
@@ -80,30 +105,12 @@ void Property::setVisible(bool state) {
_metaData.setValue(_metaDataKeyVisible, state);
}
bool Property::isVisible() const {
bool result = false;
_metaData.getValue(_metaDataKeyVisible, result);
return result;
}
void Property::setReadOnly(bool state) {
_metaData.setValue(_metaDataKeyReadOnly, state);
}
bool Property::isReadOnly() const {
bool result = false;
_metaData.getValue(_metaDataKeyReadOnly, result);
return result;
}
void Property::setViewOption(std::string option, bool value) {
_metaData.setValue("view." + option, value, true);
}
bool Property::viewOption(const std::string& option) const {
bool result = false;
_metaData.getValue("view." + option, result);
return result;
_metaData.setValue(_metaDataKeyViewPrefix + option, value, true);
}
const ghoul::Dictionary& Property::metaData() const {
@@ -111,7 +118,7 @@ const ghoul::Dictionary& Property::metaData() const {
}
void Property::onChange(std::function<void()> callback) {
_onChangeCallbacks.push_back(std::move(callback));
_onChangeCallback = std::move(callback);
}
@@ -125,5 +132,10 @@ void Property::setPropertyOwner(PropertyOwner* owner)
_owner = owner;
}
void Property::notifyListener() {
if (_onChangeCallback)
_onChangeCallback();
}
} // namespace properties
} // namespace openspace

View File

@@ -1,26 +0,0 @@
/*****************************************************************************************
* *
* 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 "openspace/properties/propertydelegate.h"

View File

@@ -37,16 +37,26 @@ bool propertyLess(Property* lhs, Property* rhs)
{
return lhs->identifier() < rhs->identifier();
}
bool subOwnerLess(PropertyOwner* lhs, PropertyOwner* rhs) {
return lhs->name() < rhs->name();
}
}
PropertyOwner::PropertyOwner()
: _name("")
{
}
PropertyOwner::~PropertyOwner()
{
for (Property* p : _properties)
delete p;
_properties.clear();
for (PropertyOwner* s : _subOwners)
delete s;
_subOwners.clear();
}
const std::vector<Property*>& PropertyOwner::properties() const
@@ -58,23 +68,76 @@ Property* PropertyOwner::property(const std::string& id) const
{
assert(std::is_sorted(_properties.begin(), _properties.end(), propertyLess));
// As the _properties list is sorted, just finding the lower bound is sufficient
std::vector<Property*>::const_iterator it
= std::lower_bound(_properties.begin(), _properties.end(), id,
[](Property* prop, const std::string& str) {
return prop->identifier() < str;
});
if (it == _properties.end() || (*it)->identifier() != id)
if (it == _properties.end() || (*it)->identifier() != id) {
// if we do not own the searched property, it must consist of a concatenated
// name and we can delegate it to a subowner
const size_t ownerSeparator = id.find(URISeparator);
if (ownerSeparator == std::string::npos) {
// if we do not own the property and there is no separator, it does not exist
LERROR("The identifier '" << id << "' did not exist in PropertyOwner '" <<
name() << "'");
return nullptr;
}
else {
const std::string ownerName = id.substr(0, ownerSeparator);
const std::string propertyName = id.substr(ownerSeparator + 1);
PropertyOwner* owner = subOwner(ownerName);
if (owner == nullptr) {
LERROR("Sub PropertyOwner '" << owner
<< "' did not exist for PropertyOwner '" << name() << "'");
return nullptr;
}
else {
// Recurse into the subOwner
return owner->property(propertyName);
}
}
}
else
return *it;
}
bool PropertyOwner::hasProperty(const std::string& id) const {
return property(id) != nullptr;
}
const std::vector<PropertyOwner*>& PropertyOwner::subOwners() const {
return _subOwners;
}
PropertyOwner* PropertyOwner::subOwner(const std::string& name) const {
assert(std::is_sorted(_subOwners.begin(), _subOwners.end(), subOwnerLess));
// As the _subOwners list is sorted, getting the lower bound is sufficient
std::vector<PropertyOwner*>::const_iterator it
= std::lower_bound(_subOwners.begin(), _subOwners.end(), name,
[](PropertyOwner* owner, const std::string& str) {
return owner->name() < str;
});
if (it == _subOwners.end() || (*it)->name() != name)
return nullptr;
else
return *it;
}
bool PropertyOwner::hasSubOwner(const std::string& name) const {
return subOwner(name) != nullptr;
}
void PropertyOwner::setPropertyGroupName(std::string groupID, std::string name)
{
_groupNames[std::move(groupID)] = std::move(name);
}
const std::string& PropertyOwner::propertyGroupName(const std::string& groupID) const
{
auto it = _groupNames.find(groupID);
@@ -88,6 +151,7 @@ void PropertyOwner::addProperty(Property* prop)
{
assert(prop != nullptr);
assert(std::is_sorted(_properties.begin(), _properties.end(), propertyLess));
assert(std::is_sorted(_subOwners.begin(), _subOwners.end(), subOwnerLess));
if (prop->identifier().empty()) {
LERROR("No property identifier specified");
@@ -95,6 +159,7 @@ void PropertyOwner::addProperty(Property* prop)
}
// See if we can find the identifier of the property to add in the properties list
// The _properties list is sorted, so getting the lower bound is sufficient
std::vector<Property*>::iterator it
= std::lower_bound(_properties.begin(), _properties.end(), prop->identifier(),
[](Property* prop, const std::string& str) {
@@ -104,12 +169,22 @@ void PropertyOwner::addProperty(Property* prop)
// If we found the property identifier, we need to bail out
if (it != _properties.end() && (*it)->identifier() == prop->identifier()) {
LERROR("Property identifier '" << prop->identifier()
<< "' already present in PropertyOwner");
<< "' already present in PropertyOwner '"
<< name() << "'");
return;
} else {
// Otherwise we have found the correct position to add it in
_properties.insert(it, prop);
prop->setPropertyOwner(this);
// Otherwise we still have to look if there is a PropertyOwner with the same name
const bool hasOwner = hasSubOwner(prop->identifier());
if (hasOwner) {
LERROR("Property identifier '" << prop->identifier() << "' already names a"
<< "registed PropertyOwner");
return;
}
else {
// now have found the correct position to add it in
_properties.insert(it, prop);
prop->setPropertyOwner(this);
}
}
}
@@ -117,6 +192,48 @@ void PropertyOwner::addProperty(Property& prop)
{
addProperty(&prop);
}
void PropertyOwner::addPropertySubOwner(openspace::properties::PropertyOwner* owner) {
assert(owner != nullptr);
assert(std::is_sorted(_properties.begin(), _properties.end(), propertyLess));
assert(std::is_sorted(_subOwners.begin(), _subOwners.end(), subOwnerLess));
if (owner->name().empty()) {
LERROR("PropertyOwner did not have a name");
return;
}
// See if we can find the name of the propertyowner to add using the lower bound
std::vector<PropertyOwner*>::iterator it
= std::lower_bound(_subOwners.begin(), _subOwners.end(), owner->name(),
[](PropertyOwner* owner, const std::string& str) {
return owner->name() < str;
});
// If we found the propertyowner's name, we need to bail out
if (it != _subOwners.end() && (*it)->name() == owner->name()) {
LERROR("PropertyOwner '" << owner->name()
<< "' already present in PropertyOwner '" << name() << "'");
return;
} else {
// We still need to check if the PropertyOwners name is used in a Property
const bool hasProp = hasProperty(owner->name());
if (hasProp) {
LERROR("PropertyOwner '" << owner->name() << "'s name already names a "
<< "Property");
return;
}
else {
// Otherwise we have found the correct position to add it in
_subOwners.insert(it, owner);
}
}
}
void PropertyOwner::addPropertySubOwner(openspace::properties::PropertyOwner& owner) {
addPropertySubOwner(&owner);
}
void PropertyOwner::removeProperty(Property* prop)
{
@@ -142,6 +259,28 @@ void PropertyOwner::removeProperty(Property& prop)
{
removeProperty(&prop);
}
void PropertyOwner::removePropertySubOwner(openspace::properties::PropertyOwner* owner) {
assert(owner != nullptr);
// See if we can find the name of the propertyowner to add
std::vector<PropertyOwner*>::iterator it
= std::lower_bound(_subOwners.begin(), _subOwners.end(), owner->name(),
[](PropertyOwner* owner, const std::string& str) {
return owner->name() < str;
});
// If we found the propertyowner, we can delete it
if (it != _subOwners.end() && (*it)->name() == owner->name()) {
_subOwners.erase(it);
} else
LERROR("PropertyOwner with name '" << owner->name()
<< "' not found for removal.");
}
void PropertyOwner::removePropertySubOwner(openspace::properties::PropertyOwner& owner) {
removePropertySubOwner(&owner);
}
void PropertyOwner::setName(std::string name)
{

View File

@@ -24,6 +24,8 @@
#include "openspace/properties/scalarproperty.h"
#include <ghoul/lua/ghoul_lua.h>
#include <limits>
using std::numeric_limits;
@@ -31,52 +33,137 @@ using std::numeric_limits;
namespace openspace {
namespace properties {
#define DEFAULT_FROM_LUA_LAMBDA(TYPE, DEFAULT_VALUE) \
[](lua_State* state, bool& success) -> TYPE { \
success = (lua_isnumber(state, -1) == 1); \
if (success) \
return static_cast<TYPE>(lua_tonumber(state, -1)); \
else \
return DEFAULT_VALUE; \
}
#define DEFAULT_TO_LUA_LAMBDA(TYPE) \
[](lua_State* state, TYPE value) -> bool { \
lua_pushnumber(state, static_cast<lua_Number>(value)); \
return true; \
}
// char16_t and char32_t are not supported on Visual Studio 2013 and are defined to
// be equal to unsigned short and unsigned int which causes a compile error
REGISTER_TEMPLATEPROPERTY_SOURCE(BoolProperty, bool, false);
REGISTER_TEMPLATEPROPERTY_SOURCE(BoolProperty, bool, false,
[](lua_State* state, bool& success) -> bool {
success = (lua_isboolean(state, -1) == 1);
if (success)
return lua_toboolean(state, -1) == 1;
else
return false;
},
[](lua_State* state, bool value) -> bool {
lua_pushboolean(state, value);
return true;
},
LUA_TBOOLEAN
);
REGISTER_NUMERICALPROPERTY_SOURCE(CharProperty, char, char(0),
numeric_limits<char>::lowest(), numeric_limits<char>::max(), char(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(Char16Property, char16_t, char16_t(0),
// numeric_limits<char16_t>::lowest(), numeric_limits<char16_t>::max(), char16_t(1));
//REGISTER_NUMERICALPROPERTY_SOURCE(Char32Property, char32_t, char32_t(0),
// numeric_limits<char32_t>::lowest(), numeric_limits<char32_t>::max(), char32_t(1));
REGISTER_NUMERICALPROPERTY_SOURCE(WCharProperty, wchar_t, wchar_t(0),
numeric_limits<wchar_t>::lowest(), numeric_limits<wchar_t>::max(), wchar_t(1));
REGISTER_NUMERICALPROPERTY_SOURCE(SignedCharProperty, signed char, (signed char)(0),
numeric_limits<signed char>::lowest(), numeric_limits<signed char>::max(),
(signed char)0);
REGISTER_NUMERICALPROPERTY_SOURCE(UCharProperty, unsigned char, (unsigned char)0,
numeric_limits<unsigned char>::lowest(), numeric_limits<unsigned char>::max(),
(unsigned char)1);
REGISTER_NUMERICALPROPERTY_SOURCE(ShortProperty, short, short(0),
numeric_limits<short>::lowest(), numeric_limits<short>::max(), short(1));
REGISTER_NUMERICALPROPERTY_SOURCE(UShortProperty, unsigned short, (unsigned short)(0),
numeric_limits<unsigned short>::lowest(), numeric_limits<unsigned short>::max(),
(unsigned short)1);
REGISTER_NUMERICALPROPERTY_SOURCE(IntProperty, int, int(0),
numeric_limits<int>::lowest(), numeric_limits<int>::max(), int(1));
REGISTER_NUMERICALPROPERTY_SOURCE(UIntProperty, unsigned int, (unsigned int)0,
numeric_limits<unsigned int>::lowest(), numeric_limits<unsigned int>::max(),
(unsigned int)1);
REGISTER_NUMERICALPROPERTY_SOURCE(LongProperty, long, long(0),
numeric_limits<long>::lowest(), numeric_limits<long>::max(), long(1));
REGISTER_NUMERICALPROPERTY_SOURCE(ULongProperty, unsigned long, (unsigned long)0,
numeric_limits<unsigned long>::lowest(), numeric_limits<unsigned long>::max(),
(unsigned long)1);
REGISTER_NUMERICALPROPERTY_SOURCE(LongLongProperty, long long, (long long)0,
numeric_limits<long long>::lowest(), numeric_limits<long long>::max(), (long long)1);
REGISTER_NUMERICALPROPERTY_SOURCE(ULongLongProperty, unsigned long long,
(unsigned long long)1, numeric_limits<unsigned long long>::lowest(),
numeric_limits<unsigned long long>::max(), (unsigned long long)1);
REGISTER_NUMERICALPROPERTY_SOURCE(FloatProperty, float, 0.f,
numeric_limits<float>::lowest(), numeric_limits<float>::max(), 0.01f);
REGISTER_NUMERICALPROPERTY_SOURCE(DoubleProperty, double, 0.0,
numeric_limits<double>::lowest(), numeric_limits<double>::max(), 0.01);
REGISTER_NUMERICALPROPERTY_SOURCE(LongDoubleProperty, long double, (long double)0,
numeric_limits<long double>::lowest(), numeric_limits<long double>::max(),
(long double)0.01f);
numeric_limits<char>::lowest(),
numeric_limits<char>::max(), char(1),
DEFAULT_FROM_LUA_LAMBDA(char, char(0)),
DEFAULT_TO_LUA_LAMBDA(char), LUA_TNUMBER);
} // namespace properties
// REGISTER_NUMERICALPROPERTY_SOURCE(Char16Property, char16_t, char16_t(0),
// numeric_limits<char16_t>::lowest(), numeric_limits<char16_t>::max(), char16_t(1));
// REGISTER_NUMERICALPROPERTY_SOURCE(Char32Property, char32_t, char32_t(0),
// numeric_limits<char32_t>::lowest(), numeric_limits<char32_t>::max(), char32_t(1));
REGISTER_NUMERICALPROPERTY_SOURCE(WCharProperty, wchar_t, wchar_t(0),
numeric_limits<wchar_t>::lowest(),
numeric_limits<wchar_t>::max(), wchar_t(1),
DEFAULT_FROM_LUA_LAMBDA(wchar_t, wchar_t(0)),
DEFAULT_TO_LUA_LAMBDA(wchar_t), LUA_TNUMBER);
REGISTER_NUMERICALPROPERTY_SOURCE(SignedCharProperty, signed char, (signed char)(0),
numeric_limits<signed char>::lowest(),
numeric_limits<signed char>::max(), (signed char)0,
DEFAULT_FROM_LUA_LAMBDA(signed char, (signed char)(0)),
DEFAULT_TO_LUA_LAMBDA(signed char), LUA_TNUMBER);
REGISTER_NUMERICALPROPERTY_SOURCE(UCharProperty, unsigned char, (unsigned char)0,
numeric_limits<unsigned char>::lowest(),
numeric_limits<unsigned char>::max(), (unsigned char)1,
DEFAULT_FROM_LUA_LAMBDA(unsigned char,
(unsigned char)(0)),
DEFAULT_TO_LUA_LAMBDA(unsigned char), LUA_TNUMBER);
REGISTER_NUMERICALPROPERTY_SOURCE(ShortProperty, short, short(0),
numeric_limits<short>::lowest(),
numeric_limits<short>::max(), short(1),
DEFAULT_FROM_LUA_LAMBDA(short, short(0)),
DEFAULT_TO_LUA_LAMBDA(short), LUA_TNUMBER);
REGISTER_NUMERICALPROPERTY_SOURCE(
UShortProperty, unsigned short, (unsigned short)(0),
numeric_limits<unsigned short>::lowest(), numeric_limits<unsigned short>::max(),
(unsigned short)1, DEFAULT_FROM_LUA_LAMBDA(unsigned short, (unsigned short)(0)),
DEFAULT_TO_LUA_LAMBDA(unsigned short), LUA_TNUMBER);
REGISTER_NUMERICALPROPERTY_SOURCE(IntProperty, int, int(0), numeric_limits<int>::lowest(),
numeric_limits<int>::max(), int(1),
DEFAULT_FROM_LUA_LAMBDA(int, int(0)),
DEFAULT_TO_LUA_LAMBDA(int), LUA_TNUMBER);
REGISTER_NUMERICALPROPERTY_SOURCE(UIntProperty, unsigned int, (unsigned int)0,
numeric_limits<unsigned int>::lowest(),
numeric_limits<unsigned int>::max(), (unsigned int)1,
DEFAULT_FROM_LUA_LAMBDA(unsigned int,
(unsigned int)(0)),
DEFAULT_TO_LUA_LAMBDA(unsigned int), LUA_TNUMBER);
REGISTER_NUMERICALPROPERTY_SOURCE(LongProperty, long, long(0),
numeric_limits<long>::lowest(),
numeric_limits<long>::max(), long(1),
DEFAULT_FROM_LUA_LAMBDA(long, long(0)),
DEFAULT_TO_LUA_LAMBDA(long), LUA_TNUMBER);
REGISTER_NUMERICALPROPERTY_SOURCE(ULongProperty, unsigned long, (unsigned long)0,
numeric_limits<unsigned long>::lowest(),
numeric_limits<unsigned long>::max(), (unsigned long)1,
DEFAULT_FROM_LUA_LAMBDA(unsigned long,
(unsigned long)(0)),
DEFAULT_TO_LUA_LAMBDA(unsigned long), LUA_TNUMBER);
REGISTER_NUMERICALPROPERTY_SOURCE(LongLongProperty, long long, (long long)0,
numeric_limits<long long>::lowest(),
numeric_limits<long long>::max(), (long long)1,
DEFAULT_FROM_LUA_LAMBDA(long long, (long long)(0)),
DEFAULT_TO_LUA_LAMBDA(long long), LUA_TNUMBER);
REGISTER_NUMERICALPROPERTY_SOURCE(
ULongLongProperty, unsigned long long, (unsigned long long)1,
numeric_limits<unsigned long long>::lowest(),
numeric_limits<unsigned long long>::max(), (unsigned long long)1,
DEFAULT_FROM_LUA_LAMBDA(unsigned long long, (unsigned long long)(0)),
DEFAULT_TO_LUA_LAMBDA(unsigned long long), LUA_TNUMBER);
REGISTER_NUMERICALPROPERTY_SOURCE(FloatProperty, float, 0.f,
numeric_limits<float>::lowest(),
numeric_limits<float>::max(), 0.01f,
DEFAULT_FROM_LUA_LAMBDA(float, float(0)),
DEFAULT_TO_LUA_LAMBDA(float), LUA_TNUMBER);
REGISTER_NUMERICALPROPERTY_SOURCE(DoubleProperty, double, 0.0,
numeric_limits<double>::lowest(),
numeric_limits<double>::max(), 0.01,
DEFAULT_FROM_LUA_LAMBDA(double, double(0)),
DEFAULT_TO_LUA_LAMBDA(double), LUA_TNUMBER);
REGISTER_NUMERICALPROPERTY_SOURCE(LongDoubleProperty, long double, (long double)0,
numeric_limits<long double>::lowest(),
numeric_limits<long double>::max(), (long double)0.01f,
DEFAULT_FROM_LUA_LAMBDA(long double, (long double)(0)),
DEFAULT_TO_LUA_LAMBDA(long double), LUA_TNUMBER);
} // namespace properties
} // namespace openspace

View File

@@ -24,38 +24,25 @@
#include <openspace/properties/stringproperty.h>
#include <ghoul/lua/ghoul_lua.h>
namespace openspace {
namespace properties {
StringProperty::StringProperty(std::string identifier, std::string guiName)
: StringProperty(
std::move(identifier), std::move(guiName),
PropertyDelegate<TemplateProperty<std::string>>::defaultValue<std::string>())
{
}
StringProperty::StringProperty(std::string identifier, std::string guiName,
std::string value)
: TemplateProperty(std::move(identifier), std::move(guiName), std::move(value))
{}
template <>
std::string PropertyDelegate<TemplateProperty<std::string>>::className() {
return "StringProperty";
}
template <>
template <>
std::string PropertyDelegate<TemplateProperty<std::string>>::defaultValue<std::string>() {
return "";
}
//REGISTER_TEMPLATEPROPERTY_SOURCE(StringProperty, std::string, "");
//
//std::string openspace::properties::StringProperty::className() const {
// return "StringProperty";
//}
REGISTER_TEMPLATEPROPERTY_SOURCE(StringProperty, std::string, "",
[](lua_State* state, bool& success) -> std::string {
success = lua_isstring(state, -1) == 1;
if (success)
return lua_tostring(state, -1);
else
return "";
},
[](lua_State* state, std::string value) -> bool {
lua_pushstring(state, value.c_str());
return true;
},
LUA_TSTRING
);
} // namespace properties
} // namespace openspace

View File

@@ -24,6 +24,10 @@
#include "openspace/properties/vectorproperty.h"
#include <ghoul/lua/ghoul_lua.h>
#include <glm/glm.hpp>
#include <limits>
using std::numeric_limits;
@@ -31,46 +35,150 @@ using std::numeric_limits;
namespace openspace {
namespace properties {
REGISTER_TEMPLATEPROPERTY_SOURCE(BVec2Property, glm::bvec2, glm::bvec2(false));
REGISTER_TEMPLATEPROPERTY_SOURCE(BVec3Property, glm::bvec3, glm::bvec3(false));
REGISTER_TEMPLATEPROPERTY_SOURCE(BVec4Property, glm::bvec4, glm::bvec4(false));
#define DEFAULT_FROM_LUA_LAMBDA(__TYPE__, __CONVFUNC__, __TESTFUNC__) \
[](lua_State * state, bool& success) -> __TYPE__ { \
__TYPE__ result; \
int number = 1; \
for (__TYPE__::size_type i = 0; i < result.length(); ++i) { \
lua_getfield(state, -1, std::to_string(number).c_str()); \
if (__TESTFUNC__(state, -1) != 1) { \
success = false; \
return __TYPE__(0); \
} else { \
result[i] = static_cast<__TYPE__::value_type>(__CONVFUNC__(state, -1)); \
lua_pop(state, 1); \
++number; \
} \
} \
success = true; \
return result; \
}
#define DEFAULT_TO_LUA_LAMBDA(__TYPE__) \
[](lua_State * state, __TYPE__ value) -> bool { \
lua_newtable(state); \
int number = 1; \
for (__TYPE__::size_type i = 0; i < value.length(); ++i) { \
lua_pushnumber(state, static_cast<lua_Number>(value[i])); \
lua_setfield(state, -2, std::to_string(number).c_str()); \
++number; \
} \
return true; \
}
// Forcing value from int to bool is acceptable here (line 48)
#ifdef WIN32
#pragma warning(disable : 4800)
#endif
REGISTER_TEMPLATEPROPERTY_SOURCE(BVec2Property, glm::bvec2, glm::bvec2(false),
DEFAULT_FROM_LUA_LAMBDA(glm::bvec2, lua_toboolean,
lua_isboolean),
DEFAULT_TO_LUA_LAMBDA(glm::bvec2), LUA_TTABLE);
REGISTER_TEMPLATEPROPERTY_SOURCE(BVec3Property, glm::bvec3, glm::bvec3(false),
DEFAULT_FROM_LUA_LAMBDA(glm::bvec3, lua_toboolean,
lua_isboolean),
DEFAULT_TO_LUA_LAMBDA(glm::bvec3), LUA_TTABLE);
REGISTER_TEMPLATEPROPERTY_SOURCE(BVec4Property, glm::bvec4, glm::bvec4(false),
DEFAULT_FROM_LUA_LAMBDA(glm::bvec4, lua_toboolean,
lua_isboolean),
DEFAULT_TO_LUA_LAMBDA(glm::bvec4), LUA_TTABLE);
#ifdef WIN32
#pragma warning(default : 4800)
#endif
REGISTER_NUMERICALPROPERTY_SOURCE(
Vec2Property, glm::vec2, glm::vec2(0), glm::vec2(numeric_limits<float>::lowest()),
glm::vec2(numeric_limits<float>::max()), glm::vec2(0.01f),
DEFAULT_FROM_LUA_LAMBDA(glm::vec2, lua_tonumber, lua_isnumber),
DEFAULT_TO_LUA_LAMBDA(glm::vec2), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(
Vec3Property, glm::vec3, glm::vec3(0), glm::vec3(numeric_limits<float>::lowest()),
glm::vec3(numeric_limits<float>::max()), glm::vec3(0.01f),
DEFAULT_FROM_LUA_LAMBDA(glm::vec3, lua_tonumber, lua_isnumber),
DEFAULT_TO_LUA_LAMBDA(glm::vec3), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(
Vec4Property, glm::vec4, glm::vec4(0), glm::vec4(numeric_limits<float>::lowest()),
glm::vec4(numeric_limits<float>::max()), glm::vec4(0.01f),
DEFAULT_FROM_LUA_LAMBDA(glm::vec4, lua_tonumber, lua_isnumber),
DEFAULT_TO_LUA_LAMBDA(glm::vec4), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(Vec2Property, glm::vec2, glm::vec2(0),
glm::vec2(numeric_limits<float>::lowest()), glm::vec2(numeric_limits<float>::max()),
glm::vec2(0.01f));
REGISTER_NUMERICALPROPERTY_SOURCE(Vec3Property, glm::vec3, glm::vec3(0),
glm::vec3(numeric_limits<float>::lowest()), glm::vec3(numeric_limits<float>::max()),
glm::vec3(0.01f));
REGISTER_NUMERICALPROPERTY_SOURCE(Vec4Property, glm::vec4, glm::vec4(0),
glm::vec4(numeric_limits<float>::lowest()), glm::vec4(numeric_limits<float>::max()),
glm::vec4(0.01f));
REGISTER_NUMERICALPROPERTY_SOURCE(DVec2Property, glm::dvec2, glm::dvec2(0),
glm::dvec2(numeric_limits<double>::lowest()),
glm::dvec2(numeric_limits<double>::max()), glm::dvec2(0.01));
glm::dvec2(numeric_limits<double>::lowest()),
glm::dvec2(numeric_limits<double>::max()),
glm::dvec2(0.01),
DEFAULT_FROM_LUA_LAMBDA(glm::dvec2, lua_tonumber,
lua_isnumber),
DEFAULT_TO_LUA_LAMBDA(glm::dvec2), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(DVec3Property, glm::dvec3, glm::dvec3(0),
glm::dvec3(numeric_limits<double>::lowest()),
glm::dvec3(numeric_limits<double>::max()), glm::dvec3(0.01));
glm::dvec3(numeric_limits<double>::lowest()),
glm::dvec3(numeric_limits<double>::max()),
glm::dvec3(0.01),
DEFAULT_FROM_LUA_LAMBDA(glm::dvec3, lua_tonumber,
lua_isnumber),
DEFAULT_TO_LUA_LAMBDA(glm::dvec3), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(DVec4Property, glm::dvec4, glm::dvec4(0),
glm::dvec4(numeric_limits<double>::lowest()),
glm::dvec4(numeric_limits<double>::max()), glm::dvec4(0.01));
glm::dvec4(numeric_limits<double>::lowest()),
glm::dvec4(numeric_limits<double>::max()),
glm::dvec4(0.01),
DEFAULT_FROM_LUA_LAMBDA(glm::dvec4, lua_tonumber,
lua_isnumber),
DEFAULT_TO_LUA_LAMBDA(glm::dvec4), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(IVec2Property, glm::ivec2, glm::ivec2(0),
glm::ivec2(numeric_limits<int>::lowest()), glm::ivec2(numeric_limits<int>::max()),
glm::ivec2(1));
glm::ivec2(numeric_limits<int>::lowest()),
glm::ivec2(numeric_limits<int>::max()), glm::ivec2(1),
DEFAULT_FROM_LUA_LAMBDA(glm::ivec2, lua_tonumber,
lua_isnumber),
DEFAULT_TO_LUA_LAMBDA(glm::ivec2), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(IVec3Property, glm::ivec3, glm::ivec3(0),
glm::ivec3(numeric_limits<int>::lowest()), glm::ivec3(numeric_limits<int>::max()),
glm::ivec3(1));
glm::ivec3(numeric_limits<int>::lowest()),
glm::ivec3(numeric_limits<int>::max()), glm::ivec3(1),
DEFAULT_FROM_LUA_LAMBDA(glm::ivec3, lua_tonumber,
lua_isnumber),
DEFAULT_TO_LUA_LAMBDA(glm::ivec3), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(IVec4Property, glm::ivec4, glm::ivec4(0),
glm::ivec4(numeric_limits<int>::lowest()), glm::ivec4(numeric_limits<int>::max()),
glm::ivec4(1));
glm::ivec4(numeric_limits<int>::lowest()),
glm::ivec4(numeric_limits<int>::max()), glm::ivec4(1),
DEFAULT_FROM_LUA_LAMBDA(glm::ivec4, lua_tonumber,
lua_isnumber),
DEFAULT_TO_LUA_LAMBDA(glm::ivec4), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(UVec2Property, glm::uvec2, glm::uvec2(0),
glm::uvec2(numeric_limits<unsigned int>::lowest()),
glm::uvec2(numeric_limits<unsigned int>::max()), glm::uvec2(1));
glm::uvec2(numeric_limits<unsigned int>::lowest()),
glm::uvec2(numeric_limits<unsigned int>::max()),
glm::uvec2(1),
DEFAULT_FROM_LUA_LAMBDA(glm::uvec2, lua_tonumber,
lua_isnumber),
DEFAULT_TO_LUA_LAMBDA(glm::uvec2), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(UVec3Property, glm::uvec3, glm::uvec3(0),
glm::uvec3(numeric_limits<unsigned int>::lowest()),
glm::uvec3(numeric_limits<unsigned int>::max()), glm::uvec3(1));
glm::uvec3(numeric_limits<unsigned int>::lowest()),
glm::uvec3(numeric_limits<unsigned int>::max()),
glm::uvec3(1),
DEFAULT_FROM_LUA_LAMBDA(glm::uvec3, lua_tonumber,
lua_isnumber),
DEFAULT_TO_LUA_LAMBDA(glm::uvec3), LUA_TTABLE);
REGISTER_NUMERICALPROPERTY_SOURCE(UVec4Property, glm::uvec4, glm::uvec4(0),
glm::uvec4(numeric_limits<unsigned int>::lowest()),
glm::uvec4(numeric_limits<unsigned int>::max()), glm::uvec4(1));
glm::uvec4(numeric_limits<unsigned int>::lowest()),
glm::uvec4(numeric_limits<unsigned int>::max()),
glm::uvec4(1),
DEFAULT_FROM_LUA_LAMBDA(glm::uvec4, lua_tonumber,
lua_isnumber),
DEFAULT_TO_LUA_LAMBDA(glm::uvec4), LUA_TTABLE);
} // namespace properties
} // namespace openspace

View File

@@ -25,22 +25,47 @@
#include <openspace/query/query.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/rendering/renderable.h>
namespace openspace {
namespace {
const std::string _loggerCat = "Query";
const std::string _loggerCat = "Query";
}
SceneGraph* getSceneGraph()
SceneGraph* sceneGraph()
{
return OsEng.renderEngine().sceneGraph();
}
SceneGraphNode* getSceneGraphNode(const std::string& name)
SceneGraphNode* sceneGraphNode(const std::string& name)
{
SceneGraph* sceneGraph = getSceneGraph();
return sceneGraph->sceneGraphNode(name);
const SceneGraph* graph = sceneGraph();
return graph->sceneGraphNode(name);
}
properties::Property* property(const std::string& uri)
{
// The URI consists of the following form at this stage:
// <node name>.{<property owner>.}^(0..n)<property id>
const size_t nodeNameSeparator = uri.find(properties::PropertyOwner::URISeparator);
if (nodeNameSeparator == std::string::npos) {
LERROR("Malformed URI '" << uri << "': At least one '" << nodeNameSeparator
<< "' separator must be present.");
return nullptr;
}
const std::string nodeName = uri.substr(0, nodeNameSeparator);
const std::string remainingUri = uri.substr(nodeNameSeparator + 1);
SceneGraphNode* node = sceneGraphNode(nodeName);
if (!node) {
LERROR("Node '" << nodeName << "' did not exist");
return nullptr;
}
properties::Property* property = node->property(remainingUri);
return property;
}
} // namespace

View File

@@ -36,17 +36,14 @@ namespace planetgeometry {
PlanetGeometry* PlanetGeometry::createFromDictionary(const ghoul::Dictionary& dictionary)
{
std::string name;
dictionary.getValue(constants::scenegraphnode::keyName, name);
if (!dictionary.hasValue<std::string>(constants::planetgeometry::keyType)) {
LERROR("PlanetGeometry for '" << name << "' did not contain a '"
<< constants::planetgeometry::keyType << "' key");
std::string geometryType;
const bool success = dictionary.getValueSafe(
constants::planetgeometry::keyType, geometryType);
if (!success) {
LERROR("PlanetGeometry did not contain a correct value of the key '"
<< constants::planetgeometry::keyType << "'");
return nullptr;
}
std::string geometryType;
dictionary.getValue(constants::planetgeometry::keyType, geometryType);
}
ghoul::TemplateFactory<PlanetGeometry>* factory
= FactoryManager::ref().factory<PlanetGeometry>();
@@ -62,6 +59,7 @@ PlanetGeometry* PlanetGeometry::createFromDictionary(const ghoul::Dictionary& di
PlanetGeometry::PlanetGeometry()
: _parent(nullptr)
{
setName("PlanetGeometry");
}
PlanetGeometry::~PlanetGeometry()

View File

@@ -47,31 +47,34 @@ RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary)
, _texture(nullptr)
, _geometry(nullptr)
{
std::string name;
bool success = dictionary.getValue(constants::scenegraphnode::keyName, name);
assert(success);
std::string path;
dictionary.getValue(constants::scenegraph::keyPathModule, path);
success = dictionary.getValue(constants::scenegraph::keyPathModule, path);
assert(success);
if (dictionary.hasKey(constants::renderableplanet::keyGeometry)) {
ghoul::Dictionary geometryDictionary;
dictionary.getValue(constants::renderableplanet::keyGeometry, geometryDictionary);
ghoul::Dictionary geometryDictionary;
success = dictionary.getValueSafe(
constants::renderableplanet::keyGeometry, geometryDictionary);
if (success) {
geometryDictionary.setValue(constants::scenegraphnode::keyName, name);
geometryDictionary.setValue(constants::scenegraph::keyPathModule, path);
geometryDictionary.setValue(constants::scenegraphnode::keyName, name());
_geometry
= planetgeometry::PlanetGeometry::createFromDictionary(geometryDictionary);
}
}
// TODO: textures need to be replaced by a good system similar to the geometry as soon
// as the requirements are fixed (ab)
std::string texturePath = "";
if (dictionary.hasKey("Textures.Color")) {
dictionary.getValue("Textures.Color", texturePath);
success = dictionary.getValueSafe("Textures.Color", texturePath);
if (success)
_colorTexturePath = path + "/" + texturePath;
}
for (properties::Property* p : _geometry->properties())
addProperty(p);
addPropertySubOwner(_geometry);
addProperty(_colorTexturePath);
addProperty(_colorTexturePath);
_colorTexturePath.onChange(std::bind(&RenderablePlanet::loadTexture, this));
}
@@ -107,10 +110,10 @@ bool RenderablePlanet::deinitialize()
void RenderablePlanet::render(const Camera* camera, const psc& thisPosition)
{
// TODO replace with more robust assert
// check so that the shader is set
assert(_programObject);
assert(_texture);
if (!_programObject)
return;
if (!_texture)
return;
// activate shader
_programObject->activate();

View File

@@ -47,38 +47,37 @@ SimpleSphereGeometry::SimpleSphereGeometry(const ghoul::Dictionary& dictionary)
, _segments("segments", "Segments", 20, 1, 1000)
, _planet(nullptr)
{
if (!dictionary.hasValue<glm::vec2>(constants::simplespheregeometry::keyRadius)) {
std::string name;
dictionary.getValue(constants::scenegraphnode::keyName, name);
LERROR("SimpleSphereGeometry of '" << name << "' did not provide a key '"
<< constants::simplespheregeometry::keyRadius
<< "'");
}
else {
glm::vec2 radius;
dictionary.getValue(constants::simplespheregeometry::keyRadius, radius);
_radius = radius;
}
using constants::scenegraphnode::keyName;
using constants::simplespheregeometry::keyRadius;
using constants::simplespheregeometry::keySegments;
if (!dictionary.hasValue<float>(constants::simplespheregeometry::keySegments)) {
std::string name;
dictionary.getValue(constants::scenegraphnode::keyName, name);
// The name is passed down from the SceneGraphNode
std::string name;
bool success = dictionary.getValue(keyName, name);
assert(success);
glm::vec2 radius;
success = dictionary.getValueSafe(keyRadius, radius);
if (!success) {
LERROR("SimpleSphereGeometry of '" << name << "' did not provide a key '"
<< constants::simplespheregeometry::keySegments
<< "'");
}
else {
float segments;
dictionary.getValue(constants::simplespheregeometry::keySegments, segments);
_segments = static_cast<int>(segments);
}
<< keyRadius << "'");
}
else
_radius = radius;
int segments;
success = dictionary.getValueSafe(keySegments, segments);
if (!success) {
LERROR("SimpleSphereGeometry of '" << name << "' did not provide a key '"
<< keySegments << "'");
}
else
_segments = segments;
addProperty(_radius);
_radius.onChange(std::bind(&SimpleSphereGeometry::createSphere, this));
addProperty(_segments);
_segments.onChange(std::bind(&SimpleSphereGeometry::createSphere, this));
//createSphere();
}
SimpleSphereGeometry::~SimpleSphereGeometry()

View File

@@ -27,6 +27,8 @@
#include <openspace/util/constants.h>
#include <openspace/util/factorymanager.h>
#include <ghoul/filesystem/filesystem.h>
namespace {
const std::string _loggerCat = "Renderable";
}
@@ -35,16 +37,19 @@ namespace openspace {
Renderable* Renderable::createFromDictionary(const ghoul::Dictionary& dictionary)
{
// The name is passed down from the SceneGraphNode
std::string name;
dictionary.getValue(constants::scenegraphnode::keyName, name);
bool success = dictionary.getValue(constants::scenegraphnode::keyName, name);
assert(success);
if (!dictionary.hasValue<std::string>(constants::renderable::keyType)) {
std::string renderableType;
success = dictionary.getValueSafe(constants::renderable::keyType, renderableType);
if (!success) {
LERROR("Renderable '" << name << "' did not have key '"
<< constants::renderable::keyType << "'");
return nullptr;
}
std::string renderableType;
dictionary.getValue(constants::renderable::keyType, renderableType);
}
ghoul::TemplateFactory<Renderable>* factory
= FactoryManager::ref().factory<Renderable>();
Renderable* result = factory->create(renderableType, dictionary);
@@ -53,16 +58,20 @@ Renderable* Renderable::createFromDictionary(const ghoul::Dictionary& dictionary
return nullptr;
}
result->setName(name);
return result;
}
Renderable::Renderable(const ghoul::Dictionary& dictionary)
: _enabled("enabled", "Is Enabled", true)
{
std::string name;
dictionary.getValue(constants::scenegraphnode::keyName, name);
setName(name);
setName("renderable");
// get path if available
const bool success = dictionary.getValueSafe(constants::scenegraph::keyPathModule, _relativePath);
if (success)
_relativePath += ghoul::filesystem::FileSystem::PathSeparator;
addProperty(_enabled);
}
Renderable::~Renderable()
@@ -83,4 +92,22 @@ void Renderable::update()
{
}
} // namespace openspace
std::string Renderable::findPath(const std::string& path) {
std::string tmp = absPath(path);
if(FileSys.fileExists(tmp))
return tmp;
tmp = absPath(_relativePath + path);
if(FileSys.fileExists(tmp))
return tmp;
LERROR("Could not find file '" << path << "'");
return "";
}
bool Renderable::isVisible() const {
return _enabled;
}
} // namespace openspace

View File

@@ -0,0 +1,342 @@
/*****************************************************************************************
* *
* 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 <openspace/rendering/renderablefieldlines.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/util/powerscaledcoordinate.h>
#include <openspace/util/kameleonwrapper.h>
#include <openspace/util/constants.h>
namespace {
const std::string _loggerCat = "RenderableFieldlines";
const std::string keyFieldlines = "Fieldlines";
const std::string keyFilename = "File";
const std::string keyHints = "Hints";
const std::string keyShaders = "Shaders";
const std::string keyVertexShader = "VertexShader";
const std::string keyFragmentShader = "FragmentShader";
}
namespace openspace {
RenderableFieldlines::RenderableFieldlines(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _VAO(0)
, _programUpdateOnSave(false)
, _update(false)
{
std::string name;
bool success = dictionary.getValue(constants::scenegraphnode::keyName, name);
assert(success);
ghoul::Dictionary fieldlines;
success = dictionary.getValueSafe(keyFieldlines, fieldlines);
if (!success) {
LERROR("RenderableFieldlines '" << name << "' did not contain a '" <<
keyFieldlines << "' key");
return;
}
for (const std::string& key : fieldlines.keys()) {
ghoul::Dictionary fieldline;
success = fieldlines.getValueSafe(key, fieldline);
if (!success) {
LERROR("Key '" << key << "' in '" << keyFieldlines <<
"' of the RenderableFieldlines '" << name <<
"' does not have a table as value");
continue;
}
std::string fileName;
fieldline.getValueSafe(keyFilename, fileName);
fileName = findPath(fileName);
if (fileName.empty())
LERROR("File not found!");
else {
ghoul::Dictionary hintsDictionary;
fieldline.getValueSafe(keyHints, hintsDictionary);
_filenames.push_back(fileName);
_hintsDictionaries.push_back(hintsDictionary);
}
}
ghoul::Dictionary shaderDictionary;
success = dictionary.getValueSafe(keyShaders, shaderDictionary);
if (!success) {
LERROR("RenderableFieldlines '" << name << "' does not contain a '" <<
keyShaders << "' table");
return;
}
std::string vshaderpath;
success = shaderDictionary.getValueSafe(keyVertexShader, vshaderpath);
if (!success) {
LERROR("RenderableFieldlines '" << name << "' does not have a '" <<
keyVertexShader << "'");
return;
}
vshaderpath = findPath(vshaderpath);
std::string fshaderpath;
success = shaderDictionary.getValueSafe(keyFragmentShader, fshaderpath);
if (!success) {
LERROR("RenderableFieldlines '" << name << "' does not have a '" <<
keyFragmentShader << "'");
return;
}
fshaderpath = findPath(fshaderpath);
_vertexSourceFile = new ghoul::filesystem::File(vshaderpath, false);
_fragmentSourceFile = new ghoul::filesystem::File(fshaderpath, false);
ShaderCreator sc = OsEng.shaderBuilder();
_fieldlinesProgram = sc.buildShader("FieldlinesProgram", vshaderpath, fshaderpath);
dictionary.getValueSafe("UpdateOnSave", _programUpdateOnSave);
setBoundingSphere(PowerScaledScalar::CreatePSS(5)); // FIXME a non-magic number perhaps
}
RenderableFieldlines::~RenderableFieldlines() {
}
bool RenderableFieldlines::initialize() {
assert(_filenames.size() != 0);
assert(_hintsDictionaries.size() != 0);
int prevEnd = 0;
std::vector<LinePoint> vertexData, seedPointsData;
std::vector<std::vector<LinePoint> > fieldlinesData;
glm::vec4 seedPointsColor = glm::vec4(1.0, 0.5, 0.0, 1.0);
for (int i = 0; i < _filenames.size(); ++i) {
fieldlinesData = getFieldlinesData(_filenames[i], _hintsDictionaries[i]);
for (int j = 0; j < fieldlinesData.size(); ++j) {
_lineStart.push_back(prevEnd);
_lineCount.push_back(fieldlinesData[j].size());
prevEnd = prevEnd + fieldlinesData[j].size();
vertexData.insert( vertexData.end(), fieldlinesData[j].begin(), fieldlinesData[j].end());
}
// Give seedpoints a color for visualizing as GL_POINTS
for (glm::vec3 seedPoint : _seedPoints) {
seedPointsData.push_back(LinePoint(seedPoint, seedPointsColor));
}
}
LDEBUG("Number of vertices : " << vertexData.size());
// ------ FIELDLINES -----------------
GLuint vertexPositionBuffer;
glGenVertexArrays(1, &_VAO); // generate array
glBindVertexArray(_VAO); // bind array
glGenBuffers(1, &vertexPositionBuffer); // generate buffer
glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer
glBufferData(GL_ARRAY_BUFFER, vertexData.size()*sizeof(LinePoint), &vertexData.front(), GL_STATIC_DRAW);
// Vertex positions
GLuint vertexLocation = 0;
glEnableVertexAttribArray(vertexLocation);
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(LinePoint), reinterpret_cast<void*>(0));
// Texture coordinates
GLuint texcoordLocation = 1;
glEnableVertexAttribArray(texcoordLocation);
glVertexAttribPointer(texcoordLocation, 4, GL_FLOAT, GL_FALSE, sizeof(LinePoint), (void*)(sizeof(glm::vec3)));
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer
glBindVertexArray(0); //unbind array
// ------ SEEDPOINTS -----------------
GLuint seedpointPositionBuffer;
glGenVertexArrays(1, &_seedpointVAO); // generate array
glBindVertexArray(_seedpointVAO); // bind array
glGenBuffers(1, &seedpointPositionBuffer); // generate buffer
glBindBuffer(GL_ARRAY_BUFFER, seedpointPositionBuffer); // bind buffer
glBufferData(GL_ARRAY_BUFFER, seedPointsData.size()*sizeof(LinePoint), &seedPointsData.front(), GL_STATIC_DRAW);
// Vertex positions
glEnableVertexAttribArray(vertexLocation);
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(LinePoint), reinterpret_cast<void*>(0));
// Texture coordinates
glEnableVertexAttribArray(texcoordLocation);
glVertexAttribPointer(texcoordLocation, 4, GL_FLOAT, GL_FALSE, sizeof(LinePoint), (void*)(3*sizeof(float)));
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer
glBindVertexArray(0); //unbind array
glPointSize(5); // size of seedpoints
// ------ SETUP SHADERS -----------------
auto privateCallback = [this](const ghoul::filesystem::File& file) {
_update = true;
};
if(_programUpdateOnSave) {
_vertexSourceFile->setCallback(privateCallback);
_fragmentSourceFile->setCallback(privateCallback);
}
_fieldlinesProgram->compileShaderObjects();
_fieldlinesProgram->linkProgramObject();
return true;
}
bool RenderableFieldlines::deinitialize() {
return true;
}
void RenderableFieldlines::render(const Camera* camera, const psc& thisPosition) {
if(_update) {
_update = false;
safeShaderCompilation();
}
glm::mat4 transform = camera->viewProjectionMatrix();
glm::mat4 camTransform = camera->viewRotationMatrix();
psc relative = thisPosition-camera->position();
transform = transform*camTransform;
transform = glm::mat4(1.0);
transform = glm::scale(transform, glm::vec3(0.01));
psc currentPosition = thisPosition;
psc campos = camera->position();
glm::mat4 camrot = camera->viewRotationMatrix();
PowerScaledScalar scaling = camera->scaling();
// Activate shader
_fieldlinesProgram->activate();
_fieldlinesProgram->setUniform("modelViewProjection", camera->viewProjectionMatrix());
_fieldlinesProgram->setUniform("modelTransform", transform);
_fieldlinesProgram->setUniform("campos", campos.vec4());
_fieldlinesProgram->setUniform("objpos", currentPosition.vec4());
_fieldlinesProgram->setUniform("camrot", camrot);
_fieldlinesProgram->setUniform("scaling", scaling.vec2());
// ------ FIELDLINES -----------------
glBindVertexArray(_VAO);
glMultiDrawArrays(GL_LINE_STRIP, &_lineStart[0], &_lineCount[0], _lineStart.size());
// // ------ SEEDPOINTS -----------------
// glBindVertexArray(_seedpointVAO);
// glMultiDrawArrays(GL_POINTS, &_lineStart[0], &_lineCount[0], _seedPoints.size());
glBindVertexArray(0);
// Deactivate shader
_fieldlinesProgram->deactivate();
}
void RenderableFieldlines::update() {
}
void RenderableFieldlines::safeShaderCompilation() {
_fieldlinesProgram->rebuildFromFile();
_fieldlinesProgram->compileShaderObjects();
_fieldlinesProgram->linkProgramObject();
}
std::vector<std::vector<LinePoint> > RenderableFieldlines::getFieldlinesData(std::string filename, ghoul::Dictionary hintsDictionary) {
std::string modelString;
float stepSize = 0.5; // default if no stepsize is specified in hints
std::string xVariable, yVariable, zVariable;
KameleonWrapper::Model model;
std::vector<std::vector<LinePoint> > fieldlinesData;
bool classification = false, lorentz = false;
glm::vec4 fieldlineColor = glm::vec4(1.0, 1.0, 1.0, 1.0); // default color if no color or classification is specified
if (hintsDictionary.hasKey("Model") && hintsDictionary.getValue("Model", modelString)) {
// ------ MODEL -----------------
if (modelString == "BATSRUS") {
model = KameleonWrapper::Model::BATSRUS;
} else if (modelString == "ENLIL") {
LWARNING("ENLIL model not supported for fieldlines");
return fieldlinesData;
} else {
LWARNING("Hints does not specify a valid 'Model'");
return fieldlinesData;
}
// ------ VARIBLES / LORENTZ -----------------
if (hintsDictionary.hasKey("Variables")) {
bool xVar, yVar, zVar;
xVar = hintsDictionary.getValue("Variables.1", xVariable);
if (xVar && xVariable == "Lorentz") {
lorentz = true;
} else {
yVar = hintsDictionary.getValue("Variables.2", yVariable);
zVar = hintsDictionary.getValue("Variables.3", zVariable);
if (!xVar || !yVar || !zVar) {
LWARNING("Error reading variables! Must be 3 and must exist in CDF data");
return fieldlinesData;
}
}
} else {
LWARNING("Hints does not specify valid 'Variables'");
return fieldlinesData;
}
// ------ STEPSIZE -----------------
if (!hintsDictionary.hasKey("Stepsize") || !hintsDictionary.getValue("Stepsize", stepSize)) {
LDEBUG("No stepsize set for fieldlines. Setting to default value (" << stepSize << ")");
}
// ------ SEEDPOINTS ---------------
ghoul::Dictionary seedpointsDictionary;
_seedPoints.clear();
if (hintsDictionary.hasKey("Seedpoints") && hintsDictionary.getValue("Seedpoints", seedpointsDictionary)) {
glm::vec3 seedPos;
for (auto index : seedpointsDictionary.keys()) {
hintsDictionary.getValue("Seedpoints."+index, seedPos);
_seedPoints.push_back(seedPos);
}
}
// ------ CLASSIFICATION & COLOR -----------
hintsDictionary.getValue("Color", fieldlineColor);
hintsDictionary.getValue("Classification", classification);
}
KameleonWrapper kw(filename, model);
if (lorentz) {
fieldlinesData = kw.getLorentzTrajectories(_seedPoints, fieldlineColor, stepSize);
} else {
if (classification)
fieldlinesData = kw.getClassifiedFieldLines(xVariable, yVariable, zVariable, _seedPoints, stepSize);
else
fieldlinesData = kw.getFieldLines(xVariable, yVariable, zVariable, _seedPoints, stepSize, fieldlineColor);
}
return fieldlinesData;
}
} // namespace openspace

View File

@@ -24,17 +24,16 @@
// open space includes
#include <openspace/rendering/renderablevolume.h>
#include <ghoul/opengl/texturereader.h>
#include <ghoul/filesystem/filesystem.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/util/kameleonwrapper.h>
#include <openspace/util/constants.h>
#include <sgct.h>
// ghoul includes
#include <ghoul/opengl/texturereader.h>
#include <ghoul/filesystem/filesystem.h>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <algorithm>
@@ -73,92 +72,178 @@ namespace {
namespace openspace {
RenderableVolume::RenderableVolume(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
{
// get path if available
_relativePath = "";
if(dictionary.hasKey(constants::scenegraph::keyPathModule)) {
dictionary.getValue(constants::scenegraph::keyPathModule, _relativePath);
_relativePath += "/";
}
RenderableVolume::RenderableVolume(const ghoul::Dictionary& dictionary) : Renderable(dictionary) {
}
RenderableVolume::~RenderableVolume() {
}
std::string RenderableVolume::findPath(const std::string& path) {
std::string tmp = absPath(path);
if(FileSys.fileExists(tmp))
return tmp;
tmp = absPath(_relativePath + path);
if(FileSys.fileExists(tmp))
return tmp;
LERROR("Could not find file '" << 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")) {
ghoul::opengl::Texture::FilterMode filtermode = ghoul::opengl::Texture::FilterMode::Linear;
ghoul::opengl::Texture::WrappingMode wrappingmode = ghoul::opengl::Texture::WrappingMode::ClampToEdge;
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;
}
std::string modelString = "";
if (hintsDictionary.hasKey("Model"))
hintsDictionary.getValue("Model", modelString);
if(modelString == "") {
LWARNING("Model not specified.");
return nullptr;
}
std::string variableCacheString = "";
if (hintsDictionary.hasKey("Variable")) {
hintsDictionary.getValue("Variable", variableCacheString);
} else if(hintsDictionary.hasKey("Variables")) {
std::string xVariable, yVariable, zVariable;
bool xVar, yVar, zVar;
xVar = hintsDictionary.getValue("Variables.1", xVariable);
yVar = hintsDictionary.getValue("Variables.2", yVariable);
zVar = hintsDictionary.getValue("Variables.3", zVariable);
if (xVar && yVar && zVar) {
variableCacheString = xVariable + "." + yVariable + "." + zVariable;
}
}
bool cache = false;
hintsDictionary.hasKey("Cache");
if (hintsDictionary.hasKey("Cache"))
hintsDictionary.getValue("Cache", cache);
std::stringstream ss;
ss << "." << dimensions[0] << "x" << dimensions[1] << "x" << dimensions[2] << "." << modelString << "." << variableCacheString << ".cache";
std::string cachepath = filepath + ss.str();
if( cache && FileSys.fileExists(cachepath)) {
FILE* file = fopen (cachepath.c_str(), "rb");
int length = dimensions[0] *dimensions[1] *dimensions[2];
float* data = new float[length];
for(int i = 0; i< length; i++){
float f;
fread(&f, sizeof(float), 1, file);
data[i] = f;
}
fclose(file);
return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT, filtermode, wrappingmode);
}
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;
}
KameleonWrapper kw(filepath, model);
std::string variableString;
if (hintsDictionary.hasKey("Variable") && hintsDictionary.getValue("Variable", variableString)) {
float* data = kw.getUniformSampledValues(variableString, dimensions);
if(cache) {
FILE* file = fopen (cachepath.c_str(), "wb");
int length = dimensions[0] *dimensions[1] *dimensions[2];
fwrite(data, sizeof(float), length, file);
fclose(file);
}
return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT, filtermode, wrappingmode);
} else if (hintsDictionary.hasKey("Variables")) {
std::string xVariable, yVariable, zVariable;
bool xVar, yVar, zVar;
xVar = hintsDictionary.getValue("Variables.1", xVariable);
yVar = hintsDictionary.getValue("Variables.2", yVariable);
zVar = hintsDictionary.getValue("Variables.3", zVariable);
if (!xVar || !yVar || !zVar) {
LERROR("Error reading variables! Must be 3 and must exist in CDF data");
} else {
float* data = kw.getUniformSampledVectorValues(xVariable, yVariable, zVariable, dimensions);
if(cache) {
FILE* file = fopen (cachepath.c_str(), "wb");
int length = dimensions[0] *dimensions[1] *dimensions[2];
fwrite(data, sizeof(float), length, file);
fclose(file);
}
return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::RGBA, GL_RGBA, GL_FLOAT, filtermode, wrappingmode);
}
} else {
LWARNING("Hints does not specify a 'Variable' or 'Variables'");
}
} else {
LWARNING("No valid file extension.");
}
return nullptr;
}
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;
glm::vec3 RenderableVolume::getVolumeOffset(
const std::string& filepath,
const ghoul::Dictionary& hintsDictionary) {
std::string modelString = "";
if (hintsDictionary.hasKey("Model"))
hintsDictionary.getValue("Model", modelString);
if(modelString == "") {
LWARNING("Model not specified.");
return glm::vec3(0);
}
KameleonWrapper::Model model;
if (modelString == "BATSRUS") {
model = KameleonWrapper::Model::BATSRUS;
} else if (modelString == "ENLIL") {
model = KameleonWrapper::Model::ENLIL;
return glm::vec3(0);
} else {
LWARNING("Hints does not specify a valid 'Model'");
return glm::vec3(0);
}
KameleonWrapper kw(filepath, model);
return kw.getModelBarycenterOffset();
}
ghoul::RawVolumeReader::ReadHints RenderableVolume::readHints(const ghoul::Dictionary& dictionary) {
@@ -228,10 +313,15 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string
if ( ! FileSys.fileExists(f)) {
return nullptr;
}
ghoul::opengl::Texture::FilterMode filtermode = ghoul::opengl::Texture::FilterMode::Linear;
ghoul::opengl::Texture::WrappingMode wrappingmode = ghoul::opengl::Texture::WrappingMode::ClampToEdge;
// check if not a txt based texture
if ( ! hasExtension(filepath, "txt")) {
return ghoul::opengl::loadTexture(f);
ghoul::opengl::Texture* t = ghoul::opengl::loadTexture(f);
t->setWrapping(wrappingmode);
return t;
}
// it is a txt based texture
@@ -259,7 +349,7 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string
auto widthValidator = [](size_t in) { if(in > 0) return in; return static_cast<size_t>(1); };
auto upperLowerValidator = [](float in) { return glm::clamp(in, 0.0f, 1.0f); };
auto intensityValidator = [](float in) { if(in > 0.0f) return in; return 1.0f; };
auto intensityValidator = [](float in) { return glm::clamp(in, 0.0f, 1.0f); };
std::string line;
while (std::getline(in, line)) {
@@ -294,15 +384,26 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string
if (mappingKeys.size() < 1) {
return nullptr;
}
// for(auto key: mappingKeys) {
// glm::vec4 rgba = key.color;
// LDEBUG("i: " << key.position << ", rgba: (" << rgba[0] << ", " << rgba[1] << ", " << rgba[2] << ", " << rgba[3] << ")");
// }
// LDEBUG("insert....");
mappingKeys.insert(mappingKeys.begin(), {lower});
mappingKeys.push_back({upper});
for(auto key: mappingKeys) {
glm::vec4 rgba = key.color;
// LDEBUG("i: " << key.position << ", rgba: (" << rgba[0] << ", " << rgba[1] << ", " << rgba[2] << ", " << rgba[3] << ")");
if (mappingKeys.front().position > lower){
mappingKeys.insert(mappingKeys.begin(), {lower,mappingKeys.front().color});
}
if (mappingKeys.back().position < upper){
mappingKeys.push_back({upper,mappingKeys.back().color});
}
// for(auto key: mappingKeys) {
// glm::vec4 rgba = key.color;
// LDEBUG("i: " << key.position << ", rgba: (" << rgba[0] << ", " << rgba[1] << ", " << rgba[2] << ", " << rgba[3] << ")");
// }
// allocate new float array with zeros
float* transferFunction = new float[width*4]();
@@ -310,8 +411,8 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string
transferFunction[i] = 0.0f;
}
size_t lowerIndex = static_cast<size_t>(floorf(lower*static_cast<float>(width)));
size_t upperIndex = static_cast<size_t>(floorf(upper*static_cast<float>(width)));
size_t lowerIndex = static_cast<size_t>(floorf(lower*static_cast<float>(width-1)));
size_t upperIndex = static_cast<size_t>(floorf(upper*static_cast<float>(width-1)));
// LDEBUG("width: " << width);
// LDEBUG("lower: " << lower);
@@ -324,9 +425,9 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string
auto currentKey = prevKey + 1;
auto lastKey = mappingKeys.end() -1;
for (size_t i=lowerIndex; i<upperIndex; i++) {
for (size_t i=lowerIndex; i<=upperIndex; i++) {
float fpos = static_cast<float>(i)/static_cast<float>(width);
float fpos = static_cast<float>(i)/static_cast<float>(width-1);
if (fpos > (*currentKey).position) {
prevKey = currentKey;
@@ -361,16 +462,25 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string
//LDEBUG("["<< position <<"] " << value);
}
// LDEBUG(weight << ", (" <<
// transferFunction[4*i+0] << ", " <<
// transferFunction[4*i+1] << ", " <<
// transferFunction[4*i+2] << ", " <<
// transferFunction[4*i+3] << ")");
// LDEBUG(std::fixed << std::setw(10) << std::left << std::setprecision(8) << weight << ", (" <<
// std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+0] << ", " <<
// std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+1] << ", " <<
// std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+2] << ", " <<
// std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+3] << ")");
}
// for (int i = 0; i <= width; ++i) {
// LDEBUG(std::fixed << "(" <<
// std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+0] << ", " <<
// std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+1] << ", " <<
// std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+2] << ", " <<
// std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+3] << ")");
// }
return new ghoul::opengl::Texture(transferFunction,
glm::size3_t(width,1,1),ghoul::opengl::Texture::Format::RGBA,
GL_RGBA, GL_FLOAT);;
GL_RGBA, GL_FLOAT,filtermode, wrappingmode);
}
} // namespace openspace

View File

@@ -1,401 +1,402 @@
/*****************************************************************************************
* *
* 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. *
****************************************************************************************/
// open space includes
#include <openspace/rendering/renderablevolumecl.h>
#include <openspace/engine/openspaceengine.h>
#include <ghoul/opengl/texturereader.h>
#include <ghoul/filesystem/filesystem.h>
#include <sgct.h>
#include <algorithm>
namespace {
std::string _loggerCat = "RenderableVolumeCL";
}
namespace openspace {
RenderableVolumeCL::RenderableVolumeCL(const ghoul::Dictionary& dictionary):
RenderableVolume(dictionary),
_backTexture(nullptr), _frontTexture(nullptr), _output(nullptr),
_clBackTexture(0), _clFrontTexture(0), _clOutput(0),
_kernelSourceFile(nullptr) {
_kernelMutex = new std::mutex;
_filename = "";
if(dictionary.hasKey("Volume")) {
if(dictionary.getValue("Volume", _filename)) {
_filename = findPath(_filename);
}
}
ghoul::Dictionary hintsDictionary;
if(dictionary.hasKey("Hints"))
dictionary.getValue("Hints", hintsDictionary);
_hints = readHints(hintsDictionary);
/*
if(dictionary.hasKey("TransferFunctions")) {
ghoul::Dictionary transferFunctions;
if(dictionary.getValue("TransferFunctions", transferFunctions)) {
auto keys = transferFunctions.keys();
for(auto key: keys) {
std::string transferFunctionPath = "";
if(transferFunctions.getValue(key, transferFunctionPath)) {
transferFunctionPath = findPath(transferFunctionPath);
if(transferFunctionPath != "") {
ghoul::filesystem::File* tmp = new ghoul::filesystem::File(transferFunctionPath, false);
ghoul::opengl::Texture* tmpTexture = ghoul::opengl::loadTexture(tmp->path());
_transferFunctions.push_back(tmpTexture);
_transferFunctionsFiles.push_back(tmp);
}
}
}
}
}
*/
if(dictionary.hasKey("UpdateOnSave")) {
dictionary.getValue("UpdateOnSave", _kernelUpdateOnSave);
}
/*
if(dictionary.hasKey("KernelOptions")) {
using namespace ghoul::opencl;
ghoul::Dictionary kernelOptions;
if(dictionary.getValue("KernelOptions", kernelOptions)) {
auto keys = kernelOptions.keys();
for(auto key: keys) {
bool value = false;
if(kernelOptions.getValue(key, value)) {
if(key == "DenormsAreZero") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::DenormsAreZero, value));
} else if(key == "FastRelaxedMath") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::FastRelaxedMath, value));
} else if(key == "FiniteMathOnly") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::FiniteMathOnly, value));
} else if(key == "KernelArgInfo") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::KernelArgInfo, value));
} else if(key == "MadEnable") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::MadEnable, value));
} else if(key == "NoSignedZero") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::NoSignedZero, value));
} else if(key == "OptDisable") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::OptDisable, value));
} else if(key == "SinglePrecisionConstant") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::SinglePrecisionConstant, value));
} else if(key == "StrictAliasing") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::StrictAliasing, value));
} else if(key == "UnsafeMathOptimizations") {
_kernelOptions.push_back(std::make_pair(CLProgram::Option::UnsafeMathOptimizations, value));
}
}
}
}
}
*/
std::string kernelPath = "";
if (dictionary.hasKey("Kernel")) {
if(dictionary.getValue("Kernel", kernelPath)) {
kernelPath = findPath(kernelPath);
}
}
if (kernelPath != "") {
_kernelSourceFile = new ghoul::filesystem::File(kernelPath, false);
}
}
RenderableVolumeCL::~RenderableVolumeCL() {
deinitialize();
delete _kernelMutex;
}
bool RenderableVolumeCL::initialize() {
assert(_filename != "");
// ------ VOLUME READING ----------------
ghoul::RawVolumeReader rawReader(_hints);
_volume = rawReader.read(_filename);
glm::size3_t d = _volume->dimensions();
// ------ SETUP GEOMETRY ----------------
const GLfloat size = 1.0f;
const GLfloat vertex_texcoord_data[] = { // square of two triangles (sigh)
// x y z s t
-size, -size, 0.0f, 0.0f, 0.0f,
size, size, 0.0f, 1.0f, 1.0f,
-size, size, 0.0f, 0.0f, 1.0f,
-size, -size, 0.0f, 0.0f, 0.0f,
size, -size, 0.0f, 1.0f, 0.0f,
size, size, 0.0f, 1.0f, 1.0f
};
GLuint vertexPositionBuffer;
glGenVertexArrays(1, &_screenQuad); // generate array
glBindVertexArray(_screenQuad); // bind array
glGenBuffers(1, &vertexPositionBuffer); // generate buffer
glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_texcoord_data), vertex_texcoord_data, GL_STATIC_DRAW);
// Vertex positions
GLuint vertexLocation = 2;
glEnableVertexAttribArray(vertexLocation);
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), reinterpret_cast<void*>(0));
// Texture coordinates
GLuint texcoordLocation = 0;
glEnableVertexAttribArray(texcoordLocation);
glVertexAttribPointer(texcoordLocation, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (void*)(3*sizeof(GLfloat)));
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer
glBindVertexArray(0); //unbind array
_boundingBox = new sgct_utils::SGCTBox(1.0f, sgct_utils::SGCTBox::Regular);
// ------ SETUP SHADERS -----------------
// TODO error control or better design pattern
OsEng.ref().configurationManager().getValue("RaycastProgram", _fboProgram);
OsEng.ref().configurationManager().getValue("Quad", _quadProgram);
// ------ SETUP FBO ---------------------
_fbo = new ghoul::opengl::FramebufferObject();
_fbo->activate();
size_t x = sgct::Engine::instance()->getActiveXResolution();
size_t y = sgct::Engine::instance()->getActiveYResolution();
_backTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1));
_frontTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1));
_output = new ghoul::opengl::Texture(glm::size3_t(x,y,1));
_backTexture->uploadTexture();
_frontTexture->uploadTexture();
_output->uploadTexture();
_fbo->attachTexture(_backTexture, GL_COLOR_ATTACHMENT0);
_fbo->attachTexture(_frontTexture, GL_COLOR_ATTACHMENT1);
_fbo->deactivate();
_context = OsEng.clContext();
_commands = _context.createCommandQueue();
_clBackTexture = _context.createTextureFromGLTexture(CL_MEM_READ_ONLY, *_backTexture);
_clFrontTexture = _context.createTextureFromGLTexture(CL_MEM_READ_ONLY, *_frontTexture);
_clVolume = _context.createTextureFromGLTexture(CL_MEM_READ_ONLY, *_volume);
_clOutput = _context.createTextureFromGLTexture(CL_MEM_WRITE_ONLY, *_output);
auto privateCallback = [this](const ghoul::filesystem::File& file) {
safeKernelCompilation();
};
_kernelSourceFile = new ghoul::filesystem::File(_kernelSourceFile->path(), false);
if(_kernelUpdateOnSave)
_kernelSourceFile->setCallback(privateCallback);
safeKernelCompilation();
size_t local_x = 32;
size_t local_y = 32;
while (local_x > 1) {
if(x % local_x == 0)
break;
local_x /= 2;
}
while (local_y > 1) {
if(y % local_y == 0)
break;
local_y /= 2;
}
_ws = new ghoul::opencl::CLWorkSize ({x,y}, {local_x,local_y});
return true;
}
bool RenderableVolumeCL::deinitialize() {
delete _ws;
_ws = nullptr;
return true;
}
void RenderableVolumeCL::render(const Camera *camera, const psc &thisPosition) {
if( ! _kernel.isValidKernel())
return;
float speed = 50.0f;
float time = sgct::Engine::getTime();
glm::mat4 transform = camera->viewProjectionMatrix();
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));
if(_kernel.isValidKernel()) {
_stepSize = 0.01f;
// ------ DRAW TO FBO -------------------
GLuint sgctFBO = ghoul::opengl::FramebufferObject::getActiveObject(); // Save SGCTs main FBO
_fbo->activate();
_fboProgram->activate();
_fboProgram->setUniform("modelViewProjection", transform);
// 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
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);
_fboProgram->deactivate();
_fbo->deactivate();
// ------ DRAW TO SCREEN ----------------
glBindFramebuffer(GL_FRAMEBUFFER, sgctFBO); // Re-bind SGCTs main FBO
glFinish();
_commands.enqueueKernelBlocking(_kernel, *_ws);
_commands.finish();
_quadProgram->activate();
glActiveTexture(GL_TEXTURE0);
_output->bind();
glClearColor(0.0f, 0.0f, 0.0f, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(_screenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
_quadProgram->deactivate();
}
}
void RenderableVolumeCL::update() {
}
void RenderableVolumeCL::safeKernelCompilation() {
std::string _loggerCat = "RenderableVolumeCL::safeKernelCompilation";
if(_context.isValidContext()) {
ghoul::opencl::CLProgram tmpProgram = _context.createProgram(_kernelSourceFile->path());
tmpProgram.setOption(ghoul::opencl::CLProgram::Option::OptDisable, true);
tmpProgram.setOption(ghoul::opencl::CLProgram::Option::KernelArgInfo, true);
if(tmpProgram.build()) {
ghoul::opencl::CLKernel tmpKernel = tmpProgram.createKernel("volumeraycaster");
if(tmpKernel.isValidKernel()) {
tmpKernel.setArgument(0, &_clFrontTexture);
tmpKernel.setArgument(1, &_clBackTexture);
tmpKernel.setArgument(2, &_clVolume);
tmpKernel.setArgument(3, &_clOutput);
// do the actual assignment behind locked doors
_kernelMutex->lock();
_program = tmpProgram;
_kernel = tmpKernel;
_kernelMutex->unlock();
LDEBUG("Done updating kernel");
} else {
LWARNING("Kernel is not valid");
}
} else {
LWARNING("Could not build CLProgram");
}
} else {
LWARNING("No valid CLContext");
}
}
/*
void RenderableVolumeCL::safeUpdateTexture(const ghoul::filesystem::File& file) {
int fileID = 0;
for (fileID = 0; fileID < _transferFunctionsFiles.size(); ++fileID) {
if (_transferFunctionsFiles.at(fileID) == &file) {
//LDEBUG("Transferfunction found at id " << fileID);
break;
}
}
if(fileID == _transferFunctionsFiles.size())
return;
LDEBUG("Updating transferfunction");
// create the new texture
ghoul::opengl::Texture* newTexture = ghoul::opengl::loadTexture(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);
if(clNewTexture == 0) {
delete newTexture;
return;
}
// everything is ok, critical point to replace current texture pointers
_textureLock->lock();
// deallocate current texture
delete _transferFunctions.at(fileID);
clReleaseMemObject(_clTransferFunctions.at(fileID));
// set the new texture
_transferFunctions.at(fileID) = newTexture;
_clTransferFunctions.at(fileID) = clNewTexture;
// update kernel
// __kernel arguments(front, back, output, [_volumes], .. fileID))
_kernel.setArgument(3 + _volumes.size() + fileID, &clNewTexture);
// end of critical section
_textureLock->unlock();
}
}
*/
} // namespace openspace
// This is still in the repository to be cannibalized for a possible rewrite (ab)
///*****************************************************************************************
// * *
// * 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. *
// ****************************************************************************************/
//
//// open space includes
//#include <openspace/rendering/renderablevolumecl.h>
//
//#include <openspace/engine/openspaceengine.h>
//
//#include <ghoul/opengl/texturereader.h>
//#include <ghoul/filesystem/filesystem.h>
//
//#include <sgct.h>
//
//#include <algorithm>
//
//namespace {
// std::string _loggerCat = "RenderableVolumeCL";
//}
//
//namespace openspace {
//
//RenderableVolumeCL::RenderableVolumeCL(const ghoul::Dictionary& dictionary):
// RenderableVolume(dictionary),
// _backTexture(nullptr), _frontTexture(nullptr), _output(nullptr),
// _clBackTexture(0), _clFrontTexture(0), _clOutput(0),
// _kernelSourceFile(nullptr) {
//
// _kernelMutex = new std::mutex;
//
// _filename = "";
// if(dictionary.hasKey("Volume")) {
// if(dictionary.getValue("Volume", _filename)) {
// _filename = findPath(_filename);
// }
// }
// ghoul::Dictionary hintsDictionary;
// if(dictionary.hasKey("Hints"))
// dictionary.getValue("Hints", hintsDictionary);
// _hints = readHints(hintsDictionary);
//
// /*
// if(dictionary.hasKey("TransferFunctions")) {
// ghoul::Dictionary transferFunctions;
// if(dictionary.getValue("TransferFunctions", transferFunctions)) {
// auto keys = transferFunctions.keys();
// for(auto key: keys) {
// std::string transferFunctionPath = "";
// if(transferFunctions.getValue(key, transferFunctionPath)) {
// transferFunctionPath = findPath(transferFunctionPath);
// if(transferFunctionPath != "") {
// ghoul::filesystem::File* tmp = new ghoul::filesystem::File(transferFunctionPath, false);
// ghoul::opengl::Texture* tmpTexture = ghoul::opengl::loadTexture(tmp->path());
//
// _transferFunctions.push_back(tmpTexture);
// _transferFunctionsFiles.push_back(tmp);
// }
// }
// }
// }
// }
// */
//
// if(dictionary.hasKey("UpdateOnSave")) {
// dictionary.getValue("UpdateOnSave", _kernelUpdateOnSave);
// }
//
// /*
// if(dictionary.hasKey("KernelOptions")) {
// using namespace ghoul::opencl;
// ghoul::Dictionary kernelOptions;
// if(dictionary.getValue("KernelOptions", kernelOptions)) {
// auto keys = kernelOptions.keys();
// for(auto key: keys) {
// bool value = false;
// if(kernelOptions.getValue(key, value)) {
// if(key == "DenormsAreZero") {
// _kernelOptions.push_back(std::make_pair(CLProgram::Option::DenormsAreZero, value));
// } else if(key == "FastRelaxedMath") {
// _kernelOptions.push_back(std::make_pair(CLProgram::Option::FastRelaxedMath, value));
// } else if(key == "FiniteMathOnly") {
// _kernelOptions.push_back(std::make_pair(CLProgram::Option::FiniteMathOnly, value));
// } else if(key == "KernelArgInfo") {
// _kernelOptions.push_back(std::make_pair(CLProgram::Option::KernelArgInfo, value));
// } else if(key == "MadEnable") {
// _kernelOptions.push_back(std::make_pair(CLProgram::Option::MadEnable, value));
// } else if(key == "NoSignedZero") {
// _kernelOptions.push_back(std::make_pair(CLProgram::Option::NoSignedZero, value));
// } else if(key == "OptDisable") {
// _kernelOptions.push_back(std::make_pair(CLProgram::Option::OptDisable, value));
// } else if(key == "SinglePrecisionConstant") {
// _kernelOptions.push_back(std::make_pair(CLProgram::Option::SinglePrecisionConstant, value));
// } else if(key == "StrictAliasing") {
// _kernelOptions.push_back(std::make_pair(CLProgram::Option::StrictAliasing, value));
// } else if(key == "UnsafeMathOptimizations") {
// _kernelOptions.push_back(std::make_pair(CLProgram::Option::UnsafeMathOptimizations, value));
// }
// }
// }
// }
// }
// */
//
// std::string kernelPath = "";
// if (dictionary.hasKey("Kernel")) {
// if(dictionary.getValue("Kernel", kernelPath)) {
// kernelPath = findPath(kernelPath);
// }
// }
// if (kernelPath != "") {
// _kernelSourceFile = new ghoul::filesystem::File(kernelPath, false);
// }
//
//}
//
//RenderableVolumeCL::~RenderableVolumeCL() {
// deinitialize();
// delete _kernelMutex;
//}
//
//bool RenderableVolumeCL::initialize() {
// assert(_filename != "");
// // ------ VOLUME READING ----------------
// ghoul::RawVolumeReader rawReader(_hints);
// _volume = rawReader.read(_filename);
// glm::size3_t d = _volume->dimensions();
//
// // ------ SETUP GEOMETRY ----------------
// const GLfloat size = 1.0f;
// const GLfloat vertex_texcoord_data[] = { // square of two triangles (sigh)
// // x y z s t
// -size, -size, 0.0f, 0.0f, 0.0f,
// size, size, 0.0f, 1.0f, 1.0f,
// -size, size, 0.0f, 0.0f, 1.0f,
// -size, -size, 0.0f, 0.0f, 0.0f,
// size, -size, 0.0f, 1.0f, 0.0f,
// size, size, 0.0f, 1.0f, 1.0f
// };
//
// GLuint vertexPositionBuffer;
// glGenVertexArrays(1, &_screenQuad); // generate array
// glBindVertexArray(_screenQuad); // bind array
// glGenBuffers(1, &vertexPositionBuffer); // generate buffer
// glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer
// glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_texcoord_data), vertex_texcoord_data, GL_STATIC_DRAW);
//
// // Vertex positions
// GLuint vertexLocation = 2;
// glEnableVertexAttribArray(vertexLocation);
// glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), reinterpret_cast<void*>(0));
//
// // Texture coordinates
// GLuint texcoordLocation = 0;
// glEnableVertexAttribArray(texcoordLocation);
// glVertexAttribPointer(texcoordLocation, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (void*)(3*sizeof(GLfloat)));
//
// glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer
// glBindVertexArray(0); //unbind array
//
// _boundingBox = new sgct_utils::SGCTBox(1.0f, sgct_utils::SGCTBox::Regular);
//
// // ------ SETUP SHADERS -----------------
// // TODO error control or better design pattern
// OsEng.ref().configurationManager().getValue("RaycastProgram", _fboProgram);
// OsEng.ref().configurationManager().getValue("Quad", _quadProgram);
//
// // ------ SETUP FBO ---------------------
// _fbo = new ghoul::opengl::FramebufferObject();
// _fbo->activate();
//
// size_t x = sgct::Engine::instance()->getActiveXResolution();
// size_t y = sgct::Engine::instance()->getActiveYResolution();
// _backTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1));
// _frontTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1));
// _output = new ghoul::opengl::Texture(glm::size3_t(x,y,1));
// _backTexture->uploadTexture();
// _frontTexture->uploadTexture();
// _output->uploadTexture();
// _fbo->attachTexture(_backTexture, GL_COLOR_ATTACHMENT0);
// _fbo->attachTexture(_frontTexture, GL_COLOR_ATTACHMENT1);
//
// _fbo->deactivate();
//
// _context = OsEng.clContext();
// _commands = _context.createCommandQueue();
//
// _clBackTexture = _context.createTextureFromGLTexture(CL_MEM_READ_ONLY, *_backTexture);
// _clFrontTexture = _context.createTextureFromGLTexture(CL_MEM_READ_ONLY, *_frontTexture);
// _clVolume = _context.createTextureFromGLTexture(CL_MEM_READ_ONLY, *_volume);
// _clOutput = _context.createTextureFromGLTexture(CL_MEM_WRITE_ONLY, *_output);
//
// auto privateCallback = [this](const ghoul::filesystem::File& file) {
// safeKernelCompilation();
// };
//
// _kernelSourceFile = new ghoul::filesystem::File(_kernelSourceFile->path(), false);
// if(_kernelUpdateOnSave)
// _kernelSourceFile->setCallback(privateCallback);
//
// safeKernelCompilation();
//
// size_t local_x = 32;
// size_t local_y = 32;
// while (local_x > 1) {
// if(x % local_x == 0)
// break;
// local_x /= 2;
// }
// while (local_y > 1) {
// if(y % local_y == 0)
// break;
// local_y /= 2;
// }
// _ws = new ghoul::opencl::CLWorkSize ({x,y}, {local_x,local_y});
//
// return true;
//
//}
//
//bool RenderableVolumeCL::deinitialize() {
//
// delete _ws;
// _ws = nullptr;
//
// return true;
//}
//
//void RenderableVolumeCL::render(const Camera *camera, const psc &thisPosition) {
//
// if( ! _kernel.isValidKernel())
// return;
//
// float speed = 50.0f;
// float time = sgct::Engine::getTime();
// glm::mat4 transform = camera->viewProjectionMatrix();
//
// 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));
//
//
// if(_kernel.isValidKernel()) {
// _stepSize = 0.01f;
//
// // ------ DRAW TO FBO -------------------
// GLuint sgctFBO = ghoul::opengl::FramebufferObject::getActiveObject(); // Save SGCTs main FBO
// _fbo->activate();
// _fboProgram->activate();
// _fboProgram->setUniform("modelViewProjection", transform);
//
// // 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
// 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);
//
// _fboProgram->deactivate();
// _fbo->deactivate();
//
// // ------ DRAW TO SCREEN ----------------
// glBindFramebuffer(GL_FRAMEBUFFER, sgctFBO); // Re-bind SGCTs main FBO
//
//
//
// glFinish();
// _commands.enqueueKernelBlocking(_kernel, *_ws);
// _commands.finish();
// _quadProgram->activate();
// glActiveTexture(GL_TEXTURE0);
// _output->bind();
// glClearColor(0.0f, 0.0f, 0.0f, 0);
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// glBindVertexArray(_screenQuad);
// glDrawArrays(GL_TRIANGLES, 0, 6);
// glBindVertexArray(0);
//
// _quadProgram->deactivate();
//
// }
//
//
//
//}
//
//void RenderableVolumeCL::update() {
//
//}
//
//void RenderableVolumeCL::safeKernelCompilation() {
// std::string _loggerCat = "RenderableVolumeCL::safeKernelCompilation";
// if(_context.isValidContext()) {
//
// ghoul::opencl::CLProgram tmpProgram = _context.createProgram(_kernelSourceFile->path());
// tmpProgram.setOption(ghoul::opencl::CLProgram::Option::OptDisable, true);
// tmpProgram.setOption(ghoul::opencl::CLProgram::Option::KernelArgInfo, true);
// if(tmpProgram.build()) {
// ghoul::opencl::CLKernel tmpKernel = tmpProgram.createKernel("volumeraycaster");
// if(tmpKernel.isValidKernel()) {
// tmpKernel.setArgument(0, &_clFrontTexture);
// tmpKernel.setArgument(1, &_clBackTexture);
// tmpKernel.setArgument(2, &_clVolume);
// tmpKernel.setArgument(3, &_clOutput);
//
// // do the actual assignment behind locked doors
// _kernelMutex->lock();
// _program = tmpProgram;
// _kernel = tmpKernel;
// _kernelMutex->unlock();
//
// LDEBUG("Done updating kernel");
// } else {
// LWARNING("Kernel is not valid");
// }
// } else {
// LWARNING("Could not build CLProgram");
// }
// } else {
// LWARNING("No valid CLContext");
// }
//}
// /*
//void RenderableVolumeCL::safeUpdateTexture(const ghoul::filesystem::File& file) {
// int fileID = 0;
// for (fileID = 0; fileID < _transferFunctionsFiles.size(); ++fileID) {
// if (_transferFunctionsFiles.at(fileID) == &file) {
// //LDEBUG("Transferfunction found at id " << fileID);
// break;
// }
// }
// if(fileID == _transferFunctionsFiles.size())
// return;
//
// LDEBUG("Updating transferfunction");
// // create the new texture
// ghoul::opengl::Texture* newTexture = ghoul::opengl::loadTexture(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);
//
// if(clNewTexture == 0) {
// delete newTexture;
// return;
// }
//
// // everything is ok, critical point to replace current texture pointers
// _textureLock->lock();
//
// // deallocate current texture
// delete _transferFunctions.at(fileID);
// clReleaseMemObject(_clTransferFunctions.at(fileID));
//
// // set the new texture
// _transferFunctions.at(fileID) = newTexture;
// _clTransferFunctions.at(fileID) = clNewTexture;
//
// // update kernel
// // __kernel arguments(front, back, output, [_volumes], .. fileID))
// _kernel.setArgument(3 + _volumes.size() + fileID, &clNewTexture);
//
// // end of critical section
// _textureLock->unlock();
// }
//}
//*/
//
//} // namespace openspace

File diff suppressed because it is too large Load Diff

View File

@@ -22,262 +22,270 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
// open space includes
#include <openspace/rendering/renderablevolumegl.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/util/powerscaledcoordinate.h>
#include <openspace/util/kameleonwrapper.h>
#include <ghoul/opengl/texturereader.h>
#include <ghoul/opencl/clworksize.h>
#include <ghoul/filesystem/filesystem.h>
#include <sgct.h>
#include <algorithm>
#include <openspace/engine/openspaceengine.h>
#include <openspace/util/constants.h>
namespace {
std::string _loggerCat = "RenderableVolumeGL";
const std::string _loggerCat = "RenderableVolumeGL";
}
namespace openspace {
RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary):
RenderableVolume(dictionary),
_backTexture(nullptr), _frontTexture(nullptr), _screenQuad(0),
_programUpdateOnSave(false) {
_shaderMutex = new std::mutex;
RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary)
: RenderableVolume(dictionary)
, _transferFunctionName("")
, _volumeName("")
, _boxScaling(1.0, 1.0, 1.0)
, _w(0.f)
, _updateTransferfunction(false)
, _id(-1)
{
std::string name;
bool success = dictionary.getValue(constants::scenegraphnode::keyName, name);
assert(success);
_filename = "";
if(dictionary.hasKey("Volume")) {
if(dictionary.getValue("Volume", _filename)) {
_filename = findPath(_filename);
}
}
LDEBUG("filename: " << _filename);
ghoul::Dictionary hintsDictionary;
if(dictionary.hasKey("Hints"))
dictionary.getValue("Hints", hintsDictionary);
_hints = readHints(hintsDictionary);
success = dictionary.getValueSafe(constants::renderablevolumegl::keyVolume,
_filename);
if (!success) {
LERROR("Node '" << name << "' did not contain a valid '" <<
constants::renderablevolumegl::keyVolume << "'");
return;
}
_filename = findPath(_filename);
std::string vshaderpath = "";
std::string fshaderpath = "";
if (dictionary.hasKey("Shaders")) {
ghoul::Dictionary shaderDictionary;
if(dictionary.getValue("Shaders", shaderDictionary)) {
if (shaderDictionary.hasKey("VertexShader")) {
shaderDictionary.getValue("VertexShader", vshaderpath);
}
if (shaderDictionary.hasKey("FragmentShader")) {
shaderDictionary.getValue("FragmentShader", fshaderpath);
}
vshaderpath = findPath(vshaderpath);
fshaderpath = findPath(fshaderpath);
_vertexSourceFile = new ghoul::filesystem::File(vshaderpath, false);
_fragmentSourceFile = new ghoul::filesystem::File(fshaderpath, false);
_twopassProgram = new ghoul::opengl::ProgramObject("TwoPassProgram");
ghoul::opengl::ShaderObject* vertexShader = new ghoul::opengl::ShaderObject(ghoul::opengl::ShaderObject::ShaderTypeVertex,vshaderpath);
ghoul::opengl::ShaderObject* fragmentShader = new ghoul::opengl::ShaderObject(ghoul::opengl::ShaderObject::ShaderTypeFragment,fshaderpath);
_twopassProgram->attachObject(vertexShader);
_twopassProgram->attachObject(fragmentShader);
}
}
if(dictionary.hasKey("UpdateOnSave")) {
dictionary.getValue("UpdateOnSave", _programUpdateOnSave);
}
LDEBUG("Volume Filename: " << _filename);
dictionary.getValueSafe(constants::renderablevolumegl::keyHints, _hintsDictionary);
_transferFunction = nullptr;
_transferFunctionFile = nullptr;
_transferFunctionPath = "";
success = dictionary.getValueSafe(
constants::renderablevolumegl::keyTransferFunction, _transferFunctionPath);
if (!success) {
LERROR("Node '" << name << "' did not contain a valid '" <<
constants::renderablevolumegl::keyTransferFunction << "'");
return;
}
_transferFunctionPath = findPath(_transferFunctionPath);
_transferFunctionFile = new ghoul::filesystem::File(_transferFunctionPath, true);
_samplerFilename = "";
success = dictionary.getValueSafe(constants::renderablevolumegl::keySampler,
_samplerFilename);
if (!success) {
LERROR("Node '" << name << "' did not contain a valid '" <<
constants::renderablevolumegl::keySampler << "'");
return;
}
_samplerFilename = findPath(_samplerFilename);
glm::vec4 scalingVec4(_boxScaling, _w);
success = dictionary.getValueSafe(constants::renderablevolumegl::keyBoxScaling,
scalingVec4);
if (success) {
_boxScaling = scalingVec4.xyz;
_w = scalingVec4.w;
}
else {
success = dictionary.getValueSafe(constants::renderablevolumegl::keyBoxScaling,
_boxScaling);
if (!success) {
LERROR("Node '" << name << "' did not contain a valid '" <<
constants::renderablevolumegl::keyBoxScaling << "'");
return;
}
}
dictionary.getValueSafe(constants::renderablevolumegl::keyVolumeName, _volumeName);
dictionary.getValueSafe(constants::renderablevolumegl::keyTransferFunctionName,
_transferFunctionName);
setBoundingSphere(PowerScaledScalar::CreatePSS(glm::length(_boxScaling)*pow(10,_w)));
}
RenderableVolumeGL::~RenderableVolumeGL() {
deinitialize();
if(_fbo)
delete _fbo;
if(_backTexture)
delete _backTexture;
if(_frontTexture)
delete _frontTexture;
if(_volume)
delete _volume;
if(_boundingBox)
delete _boundingBox;
if(_transferFunctionFile)
delete _transferFunctionFile;
if(_transferFunction)
delete _transferFunction;
}
bool RenderableVolumeGL::initialize() {
assert(_filename != "");
// assert(_filename != "");
// ------ VOLUME READING ----------------
ghoul::RawVolumeReader rawReader(_hints);
_volume = rawReader.read(_filename);
// ------ SETUP GEOMETRY ----------------
const GLfloat size = 1.0f;
const GLfloat vertex_texcoord_data[] = { // square of two triangles (sigh)
// x y z s t
-size, -size, 0.0f, 0.0f, 0.0f,
size, size, 0.0f, 1.0f, 1.0f,
-size, size, 0.0f, 0.0f, 1.0f,
-size, -size, 0.0f, 0.0f, 0.0f,
size, -size, 0.0f, 1.0f, 0.0f,
size, size, 0.0f, 1.0f, 1.0f
};
GLuint vertexPositionBuffer;
glGenVertexArrays(1, &_screenQuad); // generate array
glBindVertexArray(_screenQuad); // bind array
glGenBuffers(1, &vertexPositionBuffer); // generate buffer
glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_texcoord_data), vertex_texcoord_data, GL_STATIC_DRAW);
// Vertex positions
GLuint vertexLocation = 2;
glEnableVertexAttribArray(vertexLocation);
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), reinterpret_cast<void*>(0));
// Texture coordinates
GLuint texcoordLocation = 0;
glEnableVertexAttribArray(texcoordLocation);
glVertexAttribPointer(texcoordLocation, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (void*)(3*sizeof(GLfloat)));
glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer
glBindVertexArray(0); //unbind array
_boundingBox = new sgct_utils::SGCTBox(1.0f, sgct_utils::SGCTBox::Regular);
// ------ SETUP SHADERS -----------------
// TODO error control or better design pattern
OsEng.ref().configurationManager().getValue("RaycastProgram", _fboProgram);
auto privateCallback = [this](const ghoul::filesystem::File& file) {
safeShaderCompilation();
};
if(_programUpdateOnSave) {
_vertexSourceFile->setCallback(privateCallback);
_fragmentSourceFile->setCallback(privateCallback);
}
_twopassProgram->compileShaderObjects();
_twopassProgram->linkProgramObject();
_twopassProgram->setUniform("texBack", 0);
_twopassProgram->setUniform("texFront", 1);
_twopassProgram->setUniform("texVolume", 2);
//OsEng.ref().configurationManager().getValue("TwoPassProgram", _twopassProgram);
// ------ SETUP FBO ---------------------
_fbo = new ghoul::opengl::FramebufferObject();
_fbo->activate();
int x = sgct::Engine::instance()->getActiveXResolution();
int y = sgct::Engine::instance()->getActiveYResolution();
_backTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1));
_frontTexture = new ghoul::opengl::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();
// <<<<<<< HEAD
// =======
// _volume = loadVolume(_filename, _hintsDictionary);
// _volume->uploadTexture();
// _transferFunction = loadTransferFunction(_transferFunctionPath);
// _transferFunction->uploadTexture();
// >>>>>>> feature/fieldlines
// TODO: fix volume an transferfunction names
if(_filename != "") {
_volume = loadVolume(_filename, _hintsDictionary);
_boxOffset = getVolumeOffset(_filename, _hintsDictionary);
_volume->uploadTexture();
OsEng.renderEngine().abuffer()->addVolume(_volumeName, _volume);
}
if(_transferFunctionPath != "") {
_transferFunction = loadTransferFunction(_transferFunctionPath);
_transferFunction->uploadTexture();
OsEng.renderEngine().abuffer()->addTransferFunction(_transferFunctionName, _transferFunction);
auto textureCallback = [this](const ghoul::filesystem::File& file) {
_updateTransferfunction = true;
};
_transferFunctionFile->setCallback(textureCallback);
}
// add the sampler and get the ID
_id = OsEng.renderEngine().abuffer()->addSamplerfile(_samplerFilename);
OsEng.configurationManager().getValue("RaycastProgram", _boxProgram);
_MVPLocation = _boxProgram->uniformLocation("modelViewProjection");
_modelTransformLocation = _boxProgram->uniformLocation("modelTransform");
_typeLocation = _boxProgram->uniformLocation("volumeType");
// ============================
// GEOMETRY (quad)
// ============================
const GLfloat size = 0.5f;
const GLfloat vertex_data[] = { // square of two triangles (sigh)
// x, y, z, s,
-size, -size, size, _w,
size, size, size, _w,
-size, size, size, _w,
-size, -size, size, _w,
size, -size, size, _w,
size, size, size, _w,
-size, -size, -size, _w,
size, size, -size, _w,
-size, size, -size, _w,
-size, -size, -size, _w,
size, -size, -size, _w,
size, size, -size, _w,
size, -size, -size, _w,
size, size, size, _w,
size, -size, size, _w,
size, -size, -size, _w,
size, size, -size, _w,
size, size, size, _w,
-size, -size, -size, _w,
-size, size, size, _w,
-size, -size, size, _w,
-size, -size, -size, _w,
-size, size, -size, _w,
-size, size, size, _w,
-size, size, -size, _w,
size, size, size, _w,
-size, size, size, _w,
-size, size, -size, _w,
size, size, -size, _w,
size, size, size, _w,
-size, -size, -size, _w,
size, -size, size, _w,
-size, -size, size, _w,
-size, -size, -size, _w,
size, -size, -size, _w,
size, -size, size, _w,
};
GLuint vertexPositionBuffer;
glGenVertexArrays(1, &_boxArray); // generate array
glBindVertexArray(_boxArray); // bind array
glGenBuffers(1, &vertexPositionBuffer); // generate buffer
glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*4, reinterpret_cast<void*>(0));
glEnableVertexAttribArray(0);
return true;
}
bool RenderableVolumeGL::deinitialize() {
return true;
}
void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) {
float speed = 50.0f;
float time = sgct::Engine::getTime();
glm::mat4 transform = camera->viewProjectionMatrix();
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));
_stepSize = 0.01f;
// ------ DRAW TO FBO -------------------
GLuint sgctFBO = ghoul::opengl::FramebufferObject::getActiveObject(); // Save SGCTs main FBO
_fbo->activate();
_fboProgram->activate();
_fboProgram->setUniform("modelViewProjection", transform);
// 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
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);
_fboProgram->deactivate();
_fbo->deactivate();
// ------ DRAW TO SCREEN ----------------
glBindFramebuffer(GL_FRAMEBUFFER, sgctFBO); // Re-bind SGCTs main FBO
// Draw screenquad
glClearColor(0.2f, 0.2f, 0.2f, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_shaderMutex->lock();
_twopassProgram->activate();
_twopassProgram->setUniform("stepSize", _stepSize);
// Set textures
glActiveTexture(GL_TEXTURE0);
_backTexture->bind();
glActiveTexture(GL_TEXTURE1);
_frontTexture->bind();
glActiveTexture(GL_TEXTURE2);
_volume->bind();
glBindVertexArray(_screenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
_twopassProgram->deactivate();
_shaderMutex->unlock();
if(_updateTransferfunction) {
_updateTransferfunction = false;
ghoul::opengl::Texture* transferFunction = loadTransferFunction(_transferFunctionPath);
if(transferFunction) {
const void* data = transferFunction->pixelData();
glBindBuffer(GL_COPY_READ_BUFFER, *transferFunction);
_transferFunction->bind();
glTexImage1D( GL_TEXTURE_1D, 0, _transferFunction->internalFormat(),
_transferFunction->width(),0, _transferFunction->format(),
_transferFunction->dataType(), data);
delete transferFunction;
LDEBUG("Updated transferfunction!");
}
}
glm::mat4 transform = glm::mat4(1.0);
transform = glm::scale(transform, _boxScaling);
// fetch data
psc currentPosition = thisPosition;
psc campos = camera->position();
glm::mat4 camrot = camera->viewRotationMatrix();
PowerScaledScalar scaling = camera->scaling();
// psc addon(-1.1,0.0,0.0,0.0);
// currentPosition += addon;
psc addon(_boxOffset/100.0f); // TODO: Proper scaling/units
currentPosition += addon; // Move box to model barycenter
// TODO: Use _id to identify this volume
_boxProgram->activate();
_boxProgram->setUniform(_typeLocation, _id);
_boxProgram->setUniform("modelViewProjection", camera->viewProjectionMatrix());
_boxProgram->setUniform("modelTransform", transform);
_boxProgram->setUniform("campos", campos.vec4());
_boxProgram->setUniform("objpos", currentPosition.vec4());
_boxProgram->setUniform("camrot", camrot);
_boxProgram->setUniform("scaling", scaling.vec2());
// make sure GL_CULL_FACE is enabled (it should be)
glEnable(GL_CULL_FACE);
// Draw backface
glCullFace(GL_FRONT);
glBindVertexArray(_boxArray);
glDrawArrays(GL_TRIANGLES, 0, 6*6);
// Draw frontface (now the normal cull face is is set)
glCullFace(GL_BACK);
glDrawArrays(GL_TRIANGLES, 0, 6*6);
_boxProgram->deactivate();
}
void RenderableVolumeGL::update() {
}
void RenderableVolumeGL::safeShaderCompilation() {
_shaderMutex->lock();
_twopassProgram->rebuildFromFile();
_twopassProgram->compileShaderObjects();
_twopassProgram->linkProgramObject();
_twopassProgram->setUniform("texBack", 0);
_twopassProgram->setUniform("texFront", 1);
_twopassProgram->setUniform("texVolume", 2);
_shaderMutex->unlock();
}
} // namespace openspace
} // namespace openspace

View File

@@ -27,6 +27,7 @@
#include <openspace/engine/openspaceengine.h>
#include <openspace/scenegraph/scenegraph.h>
#include <openspace/util/camera.h>
#include <openspace/util/time.h>
#include "sgct.h"
@@ -34,6 +35,10 @@
#include <array>
#include <openspace/abuffer/abufferSingleLinked.h>
#include <openspace/abuffer/abufferfixed.h>
#include <openspace/abuffer/abufferdynamic.h>
namespace {
const std::string _loggerCat = "RenderEngine";
}
@@ -42,6 +47,7 @@ namespace openspace {
RenderEngine::RenderEngine()
: _mainCamera(nullptr)
, _sceneGraph(nullptr)
, _abuffer(nullptr)
{
}
@@ -52,20 +58,29 @@ RenderEngine::~RenderEngine()
bool RenderEngine::initialize()
{
// LDEBUG("RenderEngine::initialize()");
// init camera and set temporary position and scaling
_mainCamera = new Camera();
_mainCamera->setScaling(glm::vec2(1.0, -8.0));
_mainCamera->setPosition(psc(0.0, 0.0, 1.499823, 11.0));
_mainCamera->setPosition(psc(0.f, 0.f, 1.499823f, 11.f));
// if master, setup interaction
//if (sgct::Engine::instance()->isMaster())
OsEng.interactionHandler().setCamera(_mainCamera);
#if ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED
_abuffer = new ABufferSingleLinked();
#elif ABUFFER_IMPLEMENTATION == ABUFFER_FIXED
_abuffer = new ABufferFixed();
#elif ABUFFER_IMPLEMENTATION == ABUFFER_DYNAMIC
_abuffer = new ABufferDynamic();
#endif
return true;
}
bool RenderEngine::initializeGL()
{
// LDEBUG("RenderEngine::initializeGL()");
sgct::SGCTWindow* wPtr = sgct::Engine::instance()->getActiveWindowPtr();
// TODO: Fix the power scaled coordinates in such a way that these values can be
@@ -76,6 +91,7 @@ bool RenderEngine::initializeGL()
// development
// sgct::Engine::instance()->setNearAndFarClippingPlanes(0.1f,100.0f);
sgct::Engine::instance()->setNearAndFarClippingPlanes(0.0001f, 100.0f);
sgct::Engine::instance()->setNearAndFarClippingPlanes(0.1f, 200.0f);
// calculating the maximum field of view for the camera, used to
// determine visibility of objects in the scene graph
@@ -133,6 +149,8 @@ bool RenderEngine::initializeGL()
_mainCamera->setMaxFov(maxFov);
}
_abuffer->initialize();
// successful init
return true;
}
@@ -152,8 +170,10 @@ void RenderEngine::postSynchronizationPreDraw()
void RenderEngine::render()
{
// SGCT resets certain settings
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
//glEnable(GL_DEPTH_TEST);
//glEnable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
// setup the camera for the current frame
const glm::vec3 eyePosition
@@ -175,8 +195,13 @@ void RenderEngine::render()
// render the scene starting from the root node
_abuffer->clear();
_abuffer->preRender();
_sceneGraph->render(_mainCamera);
_abuffer->postRender();
_abuffer->resolve();
#ifndef OPENSPACE_VIDEO_EXPORT
// Print some useful information on the master viewport
if (sgct::Engine::instance()->isMaster()) {
// Apple usually has retina screens
@@ -192,6 +217,23 @@ void RenderEngine::render()
const psc origin = OsEng.interactionHandler().getOrigin();
const PowerScaledScalar pssl = (position - origin).length();
const std::string time = Time::ref().currentTimeUTC().c_str();
Freetype::print(
sgct_text::FontManager::instance()->getFont("SGCTFont", FONT_SIZE),
FONT_SIZE, FONT_SIZE * 18, "Date: %s", time.c_str()
);
Freetype::print(
sgct_text::FontManager::instance()->getFont("SGCTFont", FONT_SIZE),
FONT_SIZE, FONT_SIZE * 16, "Avg. Frametime: %.10f", sgct::Engine::instance()->getAvgDt()
);
Freetype::print(
sgct_text::FontManager::instance()->getFont("SGCTFont", FONT_SIZE),
FONT_SIZE, FONT_SIZE * 14, "Drawtime: %.10f", sgct::Engine::instance()->getDrawTime()
);
Freetype::print(
sgct_text::FontManager::instance()->getFont("SGCTFont", FONT_SIZE),
FONT_SIZE, FONT_SIZE * 12, "Frametime: %.10f", sgct::Engine::instance()->getDt()
);
Freetype::print(
sgct_text::FontManager::instance()->getFont("SGCTFont", FONT_SIZE),
FONT_SIZE, FONT_SIZE * 10, "Origin: (%.5f, %.5f, %.5f, %.5f)", origin[0],
@@ -211,7 +253,10 @@ void RenderEngine::render()
Freetype::print(
sgct_text::FontManager::instance()->getFont("SGCTFont", FONT_SIZE),
FONT_SIZE, FONT_SIZE * 2, "Scaling: (%.10f, %.2f)", scaling[0], scaling[1]);
}
#endif
}
SceneGraph* RenderEngine::sceneGraph()
@@ -401,4 +446,8 @@ Camera* RenderEngine::camera() const {
return _mainCamera;
}
ABuffer* RenderEngine::abuffer() const {
return _abuffer;
}
} // namespace openspace

View File

@@ -395,6 +395,7 @@ void RenderableStars::render(const Camera* camera, const psc& thisPosition){
_haloProgram->deactivate();
#ifdef GLPOINTS
/*
// ---------------------- RENDER POINTS -----------------------------
_pointProgram->activate();
@@ -415,7 +416,7 @@ void RenderableStars::render(const Camera* camera, const psc& thisPosition){
glDisable(GL_BLEND);
_pointProgram->deactivate();
*/
#endif
}

View File

@@ -61,7 +61,9 @@ bool VolumeRaycasterBox::initialize() {
// ------ SETUP SHADER -----------------
OsEng.configurationManager().getValue("RaycastProgram", _boxProgram);
_MVPLocation = _boxProgram->uniformLocation("modelViewProjection");
_MVPLocation = _boxProgram->uniformLocation("modelViewProjection");
_modelTransformLocation = _boxProgram->uniformLocation("modelTransform");
_typeLocation = _boxProgram->uniformLocation("volumeType");
// ------ SETUP FBO ---------------------
_fbo = new FramebufferObject();
@@ -69,8 +71,6 @@ bool VolumeRaycasterBox::initialize() {
// 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;
@@ -89,11 +89,13 @@ bool VolumeRaycasterBox::initialize() {
return true;
}
void VolumeRaycasterBox::render(const glm::mat4& MVP) {
void VolumeRaycasterBox::render(const glm::mat4& MVP,const glm::mat4& transform, int type) {
GLuint activeFBO = FramebufferObject::getActiveObject(); // Save SGCTs main FBO
_fbo->activate();
_boxProgram->activate();
_boxProgram->setUniform(_MVPLocation, MVP);
_boxProgram->setUniform(_MVPLocation, MVP);
_boxProgram->setUniform(_modelTransformLocation, transform);
_boxProgram->setUniform(_typeLocation, type);
sgct_core::Frustum::FrustumMode mode = sgct::Engine::instance()->
getActiveWindowPtr()->

View File

@@ -55,11 +55,19 @@ Ephemeris* Ephemeris::createFromDictionary(const ghoul::Dictionary& dictionary)
Ephemeris::Ephemeris()
{
}
Ephemeris::Ephemeris(const ghoul::Dictionary& dictionary)
{
}
Ephemeris::~Ephemeris()
{
}
bool Ephemeris::initialize() {
return true;
}
void Ephemeris::update() {}
} // namespace openspace

View File

@@ -24,11 +24,14 @@
// open space includes
#include <openspace/scenegraph/scenegraph.h>
#include <openspace/rendering/planets/renderableplanet.h>
#include <openspace/interaction/interactionhandler.h>
#include <openspace/util/spice.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/interaction/interactionhandler.h>
#include <openspace/rendering/planets/renderableplanet.h>
#include <openspace/scripting/scriptengine.h>
#include <openspace/util/spice.h>
#include <openspace/util/constants.h>
#include <openspace/util/shadercreator.h>
#include <openspace/query/query.h>
// ghoul includes
#include "ghoul/opengl/programobject.h"
@@ -46,26 +49,135 @@
#include <iostream>
#include <string>
namespace {
const std::string _loggerCat = "SceneGraph";
const std::string _rootNodeName = "Root";
const std::string _moduleExtension = ".mod";
#include <chrono>
//#include <unistd.h>
namespace {
const std::string _loggerCat = "SceneGraph";
const std::string _moduleExtension = ".mod";
}
namespace openspace {
void printTree(SceneGraphNode* node, std::string pre = "")
{
LDEBUGC("Tree", pre << node->nodeName());
const std::vector<SceneGraphNode*>& children = node->children();
for (SceneGraphNode* child : children)
printTree(child, pre + " ");
namespace luascriptfunctions {
/**
* \ingroup LuaScripts
* setPropertyValue(string, *):
* Sets the property identified by the URI in the first argument to the value passed to
* the second argument. The type of the second argument is arbitrary, but it must agree
* with the type the denoted Property expects
*/
int property_setValue(lua_State* L) {
using ghoul::lua::luaTypeToString;
const std::string _loggerCat = "property_setValue";
// TODO Check for argument number (ab)
std::string uri = luaL_checkstring(L, -2);
const int type = lua_type(L, -1);
// boost::any propertyValue;
// switch (type) {
// case LUA_TNONE:
// case LUA_TLIGHTUSERDATA:
// case LUA_TFUNCTION:
// case LUA_TUSERDATA:
// case LUA_TTHREAD:
// LERROR("Function parameter was of type '" << luaTypeToString(type) << "'");
// return 0;
// case LUA_TNIL:
// propertyValue = 0;
// break;
// case LUA_TBOOLEAN:
// propertyValue = lua_toboolean(L, -1);
// break;
// case LUA_TNUMBER:
// propertyValue = lua_tonumber(L, -1);
// break;
// case LUA_TSTRING:
// propertyValue = std::string(lua_tostring(L, -1));
// break;
//case LUA_TTABLE: {
// ghoul::Dictionary d;
// ghoul::lua::populateDictionary(L, d);
// propertyValue = d;
// break;
//}
// }
openspace::properties::Property* prop = property(uri);
if (!prop) {
LERROR("Property with uri '" << uri << "' could not be found");
return 0;
}
if (type != prop->typeLua())
LERROR("Property '" << uri << "' does not accept input of type '"
<< luaTypeToString(type) << "'. Requested type: '"
<< luaTypeToString(prop->typeLua()) << "'");
else
prop->setLua(L);
//prop->set(propertyValue);
return 0;
}
/**
* \ingroup LuaScripts
* getPropertyValue(string):
* Returns the value of the property identified by the passed URI as a Lua object that can
* be passed to the setPropertyValue method.
*/
int property_getValue(lua_State* L) {
const std::string _loggerCat = "property_getValue";
// TODO Check for argument number (ab)
std::string uri = luaL_checkstring(L, -1);
openspace::properties::Property* prop = property(uri);
if (!prop) {
LERROR("Property with uri '" << uri << "' could not be found");
lua_pushnil(L);
}
else {
prop->getLua(L);
//switch (type) {
// case LUA_TNONE:
// case LUA_TLIGHTUSERDATA:
// case LUA_TFUNCTION:
// case LUA_TUSERDATA:
// case LUA_TTHREAD:
// LERROR("Function parameter was of type '" << luaTypeToString(type)
// << "'");
// return 0;
// case LUA_TNIL:
// propertyValue = 0;
// break;
// case LUA_TBOOLEAN:
// propertyValue = lua_toboolean(L, -1);
// break;
// case LUA_TNUMBER:
// propertyValue = lua_tonumber(L, -1);
// break;
// case LUA_TSTRING:
// propertyValue = std::string(lua_tostring(L, -1));
// break;
// case LUA_TTABLE: {
// ghoul::Dictionary d;
// ghoul::lua::populateDictionary(L, d);
// propertyValue = d;
// break;
// }
//}
}
return 1;
}
} // namespace luascriptfunctions
SceneGraph::SceneGraph()
: _focus("Root")
, _position("Root")
: _focus(SceneGraphNode::RootNodeName)
, _position(SceneGraphNode::RootNodeName)
, _root(nullptr)
{
}
@@ -78,16 +190,97 @@ SceneGraph::~SceneGraph()
bool SceneGraph::initialize()
{
LDEBUG("Initializing SceneGraph");
LDEBUG("Creating ProgramObjects");
using ghoul::opengl::ShaderObject;
using ghoul::opengl::ProgramObject;
ProgramObject* po = nullptr;
if (OsEng.ref().configurationManager().hasKey("pscShader")
&& OsEng.ref().configurationManager().getValue("pscShader", po)) {
LWARNING("pscShader already in ConfigurationManager, deleting.");
ShaderCreator sc = OsEng.shaderBuilder();
ProgramObject* tmpProgram;
typedef std::chrono::high_resolution_clock clock_;
typedef std::chrono::duration<double, std::ratio<1> > second_;
std::chrono::time_point<clock_> beg_(clock_::now());
// pscstandard
tmpProgram = sc.buildShader("pscstandard",
"${SHADERS}/pscstandard_vs.glsl",
"${SHADERS}/pscstandard_fs.glsl");
if( ! tmpProgram) return false;
OsEng.ref().configurationManager().setValue("pscShader", tmpProgram);
// RaycastProgram
tmpProgram = sc.buildShader("RaycastProgram",
"${SHADERS}/exitpoints.vert",
"${SHADERS}/exitpoints.frag");
if( ! tmpProgram) return false;
OsEng.ref().configurationManager().setValue("RaycastProgram", tmpProgram);
// // TwoPassProgram
// tmpProgram = sc.buildShader("TwoPassProgram",
// "${SHADERS}/twopassraycaster.vert",
// "${SHADERS}/twopassraycaster.frag");
// if( ! tmpProgram) return false;
// tmpProgram->setUniform("texBack", 0);
// tmpProgram->setUniform("texFront", 1);
// tmpProgram->setUniform("texVolume", 2);
// OsEng.ref().configurationManager().setValue("TwoPassProgram", tmpProgram);
// Quad
tmpProgram = sc.buildShader("Quad",
"${SHADERS}/quadVert.glsl",
"${SHADERS}/quadFrag.glsl");
if (!tmpProgram) return false;
tmpProgram->setUniform("quadTex", 0);
OsEng.ref().configurationManager().setValue("Quad", tmpProgram);
// Star program
tmpProgram = sc.buildShader("Star",
"${SHADERS}/star_vs.glsl",
"${SHADERS}/star_fs.glsl",
"${SHADERS}/star_ge.glsl");
if (!tmpProgram) return false;
OsEng.ref().configurationManager().setValue("StarProgram", tmpProgram);
// Point program
tmpProgram = sc.buildShader("Point",
"${SHADERS}/star_vs.glsl",
"${SHADERS}/star_fs.glsl",
"${SHADERS}/star_ge.glsl");
if (!tmpProgram) return false;
OsEng.ref().configurationManager().setValue("PointProgram", tmpProgram);
double elapsed = std::chrono::duration_cast<second_>(clock_::now() - beg_).count();
LERROR("Time to load shaders: " << elapsed);
/*
auto programCreator = [] ( const std::string& name,
const std::string& vpath,
const std::string& fpath)
{
const std::string vsPath = absPath(vpath);
const std::string fsPath = absPath(fpath);
const ShaderObject::ShaderType vsType = ShaderObject::ShaderType::ShaderTypeVertex;
const ShaderObject::ShaderType fsType = ShaderObject::ShaderType::ShaderTypeFragment;
ProgramObject* po = new ProgramObject(name);
ShaderObject* vs = new ShaderObject(vsType, vsPath, name + "Vertex");
ShaderObject* fs = new ShaderObject(fsType, fsPath, name + "Fragment");
po->attachObject(vs);
po->attachObject(fs);
if ( po->compileShaderObjects() && po->linkProgramObject())
return po;
// unsuccessful compilation, cleanup and return nullptr
delete po;
po = nullptr;
//<<<<<<< HEAD
}
ShaderObject* powerscale_vs
@@ -178,14 +371,51 @@ bool SceneGraph::initialize()
OsEng.ref().configurationManager().setValue("StarProgram", _starProgram);
=======
return po;
};
// pscstandard
tmpProgram = programCreator("pscstandard",
"${SHADERS}/pscstandard_vs.glsl",
"${SHADERS}/pscstandard_fs.glsl");
if( ! tmpProgram) return false;
OsEng.ref().configurationManager().setValue("pscShader", tmpProgram);
// RaycastProgram
tmpProgram = programCreator("RaycastProgram",
"${SHADERS}/exitpoints.vert",
"${SHADERS}/exitpoints.frag");
if( ! tmpProgram) return false;
OsEng.ref().configurationManager().setValue("RaycastProgram", tmpProgram);
// TwoPassProgram
tmpProgram = programCreator("TwoPassProgram",
"${SHADERS}/twopassraycaster.vert",
"${SHADERS}/twopassraycaster.frag");
if( ! tmpProgram) return false;
tmpProgram->setUniform("texBack", 0);
tmpProgram->setUniform("texFront", 1);
tmpProgram->setUniform("texVolume", 2);
OsEng.ref().configurationManager().setValue("TwoPassProgram", tmpProgram);
// Quad
tmpProgram = programCreator("Quad",
"${SHADERS}/quadVert.glsl",
"${SHADERS}/quadFrag.glsl");
if( ! tmpProgram) return false;
tmpProgram->setUniform("quadTex", 0);
OsEng.ref().configurationManager().setValue("Quad", tmpProgram);
*/
//>>>>>>> develop
// Initialize all nodes
for (auto node : _nodes) {
bool success = node->initialize();
if (success)
LDEBUG(node->nodeName() << " initialized successfully!");
LDEBUG(node->name() << " initialized successfully!");
else
LWARNING(node->nodeName() << " not initialized.");
LWARNING(node->name() << " not initialized.");
}
// update the position of all nodes
@@ -217,7 +447,7 @@ bool SceneGraph::initialize()
glm::vec2 scaling{1.0f, -boundf[1]};
boundf[0] *= 5.0f;
psc cameraPosition = positionNode->getPosition();
psc cameraPosition = positionNode->position();
cameraPosition += psc(glm::vec4(0.f, 0.f, boundf));
c->setPosition(cameraPosition);
@@ -240,8 +470,8 @@ bool SceneGraph::deinitialize()
_nodes.erase(_nodes.begin(), _nodes.end());
_allNodes.erase(_allNodes.begin(), _allNodes.end());
_focus = "";
_position = "";
_focus.clear();
_position.clear();
return true;
}
@@ -277,9 +507,9 @@ bool SceneGraph::loadScene(const std::string& sceneDescriptionFilePath,
// initialize the root node
_root = new SceneGraphNode();
_root->setName(_rootNodeName);
_root->setName(SceneGraphNode::RootNodeName);
_nodes.push_back(_root);
_allNodes.emplace(_rootNodeName, _root);
_allNodes.emplace(SceneGraphNode::RootNodeName, _root);
Dictionary dictionary;
//load default.scene
@@ -356,12 +586,12 @@ void SceneGraph::loadModule(const std::string& modulePath)
//each element in this new dictionary becomes a scenegraph node.
SceneGraphNode* node = SceneGraphNode::createFromDictionary(element);
_allNodes.emplace(node->nodeName(), node);
_allNodes.emplace(node->name(), node);
_nodes.push_back(node);
}
// Print the tree
printTree(_root);
//printTree(_root);
}
void SceneGraph::printChildren() const
@@ -373,7 +603,7 @@ SceneGraphNode* SceneGraph::root() const
{
return _root;
}
SceneGraphNode* SceneGraph::sceneGraphNode(const std::string& name) const {
auto it = _allNodes.find(name);
if (it == _allNodes.end())
@@ -382,4 +612,27 @@ SceneGraphNode* SceneGraph::sceneGraphNode(const std::string& name) const {
return it->second;
}
scripting::ScriptEngine::LuaLibrary SceneGraph::luaLibrary() {
scripting::ScriptEngine::LuaLibrary sceneGraphLibrary = {
"",
{
{
"setPropertyValue",
&luascriptfunctions::property_setValue,
"setPropertyValue(string, *): Sets a property identified by the URI in "
"the first argument. The second argument can be any type, but it has to "
" agree with the type that the property expects"
},
{
"getPropertyValue",
&luascriptfunctions::property_getValue,
"getPropertyValue(string): Returns the value the property, identified by "
"the provided URI, has"
}
}
};
return std::move(sceneGraphLibrary);
}
} // namespace openspace

View File

@@ -40,11 +40,17 @@
#include <openspace/engine/openspaceengine.h>
#include <openspace/util/factorymanager.h>
#include <boost/algorithm/string.hpp>
#include <cctype>
namespace {
const std::string _loggerCat = "SceneGraphNode";
}
namespace openspace {
std::string SceneGraphNode::RootNodeName = "Root";
SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& dictionary)
{
@@ -61,22 +67,27 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di
<< keyName << "' key");
return nullptr;
}
dictionary.getValue(keyName, result->_nodeName);
std::string name;
dictionary.getValue(keyName, name);
result->setName(name);
if (dictionary.hasValue<ghoul::Dictionary>(keyRenderable)) {
ghoul::Dictionary renderableDictionary;
dictionary.getValue(keyRenderable, renderableDictionary);
renderableDictionary.setValue(keyName, name);
renderableDictionary.setValue(keyPathModule, path);
renderableDictionary.setValue(keyName, result->_nodeName);
result->_renderable = Renderable::createFromDictionary(renderableDictionary);
if (result->_renderable == nullptr) {
LERROR("Failed to create renderable for SceneGraphNode '"
<< result->_nodeName << "'");
<< result->name() << "'");
return nullptr;
}
LDEBUG("Successfully create renderable for '" << result->_nodeName << "'");
result->addPropertySubOwner(result->_renderable);
LDEBUG("Successfully create renderable for '" << result->name() << "'");
}
if (dictionary.hasKey(keyEphemeris)) {
ghoul::Dictionary ephemerisDictionary;
dictionary.getValue(keyEphemeris, ephemerisDictionary);
@@ -84,10 +95,11 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di
result->_ephemeris = Ephemeris::createFromDictionary(ephemerisDictionary);
if (result->_ephemeris == nullptr) {
LERROR("Failed to create ephemeris for SceneGraphNode '"
<< result->_nodeName << "'");
<< result->name() << "'");
return nullptr;
}
LDEBUG("Successfully create ephemeris for '" << result->_nodeName << "'");
//result->addPropertySubOwner(result->_ephemeris);
LDEBUG("Successfully create ephemeris for '" << result->name() << "'");
}
std::string parentName;
@@ -96,23 +108,22 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di
parentName = "Root";
}
SceneGraphNode* parentNode = getSceneGraphNode(parentName);
SceneGraphNode* parentNode = sceneGraphNode(parentName);
if (parentNode == nullptr) {
LFATAL("Could not find parent named '"
<< parentName << "' for '" << result->_nodeName << "'."
<< parentName << "' for '" << result->name() << "'."
<< " Check module definition order. Skipping module.");
}
parentNode->addNode(result);
LDEBUG("Successfully created SceneGraphNode '"
<< result->_nodeName << "'");
<< result->name() << "'");
return result;
}
SceneGraphNode::SceneGraphNode()
: _parent(nullptr)
, _nodeName("")
, _ephemeris(new StaticEphemeris)
, _renderable(nullptr)
, _renderableVisible(false)
@@ -137,7 +148,7 @@ bool SceneGraphNode::initialize()
bool SceneGraphNode::deinitialize()
{
LDEBUG("Deinitialize: " << _nodeName);
LDEBUG("Deinitialize: " << name());
delete _renderable;
_renderable = nullptr;
@@ -151,7 +162,6 @@ bool SceneGraphNode::deinitialize()
// reset variables
_parent = nullptr;
_nodeName = "";
_renderableVisible = false;
_boundingSphereVisible = false;
_boundingSphere = PowerScaledScalar(0.0, 0.0);
@@ -175,16 +185,20 @@ void SceneGraphNode::evaluate(const Camera* camera, const psc& parentPosition)
_boundingSphereVisible = false;
_renderableVisible = false;
#ifndef OPENSPACE_VIDEO_EXPORT
// check if camera is outside the node boundingsphere
/* if (toCamera.length() > _boundingSphere) {
// check if the boudningsphere is visible before avaluating children
if (!sphereInsideFrustum(thisPosition, _boundingSphere, camera)) {
// the node is completely outside of the camera view, stop evaluating this
// node
//LFATAL(_nodeName << " is outside of frustum");
return;
}
}
*/
#endif
// inside boudningsphere or parts of the sphere is visible, individual
// children needs to be evaluated
_boundingSphereVisible = true;
@@ -192,12 +206,14 @@ void SceneGraphNode::evaluate(const Camera* camera, const psc& parentPosition)
// this node has an renderable
if (_renderable) {
// check if the renderable boundingsphere is visible
_renderableVisible = true;// sphereInsideFrustum(thisPosition, _renderable->getBoundingSphere(), camera);
// _renderableVisible = sphereInsideFrustum(
// thisPosition, _renderable->getBoundingSphere(), camera);
_renderableVisible = true;
}
// evaluate all the children, tail-recursive function(?)
for (auto& child : _children) {
child->evaluate(camera, psc());
child->evaluate(camera, thisPosition);
}
}
@@ -210,7 +226,7 @@ void SceneGraphNode::render(const Camera* camera, const psc& parentPosition)
return;
}*/
if (_renderableVisible) {
if (_renderableVisible && _renderable->isVisible()) {
// LDEBUG("Render");
_renderable->render(camera, thisPosition);
}
@@ -230,36 +246,28 @@ void SceneGraphNode::addNode(SceneGraphNode* child)
_children.push_back(child);
}
void SceneGraphNode::setName(const std::string& name)
{
_nodeName = name;
}
void SceneGraphNode::setParent(SceneGraphNode* parent)
{
_parent = parent;
}
const psc& SceneGraphNode::getPosition() const
const psc& SceneGraphNode::position() const
{
return _ephemeris->position();
}
psc SceneGraphNode::getWorldPosition() const
psc SceneGraphNode::worldPosition() const
{
// recursive up the hierarchy if there are parents available
if (_parent) {
return _ephemeris->position() + _parent->getWorldPosition();
return _ephemeris->position() + _parent->worldPosition();
} else {
return _ephemeris->position();
}
}
std::string SceneGraphNode::nodeName() const{
return _nodeName;
}
SceneGraphNode* SceneGraphNode::parent() const{
SceneGraphNode* SceneGraphNode::parent() const
{
return _parent;
}
const std::vector<SceneGraphNode*>& SceneGraphNode::children() const{
@@ -279,20 +287,27 @@ PowerScaledScalar SceneGraphNode::calculateBoundingSphere(){
for (size_t i = 0; i < _children.size(); ++i) {
// when positions is dynamic, change this part to fins the most distant
// position
PowerScaledScalar child = _children.at(i)->getPosition().length()
PowerScaledScalar child = _children.at(i)->position().length()
+ _children.at(i)->calculateBoundingSphere();
if (child > maxChild) {
maxChild = child;
}
}
_boundingSphere += maxChild;
} else { // leaf
}
// if has a renderable, use that boundingsphere
if (_renderable)
_boundingSphere += _renderable->getBoundingSphere();
// if has a renderable, use that boundingsphere
if (_renderable ) {
PowerScaledScalar renderableBS = _renderable->getBoundingSphere();
if(renderableBS > _boundingSphere)
_boundingSphere = renderableBS;
}
LWARNING(name() << ": " << _boundingSphere);
return _boundingSphere;
}
PowerScaledScalar SceneGraphNode::boundingSphere() const{
return _boundingSphere;
}
@@ -302,7 +317,8 @@ void SceneGraphNode::setRenderable(Renderable* renderable) {
update();
}
const Renderable* SceneGraphNode::getRenderable() const{
const Renderable* SceneGraphNode::renderable() const
{
return _renderable;
}
@@ -338,13 +354,13 @@ bool SceneGraphNode::sphereInsideFrustum(const psc s_pos, const PowerScaledScala
}
}
SceneGraphNode* SceneGraphNode::get(const std::string& name)
SceneGraphNode* SceneGraphNode::childNode(const std::string& name)
{
if (_nodeName == name)
if (this->name() == name)
return this;
else
for (auto it : _children) {
SceneGraphNode* tmp = it->get(name);
SceneGraphNode* tmp = it->childNode(name);
if (tmp != nullptr) {
return tmp;
}
@@ -354,7 +370,7 @@ SceneGraphNode* SceneGraphNode::get(const std::string& name)
void SceneGraphNode::print() const
{
std::cout << _nodeName << std::endl;
std::cout << name() << std::endl;
for (auto it : _children) {
it->print();
}

View File

@@ -24,32 +24,49 @@
#include <openspace/scenegraph/spiceephemeris.h>
#include <openspace/util/constants.h>
#include <openspace/util/spice.h>
namespace {
const std::string _loggerCat = "SpiceEphemeris";
}
namespace openspace {
SpiceEphemeris::SpiceEphemeris(const ghoul::Dictionary& dictionary): _targetName(""),
_originName(""),
_target(0),
_origin(0),
_position()
using namespace constants::spiceephemeris;
SpiceEphemeris::SpiceEphemeris(const ghoul::Dictionary& dictionary)
: _targetName("")
, _originName("")
, _target(0)
, _origin(0)
, _position()
{
dictionary.getValue("Body", _targetName);
dictionary.getValue("Observer", _originName);
const bool hasBody = dictionary.hasKeyAndValue<std::string>(keyBody);
if (hasBody)
dictionary.getValue(keyBody, _targetName);
else
LERROR("SpiceEphemeris does not contain the key '" << keyBody << "'");
const bool hasObserver = dictionary.hasKeyAndValue<std::string>(keyOrigin);
if (hasObserver)
dictionary.getValue(keyOrigin, _originName);
else
LERROR("SpiceEphemeris does not contain the key '" << keyOrigin << "'");
}
SpiceEphemeris::~SpiceEphemeris() {}
bool SpiceEphemeris::initialize() {
if (_targetName != "" && _originName != "") {
bool SpiceEphemeris::initialize()
{
if (!_targetName.empty() && !_originName.empty()) {
int bsuccess = 0;
int osuccess = 0;
Spice::ref().bod_NameToInt(_targetName, &_target, &bsuccess);
Spice::ref().bod_NameToInt(_originName, &_origin, &osuccess);
if (bsuccess && osuccess) {
if (bsuccess && osuccess)
return true;
}
}
return false;

View File

@@ -24,31 +24,27 @@
#include <openspace/scenegraph/staticephemeris.h>
#include <openspace/util/constants.h>
namespace openspace {
StaticEphemeris::StaticEphemeris(const ghoul::Dictionary& dictionary) {
double x = 0.0, y = 0.0, z = 0.0, e = 0.0;
if (dictionary.hasKey("Position.1")) {
dictionary.getValue("Position.1", x);
dictionary.getValue("Position.2", y);
dictionary.getValue("Position.3", z);
dictionary.getValue("Position.4", e);
using namespace constants::staticephemeris;
StaticEphemeris::StaticEphemeris(const ghoul::Dictionary& dictionary)
: _position(0.f, 0.f, 0.f, 0.f)
{
const bool hasPosition = dictionary.hasKeyAndValue<glm::vec4>(keyPosition);
if (hasPosition) {
glm::vec4 tmp;
dictionary.getValue(keyPosition, tmp);
_position = tmp;
}
_position = psc(x, y, z, e);
}
StaticEphemeris::~StaticEphemeris() {}
bool StaticEphemeris::initialize() {
return true;
}
const psc& StaticEphemeris::position() const {
const psc& StaticEphemeris::position() const {
return _position;
}
void StaticEphemeris::update() {
}
} // namespace openspace

View File

@@ -0,0 +1,393 @@
/*****************************************************************************************
* *
* 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 <openspace/scripting/scriptengine.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/lua/lua_helper.h>
#include <fstream>
namespace openspace {
namespace luascriptfunctions {
void printInternal(ghoul::logging::LogManager::LogLevel level, lua_State* L) {
using ghoul::lua::luaTypeToString;
const std::string _loggerCat = "print";
const int type = lua_type(L, -1);
switch (type) {
case LUA_TNONE:
case LUA_TLIGHTUSERDATA:
case LUA_TTABLE:
case LUA_TFUNCTION:
case LUA_TUSERDATA:
case LUA_TTHREAD:
LOG(level, "Function parameter was of type '" <<
luaTypeToString(type) << "'");
case LUA_TNIL:
break;
case LUA_TBOOLEAN:
LOG(level, lua_toboolean(L, -1));
break;
case LUA_TNUMBER:
LOG(level, lua_tonumber(L, -1));
break;
case LUA_TSTRING:
LOG(level, lua_tostring(L, -1));
break;
}
}
/**
* \ingroup LuaScripts
* printDebug(*):
* Logs the passed value to the installed LogManager with a LogLevel of 'Debug'.
* For Boolean, numbers, and strings, the internal values are printed, for all other
* types, the type is printed instead
*/
int printDebug(lua_State* L) {
printInternal(ghoul::logging::LogManager::LogLevel::Debug, L);
return 0;
}
/**
* \ingroup LuaScripts
* printInfo(*):
* Logs the passed value to the installed LogManager with a LogLevel of 'Info'.
* For Boolean, numbers, and strings, the internal values are printed, for all other
* types, the type is printed instead
*/
int printInfo(lua_State* L) {
printInternal(ghoul::logging::LogManager::LogLevel::Info, L);
return 0;
}
/**
* \ingroup LuaScripts
* printWarning(*):
* Logs the passed value to the installed LogManager with a LogLevel of 'Warning'.
* For Boolean, numbers, and strings, the internal values are printed, for all other
* types, the type is printed instead
*/
int printWarning(lua_State* L) {
printInternal(ghoul::logging::LogManager::LogLevel::Warning, L);
return 0;
}
/**
* \ingroup LuaScripts
* printError(*):
* Logs the passed value to the installed LogManager with a LogLevel of 'Error'.
* For Boolean, numbers, and strings, the internal values are printed, for all other
* types, the type is printed instead
*/
int printError(lua_State* L) {
printInternal(ghoul::logging::LogManager::LogLevel::Error, L);
return 0;
}
/**
* \ingroup LuaScripts
* printFatal(*):
* Logs the passed value to the installed LogManager with a LogLevel of 'Fatal'.
* For Boolean, numbers, and strings, the internal values are printed, for all other
* types, the type is printed instead
*/
int printFatal(lua_State* L) {
printInternal(ghoul::logging::LogManager::LogLevel::Fatal, L);
return 0;
}
} // namespace luascriptfunctions
namespace scripting {
namespace {
const std::string _loggerCat = "ScriptEngine";
const std::string _openspaceLibraryName = "openspace";
const std::string _luaGlobalNamespace = "_G";
const std::string _printFunctionName = "print";
const lua_CFunction _printFunctionReplacement = luascriptfunctions::printInfo;
const int _setTableOffset = -3; // -1 (top) -1 (first argument) -1 (second argument)
}
bool ScriptEngine::LuaLibrary::operator<(const LuaLibrary& rhs) const {
return name < rhs.name;
}
ScriptEngine::ScriptEngine()
: _state(nullptr)
{
}
bool ScriptEngine::initialize() {
_state = luaL_newstate();
LDEBUG("Creating Lua state");
if (_state == nullptr) {
LFATAL("Error creating new Lua state: Memory allocation error");
return false;
}
LDEBUG("Open Lua libraries");
luaL_openlibs(_state);
LDEBUG("Add OpenSpace modules");
LDEBUG("Create openspace base library");
lua_newtable(_state);
lua_setglobal(_state, _openspaceLibraryName.c_str());
LDEBUG("Adding base functions");
addBaseLibrary();
LDEBUG("Remap print function");
remapPrintFunction();
return true;
}
void ScriptEngine::deinitialize() {
lua_close(_state);
_state = nullptr;
}
bool ScriptEngine::addLibrary(const ScriptEngine::LuaLibrary& library) {
assert(_state);
if (library.functions.empty()) {
LERROR("Lua library '" << library.name << "' does not have any functions");
return false;
}
//ghoul::lua::logStack(_state);
lua_getglobal(_state, _openspaceLibraryName.c_str());
//ghoul::lua::logStack(_state);
if (library.name.empty()) {
//ghoul::lua::logStack(_state);
addLibraryFunctions(library, true);
//ghoul::lua::logStack(_state);
lua_pop(_state, 1);
//ghoul::lua::logStack(_state);
}
else {
const bool allowed = isLibraryNameAllowed(library.name);
if (!allowed)
return false;
//ghoul::lua::logStack(_state);
lua_pushstring(_state, library.name.c_str());
//ghoul::lua::logStack(_state);
lua_newtable(_state);
//ghoul::lua::logStack(_state);
addLibraryFunctions(library, false);
lua_settable(_state, _setTableOffset);
//ghoul::lua::logStack(_state);
_registeredLibraries.insert(library);
}
return true;
}
bool ScriptEngine::runScript(const std::string& script) {
if (script.empty())
return false;
int status = luaL_loadstring(_state, script.c_str());
if (status != LUA_OK) {
LERROR("Error loading script: '" << lua_tostring(_state, -1) << "'");
return false;
}
LDEBUG("Executing script");
if (lua_pcall(_state, 0, LUA_MULTRET, 0)) {
LERROR("Error executing script: " << lua_tostring(_state, -1));
return false;
}
return true;
}
bool ScriptEngine::runScriptFile(const std::string& filename) {
if (filename.empty()) {
LWARNING("Filename was empty");
return false;
}
if (!FileSys.fileExists(filename)) {
LERROR("Script with name '" << filename << "' did not exist");
return false;
}
std::ifstream file(filename.c_str());
if (file.bad()) {
LERROR("Error opening file '" << filename << "'");
return false;
}
// Read the contents of the script
std::string script((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
const bool runSuccess = runScript(script);
return runSuccess;
}
bool ScriptEngine::hasLibrary(const std::string& name)
{
for (auto it = _registeredLibraries.begin(); it != _registeredLibraries.end(); ++it)
if (it->name == name)
return true;
return false;
}
bool ScriptEngine::isLibraryNameAllowed(const std::string& name)
{
bool result = false;
lua_getglobal(_state, _openspaceLibraryName.c_str());
const bool hasOpenSpaceLibrary = lua_istable(_state, -1);
if (!hasOpenSpaceLibrary) {
LFATAL("OpenSpace library was not created in initialize method");
return false;
}
lua_getfield(_state, -1, name.c_str());
const int type = lua_type(_state, -1);
switch (type) {
case LUA_TNONE:
case LUA_TNIL:
result = true;
break;
case LUA_TBOOLEAN:
LERROR("Library name '" << name << "' specifies a boolean");
break;
case LUA_TLIGHTUSERDATA:
LERROR("Library name '" << name << "' specifies a light user data");
break;
case LUA_TNUMBER:
LERROR("Library name '" << name << "' specifies a number");
break;
case LUA_TSTRING:
LERROR("Library name '" << name << "' specifies a string");
break;
case LUA_TTABLE: {
if (hasLibrary(name))
LERROR("Library with name '" << name << "' has been registered before");
else
LERROR("Library name '" << name << "' specifies a table");
break;
}
case LUA_TFUNCTION:
LERROR("Library name '" << name << "' specifies a function");
break;
case LUA_TUSERDATA:
LERROR("Library name '" << name << "' specifies a user data");
break;
case LUA_TTHREAD:
LERROR("Library name '" << name << "' specifies a thread");
break;
}
lua_pop(_state, 2);
return result;
}
void ScriptEngine::addLibraryFunctions(const LuaLibrary& library, bool replace)
{
for (LuaLibrary::Function p : library.functions) {
if (!replace) {
//ghoul::lua::logStack(_state);
lua_getfield(_state, -1, p.name.c_str());
//ghoul::lua::logStack(_state);
const bool isNil = lua_isnil(_state, -1);
if (!isNil) {
LERROR("Function name '" << p.name << "' was already assigned");
return;
}
lua_pop(_state, 1);
}
//ghoul::lua::logStack(_state);
lua_pushstring(_state, p.name.c_str());
//ghoul::lua::logStack(_state);
lua_pushcfunction(_state, p.function);
//ghoul::lua::logStack(_state);
lua_settable(_state, _setTableOffset);
//ghoul::lua::logStack(_state);
}
}
void ScriptEngine::addBaseLibrary() {
LuaLibrary lib = {
"",
{
{
"printDebug",
&luascriptfunctions::printDebug,
"printDebug(*): Logs the passed value to the installed LogManager with a "
"LogLevel of 'Debug'"
},
{
"printInfo",
&luascriptfunctions::printInfo,
"printInfo(*): Logs the passed value to the installed LogManager with a "
" LogLevel of 'Info'"
},
{
"printWarning",
&luascriptfunctions::printWarning,
"printWarning(*): Logs the passed value to the installed LogManager with "
"a LogLevel of 'Warning'"
},
{
"printError",
&luascriptfunctions::printError,
"printError(*): Logs the passed value to the installed LogManager with a "
"LogLevel of 'Error'"
},
{
"printFatal",
&luascriptfunctions::printFatal,
"printFatal(*): Logs the passed value to the installed LogManager with a "
"LogLevel of 'Fatal'"
}
}
};
addLibrary(lib);
}
void ScriptEngine::remapPrintFunction() {
//ghoul::lua::logStack(_state);
// lua_getglobal(_state, _luaGlobalNamespace.c_str());
//ghoul::lua::logStack(_state);
// lua_pushstring(_state, _printFunctionName.c_str());
//ghoul::lua::logStack(_state);
// lua_pushcfunction(_state, _printFunctionReplacement);
//ghoul::lua::logStack(_state);
// lua_settable(_state, _setTableOffset);
//ghoul::lua::logStack(_state);
}
} // namespace scripting
} // namespace openspace

View File

@@ -1,9 +1,8 @@
/*****************************************************************************************
* *
* GHOUL *
* General Helpful Open Utility Library *
* OpenSpace *
* *
* Copyright (c) 2012-2014 *
* 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 *
@@ -34,7 +33,8 @@
#include <openspace/tests/test_common.inl>
#include <openspace/tests/test_spicemanager.inl>
//#include <openspace/tests/test_scenegraph.inl>
//#include <openspace/tests/test_powerscalecoordinates.inl>
#include <openspace/tests/test_luaconversions.inl>
#include <openspace/tests/test_powerscalecoordinates.inl>
#include <openspace/engine/openspaceengine.h>
#include <openspace/util/constants.h>
#include <openspace/util/factorymanager.h>
@@ -64,7 +64,7 @@ int main(int argc, char** argv) {
}
LINFO("Configuration file found: " << FileSys.absolutePath(configurationFilePath));
LDEBUG("registering base path");
LDEBUG("Registering base path");
if( ! openspace::OpenSpaceEngine::registerBasePathFromConfigurationFile(configurationFilePath)) {
LFATAL("Could not register base path");
assert(false);
@@ -79,9 +79,6 @@ int main(int argc, char** argv) {
}
}
/*openspace::Time::init();
openspace::Spice::init();
openspace::Spice::ref().loadDefaultKernels();*/
openspace::FactoryManager::initialize();
testing::InitGoogleTest(&argc, argv);

View File

@@ -28,6 +28,7 @@
// renderables
#include <openspace/rendering/stars/renderablestars.h>
#include <openspace/rendering/renderablefieldlines.h>
#include <openspace/rendering/planets/renderableplanet.h>
#include <openspace/rendering/renderablevolumeexpert.h>
#include <openspace/rendering/renderablevolumecl.h>
@@ -58,13 +59,11 @@ void FactoryManager::initialize()
"RenderablePlanet");
_manager->factory<Renderable>()->registerClass<RenderableStars>(
"RenderableStars");
_manager->factory<Renderable>()->registerClass<RenderableVolumeCL>(
"RenderableVolumeCL");
//_manager->factory<Renderable>()->registerClass<RenderableVolumeCL>(
// "RenderableVolumeCL");
_manager->factory<Renderable>()->registerClass<RenderableVolumeGL>(
"RenderableVolumeGL");
_manager->factory<Renderable>()->registerClass<RenderableVolumeExpert>(
"RenderableVolumeExpert");
_manager->factory<Renderable>()->registerClass<Flare>("RenderableFlare");
_manager->factory<Renderable>()->registerClass<RenderableFieldlines>("RenderableFieldlines");
// Add Ephimerides
_manager->addFactory(new ghoul::TemplateFactory<Ephemeris>);
@@ -105,4 +104,4 @@ void FactoryManager::addFactory(ghoul::TemplateFactoryBase* factory) {
}
} // namespace openspace
} // namespace openspace

View File

@@ -31,8 +31,12 @@
#include <ccmc/ENLIL.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <iomanip>
#include <stdlib.h>
#include <glm/gtx/rotate_vector.hpp>
namespace openspace {
@@ -42,23 +46,33 @@ KameleonWrapper::KameleonWrapper(const std::string& filename, Model model): _typ
switch (_type) {
case Model::BATSRUS:
_model = new ccmc::BATSRUS();
if(!_model) LERROR("BATSRUS:Failed to create model instance");
if(!_model) LERROR("BATSRUS:Failed to create BATSRUS 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");
if (!_interpolator) LERROR("BATSRUS:Failed to create BATSRUS interpolator");
break;
case Model::ENLIL:
_model = new ccmc::ENLIL();
if(!_model) LERROR("Failed to create model instance");
if(!_model) LERROR("Failed to create ENLIL model instance");
if (_model->open(filename) != ccmc::FileReader::OK)
LERROR("Failed to open "+filename);
_interpolator = _model->createNewInterpolator();
if (!_interpolator) LERROR("Failed to create interpolator");
if (!_interpolator) LERROR("Failed to create ENLIL interpolator");
break;
default:
LERROR("No valid model type provided!");
}
getGridVariables(_xCoordVar, _yCoordVar, _zCoordVar);
_xMin = _model->getVariableAttribute(_xCoordVar, "actual_min").getAttributeFloat();
_xMax = _model->getVariableAttribute(_xCoordVar, "actual_max").getAttributeFloat();
_yMin = _model->getVariableAttribute(_yCoordVar, "actual_min").getAttributeFloat();
_yMax = _model->getVariableAttribute(_yCoordVar, "actual_max").getAttributeFloat();
_zMin = _model->getVariableAttribute(_zCoordVar, "actual_min").getAttributeFloat();
_zMax = _model->getVariableAttribute(_zCoordVar, "actual_max").getAttributeFloat();
_lastiProgress = -1; // For progressbar
}
KameleonWrapper::~KameleonWrapper() {
@@ -70,93 +84,34 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz
assert(_model && _interpolator);
assert(outDimensions.x > 0 && outDimensions.y > 0 && outDimensions.z > 0);
assert(_type == Model::ENLIL || _type == Model::BATSRUS);
LINFO("Loading CDF data");
LINFO("Loading variable " << var << " from CDF data with a uniform sampling");
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;
}
double* doubleData = new double[size];
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
double varMin = _model->getVariableAttribute(var, "actual_min").getAttributeFloat();
double varMax = _model->getVariableAttribute(var, "actual_max").getAttributeFloat();
double stepX = (_xMax-_xMin)/(static_cast<double>(outDimensions.x));
double stepY = (_yMax-_yMin)/(static_cast<double>(outDimensions.y));
double stepZ = (_zMax-_zMin)/(static_cast<double>(outDimensions.z));
//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);
// HISTOGRAM
const int bins = 200;
const float truncLim = 0.9;
std::vector<int> histogram (bins,0);
auto mapToHistogram = [varMin, varMax, bins](double val) {
double zeroToOne = (val-varMin)/(varMax-varMin);
zeroToOne *= static_cast<double>(bins);
return static_cast<int>(zeroToOne);
};
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;
progressBar(x, outDimensions.x);
for (int y = 0; y < outDimensions.y; ++y) {
for (int z = 0; z < outDimensions.z; ++z) {
@@ -164,46 +119,40 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz
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;
double xPos = _xMin + stepX*x;
double yPos = _yMin + stepY*y;
double 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);
// swap yPos and zPos because model has Z as up
double value = _interpolator->interpolate(var, xPos, zPos, yPos);
doubleData[index] = value;
histogram[mapToHistogram(value)]++;
} 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);
double rNorm = sqrt(3.0)*(double)x/(double)(outDimensions.x-1);
// Put theta in the [0..PI] range
float thetaNorm = M_PI*(float)y/(float)(outDimensions.y-1);
double thetaNorm = M_PI*(double)y/(double)(outDimensions.y-1);
// Put phi in the [0..2PI] range
float phiNorm = 2.0*M_PI*(float)z/(float)(outDimensions.z-1);
double phiNorm = 2.0*M_PI*(double)z/(double)(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);
double rPh = _xMin + rNorm*(_xMax-_xMin);
double 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.
double 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;
double value = 0.0;
// See if sample point is inside domain
if (rPh < xMin || rPh > xMax || thetaPh < yMin ||
thetaPh > yMax || phiPh < zMin || phiPh > zMax) {
if (phiPh > zMax) {
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
@@ -217,23 +166,12 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz
// 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;
value = _interpolator->interpolate(var, rPh, thetaPh, phiPh);
// value = _interpolator->interpolate(var, rPh, phiPh, thetaPh);
}
//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;
doubleData[index] = value;
histogram[mapToHistogram(value)]++;
}
}
}
@@ -241,8 +179,450 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz
std::cout << std::endl;
LINFO("Done!");
// for (int i = 0; i < outDimensions.x * outDimensions.y * outDimensions.z; ++i)
// {
// std::cout << std::setfill(' ') << std::setw(15) << doubleData[i] << ", ";
// if(i % 10 == 0)
// std::cout << std::endl;
// }
//
// for(int i = 0; i < bins-1; ++i) {
// // sum += histogram[i];
// // if(sum + histogram[i+1] > sumuntil) {
// // stop = i;
// // LDEBUG("====================");
// // break;
// // }
// LDEBUG("histogram[" << i << "]: " << histogram[i]);
// }
int sum = 0;
int stop;
const int sumuntil = size * truncLim;
for(int i = 0; i < bins; ++i) {
sum += histogram[i];
if(sum > sumuntil) {
stop = i;
// LDEBUG("====================");
break;
}
// LDEBUG("histogram[" << i << "]: " << histogram[i]);
}
double dist = varMax - varMin;
dist = (dist / static_cast<double>(bins)) * static_cast<double>(stop);
varMax = varMin + dist;
LDEBUG(var << "Min: " << varMin);
LDEBUG(var << "Max: " << varMax);
for(int i = 0; i < size; ++i) {
double normalizedVal = (doubleData[i]-varMin)/(varMax-varMin);
data[i] = static_cast<float>(glm::clamp(normalizedVal, 0.0, 1.0));
if(data[i] < 0.0) {
LERROR("Datapoint " << i << " less than 0");
}
if(data[i] > 1.0) {
LERROR("Datapoint " << i << " more than 1");
}
}
// for(int i = 0; i < size; ++i) {
// double normalizedVal = (doubleData[i]-varMin)/(varMax-varMin);
// // data[i] = static_cast<float>(glm::clamp(normalizedVal, 0.0, 1.0));
// data[i] = static_cast<float>(normalizedVal);
// }
delete[] doubleData;
return data;
}
} // namespace openspace
float* KameleonWrapper::getUniformSampledVectorValues(const std::string& xVar, const std::string& yVar, const std::string& zVar, 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 variables " << xVar << " " << yVar << " " << zVar << " from CDF data with a uniform sampling");
int channels = 4;
int size = channels*outDimensions.x*outDimensions.y*outDimensions.z;
float* data = new float[size];
float varXMin = _model->getVariableAttribute(xVar, "actual_min").getAttributeFloat();
float varXMax = _model->getVariableAttribute(xVar, "actual_max").getAttributeFloat();
float varYMin = _model->getVariableAttribute(yVar, "actual_min").getAttributeFloat();
float varYMax = _model->getVariableAttribute(yVar, "actual_max").getAttributeFloat();
float varZMin = _model->getVariableAttribute(zVar, "actual_min").getAttributeFloat();
float varZMax = _model->getVariableAttribute(zVar, "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(xVar << "Min: " << varXMin);
LDEBUG(xVar << "Max: " << varXMax);
LDEBUG(yVar << "Min: " << varYMin);
LDEBUG(yVar << "Max: " << varYMax);
LDEBUG(zVar << "Min: " << varZMin);
LDEBUG(zVar << "Max: " << varZMax);
for (int x = 0; x < outDimensions.x; ++x) {
progressBar(x, outDimensions.x);
for (int y = 0; y < outDimensions.y; ++y) {
for (int z = 0; z < outDimensions.z; ++z) {
int index = x*channels + y*channels*outDimensions.x + z*channels*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 xValue = _interpolator->interpolate(xVar, xPos, yPos, zPos);
float yValue = _interpolator->interpolate(yVar, xPos, yPos, zPos);
float zValue = _interpolator->interpolate(zVar, xPos, yPos, zPos);
// scale to [0,1]
data[index] = (xValue-varXMin)/(varXMax-varXMin); // R
data[index + 1] = (yValue-varYMin)/(varYMax-varYMin); // G
data[index + 2] = (zValue-varZMin)/(varZMax-varZMin); // B
data[index + 3] = 1.0; // GL_RGB refuses to work. Workaround by doing a GL_RGBA with hardcoded alpha
} else {
LERROR("Only BATSRUS supported for getUniformSampledVectorValues (for now)");
return data;
}
}
}
}
std::cout << std::endl;
LINFO("Done!");
return data;
}
std::vector<std::vector<LinePoint> > KameleonWrapper::getClassifiedFieldLines(
const std::string& xVar, const std::string& yVar,
const std::string& zVar, std::vector<glm::vec3> seedPoints,
float stepSize ) {
assert(_model && _interpolator);
assert(_type == Model::ENLIL || _type == Model::BATSRUS);
LINFO("Creating " << seedPoints.size() << " fieldlines from variables " << xVar << " " << yVar << " " << zVar);
std::vector<glm::vec3> fLine, bLine;
std::vector<std::vector<LinePoint> > fieldLines;
glm::vec4 color;
FieldlineEnd forwardEnd, backEnd;
if (_type == Model::BATSRUS) {
for (glm::vec3 seedPoint : seedPoints) {
fLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, stepSize, TraceDirection::FORWARD, forwardEnd);
bLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, stepSize, TraceDirection::BACK, backEnd);
bLine.insert(bLine.begin(), fLine.rbegin(), fLine.rend());
// classify
color = classifyFieldline(forwardEnd, backEnd);
// write colors
std::vector<LinePoint> line;
for (glm::vec3 position : bLine) {
line.push_back(LinePoint(position, color));
}
fieldLines.push_back(line);
}
} else {
LERROR("Fieldlines are only supported for BATSRUS model");
}
return fieldLines;
}
std::vector<std::vector<LinePoint> > KameleonWrapper::getFieldLines(
const std::string& xVar, const std::string& yVar,
const std::string& zVar, std::vector<glm::vec3> seedPoints,
float stepSize, glm::vec4 color ) {
assert(_model && _interpolator);
assert(_type == Model::ENLIL || _type == Model::BATSRUS);
LINFO("Creating " << seedPoints.size() << " fieldlines from variables " << xVar << " " << yVar << " " << zVar);
std::vector<glm::vec3> fLine, bLine;
std::vector<std::vector<LinePoint> > fieldLines;
FieldlineEnd forwardEnd, backEnd;
if (_type == Model::BATSRUS) {
for (glm::vec3 seedPoint : seedPoints) {
fLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, stepSize, TraceDirection::FORWARD, forwardEnd);
bLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, stepSize, TraceDirection::BACK, backEnd);
bLine.insert(bLine.begin(), fLine.rbegin(), fLine.rend());
// write colors
std::vector<LinePoint> line;
for (glm::vec3 position : bLine) {
line.push_back(LinePoint(position, color));
}
fieldLines.push_back(line);
}
} else {
LERROR("Fieldlines are only supported for BATSRUS model");
}
return fieldLines;
}
std::vector<std::vector<LinePoint> > KameleonWrapper::getLorentzTrajectories(
std::vector<glm::vec3> seedPoints, glm::vec4 color, float stepsize) {
LINFO("Creating " << seedPoints.size() << " Lorentz force trajectories");
std::vector<std::vector<LinePoint> > trajectories;
std::vector<glm::vec3> plusTraj, minusTraj;
for (auto seedPoint : seedPoints) {
plusTraj = traceLorentzTrajectory(seedPoint, stepsize, 1.0);
minusTraj = traceLorentzTrajectory(seedPoint, stepsize, -1.0);
minusTraj.insert(minusTraj.begin(), plusTraj.rbegin(), plusTraj.rend());
// write colors
std::vector<LinePoint> trajectory;
for (glm::vec3 position : minusTraj) {
trajectory.push_back(LinePoint(position, color));
}
trajectories.push_back(trajectory);
}
return trajectories;
}
glm::vec3 KameleonWrapper::getModelBarycenterOffset() {
glm::vec3 offset;
offset.x = _xMin+(std::abs(_xMin)+std::abs(_xMax))/2.0f;
offset.y = _yMin+(std::abs(_yMin)+std::abs(_yMax))/2.0f;
offset.z = _zMin+(std::abs(_zMin)+std::abs(_zMax))/2.0f;
return offset;
}
std::vector<glm::vec3> KameleonWrapper::traceCartesianFieldline(
const std::string& xVar, const std::string& yVar,
const std::string& zVar, glm::vec3 seedPoint,
float stepSize, TraceDirection direction, FieldlineEnd& end) {
glm::vec3 color, pos, k1, k2, k3, k4;
std::vector<glm::vec3> line;
float stepX, stepY, stepZ;
int numSteps = 0, maxSteps = 5000;
pos = seedPoint;
_model->loadVariable(xVar);
_model->loadVariable(yVar);
_model->loadVariable(zVar);
long int xID = _model->getVariableID(xVar);
long int yID = _model->getVariableID(yVar);
long int zID = _model->getVariableID(zVar);
// While we are inside the models boundries and not inside earth
while ((pos.x < _xMax && pos.x > _xMin && pos.y < _yMax && pos.y > _yMin &&
pos.z < _zMax && pos.z > _zMin) && !(pos.x*pos.x + pos.y*pos.y + pos.z*pos.z < 1.0)) {
// Save position. Model has +Z as up
line.push_back(glm::vec3(pos.x, pos.z, pos.y));
// Calculate new position with Runge-Kutta 4th order
k1.x = _interpolator->interpolate(xID, pos.x, pos.y, pos.z, stepX, stepY, stepZ);
k1.y = _interpolator->interpolate(yID, pos.x, pos.y, pos.z);
k1.z = _interpolator->interpolate(zID, pos.x, pos.y, pos.z);
k1 = (float)direction*glm::normalize(k1);
stepX=stepX*stepSize, stepY=stepY*stepSize, stepZ=stepZ*stepSize;
k2.x = _interpolator->interpolate(xID, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z);
k2.y = _interpolator->interpolate(yID, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z);
k2.z = _interpolator->interpolate(zID, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z);
k2 = (float)direction*glm::normalize(k2);
k3.x = _interpolator->interpolate(xID, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z);
k3.y = _interpolator->interpolate(yID, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z);
k3.z = _interpolator->interpolate(zID, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z);
k3 = (float)direction*glm::normalize(k3);
k4.x = _interpolator->interpolate(xID, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z);
k4.y = _interpolator->interpolate(yID, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z);
k4.z = _interpolator->interpolate(zID, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z);
k4 = (float)direction*glm::normalize(k4);
pos.x = pos.x + (stepX/6.0)*(k1.x + 2.0*k2.x + 2.0*k3.x + k4.x);
pos.y = pos.y + (stepY/6.0)*(k1.y + 2.0*k2.y + 2.0*k3.y + k4.y);
pos.z = pos.z + (stepZ/6.0)*(k1.z + 2.0*k2.z + 2.0*k3.z + k4.z);
++numSteps;
if (numSteps > maxSteps) {
LDEBUG("Max number of steps taken (" << maxSteps <<")");
break;
}
}
// Save last position. Model has +Z as up
line.push_back(glm::vec3(pos.x, pos.z, pos.y));
if (pos.z > 0.0 && (pos.x*pos.x + pos.y*pos.y + pos.z*pos.z < 1.0))
end = FieldlineEnd::NORTH;
else if (pos.z < 0.0 && (pos.x*pos.x + pos.y*pos.y + pos.z*pos.z < 1.0))
end = FieldlineEnd::SOUTH;
else
end = FieldlineEnd::OUT;
return line;
}
std::vector<glm::vec3> KameleonWrapper::traceLorentzTrajectory(glm::vec3 seedPoint,
float stepsize, float eCharge) {
glm::vec3 B, E, v0, k1, k2, k3, k4, sPos, tmpV;
float stepX = stepsize, stepY = stepsize, stepZ = stepsize;
long int bxID = _model->getVariableID("bx");
long int byID = _model->getVariableID("by");
long int bzID = _model->getVariableID("bz");
long int jxID = _model->getVariableID("jx");
long int jyID = _model->getVariableID("jy");
long int jzID = _model->getVariableID("jz");
std::vector<glm::vec3> trajectory;
glm::vec3 pos = seedPoint;
int numSteps = 0, maxSteps = 5000;
v0.x = _interpolator->interpolate("ux", pos.x, pos.y, pos.z);
v0.y = _interpolator->interpolate("uy", pos.x, pos.y, pos.z);
v0.z = _interpolator->interpolate("uz", pos.x, pos.y, pos.z);
v0 = glm::normalize(v0);
// While we are inside the models boundries and not inside earth
while ((pos.x < _xMax && pos.x > _xMin && pos.y < _yMax && pos.y > _yMin &&
pos.z < _zMax && pos.z > _zMin) && !(pos.x*pos.x + pos.y*pos.y + pos.z*pos.z < 1.0)) {
// Save position. Model has +Z as up
trajectory.push_back(glm::vec3(pos.x, pos.z, pos.y));
// Calculate new position with Lorentz force quation and Runge-Kutta 4th order
B.x = _interpolator->interpolate(bxID, pos.x, pos.y, pos.z);
B.y = _interpolator->interpolate(byID, pos.x, pos.y, pos.z);
B.z = _interpolator->interpolate(bzID, pos.x, pos.y, pos.z);
E.x = _interpolator->interpolate(jxID, pos.x, pos.y, pos.z);
E.y = _interpolator->interpolate(jyID, pos.x, pos.y, pos.z);
E.z = _interpolator->interpolate(jzID, pos.x, pos.y, pos.z);
k1 = eCharge*(E + glm::cross(v0, B));
k1 = glm::normalize(k1);
sPos = glm::vec3( pos.x+(stepX/2.0)*v0.x+(stepX*stepX/8.0)*k1.x,
pos.y+(stepY/2.0)*v0.y+(stepY*stepY/8.0)*k1.y,
pos.z+(stepZ/2.0)*v0.z+(stepZ*stepZ/8.0)*k1.z);
B.x = _interpolator->interpolate(bxID, sPos.x, sPos.y, sPos.z);
B.y = _interpolator->interpolate(byID, sPos.x, sPos.y, sPos.z);
B.z = _interpolator->interpolate(bzID, sPos.x, sPos.y, sPos.z);
E.x = _interpolator->interpolate(jxID, sPos.x, sPos.y, sPos.z);
E.y = _interpolator->interpolate(jyID, sPos.x, sPos.y, sPos.z);
E.z = _interpolator->interpolate(jzID, sPos.x, sPos.y, sPos.z);
tmpV = v0+(stepX/2.0f)*k1;
k2 = eCharge*(E + glm::cross(tmpV, B));
k2 = glm::normalize(k2);
B.x = _interpolator->interpolate(bxID, sPos.x, sPos.y, sPos.z);
B.y = _interpolator->interpolate(byID, sPos.x, sPos.y, sPos.z);
B.z = _interpolator->interpolate(bzID, sPos.x, sPos.y, sPos.z);
E.x = _interpolator->interpolate(jxID, sPos.x, sPos.y, sPos.z);
E.y = _interpolator->interpolate(jyID, sPos.x, sPos.y, sPos.z);
E.z = _interpolator->interpolate(jzID, sPos.x, sPos.y, sPos.z);
tmpV = v0+(stepX/2.0f)*k2;
k3 = eCharge*(E + glm::cross(tmpV, B));
k3 = glm::normalize(k3);
sPos = glm::vec3( pos.x+stepX*v0.x+(stepX*stepX/2.0)*k1.x,
pos.y+stepY*v0.y+(stepY*stepY/2.0)*k1.y,
pos.z+stepZ*v0.z+(stepZ*stepZ/2.0)*k1.z);
B.x = _interpolator->interpolate(bxID, sPos.x, sPos.y, sPos.z);
B.y = _interpolator->interpolate(byID, sPos.x, sPos.y, sPos.z);
B.z = _interpolator->interpolate(bzID, sPos.x, sPos.y, sPos.z);
E.x = _interpolator->interpolate(jxID, sPos.x, sPos.y, sPos.z);
E.y = _interpolator->interpolate(jyID, sPos.x, sPos.y, sPos.z);
E.z = _interpolator->interpolate(jzID, sPos.x, sPos.y, sPos.z);
tmpV = v0+stepX*k3;
k4 = eCharge*(E + glm::cross(tmpV, B));
k4 = glm::normalize(k4);
pos.x = pos.x + stepX*v0.x + (stepX*stepX/6.0)*(k1.x + k2.x + k3.x);
pos.y = pos.y + stepY*v0.y + (stepY*stepY/6.0)*(k1.y + k2.y + k3.y);
pos.z = pos.z + stepZ*v0.z + (stepZ*stepZ/6.0)*(k1.z + k2.z + k3.z);
v0.x = v0.x + (stepX/6.0)*(k1.x + 2.0*k2.x + 2.0*k3.x + k4.z);
v0.y = v0.y + (stepY/6.0)*(k1.y + 2.0*k2.y + 2.0*k3.y + k4.y);
v0.z = v0.z + (stepZ/6.0)*(k1.z + 2.0*k2.z + 2.0*k3.z + k4.z);
++numSteps;
if (numSteps > maxSteps) {
LDEBUG("Max number of steps taken (" << maxSteps <<")");
break;
}
}
// Save last position. Model has +Z as up
trajectory.push_back(glm::vec3(pos.x, pos.z, pos.y));
return trajectory;
}
void KameleonWrapper::getGridVariables(std::string& x, std::string& y, std::string& z) {
// 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");
x = tokens.at(0);
y = tokens.at(1);
z = tokens.at(2);
}
void KameleonWrapper::progressBar(int current, int end) {
float progress = static_cast<float>(current) / static_cast<float>(end-1);
int iprogress = static_cast<int>(progress*100.0f);
int barWidth = 70;
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;
}
glm::vec4 KameleonWrapper::classifyFieldline(FieldlineEnd fEnd, FieldlineEnd bEnd) {
glm::vec4 color;
if ( (fEnd == FieldlineEnd::NORTH || fEnd == FieldlineEnd::SOUTH)
&& (bEnd == FieldlineEnd::NORTH || bEnd == FieldlineEnd::SOUTH)) {
// closed
color = glm::vec4(1.0, 0.0, 0.0, 1.0);
} else if ((fEnd == FieldlineEnd::OUT && bEnd == FieldlineEnd::NORTH)
|| (bEnd == FieldlineEnd::OUT && fEnd == FieldlineEnd::NORTH)) {
// north
color = glm::vec4(1.0, 1.0, 0.0, 1.0);
} else if ((fEnd == FieldlineEnd::OUT && bEnd == FieldlineEnd::SOUTH)
|| (bEnd == FieldlineEnd::OUT && fEnd == FieldlineEnd::SOUTH)) {
// south
color = glm::vec4(0.0, 1.0, 0.0, 1.0);
} else if (fEnd == FieldlineEnd::OUT && bEnd == FieldlineEnd::OUT) {
// solar wind
color = glm::vec4(0.0, 0.0, 1.0, 1.0);
}
return color;
}
} // namespace openspace

195
src/util/shadercreator.cpp Normal file
View File

@@ -0,0 +1,195 @@
/*****************************************************************************************
* *
* 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 <openspace/util/shadercreator.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/opengl/shaderobject.h>
#include <ghoul/filesystem/filesystem.h>
#include <regex>
#include <iostream>
#include <fstream>
// #include <ifstream>
// #include <ofstream>
using ghoul::opengl::ProgramObject;
using ghoul::opengl::ShaderObject;
namespace {
const std::string _loggerCat = "ShaderCreator";
const std::string defaultSourceFileExtension = "OpenSpaceGenerated.glsl";
const std::string separator = "//=====================================================================\n";
const ShaderObject::ShaderType vsType = ShaderObject::ShaderType::ShaderTypeVertex;
const ShaderObject::ShaderType fsType = ShaderObject::ShaderType::ShaderTypeFragment;
const ShaderObject::ShaderType gsType = ShaderObject::ShaderType::ShaderTypeGeometry;
}
namespace openspace {
ShaderCreator::ShaderCreator():
_createSourceFile(false),
_sourceFileExtension(defaultSourceFileExtension),
_sourceFileHeader(""),
_maxDepth(2)
{
}
ShaderCreator::~ShaderCreator() {
}
void ShaderCreator::createSourceFile(bool b) {
_createSourceFile = b;
}
void ShaderCreator::sourceFileExtension(const std::string& extension) {
if(extension != "") {
_sourceFileExtension = extension;
}
}
void ShaderCreator::sourceFileHeader(const std::string& header) {
_sourceFileHeader = header;
}
ghoul::opengl::ProgramObject* ShaderCreator::buildShader(
const std::string& name, const std::string& vpath, const std::string& fpath, const std::string& gpath)
{
std::string vsPath = absPath(vpath);
std::string fsPath = absPath(fpath);
std::string gsPath = absPath(gpath);
if( ! FileSys.fileExists(vsPath))
return nullptr;
if( ! FileSys.fileExists(fsPath))
return nullptr;
if (gsPath != "" && !FileSys.fileExists(gsPath))
return nullptr;
if(_createSourceFile) {
_generateSource(vsPath);
_generateSource(fsPath);
vsPath = _generateFilename(vsPath);
fsPath = _generateFilename(fsPath);
}
ProgramObject* po = new ProgramObject(name);
ShaderObject* vs = new ShaderObject(vsType, vsPath, name + " Vertex");
ShaderObject* fs = new ShaderObject(fsType, fsPath, name + " Fragment");
po->attachObject(vs);
po->attachObject(fs);
if (gsPath != "") {
_generateSource(gsPath);
gsPath = _generateFilename(gsPath);
ShaderObject* gs = new ShaderObject(gsType, gsPath, name + " Geometry");
po->attachObject(gs);
}
if ( po->compileShaderObjects() && po->linkProgramObject())
return po;
// unsuccessful compilation, cleanup and return nullptr
delete po;
po = nullptr;
return po;
}
void ShaderCreator::_generateSource(const std::string& filename) {
std::string generatedSource = "";
if(_sourceFileHeader != "")
generatedSource += separator + "// HEADER\n" + separator + _sourceFileHeader + "\n";
generatedSource += _loadSource(filename);
std::ofstream of(_generateFilename(filename));
of << generatedSource;
of.close();
}
std::string ShaderCreator::_loadSource(const std::string& filename, unsigned int depth) {
std::string contents = "", line;
std::ifstream f(filename);
// Pre-allocate memory so the return string doesn't have to resize too often
// f.seekg( 0, std::ios::end );
// unsigned int fsize = f.tellg();
// f.seekg( 0);
// contents.reserve(fsize*3);
// line.reserve(fsize*3);
contents += "\n";
contents += separator;
contents += "// Filename: " + filename + "\n";
// contents += "// Size: " + std::to_string(fsize) + "\n";
contents += separator;
if(depth > _maxDepth) {
contents += "// TOO DEEP";
return contents;
}
if( ! FileSys.fileExists(filename)){
contents += "// FILE NOT FOUND\n";
return contents;
}
std::regex e1(R"(^\s*#include \"(.+)\"\s*)");
std::regex e2(R"(^\s*#include <(.+)>\s*)");
while(std::getline(f, line)) {
std::smatch m;
if(std::regex_search(line, m, e1)) {
using namespace ghoul::filesystem;
std::string includeFilename = m[1];
File f(filename);
includeFilename = f.directoryName() + FileSystem::PathSeparator + includeFilename;
//includeFilename = filename.substr(0, filename.find_last_of("/")+1) + includeFilename;
line = _loadSource(includeFilename, depth + 1);
} else if(std::regex_search(line, m, e2)) {
std::string includeFilename = m[1];
line = _loadSource(absPath(includeFilename), depth + 1);
}
contents += line + "\n";
}
f.close();
return contents;
}
std::string ShaderCreator::_generateFilename(const std::string& filename) {
// If way of confirming and creating a directory this could be a good solution
// to avoid cluttering in folders
// if(_cacheFolder != "") {
// size_t delimiter = filename.find_last_of("/");
// std::string file = filename.substr(delimiter+1, filename.length() - delimiter);
// std::string path = filename.substr(0, filename.find_last_of("/"));
// return path + "/" + _cacheFolder + "/" + file + "." + _sourceFileExtension;
// }
return filename + "." + _sourceFileExtension;
}
}

View File

@@ -128,7 +128,7 @@ bool Spice::spk_getPosition(const std::string &target, const std::string &origin
assert(this_);
assert(Time::ref().isInitialized());
SpiceDouble et = Time::ref().getTime();
SpiceDouble et = Time::ref().currentTime();
SpiceDouble lt;
spkpos_c(target.c_str(), et, "J2000", "LT+S", origin.c_str(), state, &lt);
int failed = failed_c();
@@ -143,7 +143,7 @@ void Spice::spk_getPosition(int target, int origin, double state[3]) {
assert(this_);
assert(Time::ref().isInitialized());
SpiceDouble et = Time::ref().getTime();
SpiceDouble et = Time::ref().currentTime();
SpiceDouble lt;
spkezp_c (target, et, "J2000", "NONE", origin, state, &lt);
}
@@ -156,7 +156,7 @@ bool Spice::spk_getOrientation(const std::string &target, double state[3][3]) {
// ghoul logging
std::string _loggerCat = "Spice::spk_getOrientation";
SpiceDouble et = Time::ref().getTime();
SpiceDouble et = Time::ref().currentTime();
std::string newname = "IAU_";
newname += target;
pxform_c ( "J2000", newname.c_str(), et, state );

View File

@@ -21,9 +21,11 @@
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <stdio.h>
#include <iostream>
#include <cassert>
#include <cstring>
#ifdef WIN32
#include <Windows.h>
@@ -31,6 +33,7 @@
#include "openspace/util/spicemanager.h"
#include "ghoul/filesystem/filesystem.h"
#include "ghoul/logging/logmanager.h"
namespace {
const std::string _loggerCat = "SpiceManager";
@@ -67,7 +70,7 @@ int SpiceManager::loadKernel(const std::string& fullPath, const std::string& sho
std::string currentDirectory = FileSys.currentDirectory();
std::string::size_type last = fullPath.find_last_of(ghoul::filesystem::FileSystem::PathSeparator);
if (last == std::string::npos)
return false;
return 0;
std::string kernelDir = fullPath.substr(0, last);
FileSys.setCurrentDirectory(kernelDir);
furnsh_c(fullPath.c_str());
@@ -206,12 +209,32 @@ bool SpiceManager::getValueFromID(const std::string& bodyname,
return true;
}
double SpiceManager::stringToEphemerisTime(const std::string& epochString) const{
double SpiceManager::convertStringToTdbSeconds(const std::string& epochString) const{
double et;
str2et_c(epochString.c_str(), &et);
return et;
}
std::string SpiceManager::convertTdbSecondsToString(double seconds,
const std::string& format) const
{
const int bufferSize = 128;
SpiceChar buffer[bufferSize];
timout_c(seconds, format.c_str(), bufferSize - 1, buffer);
int failed = failed_c();
if (failed) {
char msg[1024];
getmsg_c("LONG", 1024, msg);
//LERROR("Error retrieving position of target '" + target + "'");
LERROR("Spice reported: " + std::string(msg));
reset_c();
return "";
}
return std::string(buffer);
}
bool SpiceManager::getTargetPosition(const std::string& target,
double ephemerisTime,
const std::string& referenceFrame,
@@ -223,10 +246,18 @@ bool SpiceManager::getTargetPosition(const std::string& target,
//method to put error out...
spkpos_c(target.c_str(), ephemerisTime, referenceFrame.c_str(),
aberrationCorrection.c_str(), observer.c_str(), pos, &lightTime);
if (pos[0] == NULL || pos[1] == NULL || pos[2] == NULL)
return false;
int failed = failed_c();
if(failed) {
char msg[1024];
getmsg_c ( "LONG", 1024, msg );
LERROR("Error retrieving position of target '" + target + "'");
LERROR("Spice reported: " + std::string(msg));
reset_c();
return false;
}
memcpy(&targetPosition, pos, sizeof(double)* 3);
return true;
@@ -244,11 +275,18 @@ bool SpiceManager::getTargetState(const std::string& target,
spkezr_c(target.c_str(), ephemerisTime, referenceFrame.c_str(),
aberrationCorrection.c_str(), observer.c_str(), state, &lightTime);
int failed = failed_c();
if(failed) {
char msg[1024];
getmsg_c ( "LONG", 1024, msg );
LERROR("Error retrieving state of target '" + target + "'");
LERROR("Spice reported: " + std::string(msg));
reset_c();
return false;
}
for (int i = 0; i < 3; i++){
if (state[i] == NULL || state[i + 3] == NULL){
return false;
}
memcpy(&targetPosition, state , sizeof(double)* 3);
memcpy(&targetVelocity, state +3, sizeof(double)* 3);
}
@@ -281,7 +319,6 @@ bool SpiceManager::getFieldOfView(const std::string& naifInstrumentId,
double boresightVector[],
std::vector<glm::dvec3>& bounds,
int& nrReturned) const{
int n;
int found;
int naifId;
int maxVectors = 12;

View File

@@ -1,62 +1,253 @@
/*****************************************************************************************
* *
* 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. *
****************************************************************************************/
// open space includes
#include <openspace/util/time.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/interaction/interactionhandler.h>
#include <openspace/util/constants.h>
#include <openspace/util/spicemanager.h>
// std includes
#include <cassert>
// spice includes
#include "SpiceUsr.h"
#include <ghoul/filesystem/filesystem.h>
#include <cassert>
#include <string>
namespace {
const std::string _loggerCat = "Time";
}
namespace openspace {
Time* Time::this_ = nullptr;
namespace luascriptfunctions {
Time::Time() {
time_ = 0.0;
/**
* \ingroup LuaScripts
* setDeltaTime(number):
* Sets the delta time by calling the Time::setDeltaTime method
*/
int time_setDeltaTime(lua_State* L) {
const bool isFunction = (lua_isfunction(L, -1) != 0);
if (isFunction) {
// If the top of the stack is a function, it is ourself
const char* msg = lua_pushfstring(L, "method called without argument");
return luaL_error(L, "bad argument (%s)", msg);
}
// load spice time kernel
furnsh_c (absPath("${OPENSPACE_DATA}/spice/naif0010.tls").c_str());
// convert UTC to ET
str2et_c ( "2006 JAN 31 01:00", &time_ );
}
Time::~Time() {
const bool isNumber = (lua_isnumber(L, -1) != 0);
if (isNumber) {
double value = lua_tonumber(L, -1);
openspace::Time::ref().setDeltaTime(value);
return 0;
}
else {
const char* msg = lua_pushfstring(L, "%s expected, got %s",
lua_typename(L, LUA_TNUMBER), luaL_typename(L, -1));
return luaL_error(L, "bad argument #%d (%s)", 1, msg);
}
}
void Time::init() {
assert( this_ == nullptr);
this_ = new Time();
/**
* \ingroup LuaScripts
* deltaTime():
* Returns the delta time by calling the Time::deltaTime method
*/
int time_deltaTime(lua_State* L) {
lua_pushnumber(L, openspace::Time::ref().deltaTime());
return 1;
}
void Time::deinit() {
assert(this_);
delete this_;
this_ = nullptr;
/**
* \ingroup LuaScripts
* setTime({number, string}):
* Sets the simulation time to the passed value. If the parameter is a number, it is
* interpreted as the number of seconds past the J2000 epoch and the
* Time::setTime(double) method is called. If the parameter is a string, it is
* interpreted as a structured date string and the Time::setTime(std::string) method
* is called
*/
int time_setTime(lua_State* L) {
const bool isFunction = (lua_isfunction(L, -1) != 0);
if (isFunction) {
// If the top of the stack is a function, it is ourself
const char* msg = lua_pushfstring(L, "method called without argument");
return luaL_error(L, "bad argument (%s)", 1, msg);
}
const bool isNumber = (lua_isnumber(L, -1) != 0);
const bool isString = (lua_isstring(L, -1) != 0);
if (!isNumber && !isString) {
const char* msg = lua_pushfstring(L, "%s or %s expected, got %s",
lua_typename(L, LUA_TNUMBER),
lua_typename(L, LUA_TSTRING), luaL_typename(L, -1));
return luaL_error(L, "bad argument #%d (%s)", 1, msg);
}
if (isNumber) {
double value = lua_tonumber(L, -1);
openspace::Time::ref().setTime(value);
return 0;
}
if (isString) {
const char* time = lua_tostring(L, -1);
openspace::Time::ref().setTime(time);
return 0;
}
return 0;
}
/**
* \ingroup LuaScripts
* currentTime():
* Returns the current simulation time as the number of seconds past the J2000 epoch.
* It is returned by calling the Time::currentTime method.
*/
int time_currentTime(lua_State* L) {
lua_pushnumber(L, openspace::Time::ref().currentTime());
return 1;
}
/**
* \ingroup LuaScripts
* currentTimeUTC():
* Returns the current simulation time as a structured ISO 8601 string using the UTC
* timezone by calling the Time::currentTimeUTC method
*/
int time_currentTimeUTC(lua_State* L) {
lua_pushstring(L, openspace::Time::ref().currentTimeUTC().c_str());
return 1;
}
} // namespace luascriptfunctions
Time* Time::_instance = nullptr;
Time::Time()
: _time(-1.0)
, _deltaTimePerSecond(1.0)
{
}
bool Time::initialize(const std::string& lskKernel) {
assert( _instance == nullptr);
if (!lskKernel.empty()) {
const int success = SpiceManager::ref().loadKernel(
absPath(lskKernel), "TimeKernel");
if (success == 0) {
LERROR("Error loading SPICE time kernel '" << lskKernel << "'");
return false;
}
}
_instance = new Time();
return true;
}
void Time::deinitialize() {
assert(_instance);
delete _instance;
_instance = nullptr;
}
Time& Time::ref() {
assert(this_);
return *this_;
assert(_instance);
return *_instance;
}
bool Time::isInitialized() {
return this_ != nullptr;
return (_instance != nullptr);
}
void Time::setTime(const char* stringTime) {
assert(this_);
// convert UTC to ET
str2et_c ( stringTime, &time_ );
void Time::setTime(double value) {
_time = std::move(value);
}
double Time::getTime() {
assert(this_);
return time_;
double Time::currentTime() const {
assert(_instance);
return _time;
}
double Time::advanceTime(double tickTime) {
return _time += _deltaTimePerSecond * tickTime;
}
void Time::setDeltaTime(double deltaT) {
_deltaTimePerSecond = std::move(deltaT);
}
double Time::deltaTime() const {
return _deltaTimePerSecond;
}
void Time::setTime(std::string time) {
_time = SpiceManager::ref().convertStringToTdbSeconds(std::move(time));
}
std::string Time::currentTimeUTC() const {
return SpiceManager::ref().convertTdbSecondsToString(_time, "YYYY-MM-DDTHR:MN:SC.#####");
}
scripting::ScriptEngine::LuaLibrary Time::luaLibrary() {
scripting::ScriptEngine::LuaLibrary timeLibrary = {
"time",
{
{
"setDeltaTime",
&luascriptfunctions::time_setDeltaTime,
"setDeltaTime(number): Sets the amount of simulation time that happens "
"in one second of real time"
},
{
"deltaTime",
&luascriptfunctions::time_deltaTime,
"deltaTime: Returns the amount of simulated time that passes in one "
"second of real time"
},
{
"setTime",
&luascriptfunctions::time_setTime,
"setTime({number, string}): Sets the current simulation time to the "
"specified value. If the parameter is a number, the value is the number "
"of seconds past the J2000 epoch. If it is a string, it has to be a "
"valid ISO 8601 date string (YYYY-MM-DDTHH:MN:SS)"
},
{
"currentTime",
&luascriptfunctions::time_currentTime,
"currentTime(): Returns the current time as the number of seconds since "
"the J2000 epoch"
},
{
"currentTimeUTC",
&luascriptfunctions::time_currentTimeUTC,
"currentTimeUTC: Returns the current time as an ISO 8601 date string "
"(YYYY-MM-DDTHH:MN:SS"
}
}
};
return std::move(timeLibrary);
}
} // namespace openspace