mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-08 04:31:08 -06:00
Merge branch 'master' of github.com:OpenSpace/OpenSpace into feature/data-management
This commit is contained in:
@@ -8,4 +8,4 @@ The project stems from the same academic collaboration between Sweden’s [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).
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
BIN
data/fonts/arimo/Arimo-Bold.ttf
Normal file
BIN
data/fonts/arimo/Arimo-Bold.ttf
Normal file
Binary file not shown.
BIN
data/fonts/arimo/Arimo-BoldItalic.ttf
Normal file
BIN
data/fonts/arimo/Arimo-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
data/fonts/arimo/Arimo-Italic.ttf
Normal file
BIN
data/fonts/arimo/Arimo-Italic.ttf
Normal file
Binary file not shown.
BIN
data/fonts/arimo/Arimo-Regular.ttf
Normal file
BIN
data/fonts/arimo/Arimo-Regular.ttf
Normal file
Binary file not shown.
202
data/fonts/arimo/LICENSE.txt
Normal file
202
data/fonts/arimo/LICENSE.txt
Normal 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.
|
||||
2
ext/sgct
2
ext/sgct
Submodule ext/sgct updated: 34d3ebb4dd...ee29d15894
@@ -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;
|
||||
|
||||
@@ -46,7 +46,6 @@ namespace ghoul::opengl {
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class RenderableVolume;
|
||||
class Camera;
|
||||
class Scene;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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; }
|
||||
|
||||
127
modules/base/rendering/screenspaceimagelocal.cpp
Normal file
127
modules/base/rendering/screenspaceimagelocal.cpp
Normal 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
|
||||
53
modules/base/rendering/screenspaceimagelocal.h
Normal file
53
modules/base/rendering/screenspaceimagelocal.h
Normal 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__
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
@@ -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__
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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})
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__
|
||||
|
||||
207
modules/kameleonvolume/tasks/kameleonvolumetorawtask.cpp
Normal file
207
modules/kameleonvolume/tasks/kameleonvolumetorawtask.cpp
Normal 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
|
||||
59
modules/kameleonvolume/tasks/kameleonvolumetorawtask.h
Normal file
59
modules/kameleonvolume/tasks/kameleonvolumetorawtask.h
Normal 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__
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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__
|
||||
473
modules/volume/rendering/renderabletimevaryingvolume.cpp
Normal file
473
modules/volume/rendering/renderabletimevaryingvolume.cpp
Normal 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
|
||||
109
modules/volume/rendering/renderabletimevaryingvolume.h
Normal file
109
modules/volume/rendering/renderabletimevaryingvolume.h
Normal 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__
|
||||
@@ -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
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
48
modules/volume/volumegridtype.cpp
Normal file
48
modules/volume/volumegridtype.cpp
Normal 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
|
||||
@@ -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__
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -33,6 +33,7 @@ class VolumeModule : public OpenSpaceModule {
|
||||
public:
|
||||
constexpr static const char* Name = "Volume";
|
||||
|
||||
void internalInitialize() override;
|
||||
VolumeModule();
|
||||
};
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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"
|
||||
),
|
||||
|
||||
@@ -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());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -96,7 +96,6 @@ void SceneLoader::loadScene(Scene* scene, const std::string& path) {
|
||||
//_assetLoader->rootAsset()->getSynchronizations();
|
||||
|
||||
// also show
|
||||
|
||||
|
||||
try {
|
||||
_assetLoader->rootAsset()->initialize();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
****************************************************************************************/
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <openspace/util/concurrentqueue.h>
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
|
||||
93
tests/test_rawvolumeio.inl
Normal file
93
tests/test_rawvolumeio.inl
Normal 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));
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user