Merge branch 'master' of github.com:OpenSpace/OpenSpace into feature/data-management

This commit is contained in:
Emil Axelsson
2017-10-16 11:07:24 +02:00
91 changed files with 2283 additions and 443 deletions

View File

@@ -8,4 +8,4 @@ The project stems from the same academic collaboration between Swedens [Link
This repository contains the source code and example scenes for OpenSpace, but does not contain any data. To build and install the client, we refer to the [Wiki](https://github.com/OpenSpace/OpenSpace/wiki) pages here on GitHub, specifically [building](https://github.com/OpenSpace/OpenSpace/wiki/General-Getting-Started-Guide%3A-Compiling-OpenSpace) for [Windows](https://github.com/OpenSpace/OpenSpace/wiki/Guides-Compile-OpenSpace-on-Windows), [Linux](https://github.com/OpenSpace/OpenSpace/wiki/Guides-Compile-OpenSpace-on-Linux), and [MacOS](https://github.com/OpenSpace/OpenSpace/wiki/Guides-Compile-OpenSpace-on-OSX). Required preexisting dependencies are: [Boost](http://www.boost.org/) and [Qt](http://www.qt.io/download). Feel free to create issues for missing features, bug reports, or compile problems or contact us via [email](mailto:alexander.bock@me.com?subject=OpenSpace:).
Regarding any issues, you are very welcome on our [Slack support channel](https://openspacesupport.slack.com) to which you can freely [sign-up](https://join.slack.com/openspacesupport/shared_invite/MjA4ODY1MDQzNTUzLTE0OTk0MzUyODEtOGZkYTMwNmI5ZA).
Regarding any issues, you are very welcome on our [Slack support channel](https://openspacesupport.slack.com) to which you can freely [sign-up](https://join.slack.com/t/openspacesupport/shared_invite/enQtMjUxNzUyMTQ1ODQxLTI4YjNmMTY3ZDI1N2Q1NWM1ZjQ1NTQyNzAxM2YyMGQ5Y2NmYWJiNjI1NjU4YTkyNTc5ZDE5NzdhNGM2YmUzYTk).

View File

@@ -555,7 +555,8 @@ int main_main(int argc, char** argv) {
{ { 4, 2 }, sgct::Engine::RunMode::OpenGL_4_2_Core_Profile },
{ { 4, 3 }, sgct::Engine::RunMode::OpenGL_4_3_Core_Profile },
{ { 4, 4 }, sgct::Engine::RunMode::OpenGL_4_4_Core_Profile },
{ { 4, 5 }, sgct::Engine::RunMode::OpenGL_4_5_Core_Profile }
{ { 4, 5 }, sgct::Engine::RunMode::OpenGL_4_5_Core_Profile },
{ { 4, 6 }, sgct::Engine::RunMode::OpenGL_4_6_Core_Profile }
};
ghoul_assert(
versionMapping.find(glVersion) != versionMapping.end(),

View File

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

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

View File

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

View File

@@ -55,13 +55,14 @@ public:
const ghoul::Dictionary& dictionary);
ScreenSpaceRenderable(const ghoul::Dictionary& dictionary);
virtual ~ScreenSpaceRenderable();
virtual ~ScreenSpaceRenderable() = default;
virtual void render() = 0;
virtual bool initialize() = 0;
virtual bool deinitialize() = 0;
virtual void render();
virtual bool initialize();
virtual bool deinitialize();
virtual void update() = 0;
virtual bool isReady() const = 0;
virtual bool isReady() const;
bool isEnabled() const;
glm::vec3 euclideanPosition() const;

View File

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

View File

@@ -35,7 +35,8 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderabletrailorbit.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderabletrailtrajectory.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceframebuffer.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceimage.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceimagelocal.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceimageonline.h
${CMAKE_CURRENT_SOURCE_DIR}/translation/statictranslation.h
${CMAKE_CURRENT_SOURCE_DIR}/rotation/staticrotation.h
${CMAKE_CURRENT_SOURCE_DIR}/scale/staticscale.h
@@ -53,7 +54,8 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderabletrailorbit.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderabletrailtrajectory.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceframebuffer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceimage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceimagelocal.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceimageonline.cpp
${CMAKE_CURRENT_SOURCE_DIR}/translation/statictranslation.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rotation/staticrotation.cpp
${CMAKE_CURRENT_SOURCE_DIR}/scale/staticscale.cpp

View File

@@ -39,7 +39,8 @@
#include <modules/base/rendering/renderableplane.h>
#include <modules/base/rendering/modelgeometry.h>
#include <modules/base/rendering/multimodelgeometry.h>
#include <modules/base/rendering/screenspaceimage.h>
#include <modules/base/rendering/screenspaceimagelocal.h>
#include <modules/base/rendering/screenspaceimageonline.h>
#include <modules/base/rendering/screenspaceframebuffer.h>
#include <modules/base/translation/statictranslation.h>
@@ -67,7 +68,8 @@ void BaseModule::internalInitialize() {
auto fScreenSpaceRenderable = FactoryManager::ref().factory<ScreenSpaceRenderable>();
ghoul_assert(fScreenSpaceRenderable, "ScreenSpaceRenderable factory was not created");
fScreenSpaceRenderable->registerClass<ScreenSpaceImage>("ScreenSpaceImage");
fScreenSpaceRenderable->registerClass<ScreenSpaceImageLocal>("ScreenSpaceImageLocal");
fScreenSpaceRenderable->registerClass<ScreenSpaceImageOnline>("ScreenSpaceImageOnline");
fScreenSpaceRenderable->registerClass<ScreenSpaceFramebuffer>("ScreenSpaceFramebuffer");
auto fRenderable = FactoryManager::ref().factory<Renderable>();
@@ -108,7 +110,8 @@ std::vector<documentation::Documentation> BaseModule::documentations() const {
RenderableTrailOrbit::Documentation(),
RenderableTrailTrajectory::Documentation(),
ScreenSpaceFramebuffer::Documentation(),
ScreenSpaceImage::Documentation(),
ScreenSpaceImageLocal::Documentation(),
ScreenSpaceImageOnline::Documentation(),
StaticRotation::Documentation(),
StaticScale::Documentation(),
StaticTranslation::Documentation(),

View File

@@ -76,29 +76,14 @@ ScreenSpaceFramebuffer::ScreenSpaceFramebuffer(const ghoul::Dictionary& dictiona
ScreenSpaceFramebuffer::~ScreenSpaceFramebuffer() {}
bool ScreenSpaceFramebuffer::initialize() {
_originalViewportSize = OsEng.windowWrapper().currentWindowResolution();
createPlane();
createShaders();
ScreenSpaceRenderable::initialize();
createFragmentbuffer();
return isReady();
}
bool ScreenSpaceFramebuffer::deinitialize() {
glDeleteVertexArrays(1, &_quad);
_quad = 0;
glDeleteBuffers(1, &_vertexPositionBuffer);
_vertexPositionBuffer = 0;
_texture = nullptr;
RenderEngine& renderEngine = OsEng.renderEngine();
if (_shader) {
renderEngine.removeRenderProgram(_shader);
_shader = nullptr;
}
ScreenSpaceRenderable::deinitialize();
_framebuffer->detachAll();
removeAllRenderFunctions();

View File

@@ -31,8 +31,6 @@
#include <ghoul/opengl/framebufferobject.h>
#include <ghoul/opengl/textureunit.h>
#include <modules/base/rendering/screenspaceimage.h>
namespace openspace {
namespace documentation { struct Documentation; }

View File

@@ -0,0 +1,127 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/base/rendering/screenspaceimagelocal.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/wrapper/windowwrapper.h>
#include <openspace/rendering/renderengine.h>
#include <ghoul/opengl/programobject.h>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/filesystem/filesystem>
#include <ghoul/opengl/textureconversion.h>
namespace {
const char* KeyName = "Name";
const char* KeyUrl = "URL";
static const openspace::properties::Property::PropertyInfo TexturePathInfo = {
"TexturePath",
"Texture path",
"Sets the path of the texture that is displayed on this screen space plane. If "
"this value is changed, the image at the new path will automatically be loaded "
"and displayed. The size of the image will also automatically set the default "
"size of this plane."
};
} // namespace
namespace openspace {
documentation::Documentation ScreenSpaceImageLocal::Documentation() {
using namespace openspace::documentation;
return {
"ScreenSpace Local Image",
"base_screenspace_image_local",
{
{
KeyName,
new StringVerifier,
Optional::Yes,
"Specifies the GUI name of the ScreenspaceImage"
},
{
TexturePathInfo.identifier,
new StringVerifier,
Optional::Yes,
TexturePathInfo.description
}
}
};
}
ScreenSpaceImageLocal::ScreenSpaceImageLocal(const ghoul::Dictionary& dictionary)
: ScreenSpaceRenderable(dictionary)
, _texturePath(TexturePathInfo)
, _textureIsDirty(false)
{
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"ScreenSpaceImageLocal"
);
if (dictionary.hasKey(KeyName)) {
setName(dictionary.value<std::string>(KeyName));
}
else {
static int id = 0;
setName("ScreenSpaceImageLocal " + std::to_string(id));
++id;
}
_texturePath.onChange([this]() { _textureIsDirty = true; });
addProperty(_texturePath);
if (dictionary.hasKey(TexturePathInfo.identifier)) {
_texturePath = dictionary.value<std::string>(TexturePathInfo.identifier);
}
}
void ScreenSpaceImageLocal::update() {
if (_textureIsDirty && !_texturePath.value().empty()) {
std::unique_ptr<ghoul::opengl::Texture> texture =
ghoul::io::TextureReader::ref().loadTexture(absPath(_texturePath));
if (texture) {
// Images don't need to start on 4-byte boundaries, for example if the
// image is only RGB
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
texture->uploadTexture();
// Textures of planets looks much smoother with AnisotropicMipMap rather than linear
texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear);
_texture = std::move(texture);
_textureIsDirty = false;
}
}
}
} // namespace openspace

View File

@@ -0,0 +1,53 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2017 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_BASE___SCREENSPACEIMAGELOCAL___H__
#define __OPENSPACE_MODULE_BASE___SCREENSPACEIMAGELOCAL___H__
#include <openspace/rendering/screenspacerenderable.h>
#include <openspace/properties/stringproperty.h>
#include <ghoul/opengl/texture.h>
namespace openspace {
namespace documentation { struct Documentation; }
class ScreenSpaceImageLocal : public ScreenSpaceRenderable {
public:
ScreenSpaceImageLocal(const ghoul::Dictionary& dictionary);
void update() override;
static documentation::Documentation Documentation();
private:
properties::StringProperty _texturePath;
bool _textureIsDirty;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_BASE___SCREENSPACEIMAGELOCAL___H__

View File

@@ -22,7 +22,7 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/base/rendering/screenspaceimage.h>
#include <modules/base/rendering/screenspaceimageonline.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
@@ -38,12 +38,11 @@
namespace {
const char* KeyName = "Name";
const char* KeyTexturePath = "TexturePath";
const char* KeyUrl = "URL";
static const openspace::properties::Property::PropertyInfo TexturePathInfo = {
"TexturePath",
"Texture path",
"Sets the path of the texture that is displayed on this screen space plane. If "
"Sets the URL of the texture that is displayed on this screen space plane. If "
"this value is changed, the image at the new path will automatically be loaded "
"and displayed. The size of the image will also automatically set the default "
"size of this plane."
@@ -52,11 +51,11 @@ namespace {
namespace openspace {
documentation::Documentation ScreenSpaceImage::Documentation() {
documentation::Documentation ScreenSpaceImageOnline::Documentation() {
using namespace openspace::documentation;
return {
"ScreenSpace Image",
"base_screenspace_image",
"ScreenSpace Online Image",
"base_screenspace_image_online",
{
{
KeyName,
@@ -68,16 +67,14 @@ documentation::Documentation ScreenSpaceImage::Documentation() {
KeyTexturePath,
new StringVerifier,
Optional::Yes,
"Specifies the image that is shown on the screenspace-aligned plane. If "
"this value is set and the URL is not, the disk image is used."
TexturePathInfo.description
}
}
};
}
ScreenSpaceImage::ScreenSpaceImage(const ghoul::Dictionary& dictionary)
ScreenSpaceImageOnline::ScreenSpaceImageOnline(const ghoul::Dictionary& dictionary)
: ScreenSpaceRenderable(dictionary)
, _downloadImage(false)
, _textureIsDirty(false)
, _texturePath(TexturePathInfo)
{
@@ -92,138 +89,78 @@ ScreenSpaceImage::ScreenSpaceImage(const ghoul::Dictionary& dictionary)
}
else {
static int id = 0;
setName("ScreenSpaceImage " + std::to_string(id));
setName("ScreenSpaceImageOnline " + std::to_string(id));
++id;
}
std::string texturePath;
if (dictionary.getValue(KeyTexturePath, texturePath)) {
_texturePath = dictionary.value<std::string>(KeyTexturePath);
}
if (dictionary.getValue(KeyUrl, _url)) {
_downloadImage = true;
}
_texturePath.onChange([this]() { _textureIsDirty = true; });
addProperty(_texturePath);
}
bool ScreenSpaceImage::initialize() {
_originalViewportSize = OsEng.windowWrapper().currentWindowResolution();
createPlane();
createShaders();
updateTexture();
return isReady();
}
bool ScreenSpaceImage::deinitialize() {
glDeleteVertexArrays(1, &_quad);
_quad = 0;
glDeleteBuffers(1, &_vertexPositionBuffer);
_vertexPositionBuffer = 0;
_texturePath = "";
_texture = nullptr;
if (_shader) {
OsEng.renderEngine().removeRenderProgram(_shader);
_shader = nullptr;
std::string texturePath;
if (dictionary.hasKey(TexturePathInfo.identifier)) {
_texturePath = dictionary.value<std::string>(TexturePathInfo.identifier);
}
return true;
}
void ScreenSpaceImage::render() {
draw(rotationMatrix() * translationMatrix() * scaleMatrix());
}
void ScreenSpaceImageOnline::update() {
if (_textureIsDirty) {
if (!_imageFuture.valid()) {
std::future<DownloadManager::MemoryFile> future = downloadImageToMemory(_texturePath);
if (future.valid()) {
_imageFuture = std::move(future);
}
}
void ScreenSpaceImage::update() {
bool download = _downloadImage ? (_futureImage.valid() && DownloadManager::futureReady(_futureImage)) : true;
if (download && _textureIsDirty) {
loadTexture();
}
}
if (_imageFuture.valid() && DownloadManager::futureReady(_imageFuture)) {
DownloadManager::MemoryFile imageFile = _imageFuture.get();
bool ScreenSpaceImage::isReady() const {
return _shader && _texture;
}
if (imageFile.corrupted) {
LERRORC(
"ScreenSpaceImageOnline",
"Error loading image from URL '" << _texturePath << "'"
);
return;
}
void ScreenSpaceImage::loadTexture() {
std::unique_ptr<ghoul::opengl::Texture> texture = nullptr;
if (!_downloadImage)
texture = loadFromDisk();
else
texture = loadFromMemory();
std::unique_ptr<ghoul::opengl::Texture> texture =
ghoul::io::TextureReader::ref().loadTexture(
reinterpret_cast<void*>(imageFile.buffer),
imageFile.size,
imageFile.format
);
if (texture) {
// LDEBUG("Loaded texture from '" << absPath(_texturePath) << "'");
texture->uploadTexture();
if (texture) {
// Images don't need to start on 4-byte boundaries, for example if the
// image is only RGB
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Textures of planets looks much smoother with AnisotropicMipMap rather than linear
texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear);
texture->uploadTexture();
_texture = std::move(texture);
_textureIsDirty = false;
}
}
// Textures of planets looks much smoother with AnisotropicMipMap rather than linear
texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear);
void ScreenSpaceImage::updateTexture() {
if (!_downloadImage) {
loadTexture();
} else {
if (_futureImage.valid())
return;
std::future<DownloadManager::MemoryFile> future = downloadImageToMemory(_url);
if (future.valid()) {
_futureImage = std::move(future);
_texture = std::move(texture);
_textureIsDirty = false;
}
}
}
}
std::unique_ptr<ghoul::opengl::Texture> ScreenSpaceImage::loadFromDisk() {
if (_texturePath.value() != "")
return (ghoul::io::TextureReader::ref().loadTexture(absPath(_texturePath.value())));
return nullptr;
}
std::unique_ptr<ghoul::opengl::Texture> ScreenSpaceImage::loadFromMemory() {
if (_futureImage.valid() && DownloadManager::futureReady(_futureImage)) {
DownloadManager::MemoryFile imageFile = _futureImage.get();
if (imageFile.corrupted) {
return nullptr;
}
return (ghoul::io::TextureReader::ref().loadTexture(
reinterpret_cast<void*>(imageFile.buffer),
imageFile.size,
imageFile.format)
);
}
else {
return nullptr;
}
}
std::future<DownloadManager::MemoryFile> ScreenSpaceImage::downloadImageToMemory(
std::future<DownloadManager::MemoryFile> ScreenSpaceImageOnline::downloadImageToMemory(
std::string url)
{
return OsEng.downloadManager().fetchFile(
url,
[url](const DownloadManager::MemoryFile&) {
LDEBUGC(
"ScreenSpaceImage",
"ScreenSpaceImageOnline",
"Download to memory finished for screen space image"
);
},
[url](const std::string& err) {
LDEBUGC(
"ScreenSpaceImage",
"ScreenSpaceImageOnline",
"Download to memory failer for screen space image: " + err
);
}

View File

@@ -22,8 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_BASE___SCREENSPACEIMAGE___H__
#define __OPENSPACE_MODULE_BASE___SCREENSPACEIMAGE___H__
#ifndef __OPENSPACE_MODULE_BASE___SCREENSPACEIMAGEONLINE___H__
#define __OPENSPACE_MODULE_BASE___SCREENSPACEIMAGEONLINE___H__
#include <openspace/rendering/screenspacerenderable.h>
@@ -36,37 +36,24 @@ namespace openspace {
namespace documentation { struct Documentation; }
class ScreenSpaceImage : public ScreenSpaceRenderable {
class ScreenSpaceImageOnline : public ScreenSpaceRenderable {
public:
ScreenSpaceImage(const ghoul::Dictionary& dictionary);
ScreenSpaceImageOnline(const ghoul::Dictionary& dictionary);
bool initialize() override;
bool deinitialize() override;
void render() override;
void update() override;
bool isReady() const override;
static documentation::Documentation Documentation();
protected:
void loadTexture();
void updateTexture();
std::string _url;
bool _downloadImage;
bool _textureIsDirty;
std::future<DownloadManager::MemoryFile> _futureImage;
private:
std::future<DownloadManager::MemoryFile> downloadImageToMemory(std::string url);
std::unique_ptr<ghoul::opengl::Texture> loadFromDisk();
std::unique_ptr<ghoul::opengl::Texture> loadFromMemory();
std::future<DownloadManager::MemoryFile> _imageFuture;
properties::StringProperty _texturePath;
private:
std::future<DownloadManager::MemoryFile> downloadImageToMemory(std::string url);
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_BASE___SCREENSPACEIMAGE___H__
#endif // __OPENSPACE_MODULE_BASE___SCREENSPACEIMAGEONLINE___H__

View File

@@ -24,7 +24,7 @@
#version __CONTEXT__
layout(location = 0) in vec4 in_position;
layout(location = 0) in vec2 in_position;
layout(location = 1) in vec2 in_st;
out vec2 vs_st;
@@ -36,6 +36,6 @@ uniform mat4 ViewProjectionMatrix;
void main() {
vs_st = in_st;
vs_position = ViewProjectionMatrix * ModelTransform * in_position;
vs_position = ViewProjectionMatrix * ModelTransform * vec4(in_position, 0.0, 1.0);
gl_Position = vec4(vs_position);
}

View File

@@ -158,7 +158,7 @@ void RenderableGalaxy::initialize() {
_aspect = static_cast<glm::vec3>(_volumeDimensions);
_aspect = _aspect / std::max(std::max(_aspect.x, _aspect.y), _aspect.z);
RawVolumeReader<glm::tvec4<GLfloat>> reader(_volumeFilename, _volumeDimensions);
volume::RawVolumeReader<glm::tvec4<GLfloat>> reader(_volumeFilename, _volumeDimensions);
_volume = reader.read();
_texture = std::make_unique<ghoul::opengl::Texture>(

View File

@@ -63,7 +63,7 @@ private:
std::string _pointsFilename;
std::unique_ptr<GalaxyRaycaster> _raycaster;
std::unique_ptr<RawVolume<glm::tvec4<GLfloat>>> _volume;
std::unique_ptr<volume::RawVolume<glm::tvec4<GLfloat>>> _volume;
std::unique_ptr<ghoul::opengl::Texture> _texture;
glm::mat4 _pointTransform;
glm::vec3 _aspect;

View File

@@ -83,6 +83,8 @@ std::string MilkywayConversionTask::description()
}
void MilkywayConversionTask::perform(const Task::ProgressCallback& progressCallback) {
using namespace openspace::volume;
std::vector<std::string> filenames;
for (int i = 0; i < _inNSlices; i++) {
filenames.push_back(_inFilenamePrefix + std::to_string(i + _inFirstIndex) + _inFilenameSuffix);

View File

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

View File

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

View File

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

View File

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

View File

@@ -47,7 +47,9 @@ namespace {
const char* _loggerCat = "GUI";
const char* configurationFile = "imgui.ini";
const char* GuiFont = "${FONTS}/Roboto/Roboto-Regular.ttf";
//const char* GuiFont = "${FONTS}/ubuntu/Ubuntu-Regular.ttf";
const char* GuiFont = "${FONTS}/arimo/Arimo-Regular.ttf";
const float FontSize = 14.f;
const ImVec2 size = ImVec2(350, 500);
//GLuint fontTex = 0;
@@ -211,17 +213,25 @@ static void RenderDrawLists(ImDrawData* drawData) {
}
void addScreenSpaceRenderable(std::string texturePath) {
void addScreenSpaceRenderableLocal(std::string texturePath) {
if (!FileSys.fileExists(texturePath)) {
LWARNING("Could not find image '" << texturePath << "'");
return;
}
const std::string luaTable =
"{Type = 'ScreenSpaceImage', TexturePath = openspace.absPath('" + texturePath + "') }";
"{Type = 'ScreenSpaceImageLocal', TexturePath = openspace.absPath('" + texturePath + "') }";
const std::string script = "openspace.registerScreenSpaceRenderable(" + luaTable + ");";
OsEng.scriptEngine().queueScript(script, openspace::scripting::ScriptEngine::RemoteScripting::Yes);
}
void addScreenSpaceRenderableOnline(std::string texturePath) {
const std::string luaTable =
"{Type = 'ScreenSpaceImageOnline', TexturePath = '" + texturePath + "' }";
const std::string script = "openspace.registerScreenSpaceRenderable(" + luaTable + ");";
OsEng.scriptEngine().queueScript(script, openspace::scripting::ScriptEngine::RemoteScripting::Yes);
}
} // namespace
namespace openspace::gui {
@@ -242,7 +252,9 @@ GUI::GUI()
addPropertySubOwner(_property);
addPropertySubOwner(_screenSpaceProperty);
addPropertySubOwner(_virtualProperty);
#ifdef GLOBEBROWSING_USE_GDAL
addPropertySubOwner(_globeBrowsing);
#endif // GLOBEBROWSING_USE_GDAL
addPropertySubOwner(_filePath);
addPropertySubOwner(_time);
#ifdef OPENSPACE_MODULE_ISWA_ENABLED
@@ -287,7 +299,7 @@ void GUI::initialize() {
io.RenderDrawListsFn = RenderDrawLists;
io.Fonts->AddFontFromFileTTF(
absPath(GuiFont).c_str(),
16.f
FontSize
);
ImGuiStyle& style = ImGui::GetStyle();
@@ -295,32 +307,58 @@ void GUI::initialize() {
style.WindowRounding = 0.f;
style.FramePadding = { 3.f, 3.f };
style.FrameRounding = 0.f;
style.ScrollbarSize = 15.f;
style.ItemSpacing = { 3.f, 2.f };
style.ItemInnerSpacing = { 3.f, 2.f };
style.TouchExtraPadding = { 1.f, 1.f };
style.IndentSpacing = 15.f;
style.ScrollbarSize = 10.f;
style.ScrollbarRounding = 0.f;
style.IndentSpacing = 25;
style.ItemSpacing = { 4.f, 2.f };
style.GrabMinSize = 10.f;
style.GrabRounding = 16.f;
style.Colors[ImGuiCol_WindowBg] = ImVec4(0.0f, 0.21f, 0.24f, 1.0f);
style.Colors[ImGuiCol_Border] = ImVec4(0.1f, 0.39f, 0.42f, 0.59f);
style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
style.Colors[ImGuiCol_TitleBg] = ImVec4(0.5f, 0.94f, 1.0f, 0.45f);
style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.5f, 0.94f, 1.0f, 0.45f);
style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.12f, 0.71f, 0.8f, 0.43f);
style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.4f, 0.75f, 0.8f, 0.65f);
style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.4f, 0.75f, 0.8f, 0.65f);
style.Colors[ImGuiCol_ComboBg] = ImVec4(0.18f, 0.51f, 0.78f, 1.f);
style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.5f, 0.8f, 0.76f, 1.0f);
style.Colors[ImGuiCol_Button] = ImVec4(0.0f, 0.36f, 0.67f, 0.6f);
style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.0f, 0.51f, 0.94f, 1.0f);
style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.0f, 0.43f, 0.8f, 1.0f);
style.Colors[ImGuiCol_Header] = ImVec4(0.f, 0.36f, 0.67f, 0.45f);
style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.f, 0.54f, 1.0f, 0.8f);
style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.63f, 0.87f, 0.8f);
style.Colors[ImGuiCol_ResizeGrip] = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
style.Colors[ImGuiCol_CloseButton] = ImVec4(0.75f, 0.75f, 0.75f, 1.0f);
style.Colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.52f, 0.52f, 0.52f, 0.6f);
style.Colors[ImGuiCol_CloseButtonActive] = ImVec4(0.52f, 0.52f, 0.52f, 1.0f);
style.Colors[ImGuiCol_WindowBg] = ImVec4(0.13f, 0.13f, 0.13f, 0.96f);
style.Colors[ImGuiCol_Border] = ImVec4(0.65f, 0.65f, 0.65f, 0.59f);
style.Colors[ImGuiCol_TitleBg] = ImVec4(0.71f, 0.81f, 1.00f, 0.45f);
style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.71f, 0.81f, 1.00f, 0.45f);
style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.51f, 0.69f, 1.00f, 0.63f);
style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.12f, 0.71f, 0.80f, 0.43f);
style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.75f, 0.80f, 0.65f);
style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.40f, 0.75f, 0.80f, 0.65f);
style.Colors[ImGuiCol_ComboBg] = ImVec4(0.18f, 0.51f, 0.78f, 1.00f);
style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.50f, 0.80f, 0.76f, 1.00f);
style.Colors[ImGuiCol_Button] = ImVec4(0.36f, 0.54f, 0.68f, 0.62f);
style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.00f, 0.51f, 0.94f, 1.00f);
style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.00f, 0.43f, 0.80f, 1.00f);
style.Colors[ImGuiCol_Header] = ImVec4(0.69f, 0.69f, 0.69f, 0.45f);
style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.36f, 0.54f, 0.68f, 0.62f);
style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.63f, 0.87f, 0.80f);
style.Colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
style.Colors[ImGuiCol_CloseButton] = ImVec4(0.75f, 0.75f, 0.75f, 1.00f);
style.Colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.52f, 0.52f, 0.52f, 0.60f);
style.Colors[ImGuiCol_CloseButtonActive] = ImVec4(0.52f, 0.52f, 0.52f, 1.00f);
//style.Colors[ImGuiCol_WindowBg] = ImVec4(0.0f, 0.21f, 0.24f, 1.0f);
//style.Colors[ImGuiCol_Border] = ImVec4(0.1f, 0.39f, 0.42f, 0.59f);
//style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
//style.Colors[ImGuiCol_TitleBg] = ImVec4(0.5f, 0.94f, 1.0f, 0.45f);
//style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.5f, 0.94f, 1.0f, 0.45f);
//style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.0f, 0.0f, 0.0f, 0.0f);
//style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.12f, 0.71f, 0.8f, 0.43f);
//style.Colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.4f, 0.75f, 0.8f, 0.65f);
//style.Colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.4f, 0.75f, 0.8f, 0.65f);
//style.Colors[ImGuiCol_ComboBg] = ImVec4(0.18f, 0.51f, 0.78f, 1.f);
//style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.5f, 0.8f, 0.76f, 1.0f);
//style.Colors[ImGuiCol_Button] = ImVec4(0.0f, 0.36f, 0.67f, 0.6f);
//style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.0f, 0.51f, 0.94f, 1.0f);
//style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.0f, 0.43f, 0.8f, 1.0f);
//style.Colors[ImGuiCol_Header] = ImVec4(0.f, 0.36f, 0.67f, 0.45f);
//style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.f, 0.54f, 1.0f, 0.8f);
//style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.63f, 0.87f, 0.8f);
//style.Colors[ImGuiCol_ResizeGrip] = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
//style.Colors[ImGuiCol_CloseButton] = ImVec4(0.75f, 0.75f, 0.75f, 1.0f);
//style.Colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.52f, 0.52f, 0.52f, 0.6f);
//style.Colors[ImGuiCol_CloseButtonActive] = ImVec4(0.52f, 0.52f, 0.52f, 1.0f);
_property.initialize();
_property.setHasRegularProperties(true);
@@ -330,7 +368,9 @@ void GUI::initialize() {
_globalProperty.setHasRegularProperties(true);
_virtualProperty.initialize();
_filePath.initialize();
#ifdef GLOBEBROWSING_USE_GDAL
_globeBrowsing.initialize();
#endif // GLOBEBROWSING_USE_GDAL
_performance.initialize();
_help.initialize();
_parallel.initialize();
@@ -352,7 +392,9 @@ void GUI::deinitialize() {
_screenSpaceProperty.deinitialize();
_virtualProperty.deinitialize();
_filePath.deinitialize();
#ifdef GLOBEBROWSING_USE_GDAL
_globeBrowsing.deinitialize();
#endif // GLOBEBROWSING_USE_GDAL
_property.deinitialize();
delete iniFileBuffer;
@@ -427,8 +469,10 @@ void GUI::initializeGL() {
_screenSpaceProperty.initializeGL();
_globalProperty.initializeGL();
_performance.initializeGL();
_help.initializeGL();
_help.initializeGL();
#ifdef GLOBEBROWSING_USE_GDAL
_globeBrowsing.initializeGL();
#endif // GLOBEBROWSING_USE_GDAL
_filePath.initializeGL();
_parallel.initializeGL();
#ifdef OPENSPACE_MODULE_ISWA_ENABLED
@@ -459,7 +503,9 @@ void GUI::deinitializeGL() {
_performance.deinitializeGL();
_globalProperty.deinitializeGL();
_screenSpaceProperty.deinitializeGL();
#ifdef GLOBEBROWSING_USE_GDAL
_globeBrowsing.deinitializeGL();
#endif // GLOBEBROWSING_USE_GDAL
_filePath.deinitializeGL();
_property.deinitializeGL();
}
@@ -520,9 +566,11 @@ void GUI::endFrame() {
_filePath.render();
}
#ifdef GLOBEBROWSING_USE_GDAL
if (_globeBrowsing.isEnabled()) {
_globeBrowsing.render();
}
#endif // GLOBEBROWSING_USE_GDAL
}
ImGui::Render();
@@ -622,9 +670,11 @@ void GUI::render() {
ImGui::Checkbox("File Paths", &filePath);
_filePath.setEnabled(filePath);
#ifdef GLOBEBROWSING_USE_GDAL
bool globeBrowsing = _globeBrowsing.isEnabled();
ImGui::Checkbox("GlobeBrowsing", &globeBrowsing);
_globeBrowsing.setEnabled(globeBrowsing);
#endif // GLOBEBROWSING_USE_GDAL
#ifdef OPENSPACE_MODULE_ISWA_ENABLED
bool iswa = _iswa.isEnabled();
@@ -642,16 +692,27 @@ void GUI::render() {
renderAndUpdatePropertyVisibility();
static const int addImageBufferSize = 256;
static char addImageBuffer[addImageBufferSize];
static char addImageLocalBuffer[addImageBufferSize];
static char addImageOnlineBuffer[addImageBufferSize];
bool addImage = ImGui::InputText(
"addImage",
addImageBuffer,
bool addImageLocal = ImGui::InputText(
"Add Local Image",
addImageLocalBuffer,
addImageBufferSize,
ImGuiInputTextFlags_EnterReturnsTrue
);
if (addImage) {
addScreenSpaceRenderable(std::string(addImageBuffer));
if (addImageLocal) {
addScreenSpaceRenderableLocal(std::string(addImageLocalBuffer));
}
bool addImageOnline = ImGui::InputText(
"Add Online Image",
addImageOnlineBuffer,
addImageBufferSize,
ImGuiInputTextFlags_EnterReturnsTrue
);
if (addImageOnline) {
addScreenSpaceRenderableOnline(std::string(addImageOnlineBuffer));
}
ImGui::Checkbox("ImGUI Internals", &_showInternals);

View File

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

View File

@@ -36,7 +36,7 @@ namespace {
namespace openspace {
ScreenSpaceCygnet::ScreenSpaceCygnet(const ghoul::Dictionary& dictionary)
: ScreenSpaceImage(dictionary)
: ScreenSpaceImageOnline(dictionary)
{
// hacky, have to first get as float and then cast to int.
float cygnetid;
@@ -48,7 +48,7 @@ ScreenSpaceCygnet::ScreenSpaceCygnet(const ghoul::Dictionary& dictionary)
_updateTime = (int) interval;
_downloadImage = true;
_url = IswaManager::ref().iswaUrl(_cygnetId);
_texturePath = IswaManager::ref().iswaUrl(_cygnetId);
_openSpaceTime = OsEng.timeManager().time().j2000Seconds();
_lastUpdateOpenSpaceTime = _openSpaceTime;
@@ -77,14 +77,9 @@ void ScreenSpaceCygnet::update(){
(_realTime.count()-_lastUpdateRealTime.count()) > _minRealTimeUpdateInterval);
if((OsEng.timeManager().time().timeJumped() || timeToUpdate )){
_url = IswaManager::ref().iswaUrl(_cygnetId);
updateTexture();
_texturePath = IswaManager::ref().iswaUrl(_cygnetId);
_lastUpdateRealTime = _realTime;
_lastUpdateOpenSpaceTime = _openSpaceTime;
}
if(_futureImage.valid() && DownloadManager::futureReady(_futureImage)) {
loadTexture();
}
}
}

View File

@@ -28,14 +28,14 @@
#include <chrono>
#include <future>
#include <openspace/rendering/screenspacerenderable.h>
#include <modules/base/rendering/screenspaceimage.h>
#include <modules/base/rendering/screenspaceimageonline.h>
#include <openspace/engine/downloadmanager.h>
#include <modules/iswa/util/iswamanager.h>
namespace openspace {
class ScreenSpaceCygnet : public ScreenSpaceImage {
class ScreenSpaceCygnet : public ScreenSpaceImageOnline {
public:
ScreenSpaceCygnet(const ghoul::Dictionary& dictionary);
~ScreenSpaceCygnet();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -35,7 +35,7 @@ return {
-- Scene = "${ASSETS}/rosetta.scene",
-- Scene = "${ASSETS}/osirisrex.scene",
Task = "${TASKS}/default.task",
TasksRoot = "${OPENSPACE_DATA}/tasks",
Paths = {
SCRIPTS = "${BASE_PATH}/scripts",
@@ -43,7 +43,6 @@ return {
OPENSPACE_DATA = "${BASE_PATH}/data",
ASSETS = "${BASE_PATH}/assets",
SYNC = "${BASE_PATH}/sync",
TASKS = "${OPENSPACE_DATA}/tasks",
SPICE = "${OPENSPACE_DATA}/spice",
MODULES = "${BASE_PATH}/modules",
TESTDIR = "${BASE_PATH}/tests",

View File

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

View File

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

View File

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

View File

@@ -37,11 +37,6 @@ namespace {
const char* _loggerCat = "ScreenSpaceRenderable";
const char* KeyType = "Type";
const char* KeyFlatScreen = "FlatScreen";
const char* KeyPosition = "Position";
const char* KeyScale = "Scale";
const char* KeyDepth = "Depth";
const char* KeyAlpha = "Alpha";
const char* KeyTag = "Tag";
const float PlaneDepth = -2.f;
@@ -126,6 +121,59 @@ documentation::Documentation ScreenSpaceRenderable::Documentation() {
"available types of Screenspace renderable depend on the configuration of"
"the application and can be written to disk on application startup into "
"the FactoryDocumentation."
},
{
EnabledInfo.identifier,
new BoolVerifier,
Optional::Yes,
EnabledInfo.description
},
{
FlatScreenInfo.identifier,
new BoolVerifier,
Optional::Yes,
FlatScreenInfo.description
},
{
EuclideanPositionInfo.identifier,
new DoubleVector2Verifier,
Optional::Yes,
EuclideanPositionInfo.description
},
{
SphericalPositionInfo.identifier,
new DoubleVector2Verifier,
Optional::Yes,
SphericalPositionInfo.description
},
{
DepthInfo.identifier,
new DoubleVerifier,
Optional::Yes,
DepthInfo.description
},
{
ScaleInfo.identifier,
new DoubleVerifier,
Optional::Yes,
ScaleInfo.description
},
{
AlphaInfo.identifier,
new DoubleVerifier,
Optional::Yes,
AlphaInfo.description
},
{
KeyTag,
new OrVerifier(
new StringVerifier,
new StringListVerifier
),
Optional::Yes,
"Defines either a single or multiple tags that apply to this "
"ScreenSpaceRenderable, thus making it possible to address multiple, "
"seprate Renderables with a single property change."
}
}
};
@@ -143,15 +191,7 @@ std::unique_ptr<ScreenSpaceRenderable> ScreenSpaceRenderable::createFromDictiona
std::string renderableType = dictionary.value<std::string>(KeyType);
auto factory = FactoryManager::ref().factory<ScreenSpaceRenderable>();
std::unique_ptr<ScreenSpaceRenderable> result = factory->create(renderableType, dictionary);
if (result == nullptr) {
LERROR("Failed to create a ScreenSpaceRenderable object of type '" <<
renderableType << "'"
);
return nullptr;
}
return result;
return factory->create(renderableType, dictionary);
}
ScreenSpaceRenderable::ScreenSpaceRenderable(const ghoul::Dictionary& dictionary)
@@ -182,25 +222,61 @@ ScreenSpaceRenderable::ScreenSpaceRenderable(const ghoul::Dictionary& dictionary
{
addProperty(_enabled);
addProperty(_useFlatScreen);
addProperty(_euclideanPosition);
// Setting spherical/euclidean onchange handler
_useFlatScreen.onChange([this]() {
if (_useFlatScreen) {
addProperty(_euclideanPosition);
removeProperty(_sphericalPosition);
}
else {
removeProperty(_euclideanPosition);
addProperty(_sphericalPosition);
}
useEuclideanCoordinates(_useFlatScreen);
});
addProperty(_depth);
addProperty(_scale);
addProperty(_alpha);
addProperty(_delete);
dictionary.getValue(KeyFlatScreen, _useFlatScreen);
if (dictionary.hasKey(EnabledInfo.identifier)) {
_enabled = dictionary.value<bool>(EnabledInfo.identifier);
}
if (dictionary.hasKey(FlatScreenInfo.identifier)) {
_useFlatScreen = dictionary.value<bool>(FlatScreenInfo.identifier);
}
useEuclideanCoordinates(_useFlatScreen);
if (_useFlatScreen) {
dictionary.getValue(KeyPosition, _euclideanPosition);
if (dictionary.hasKey(EuclideanPositionInfo.identifier)) {
_euclideanPosition = dictionary.value<glm::vec2>(
EuclideanPositionInfo.identifier
);
}
}
else {
dictionary.getValue(KeyPosition, _sphericalPosition);
if (dictionary.hasKey(SphericalPositionInfo.identifier)) {
_sphericalPosition = dictionary.value<glm::vec2>(
SphericalPositionInfo.identifier
);
}
}
if (dictionary.hasKey(ScaleInfo.identifier)) {
_scale = static_cast<float>(dictionary.value<double>(ScaleInfo.identifier));
}
dictionary.getValue(KeyScale, _scale);
dictionary.getValue(KeyDepth, _depth);
dictionary.getValue(KeyAlpha, _alpha);
if (dictionary.hasKey(DepthInfo.identifier)) {
_depth = static_cast<float>(dictionary.value<double>(DepthInfo.identifier));
}
if (dictionary.hasKey(AlphaInfo.identifier)) {
_alpha = static_cast<float>(dictionary.value<double>(AlphaInfo.identifier));
}
if (dictionary.hasKeyAndValue<std::string>(KeyTag)) {
std::string tagName = dictionary.value<std::string>(KeyTag);
@@ -219,18 +295,6 @@ ScreenSpaceRenderable::ScreenSpaceRenderable(const ghoul::Dictionary& dictionary
}
}
// Setting spherical/euclidean onchange handler
_useFlatScreen.onChange([this](){
if (_useFlatScreen) {
addProperty(_euclideanPosition);
removeProperty(_sphericalPosition);
} else {
removeProperty(_euclideanPosition);
addProperty(_sphericalPosition);
}
useEuclideanCoordinates(_useFlatScreen);
});
_delete.onChange([this](){
std::string script =
"openspace.unregisterScreenSpaceRenderable('" + name() + "');";
@@ -241,7 +305,40 @@ ScreenSpaceRenderable::ScreenSpaceRenderable(const ghoul::Dictionary& dictionary
});
}
ScreenSpaceRenderable::~ScreenSpaceRenderable() {}
bool ScreenSpaceRenderable::initialize() {
_originalViewportSize = OsEng.windowWrapper().currentWindowResolution();
createPlane();
createShaders();
return isReady();
}
bool ScreenSpaceRenderable::deinitialize() {
glDeleteVertexArrays(1, &_quad);
_quad = 0;
glDeleteBuffers(1, &_vertexPositionBuffer);
_vertexPositionBuffer = 0;
_texture = nullptr;
RenderEngine& renderEngine = OsEng.renderEngine();
if (_shader) {
renderEngine.removeRenderProgram(_shader);
_shader = nullptr;
}
return true;
}
void ScreenSpaceRenderable::render() {
draw(rotationMatrix() * translationMatrix() * scaleMatrix());
}
bool ScreenSpaceRenderable::isReady() const {
return _shader && _texture;
}
bool ScreenSpaceRenderable::isEnabled() const {
return _enabled;
@@ -262,29 +359,27 @@ float ScreenSpaceRenderable::depth() const {
void ScreenSpaceRenderable::createPlane() {
glGenVertexArrays(1, &_quad);
glGenBuffers(1, &_vertexPositionBuffer);
// ============================
// GEOMETRY (quad)
// ============================
const GLfloat vertex_data[] = {
// x y z w s t
-1, -1, 0.0f, 1, 0, 0,
1, 1, 0.0f, 1, 1, 1,
-1, 1, 0.0f, 1, 0, 1,
-1, -1, 0.0f, 1, 0, 0,
1, -1, 0.0f, 1, 1, 0,
1, 1, 0.0f, 1, 1, 1,
const GLfloat data[] = {
// x y s t
-1.f, -1.f, 0.f, 0.f,
1.f, 1.f, 1.f, 1.f,
-1.f, 1.f, 0.f, 1.f,
-1.f, -1.f, 0.f, 0.f,
1.f, -1.f, 1.f, 0.f,
1.f, 1.f, 1.f, 1.f,
};
glBindVertexArray(_quad);
glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(
0,
4,
2,
GL_FLOAT,
GL_FALSE,
sizeof(GLfloat) * 6,
sizeof(GLfloat) * 4,
nullptr
);
@@ -294,8 +389,8 @@ void ScreenSpaceRenderable::createPlane() {
2,
GL_FLOAT,
GL_FALSE,
sizeof(GLfloat) * 6,
reinterpret_cast<void*>(sizeof(GLfloat) * 4)
sizeof(GLfloat) * 4,
reinterpret_cast<void*>(sizeof(GLfloat) * 2)
);
}

View File

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

View File

@@ -96,7 +96,6 @@ void SceneLoader::loadScene(Scene* scene, const std::string& path) {
//_assetLoader->rootAsset()->getSynchronizations();
// also show
try {
_assetLoader->rootAsset()->initialize();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -23,6 +23,7 @@
****************************************************************************************/
#include "gtest/gtest.h"
#include <openspace/util/concurrentqueue.h>
#define _USE_MATH_DEFINES

View File

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