mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-06 19:39:56 -05:00
Merging Master
This commit is contained in:
+3
-3
@@ -10,9 +10,6 @@
|
||||
[submodule "modules/touch/ext/libTUIO11"]
|
||||
path = modules/touch/ext/libTUIO11
|
||||
url = https://github.com/mkalten/TUIO11_CPP
|
||||
[submodule "modules/sync/ext/libtorrent"]
|
||||
path = modules/sync/ext/libtorrent
|
||||
url = https://github.com/OpenSpace/libtorrent.git
|
||||
[submodule "apps/OpenSpace-MinVR/ext/minvr"]
|
||||
path = apps/OpenSpace-MinVR/ext/minvr
|
||||
url = https://github.com/OpenSpace/minvr
|
||||
@@ -26,3 +23,6 @@
|
||||
[submodule "modules/fitsfilereader/ext/cfitsio"]
|
||||
path = modules/fitsfilereader/ext/cfitsio
|
||||
url = https://github.com/OpenSpace/cfitsio.git
|
||||
[submodule "apps/OpenSpace-MinVR/ext/glfw"]
|
||||
path = apps/OpenSpace-MinVR/ext/glfw
|
||||
url = https://github.com/opensgct/glfw
|
||||
|
||||
@@ -285,6 +285,11 @@ if (OPENSPACE_WITH_ABUFFER_RENDERER)
|
||||
target_compile_definitions(openspace-core PUBLIC "OPENSPACE_WITH_ABUFFER_RENDERER")
|
||||
endif ()
|
||||
|
||||
option(OPENSPACE_WITH_INSTRUMENTATION "Add instrumentation options" OFF)
|
||||
if (OPENSPACE_WITH_INSTRUMENTATION)
|
||||
target_compile_definitions(openspace-core PUBLIC "OPENSPACE_WITH_INSTRUMENTATION")
|
||||
endif ()
|
||||
|
||||
|
||||
# Just in case, create the bin directory
|
||||
add_custom_command(
|
||||
|
||||
@@ -50,7 +50,7 @@ target_include_directories(OpenSpace-MinVR PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/ex
|
||||
target_include_directories(OpenSpace-MinVR PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/ext/minvr/external/GLFW/src/include)
|
||||
|
||||
|
||||
target_link_libraries(OpenSpace-MinVR libOpenSpace MinVR)
|
||||
target_link_libraries(OpenSpace-MinVR openspace-core MinVR)
|
||||
|
||||
# Web Browser and Web gui
|
||||
# Why not put these in the module's path? Because they do not have access to the
|
||||
|
||||
@@ -200,7 +200,14 @@ void Handler::onVREvent(const VRDataIndex& eventData) {
|
||||
if (button == MouseButton::Right && action == MouseAction::Press) {
|
||||
windowingGlobals.mouseButtons |= 1 << 2;
|
||||
}
|
||||
global::openSpaceEngine.mouseButtonCallback(button, action);
|
||||
|
||||
using KM = KeyModifier;
|
||||
KM mod = KM::NoModifier;
|
||||
mod |= keyboardState.modifierShift ? KM::Shift : KM::NoModifier;
|
||||
mod |= keyboardState.modifierCtrl ? KM::Control : KM::NoModifier;
|
||||
mod |= keyboardState.modifierAlt ? KM::Alt : KM::NoModifier;
|
||||
|
||||
global::openSpaceEngine.mouseButtonCallback(button, action, mod);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -341,6 +348,14 @@ int main(int argc, char** argv) {
|
||||
|
||||
ghoul::initialize();
|
||||
|
||||
// Register the path of the executable,
|
||||
// to make it possible to find other files in the same directory.
|
||||
FileSys.registerPathToken(
|
||||
"${BIN}",
|
||||
ghoul::filesystem::File(absPath(argv[0])).directoryName(),
|
||||
ghoul::filesystem::FileSystem::Override::Yes
|
||||
);
|
||||
|
||||
// Create the OpenSpace engine and get arguments for the SGCT engine
|
||||
std::string windowConfiguration;
|
||||
try {
|
||||
|
||||
+44
-44
@@ -76,6 +76,8 @@ constexpr const bool EnableDetailedVtune = false;
|
||||
#include "nvToolsExt.h"
|
||||
#endif // OPENSPACE_HAS_NVTOOLS
|
||||
|
||||
using namespace openspace;
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr const char* _loggerCat = "main";
|
||||
@@ -157,9 +159,9 @@ LONG WINAPI generateMiniDump(EXCEPTION_POINTERS* exceptionPointers) {
|
||||
|
||||
std::string dumpFile = fmt::format(
|
||||
"OpenSpace_{}_{}_{}-{}-{}-{}-{}-{}-{}--{}--{}.dmp",
|
||||
openspace::OPENSPACE_VERSION_MAJOR,
|
||||
openspace::OPENSPACE_VERSION_MINOR,
|
||||
openspace::OPENSPACE_VERSION_PATCH,
|
||||
OPENSPACE_VERSION_MAJOR,
|
||||
OPENSPACE_VERSION_MINOR,
|
||||
OPENSPACE_VERSION_PATCH,
|
||||
stLocalTime.wYear,
|
||||
stLocalTime.wMonth,
|
||||
stLocalTime.wDay,
|
||||
@@ -260,7 +262,7 @@ void mainInitFunc() {
|
||||
LTRACE("main::mainInitFunc(begin)");
|
||||
|
||||
LDEBUG("Initializing OpenSpace Engine started");
|
||||
openspace::global::openSpaceEngine.initialize();
|
||||
global::openSpaceEngine.initialize();
|
||||
LDEBUG("Initializing OpenSpace Engine finished");
|
||||
|
||||
{
|
||||
@@ -287,7 +289,7 @@ void mainInitFunc() {
|
||||
|
||||
|
||||
LDEBUG("Initializing OpenGL in OpenSpace Engine started");
|
||||
openspace::global::openSpaceEngine.initializeGL();
|
||||
global::openSpaceEngine.initializeGL();
|
||||
LDEBUG("Initializing OpenGL in OpenSpace Engine finished");
|
||||
|
||||
|
||||
@@ -366,7 +368,7 @@ void mainInitFunc() {
|
||||
//
|
||||
|
||||
std::string screenshotPath = "${SCREENSHOTS}";
|
||||
if (openspace::global::configuration.shouldUseScreenshotDate) {
|
||||
if (global::configuration.shouldUseScreenshotDate) {
|
||||
std::time_t now = std::time(nullptr);
|
||||
std::tm* nowTime = std::localtime(&now);
|
||||
char mbstr[128];
|
||||
@@ -412,13 +414,13 @@ void mainPreSyncFunc() {
|
||||
#endif // OPENSPACE_HAS_VTUNE
|
||||
LTRACE("main::mainPreSyncFunc(begin)");
|
||||
|
||||
openspace::global::openSpaceEngine.preSynchronization();
|
||||
global::openSpaceEngine.preSynchronization();
|
||||
|
||||
// Query joystick status
|
||||
using namespace openspace::interaction;
|
||||
using namespace interaction;
|
||||
|
||||
for (int i = GLFW_JOYSTICK_1; i <= GLFW_JOYSTICK_LAST; ++i) {
|
||||
JoystickInputState& state = openspace::global::joystickInputStates[i];
|
||||
JoystickInputState& state = global::joystickInputStates[i];
|
||||
|
||||
int present = glfwJoystickPresent(i);
|
||||
if (present == GLFW_FALSE) {
|
||||
@@ -511,7 +513,7 @@ void mainPostSyncPreDrawFunc() {
|
||||
#endif // OPENSPACE_HAS_NVTOOLS
|
||||
LTRACE("main::postSynchronizationPreDraw(begin)");
|
||||
|
||||
openspace::global::openSpaceEngine.postSynchronizationPreDraw();
|
||||
global::openSpaceEngine.postSynchronizationPreDraw();
|
||||
|
||||
#ifdef OPENVR_SUPPORT
|
||||
if (FirstOpenVRWindow) {
|
||||
@@ -559,7 +561,7 @@ void mainRenderFunc() {
|
||||
#endif
|
||||
|
||||
try {
|
||||
openspace::global::openSpaceEngine.render(
|
||||
global::openSpaceEngine.render(
|
||||
SgctEngine->getModelMatrix(),
|
||||
viewMatrix,
|
||||
projectionMatrix
|
||||
@@ -591,7 +593,7 @@ void mainDraw2DFunc() {
|
||||
LTRACE("main::mainDraw2DFunc(begin)");
|
||||
|
||||
try {
|
||||
openspace::global::openSpaceEngine.drawOverlays();
|
||||
global::openSpaceEngine.drawOverlays();
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
@@ -627,7 +629,7 @@ void mainPostDrawFunc() {
|
||||
}
|
||||
#endif // OPENVR_SUPPORT
|
||||
|
||||
openspace::global::openSpaceEngine.postDraw();
|
||||
global::openSpaceEngine.postDraw();
|
||||
|
||||
#ifdef OPENSPACE_HAS_SPOUT
|
||||
for (const SpoutWindow& w : SpoutWindows) {
|
||||
@@ -667,7 +669,7 @@ void mainPostDrawFunc() {
|
||||
|
||||
|
||||
|
||||
void mainKeyboardCallback(int key, int, int action, int mods) {
|
||||
void mainKeyboardCallback(int key, int, int action, int modifiers) {
|
||||
#ifdef OPENSPACE_HAS_VTUNE
|
||||
if (EnableDetailedVtune) {
|
||||
__itt_frame_begin_v3(_vTune.keyboard, nullptr);
|
||||
@@ -675,11 +677,10 @@ void mainKeyboardCallback(int key, int, int action, int mods) {
|
||||
#endif // OPENSPACE_HAS_VTUNE
|
||||
LTRACE("main::mainKeyboardCallback(begin)");
|
||||
|
||||
openspace::global::openSpaceEngine.keyboardCallback(
|
||||
openspace::Key(key),
|
||||
openspace::KeyModifier(mods),
|
||||
openspace::KeyAction(action)
|
||||
);
|
||||
const Key k = Key(key);
|
||||
const KeyModifier m = KeyModifier(modifiers);
|
||||
const KeyAction a = KeyAction(action);
|
||||
global::openSpaceEngine.keyboardCallback(k, m, a);
|
||||
|
||||
LTRACE("main::mainKeyboardCallback(begin)");
|
||||
#ifdef OPENSPACE_HAS_VTUNE
|
||||
@@ -699,11 +700,10 @@ void mainMouseButtonCallback(int key, int action, int modifiers) {
|
||||
#endif // OPENSPACE_HAS_VTUNE
|
||||
LTRACE("main::mainMouseButtonCallback(begin)");
|
||||
|
||||
openspace::global::openSpaceEngine.mouseButtonCallback(
|
||||
openspace::MouseButton(key),
|
||||
openspace::MouseAction(action),
|
||||
openspace::KeyModifier(modifiers)
|
||||
);
|
||||
const MouseButton k = MouseButton(key);
|
||||
const MouseAction a = MouseAction(action);
|
||||
const KeyModifier m = KeyModifier(modifiers);
|
||||
global::openSpaceEngine.mouseButtonCallback(k, a, m);
|
||||
|
||||
LTRACE("main::mainMouseButtonCallback(end)");
|
||||
#ifdef OPENSPACE_HAS_VTUNE
|
||||
@@ -722,7 +722,7 @@ void mainMousePosCallback(double x, double y) {
|
||||
}
|
||||
#endif // OPENSPACE_HAS_VTUNE
|
||||
|
||||
openspace::global::openSpaceEngine.mousePositionCallback(x, y);
|
||||
global::openSpaceEngine.mousePositionCallback(x, y);
|
||||
|
||||
#ifdef OPENSPACE_HAS_VTUNE
|
||||
if (EnableDetailedVtune) {
|
||||
@@ -741,7 +741,7 @@ void mainMouseScrollCallback(double posX, double posY) {
|
||||
#endif // OPENSPACE_HAS_VTUNE
|
||||
LTRACE("main::mainMouseScrollCallback(begin");
|
||||
|
||||
openspace::global::openSpaceEngine.mouseScrollWheelCallback(posX, posY);
|
||||
global::openSpaceEngine.mouseScrollWheelCallback(posX, posY);
|
||||
|
||||
LTRACE("main::mainMouseScrollCallback(end)");
|
||||
#ifdef OPENSPACE_HAS_VTUNE
|
||||
@@ -753,17 +753,15 @@ void mainMouseScrollCallback(double posX, double posY) {
|
||||
|
||||
|
||||
|
||||
void mainCharCallback(unsigned int codepoint, int mods) {
|
||||
void mainCharCallback(unsigned int codepoint, int modifiers) {
|
||||
#ifdef OPENSPACE_HAS_VTUNE
|
||||
if (EnableDetailedVtune) {
|
||||
__itt_frame_begin_v3(_vTune.character, nullptr);
|
||||
}
|
||||
#endif // OPENSPACE_HAS_VTUNE
|
||||
|
||||
openspace::global::openSpaceEngine.charCallback(
|
||||
codepoint,
|
||||
openspace::KeyModifier(mods)
|
||||
);
|
||||
const KeyModifier m = KeyModifier(modifiers);
|
||||
global::openSpaceEngine.charCallback(codepoint, m);
|
||||
|
||||
#ifdef OPENSPACE_HAS_VTUNE
|
||||
if (EnableDetailedVtune) {
|
||||
@@ -782,7 +780,7 @@ void mainEncodeFun() {
|
||||
#endif // OPENSPACE_HAS_VTUNE
|
||||
LTRACE("main::mainEncodeFun(begin)");
|
||||
|
||||
std::vector<char> data = openspace::global::openSpaceEngine.encode();
|
||||
std::vector<char> data = global::openSpaceEngine.encode();
|
||||
_synchronizationBuffer.setVal(std::move(data));
|
||||
sgct::SharedData::instance()->writeVector(&_synchronizationBuffer);
|
||||
|
||||
@@ -806,7 +804,7 @@ void mainDecodeFun() {
|
||||
|
||||
sgct::SharedData::instance()->readVector(&_synchronizationBuffer);
|
||||
std::vector<char> data = _synchronizationBuffer.getVal();
|
||||
openspace::global::openSpaceEngine.decode(std::move(data));
|
||||
global::openSpaceEngine.decode(std::move(data));
|
||||
|
||||
LTRACE("main::mainDecodeFun(end)");
|
||||
#ifdef OPENSPACE_HAS_VTUNE
|
||||
@@ -833,7 +831,7 @@ void mainLogCallback(const char* msg) {
|
||||
|
||||
|
||||
void setSgctDelegateFunctions() {
|
||||
openspace::WindowDelegate& sgctDelegate = openspace::global::windowDelegate;
|
||||
WindowDelegate& sgctDelegate = global::windowDelegate;
|
||||
sgctDelegate.terminate = []() { sgct::Engine::instance()->terminate(); };
|
||||
sgctDelegate.setBarrier = [](bool enabled) {
|
||||
sgct::SGCTWindow::setBarrier(enabled);
|
||||
@@ -1101,7 +1099,7 @@ int main(int argc, char** argv) {
|
||||
ghoul::cmdparser::CommandlineParser::AllowUnknownCommands::Yes
|
||||
);
|
||||
|
||||
openspace::CommandlineArguments commandlineArguments;
|
||||
CommandlineArguments commandlineArguments;
|
||||
parser.addCommand(std::make_unique<ghoul::cmdparser::SingleCommand<std::string>>(
|
||||
commandlineArguments.configurationName, "--file", "-f",
|
||||
"Provides the path to the OpenSpace configuration file. Only the '${TEMPORARY}' "
|
||||
@@ -1141,8 +1139,6 @@ int main(int argc, char** argv) {
|
||||
// Create the OpenSpace engine and get arguments for the SGCT engine
|
||||
std::string windowConfiguration;
|
||||
try {
|
||||
using namespace openspace;
|
||||
|
||||
// Find configuration
|
||||
std::string configurationFilePath = commandlineArguments.configurationName;
|
||||
if (commandlineArguments.configurationName.empty()) {
|
||||
@@ -1178,16 +1174,17 @@ int main(int argc, char** argv) {
|
||||
// Determining SGCT configuration file
|
||||
LDEBUG("SGCT Configuration file: " + global::configuration.windowConfiguration);
|
||||
|
||||
windowConfiguration = openspace::global::configuration.windowConfiguration;
|
||||
windowConfiguration = global::configuration.windowConfiguration;
|
||||
}
|
||||
catch (const openspace::documentation::SpecificationError& e) {
|
||||
catch (const documentation::SpecificationError& e) {
|
||||
LFATALC("main", "Loading of configuration file failed");
|
||||
for (const openspace::documentation::TestResult::Offense& o : e.result.offenses) {
|
||||
for (const documentation::TestResult::Offense& o : e.result.offenses) {
|
||||
LERRORC(o.offender, ghoul::to_string(o.reason));
|
||||
}
|
||||
for (const openspace::documentation::TestResult::Warning& w : e.result.warnings) {
|
||||
for (const documentation::TestResult::Warning& w : e.result.warnings) {
|
||||
LWARNINGC(w.offender, ghoul::to_string(w.reason));
|
||||
}
|
||||
ghoul::deinitialize();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
@@ -1196,10 +1193,11 @@ int main(int argc, char** argv) {
|
||||
if (ghoul::logging::LogManager::isInitialized()) {
|
||||
LogMgr.flushLogs();
|
||||
}
|
||||
ghoul::deinitialize();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
openspace::global::openSpaceEngine.registerPathTokens();
|
||||
global::openSpaceEngine.registerPathTokens();
|
||||
|
||||
// Prepend the outgoing sgctArguments with the program name
|
||||
// as well as the configuration file that sgct is supposed to use
|
||||
@@ -1293,8 +1291,8 @@ int main(int argc, char** argv) {
|
||||
|
||||
auto cleanup = [&](bool isInitialized) {
|
||||
if (isInitialized) {
|
||||
openspace::global::openSpaceEngine.deinitializeGL();
|
||||
openspace::global::openSpaceEngine.deinitialize();
|
||||
global::openSpaceEngine.deinitializeGL();
|
||||
global::openSpaceEngine.deinitialize();
|
||||
}
|
||||
|
||||
// Clear function bindings to avoid crash after destroying the OpenSpace Engine
|
||||
@@ -1321,6 +1319,8 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
#endif // OPENSPACE_HAS_SPOUT
|
||||
|
||||
ghoul::deinitialize();
|
||||
};
|
||||
|
||||
if (!initSuccess) {
|
||||
|
||||
+21
-36
@@ -22,43 +22,26 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
|
||||
#include <ghoul/opengl/ghoul_gl.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 <openspace/network/parallelserver.h>
|
||||
#include <ghoul/fmt.h>
|
||||
#include <ghoul/cmdparser/commandlineparser.h>
|
||||
#include <ghoul/cmdparser/singlecommand.h>
|
||||
|
||||
#include <openspace/engine/windowdelegate.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
|
||||
#include <openspace/network/parallelserver.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <ghoul/glm.h>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <iomanip>
|
||||
#include <ios>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "Wormhole";
|
||||
}
|
||||
constexpr const char*_loggerCat = "Wormhole";
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
using namespace openspace;
|
||||
using namespace ghoul::cmdparser;
|
||||
|
||||
std::vector<std::string> arguments(argv, argv + argc);
|
||||
|
||||
ghoul::cmdparser::CommandlineParser commandlineParser(
|
||||
CommandlineParser commandlineParser(
|
||||
"Wormhole",
|
||||
ghoul::cmdparser::CommandlineParser::AllowUnknownCommands::Yes
|
||||
CommandlineParser::AllowUnknownCommands::Yes
|
||||
);
|
||||
|
||||
std::stringstream defaultPassword;
|
||||
@@ -73,43 +56,43 @@ int main(int argc, char** argv) {
|
||||
std::chrono::system_clock::now().time_since_epoch().count() + 1
|
||||
) % 0xffffff);
|
||||
|
||||
std::string portString = "";
|
||||
std::string portString;
|
||||
commandlineParser.addCommand(
|
||||
std::make_unique<ghoul::cmdparser::SingleCommand<std::string>>(
|
||||
portString,
|
||||
"--port",
|
||||
"-p",
|
||||
"Sets the port to listen on"
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
std::string password = "";
|
||||
std::string password;
|
||||
commandlineParser.addCommand(
|
||||
std::make_unique<ghoul::cmdparser::SingleCommand<std::string>>(
|
||||
password,
|
||||
"--password",
|
||||
"-l",
|
||||
"Sets the password to use"
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
std::string changeHostPassword = "";
|
||||
std::string changeHostPassword;
|
||||
commandlineParser.addCommand(
|
||||
std::make_unique<ghoul::cmdparser::SingleCommand<std::string>>(
|
||||
changeHostPassword,
|
||||
"--hostpassword",
|
||||
"-h",
|
||||
"Sets the host password to use"
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
commandlineParser.setCommandLine(arguments);
|
||||
commandlineParser.execute();
|
||||
|
||||
if (password == "") {
|
||||
if (password.empty()) {
|
||||
password = defaultPassword.str();
|
||||
}
|
||||
if (changeHostPassword == "") {
|
||||
if (changeHostPassword.empty()) {
|
||||
changeHostPassword = defaultChangeHostPassword.str();
|
||||
}
|
||||
|
||||
@@ -118,11 +101,11 @@ int main(int argc, char** argv) {
|
||||
|
||||
int port = 25001;
|
||||
|
||||
if (portString != "") {
|
||||
if (!portString.empty()) {
|
||||
try {
|
||||
port = std::stoi(portString);
|
||||
}
|
||||
catch (...) {
|
||||
catch (const std::invalid_argument&) {
|
||||
LERROR(fmt::format("Invalid port: {}", portString));
|
||||
}
|
||||
}
|
||||
@@ -132,7 +115,9 @@ int main(int argc, char** argv) {
|
||||
server.setDefaultHostAddress("127.0.0.1");
|
||||
LINFO(fmt::format("Server listening to port {}", port));
|
||||
|
||||
while (std::cin.get() != 'q') {}
|
||||
while (std::cin.get() != 'q') {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
|
||||
}
|
||||
|
||||
server.stop();
|
||||
LINFO("Server stopped");
|
||||
|
||||
+10
-11
@@ -12,14 +12,19 @@ local Keybindings = {
|
||||
{
|
||||
Key = "E",
|
||||
Command = "openspace.time.setPause(true);" ..
|
||||
"openspace.setPropertyValue('*Trail.Renderable.Enabled', false)"..
|
||||
"openspace.setPropertyValue('Scene.Apollo8LaunchTrail.Renderable.Enabled', false)"..
|
||||
"openspace.sessionRecording.startPlayback('apollo8')",
|
||||
"openspace.time.setDeltaTime(1);" ..
|
||||
"openspace.time.setTime('1968 DEC 24 16:37:31');" ..
|
||||
"openspace.navigation.setNavigationState({" ..
|
||||
" Anchor = 'Apollo8'," ..
|
||||
" Position = { 1.494592E1, 3.236777E1, -4.171296E1 }," ..
|
||||
" ReferenceFrame = 'Root'," ..
|
||||
" Up = { 0.960608E0, -0.212013E0, 0.179675E0 }" ..
|
||||
"});" ..
|
||||
"openspace.setPropertyValue('*Trail.Renderable.Enabled', false)",
|
||||
Documentation = "Jump to right before the earthrise photo",
|
||||
Name = "Set Earthrise time",
|
||||
GuiPath = "/Missions/Apollo/8",
|
||||
Local = false
|
||||
|
||||
},
|
||||
{
|
||||
Key = "U",
|
||||
@@ -115,13 +120,7 @@ asset.onInitialize(function ()
|
||||
openspace.setPropertyValueSingle('NavigationHandler.OrbitalNavigator.MinimumAllowedDistance', 0.000000);
|
||||
openspace.setPropertyValueSingle('Scene.Moon.Renderable.LodScaleFactor', 24.0);
|
||||
|
||||
openspace.navigation.setCameraState({
|
||||
Anchor = earthAsset.Earth.Identifier,
|
||||
Position = { 0, 0, 0 },
|
||||
Rotation = { 0.758797, 0.221490, -0.605693, -0.091135 },
|
||||
})
|
||||
|
||||
openspace.globebrowsing.goToGeo(20, -60, 15000000)
|
||||
openspace.globebrowsing.goToGeo(earthAsset.Earth.Identifier, 20, -60, 15000000)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function ()
|
||||
|
||||
@@ -2,15 +2,15 @@ asset.require('./base')
|
||||
|
||||
--moonrocks.scene
|
||||
local sceneHelper = asset.require('util/scene_helper')
|
||||
|
||||
-- local station2 = asset.require('scene/solarsystem/missions/apollo/bouldersstation2')
|
||||
-- local station6 = asset.require('scene/solarsystem/missions/apollo/bouldersstation6')
|
||||
-- local station7 = asset.require('scene/solarsystem/missions/apollo/bouldersstation7')
|
||||
asset.require('scene/solarsystem/missions/apollo/apollo8')
|
||||
asset.require('scene/solarsystem/missions/apollo/apollo11')
|
||||
asset.require('scene/solarsystem/missions/apollo/a11_lem')
|
||||
asset.require('scene/solarsystem/missions/apollo/a17_lem')
|
||||
asset.require('scene/solarsystem/missions/apollo/apollo_globebrowsing')
|
||||
asset.require('scene/solarsystem/missions/apollo/apollo_11_lem_flipbook')
|
||||
asset.require('scene/solarsystem/missions/apollo/insignias_map')
|
||||
|
||||
local Keybindings = {
|
||||
{
|
||||
@@ -37,11 +37,11 @@ local Keybindings = {
|
||||
},
|
||||
{
|
||||
Key = "F11",
|
||||
Command = "openspace.time.setTime('1969 JUL 20 20:17:40');" ..
|
||||
Command = "openspace.time.setTime('1969 JUL 20 20:17:40');" ..
|
||||
"openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.HeightLayers.LRO_NAC_Apollo_11.Enabled', true);" ..
|
||||
"openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A11_M177481212_p_longlat.Enabled', true);" ..
|
||||
"openspace.setPropertyValueSingle('Scene.Moon.Renderable.LodScaleFactor', 20.11);" ..
|
||||
"openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'Apollo11LemModel');" ..
|
||||
"openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'Apollo11LemPosition');" ..
|
||||
"openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);" ..
|
||||
"openspace.setPropertyValueSingle('Scene.Apollo11MoonTrail.Renderable.Enabled', true);" ..
|
||||
"openspace.setPropertyValueSingle('Scene.Apollo11LemTrail.Renderable.Enabled', true);",
|
||||
@@ -82,10 +82,14 @@ asset.onInitialize(function ()
|
||||
|
||||
sceneHelper.bindKeys(Keybindings)
|
||||
|
||||
openspace.markInterestingNodes({ "Moon", "Apollo11LemModel", "Apollo17LemModel", "Apollo11", "Apollo11LunarLander" })
|
||||
openspace.markInterestingNodes({
|
||||
"Moon", "Apollo11LemModel", "Apollo17LemModel",
|
||||
"Apollo11", "Apollo11LunarLander",
|
||||
-- "Station_2_Boulder2", "Station_6_Fragment1"
|
||||
})
|
||||
|
||||
openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_travmap.BlendMode', 0);
|
||||
-- To enable both sites by default, uncomment these lines
|
||||
-- openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_travmap.BlendMode', 0.000000);
|
||||
-- openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_travmap.Enabled', true);
|
||||
-- openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.HeightLayers.LRO_NAC_Apollo_17.Enabled', true);
|
||||
-- openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_LEM.Enabled', true);
|
||||
@@ -95,17 +99,19 @@ asset.onInitialize(function ()
|
||||
-- openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_station7.BlendMode', 0.000000);
|
||||
-- openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.HeightLayers.LRO_NAC_Apollo_11.Enabled', true);
|
||||
-- openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A11_M177481212_p_longlat.Enabled', true);
|
||||
|
||||
openspace.navigation.setCameraState({
|
||||
Anchor = moonAsset.Moon.Identifier,
|
||||
Position = { 0, 0, 0 },
|
||||
Rotation = { 0, 0, 0, 0 },
|
||||
})
|
||||
openspace.globebrowsing.goToGeo(20, -60, 15000000)
|
||||
|
||||
openspace.setPropertyValueSingle('Scene.Apollo11LemDescentModel.Renderable.RotationVector', { 273.205475,6.904110,308.712311 });
|
||||
openspace.setPropertyValueSingle('Scene.Apollo11LemLandedModel.Renderable.RotationVector', { 273.205475,6.904110,308.712311 });
|
||||
|
||||
openspace.globebrowsing.goToGeo(moonAsset.Moon.Identifier, 20, -60, 15000000)
|
||||
|
||||
openspace.setPropertyValueSingle("Scene.Moon.Renderable.PerformShading", false)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function ()
|
||||
openspace.removeInterestingNodes({ "Moon", "Apollo11Lem", "Apollo17Lem", "Apollo11", "Apollo11LunarLander" })
|
||||
openspace.removeInterestingNodes({
|
||||
"Moon", "Apollo11Lem", "Apollo17Lem",
|
||||
"Apollo11", "Apollo11LemPosition",
|
||||
-- "Station_6_Fragment1", "Station_6_Fragments_2_3"
|
||||
})
|
||||
end)
|
||||
|
||||
@@ -10,10 +10,9 @@ asset.onInitialize(function ()
|
||||
|
||||
openspace.markInterestingNodes({ "Dawn", "Ceres", "Vesta" })
|
||||
|
||||
openspace.navigation.setCameraState({
|
||||
openspace.navigation.setNavigationState({
|
||||
Anchor = DawnAsset.Dawn.Identifier,
|
||||
Position = { 526781518487.171326, 257168309890.072144, -1381125204152.817383 },
|
||||
Rotation = { -0.106166, 0.981574, -0.084545, 0.134513 },
|
||||
})
|
||||
end)
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
local assetHelper = asset.require('util/asset_helper')
|
||||
local sceneHelper = asset.require('util/scene_helper')
|
||||
local propertyHelper = asset.require('util/property_helper')
|
||||
local debugHelper = asset.require('util/debug_helper')
|
||||
|
||||
-- At this point, a sceene needs basic spice data to load.
|
||||
-- At this point, a scene needs basic spice data to load.
|
||||
asset.require('spice/base')
|
||||
|
||||
asset.require('util/default_keybindings')
|
||||
@@ -12,10 +13,15 @@ asset.require('util/default_joystick')
|
||||
asset.require('util/webgui')
|
||||
local spheres = asset.require('examples/spheres')
|
||||
|
||||
debugHelper.registerCartesianAxes(asset, {
|
||||
Parent = "Root",
|
||||
Scale = 10
|
||||
})
|
||||
|
||||
asset.onInitialize(function ()
|
||||
openspace.navigation.setCameraState({
|
||||
Anchor = spheres.ExampleSphere1.Identifier,
|
||||
Position = { 20, 0, 0 },
|
||||
Rotation = { 0.758797, 0.221490, -0.605693, -0.091135 }
|
||||
openspace.navigation.setNavigationState({
|
||||
Anchor = "Root",
|
||||
Position = { 20, 20, 20 },
|
||||
Up = {0, 1, 0},
|
||||
})
|
||||
end)
|
||||
|
||||
@@ -35,10 +35,9 @@ asset.onInitialize(function ()
|
||||
|
||||
openspace.markInterestingNodes({ "Gaia" })
|
||||
|
||||
openspace.navigation.setCameraState({
|
||||
openspace.navigation.setNavigationState({
|
||||
Anchor = earthAsset.Earth.Identifier,
|
||||
Position = { 1000000000000.0, 1000000000000.0, 1000000000000.0 },
|
||||
Rotation = { 0.683224, -0.765934, -0.601234, -0.418073 },
|
||||
})
|
||||
end)
|
||||
|
||||
|
||||
@@ -60,10 +60,11 @@ asset.onInitialize(function ()
|
||||
|
||||
openspace.markInterestingNodes({ "Insight" })
|
||||
|
||||
openspace.navigation.setCameraState({
|
||||
openspace.navigation.setNavigationState({
|
||||
Anchor = insightAsset.Insight.Identifier,
|
||||
Position = { 0, 0, 0 },
|
||||
Rotation = { 0.758797, 0.221490, -0.605693, -0.091135 },
|
||||
Position = { 8.430115E0, -1.791710E1, 2.813660E0 },
|
||||
ReferenceFrame = "Root",
|
||||
Up = { 0.494659E0,0.357162E0,0.792306E0 },
|
||||
})
|
||||
|
||||
end)
|
||||
|
||||
@@ -18,10 +18,11 @@ asset.onInitialize(function ()
|
||||
28800, 57600, 115200, 230400, 460800, 921600, 1843200, 3686400, 7372800, 14745600
|
||||
})
|
||||
|
||||
openspace.navigation.setCameraState({
|
||||
openspace.navigation.setNavigationState({
|
||||
Anchor = junoAsset.Juno.Identifier,
|
||||
Position = { 1837386367.601345, -389860693812.834839, 714830404470.398926 },
|
||||
Rotation = { -0.336540, 0.711402, -0.099212, 0.608937 },
|
||||
Position = { 1.243398E8, 7.176068E7, -1.519733E7 },
|
||||
ReferenceFrame = "Root",
|
||||
Up = { -0.377400E0, 0.764573E0, 0.522492E0 },
|
||||
})
|
||||
end)
|
||||
|
||||
|
||||
@@ -33,10 +33,11 @@ asset.onInitialize(function ()
|
||||
28800, 57600, 115200, 230400, 460800, 921600, 1843200, 3686400, 7372800, 14745600
|
||||
})
|
||||
|
||||
openspace.navigation.setCameraState({
|
||||
openspace.navigation.setNavigationState({
|
||||
Anchor = "Mercury",
|
||||
Position = { 526781518487.171326, 257168309890.072144, -1381125204152.817383 },
|
||||
Rotation = {0.180662, 0.021334, 0.979084, 0.091111},
|
||||
Position = { 2.423690E11, 1.979038E11, -2.241483E10 },
|
||||
ReferenceFrame = "Root",
|
||||
Up = { -0.492046E0, 0.666088E0, 0.560551E0 }
|
||||
})
|
||||
end)
|
||||
|
||||
|
||||
@@ -255,10 +255,11 @@ asset.onInitialize(function ()
|
||||
openspace.setPropertyValueSingle('Scene.Charon.Renderable.Enabled', false)
|
||||
openspace.setPropertyValueSingle("Scene.PlutoBarycenterTrail.Renderable.Enabled", false)
|
||||
|
||||
openspace.navigation.setCameraState({
|
||||
Anchor = NewHorizonsAsset.NewHorizons.Identifier,
|
||||
Position = { 4662120063743.592773, 1263245003503.724854, -955413856565.788086 },
|
||||
Rotation = { 0.683224, -0.165934, 0.701234, 0.118073 },
|
||||
openspace.navigation.setNavigationState({
|
||||
Anchor = "NewHorizons",
|
||||
ReferenceFrame = "Root",
|
||||
Position = { -6.572656E1, -7.239404E1, -2.111890E1 },
|
||||
Up = { 0.102164, -0.362945, 0.926193 }
|
||||
})
|
||||
end)
|
||||
|
||||
|
||||
@@ -134,10 +134,9 @@ asset.onInitialize(function ()
|
||||
|
||||
openspace.markInterestingNodes({ "OsirisRex", "BennuBarycenter", "Earth" })
|
||||
|
||||
openspace.navigation.setCameraState({
|
||||
openspace.navigation.setNavigationState({
|
||||
Anchor = OsirisRexAsset.OsirisRex.Identifier,
|
||||
Position = { 26974590199.661884, 76314608558.908020, -127086452897.101791 },
|
||||
Rotation = { 0.729548, -0.126024, 0.416827, 0.527382 },
|
||||
Position = { 26974590199.661884, 76314608558.908020, -127086452897.101791 }
|
||||
})
|
||||
end)
|
||||
|
||||
|
||||
@@ -134,10 +134,11 @@ asset.onInitialize(function ()
|
||||
28800, 57600, 115200, 230400, 460800, 921600, 1843200, 3686400, 7372800, 14745600
|
||||
})
|
||||
|
||||
openspace.navigation.setCameraState({
|
||||
openspace.navigation.setNavigationState({
|
||||
Anchor = Comet67PAsset.Comet67P.Identifier,
|
||||
Position = { 526781518487.171326, 257168309890.072144, -1381125204152.817383 },
|
||||
Rotation = { -0.106166, 0.981574, -0.084545, 0.134513 },
|
||||
ReferenceFrame = "Root",
|
||||
Position = { -7.294781E5 , -6.657894E5, 2.509047E6 },
|
||||
Up = { 0.146529E0, 0.944727E0, 0.293290E0 }
|
||||
})
|
||||
|
||||
openspace.setPropertyValue('Scene.67P.Renderable.PerformShading', false);
|
||||
|
||||
@@ -1,19 +1,30 @@
|
||||
-- Download a dataset of 618 million stars (28 GB), already preprocessed and stored in a binary octree.
|
||||
-- The octree was generated from the full DR2 by filtering away all stars with a parallax error higher than 0.5
|
||||
-- Max Star Per Node = 50,000 and max distance = 500kpc
|
||||
asset.syncedResource({
|
||||
local gaia618Destination = asset.syncedResource({
|
||||
Name = "Gaia DR2 618M Octree",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "gaia_stars_618M_octree",
|
||||
Version = 1
|
||||
})
|
||||
local gaia618DestinationExtracted = gaia618Destination + '/data';
|
||||
|
||||
-- Download the full DR2 dataset with 24 values per star (preprocessed with theReadFitsTask (gaia_read.task) into 8 binary files).
|
||||
-- From these files new subsets can be created with the ConstructOctreeTask (gaia_octree.task).
|
||||
-- Total size of download is 151 GB.
|
||||
asset.syncedResource({
|
||||
local gaiaFull = asset.syncedResource({
|
||||
Name = "Gaia DR2 Full Raw",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "gaia_stars_dr2_raw",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
asset.onInitialize(function()
|
||||
if not openspace.directoryExists(gaia618DestinationExtracted) then
|
||||
openspace.printInfo("Extracted Gaia dataset")
|
||||
openspace.unzipFile(gaia618Destination .. '/DR2_full_Octree[50kSPN,500dist]_50,50.zip', gaia618DestinationExtracted, true)
|
||||
end
|
||||
end)
|
||||
|
||||
asset.export('GaiaDR2_618M', gaia618DestinationExtracted)
|
||||
asset.export('GaiaFullDataset', gaiaFull)
|
||||
|
||||
@@ -20,7 +20,8 @@ local OumuamuaTrail = {
|
||||
Color = { 0.9, 0.9, 0.0 },
|
||||
StartTime = "2014 JAN 01 00:00:00",
|
||||
EndTime = "2023 JAN 01 00:00:00",
|
||||
SampleInterval = 60
|
||||
SampleInterval = 7000,
|
||||
TimeStampSubsampleFactor = 1
|
||||
},
|
||||
GUI = {
|
||||
Name = "'Oumuamua Trail",
|
||||
|
||||
@@ -15,8 +15,8 @@ local Apollo11Lem = {
|
||||
Globe = moonAsset.Moon.Identifier,
|
||||
Longitude = -360+23.47306,
|
||||
Latitude = 0.67402,
|
||||
FixedAltitude = -1927.65,
|
||||
UseFixedAltitude = true
|
||||
Altitude = -1927.65,
|
||||
UseHeightMap = false
|
||||
},
|
||||
},
|
||||
GUI = {
|
||||
|
||||
@@ -14,6 +14,7 @@ local Apollo17Lem = {
|
||||
Globe = moonAsset.Moon.Identifier,
|
||||
Longitude = -329.22833,
|
||||
Latitude = 20.19092,
|
||||
UseHeightmap = true
|
||||
},
|
||||
},
|
||||
GUI = {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
local assetHelper = asset.require('util/asset_helper')
|
||||
local sunTransforms = asset.require('scene/solarsystem/sun/transforms')
|
||||
local descentKeyframes = asset.require('./apollo11_lem_descent.asset')
|
||||
local descentRotationKeyframes = asset.require('./apollo11_lem_descent_rotation.asset')
|
||||
local model = asset.require('scene/solarsystem/missions/apollo/lem_model')
|
||||
|
||||
asset.require('spice/base')
|
||||
|
||||
@@ -11,7 +14,7 @@ local kernelsFolder = asset.syncedResource({
|
||||
})
|
||||
|
||||
local modelFolder = asset.syncedResource({
|
||||
Name = "Apollo Kernels",
|
||||
Name = "Apollo Models",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "apollo_11_models",
|
||||
Version = 1
|
||||
@@ -24,7 +27,7 @@ local kernels = {
|
||||
kernelsFolder .. '/apollo11_orbits_full9km.bsp',
|
||||
kernelsFolder .. '/apollo11_orbits_lm9km.bsp',
|
||||
}
|
||||
|
||||
--landing - 1969-07-20T20:17:40
|
||||
local apolloSpiceId = "-911"
|
||||
local apolloLemSpiceId = "-911500"
|
||||
|
||||
@@ -107,81 +110,44 @@ local Apollo11MoonTrail = {
|
||||
}
|
||||
}
|
||||
|
||||
-- Uncomment if you want to follow the mock decent
|
||||
-- local Apollo11LemPosition = {
|
||||
-- Identifier = "Apollo11LemPosition",
|
||||
-- Parent = "Moon",
|
||||
-- TimeFrame = {
|
||||
-- Type = "TimeFrameInterval",
|
||||
-- Start = "1969 JUL 20 19:10:25.183",
|
||||
-- End = "1969 JUL 20 20:17:46.183"
|
||||
-- },
|
||||
-- Transform = {
|
||||
-- Translation = {
|
||||
-- Type = "SpiceTranslation",
|
||||
-- Target = apolloLemSpiceId,
|
||||
-- Observer = "MOON",
|
||||
-- Frame = "MOON_ME",
|
||||
-- Kernels = kernels
|
||||
-- },
|
||||
-- },
|
||||
-- GUI = {
|
||||
-- Hidden = true,
|
||||
-- Name = "Apollo 11 Lunar Lander Position",
|
||||
-- Path = "/Solar System/Missions/Apollo/11"
|
||||
-- }
|
||||
-- }
|
||||
|
||||
-- local Apollo11LunarLanderModel = {
|
||||
-- Identifier = "Apollo11LunarLander",
|
||||
-- Parent = Apollo11LemPosition.Identifier,
|
||||
-- Transform = {
|
||||
-- Rotation = {
|
||||
-- Type = "StaticRotation",
|
||||
-- Rotation = {0.0, 0.0, -3.1415/2}
|
||||
-- },
|
||||
-- Scale = {
|
||||
-- Type = "StaticScale",
|
||||
-- Scale = 100.0
|
||||
-- }
|
||||
-- },
|
||||
-- TimeFrame = {
|
||||
-- Type = "TimeFrameInterval",
|
||||
-- Start = "1969 JUL 20 19:10:25.183",
|
||||
-- End = "1969 JUL 20 20:17:46.183"
|
||||
-- },
|
||||
-- Renderable = {
|
||||
-- Type = "RenderableModel",
|
||||
-- Geometry = {
|
||||
-- Type = "MultiModelGeometry",
|
||||
-- GeometryFile = modelFolder .. "/lem_nasa.obj"
|
||||
-- },
|
||||
-- ColorTexture = modelFolder .. "/gray.png",
|
||||
-- LightSources = assetHelper.getDefaultLightSources(sunTransforms.SolarSystemBarycenter.Identifier)
|
||||
-- },
|
||||
-- GUI = {
|
||||
-- Hidden = false,
|
||||
-- Name = "Apollo 11 Lunar Lander",
|
||||
-- Path = "/Solar System/Missions/Apollo/11"
|
||||
-- }
|
||||
-- }
|
||||
|
||||
local Apollo11LemTrail = {
|
||||
Identifier = "Apollo11LemTrail",
|
||||
Parent = "Moon",
|
||||
Renderable = {
|
||||
Type = "RenderableTrailTrajectory",
|
||||
Translation = {
|
||||
local lemTranslation = {
|
||||
Type = "TimelineTranslation",
|
||||
Keyframes = {
|
||||
-- 20:14:30 is an arbitrary cutoff, but last 4 minutes data in descentKeyframes
|
||||
-- begins at 20.14.40. Due to linear interpolation, we will get
|
||||
-- a 10s linear transition to the location where the descentKeyframes start.
|
||||
['1969 JUL 20 20:14:30'] = {
|
||||
Type = "SpiceTranslation",
|
||||
Target = apolloLemSpiceId,
|
||||
Observer = "MOON",
|
||||
Frame = "IAU_MOON",
|
||||
Kernels = kernels
|
||||
},
|
||||
Color = {0.780000,0.940000,0.340000 },
|
||||
['1969 JUL 20 20:14:40'] = {
|
||||
Type = "TimelineTranslation",
|
||||
Keyframes = descentKeyframes.keyframes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
local lemRotation = {
|
||||
Type = "TimelineRotation",
|
||||
Keyframes = descentRotationKeyframes.keyframes
|
||||
}
|
||||
|
||||
|
||||
|
||||
local Apollo11LemTrail = {
|
||||
Identifier = "Apollo11LemTrail",
|
||||
Parent = "Moon",
|
||||
Renderable = {
|
||||
Type = "RenderableTrailTrajectory",
|
||||
Translation = lemTranslation,
|
||||
Color = { 0.780000,0.940000,0.340000 },
|
||||
StartTime = "1969 JUL 20 19:10:25.183",
|
||||
EndTime = "1969 JUL 20 20:17:46.183",
|
||||
SampleInterval = 60,
|
||||
SampleInterval = 2,
|
||||
EnableFade = false,
|
||||
Enabled = false,
|
||||
},
|
||||
@@ -191,11 +157,91 @@ local Apollo11LemTrail = {
|
||||
}
|
||||
}
|
||||
|
||||
local Apollo11LemPosition = {
|
||||
Identifier = "Apollo11LemPosition",
|
||||
Parent = "Moon",
|
||||
TimeFrame = {
|
||||
Type = "TimeFrameInterval",
|
||||
Start = "1969 JUL 20 19:10:25.183"
|
||||
},
|
||||
Transform = {
|
||||
Translation = lemTranslation,
|
||||
Rotation = lemRotation
|
||||
},
|
||||
GUI = {
|
||||
Hidden = false,
|
||||
Name = "Apollo 11 Lunar Lander Position",
|
||||
Path = "/Solar System/Missions/Apollo/11"
|
||||
}
|
||||
}
|
||||
--landing - 1969-07-20T20:17:40
|
||||
|
||||
local Apollo11LemDescentModel = {
|
||||
Identifier = "Apollo11LemDescentModel",
|
||||
Parent = Apollo11LemPosition.Identifier,
|
||||
TimeFrame = {
|
||||
Type = "TimeFrameInterval",
|
||||
Start = "1969 JUL 19 19:38:29.183",
|
||||
End = "1969 JUL 20 20:17:40.0"
|
||||
},
|
||||
Transform = {
|
||||
Scale = {
|
||||
Type = "StaticScale",
|
||||
Scale = 0.24
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableModel",
|
||||
Geometry = {
|
||||
Type = "MultiModelGeometry",
|
||||
GeometryFile = model.modelFolder .. "/lmremoved.obj"
|
||||
},
|
||||
ColorTexture = model.modelFolder .. "/LM-2_ver2clean_u1_v1.jpeg",
|
||||
LightSources = assetHelper.getDefaultLightSources(sunTransforms.SolarSystemBarycenter.Identifier)
|
||||
},
|
||||
GUI = {
|
||||
Hidden = false,
|
||||
Name = "Apollo 11 Descent Lem",
|
||||
Path = "/Solar System/Missions/Apollo/11"
|
||||
}
|
||||
}
|
||||
|
||||
local Apollo11LemLandedModel = {
|
||||
Identifier = "Apollo11LemLandedModel",
|
||||
Parent = Apollo11LemPosition.Identifier,
|
||||
TimeFrame = {
|
||||
Type = "TimeFrameInterval",
|
||||
Start = "1969 JUL 20 20:17:40.0"
|
||||
},
|
||||
Transform = {
|
||||
Scale = {
|
||||
Type = "StaticScale",
|
||||
Scale = 0.24
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableModel",
|
||||
Geometry = {
|
||||
Type = "MultiModelGeometry",
|
||||
GeometryFile = model.modelFolder .. "/LM-2_ver2clean.obj"
|
||||
},
|
||||
ColorTexture = model.modelFolder .. "/LM-2_ver2clean_u1_v1.jpeg",
|
||||
LightSources = assetHelper.getDefaultLightSources(sunTransforms.SolarSystemBarycenter.Identifier)
|
||||
},
|
||||
GUI = {
|
||||
Hidden = false,
|
||||
Name = "Apollo 11 Landed Lem",
|
||||
Path = "/Solar System/Missions/Apollo/11"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
local exportList = {
|
||||
Apollo11Position,
|
||||
-- Apollo11LemPosition,
|
||||
Apollo11Position,
|
||||
Apollo11LemPosition,
|
||||
Apollo11Model,
|
||||
-- Apollo11LunarLanderModel,
|
||||
Apollo11LemDescentModel,
|
||||
Apollo11LemLandedModel,
|
||||
Apollo11MoonTrail,
|
||||
Apollo11LemTrail,
|
||||
}
|
||||
|
||||
@@ -2,36 +2,36 @@
|
||||
|
||||
|
||||
local heightmaps = asset.syncedResource({
|
||||
Name = "Apollo Globebrowsing",
|
||||
Name = "Apollo Globebrowsing Heightmaps",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "apollo_globebrowsing_heightmaps",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local basemaps = asset.syncedResource({
|
||||
Name = "Apollo Globebrowsing",
|
||||
Name = "Apollo Globebrowsing Basemaps",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "apollo_globebrowsing_basemaps",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local naclighting = asset.syncedResource({
|
||||
Name = "Apollo Globebrowsing",
|
||||
Name = "Apollo Globebrowsing NAC Lighting",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "apollo_globebrowsing_naclighting",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
local stations = asset.syncedResource({
|
||||
Name = "Apollo 17 Globebrowsing",
|
||||
Name = "Apollo 17 Globebrowsing Stations",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "apollo_17_stations",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
asset.onInitialize(function ()
|
||||
openspace.globebrowsing.addBlendingLayersFromDirectory(heightmaps,"Moon")
|
||||
openspace.globebrowsing.addBlendingLayersFromDirectory(basemaps,"Moon")
|
||||
openspace.globebrowsing.addBlendingLayersFromDirectory(naclighting,"Moon")
|
||||
openspace.globebrowsing.addBlendingLayersFromDirectory(stations,"Moon")
|
||||
openspace.globebrowsing.addBlendingLayersFromDirectory(heightmaps, "Moon")
|
||||
openspace.globebrowsing.addBlendingLayersFromDirectory(basemaps, "Moon")
|
||||
openspace.globebrowsing.addBlendingLayersFromDirectory(naclighting, "Moon")
|
||||
openspace.globebrowsing.addBlendingLayersFromDirectory(stations, "Moon")
|
||||
end)
|
||||
|
||||
@@ -33,8 +33,8 @@ local Station2Boulder1Holder = {
|
||||
Globe = moonAsset.Moon.Identifier,
|
||||
Longitude = -360+30.5294692,
|
||||
Latitude = 20.098824,
|
||||
FixedAltitude = -2442.8,
|
||||
UseFixedAltitude = true
|
||||
Altitude = -2442.8,
|
||||
UseHeightMap = false
|
||||
}
|
||||
},
|
||||
GUI = {
|
||||
@@ -78,8 +78,8 @@ local Station2Boulder2Holder = {
|
||||
Globe = moonAsset.Moon.Identifier,
|
||||
Longitude = -360+30.5287892,
|
||||
Latitude = 20.098240,
|
||||
FixedAltitude = -2434.6,
|
||||
UseFixedAltitude = true
|
||||
Altitude = -2434.6,
|
||||
UseHeightMap = false
|
||||
}
|
||||
},
|
||||
GUI = {
|
||||
@@ -123,8 +123,8 @@ local Station2Boulder3Holder = {
|
||||
Globe = moonAsset.Moon.Identifier,
|
||||
Longitude = -360+30.5294692,
|
||||
Latitude = 20.098610,
|
||||
FixedAltitude = -2441.55,
|
||||
UseFixedAltitude = true
|
||||
Altitude = -2441.55,
|
||||
UseHeightMap = false
|
||||
}
|
||||
},
|
||||
GUI = {
|
||||
|
||||
@@ -37,6 +37,8 @@ local Station6Frag1Holder = {
|
||||
Globe = moonAsset.Moon.Identifier,
|
||||
Longitude = -360+30.80068,
|
||||
Latitude = 20.2903,
|
||||
Altitude = -2562.6,
|
||||
UseHeightmap = false
|
||||
}
|
||||
},
|
||||
GUI = {
|
||||
@@ -54,6 +56,8 @@ local Station6Frag1Model = {
|
||||
Globe = moonAsset.Moon.Identifier,
|
||||
Longitude = -360+30.8007,
|
||||
Latitude = 20.2903,
|
||||
Altitude = -2562.6,
|
||||
UseHeightmap = false
|
||||
}
|
||||
},
|
||||
Transform = {
|
||||
@@ -104,8 +108,8 @@ local Station6Frag2Model = {
|
||||
Globe = moonAsset.Moon.Identifier,
|
||||
Longitude = -360+30.80055,
|
||||
Latitude = 20.289808,
|
||||
FixedAltitude = -2566.5,
|
||||
UseFixedAltitude = true
|
||||
Altitude = -2566.5,
|
||||
UseHeightmap = false
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
@@ -140,8 +144,8 @@ local Station6Frag3Model = {
|
||||
Globe = moonAsset.Moon.Identifier,
|
||||
Longitude = -360+30.80053,
|
||||
Latitude = 20.29030,
|
||||
FixedAltitude = -2563.0,
|
||||
UseFixedAltitude = true
|
||||
Altitude = -2563.0,
|
||||
UseHeightMap = false
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
|
||||
@@ -34,8 +34,8 @@ local Station7BoulderHolder = {
|
||||
Globe = moonAsset.Moon.Identifier,
|
||||
Longitude = -360+30.8165882,
|
||||
Latitude = 20.2908556,
|
||||
FixedAltitude = -2593.5,
|
||||
UseFixedAltitude = true
|
||||
Altitude = -2593.5,
|
||||
UseHeightMap = true
|
||||
}
|
||||
},
|
||||
GUI = {
|
||||
|
||||
@@ -2,7 +2,7 @@ local modelFolder = asset.syncedResource({
|
||||
Name = "Apollo Lem Models",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "apollo_lem_model",
|
||||
Version = 2
|
||||
Version = 3
|
||||
})
|
||||
|
||||
asset.export('modelFolder', modelFolder)
|
||||
|
||||
@@ -20,7 +20,7 @@ local images = asset.syncedResource({
|
||||
local models = asset.syncedResource({
|
||||
Name = "Vesta Models",
|
||||
Type = "HttpSynchronization",
|
||||
Identifier = "vesta_comet",
|
||||
Identifier = "vesta_model",
|
||||
Version = 1
|
||||
})
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ local carpoGroup = {
|
||||
{
|
||||
Identifier = "Carpo",
|
||||
Parent = {
|
||||
Name = parentIdentifier,
|
||||
Identifier = parentIdentifier,
|
||||
Spice = parentSpice
|
||||
},
|
||||
Spice = "CARPO",
|
||||
|
||||
@@ -20,7 +20,8 @@ local TeslaRoadsterTrail = {
|
||||
Color = { 0.9, 0.9, 0.0 },
|
||||
StartTime = "2018 FEB 8 00:00:00",
|
||||
EndTime = "2022 FEB 7 00:00:00",
|
||||
SampleInterval = 60
|
||||
SampleInterval = 3000,
|
||||
TimeStampSubsampleFactor = 1
|
||||
},
|
||||
GUI = {
|
||||
Name = "Tesla Roadster Trail",
|
||||
|
||||
@@ -42,6 +42,29 @@ local registerSceneGraphNodes = function (sceneAsset, nodes, override)
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
local registerScreenSpaceRenderables = function (sceneAsset, renderables, override)
|
||||
override = override or false
|
||||
if not override then
|
||||
if tableLength(renderables) == 0 then
|
||||
openspace.printWarning(sceneAsset.filePath .. ": Register function was called with an empty node list. Pass 'true' as third argument to silence this warning.")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
sceneAsset.onInitialize(function ()
|
||||
for i, node in ipairs(renderables) do
|
||||
openspace.addScreenSpaceRenderable(node)
|
||||
end
|
||||
end)
|
||||
sceneAsset.onDeinitialize(function ()
|
||||
for i = #renderables, 1, -1 do
|
||||
renderable = renderables[i]
|
||||
openspace.removeScreenSpaceRenderable(renderable.Identifier)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local registerDashboardItems = function (dashboardAsset, items)
|
||||
dashboardAsset.onInitialize(
|
||||
function ()
|
||||
@@ -176,6 +199,7 @@ end
|
||||
|
||||
asset.export("registerSceneGraphNodes", registerSceneGraphNodes)
|
||||
asset.export("registerSceneGraphNodesAndExport", registerSceneGraphNodesAndExport)
|
||||
asset.export("registerScreenSpaceRenderables", registerScreenSpaceRenderables)
|
||||
asset.export("registerSpiceKernels", registerSpiceKernels)
|
||||
asset.export("registerDashboardItems", registerDashboardItems)
|
||||
asset.export("requireAll", requireAll)
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
asset.require('./static_server')
|
||||
|
||||
local guiCustomization = asset.require('customization/gui')
|
||||
|
||||
-- Select which commit hashes to use for the frontend and backend
|
||||
local frontendHash = "c603ad07d1407a7d3def43f1e203244cee1c06f6"
|
||||
local backendHash = "84737f9785f12efbb12d2de9d511154c6215fe9c"
|
||||
|
||||
local frontendHash = "2d1bb8d8d8478b6ed025ccc6f1e0ceacf04b6114"
|
||||
local dataProvider = "data.openspaceproject.com/files/webgui"
|
||||
|
||||
local backend = asset.syncedResource({
|
||||
Identifier = "WebGuiBackend",
|
||||
Name = "Web Gui Backend",
|
||||
Type = "UrlSynchronization",
|
||||
Url = dataProvider .. "/backend/" .. backendHash .. "/backend.zip"
|
||||
})
|
||||
|
||||
local frontend = asset.syncedResource({
|
||||
Identifier = "WebGuiFrontend",
|
||||
Name = "Web Gui Frontend",
|
||||
@@ -27,22 +20,21 @@ asset.onInitialize(function ()
|
||||
openspace.unzipFile(frontend .. "/frontend.zip", dest, true)
|
||||
end
|
||||
|
||||
-- Unzip the frontend bundle
|
||||
dest = backend .. "/backend"
|
||||
if not openspace.directoryExists(dest) then
|
||||
openspace.unzipFile(backend .. "/backend.zip", dest, true)
|
||||
end
|
||||
-- Serve the production GUI:
|
||||
local directories = openspace.getPropertyValue("Modules.WebGui.Directories")
|
||||
directories[#directories + 1] = "frontend"
|
||||
directories[#directories + 1] = frontend .. '/frontend'
|
||||
openspace.setPropertyValueSingle("Modules.WebGui.Directories", directories)
|
||||
openspace.setPropertyValueSingle("Modules.WebGui.DefaultEndpoint", "frontend")
|
||||
|
||||
-- Do not serve the files if we are in webgui development mode.
|
||||
-- In that case, you have to serve the webgui manually, using `npm start`.
|
||||
if not guiCustomization.webguiDevelopmentMode then
|
||||
if guiCustomization.webguiDevelopmentMode then
|
||||
-- Route CEF to the deveopment version of the GUI.
|
||||
-- This must be manually served using `npm start`
|
||||
-- in the OpenSpace-WebGuiFrontend repository.
|
||||
openspace.setPropertyValueSingle(
|
||||
"Modules.WebGui.ServerProcessEntryPoint", backend .. "/backend/backend.js"
|
||||
"Modules.CefWebGui.GuiUrl",
|
||||
"http://127.0.0.1:4690/frontend/#/onscreen"
|
||||
)
|
||||
openspace.setPropertyValueSingle(
|
||||
"Modules.WebGui.WebDirectory", frontend .. "/frontend"
|
||||
)
|
||||
openspace.setPropertyValueSingle("Modules.WebGui.ServerProcessEnabled", true)
|
||||
end
|
||||
|
||||
-- The GUI contains date and simulation increment,
|
||||
@@ -54,5 +46,17 @@ asset.onInitialize(function ()
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function ()
|
||||
openspace.setPropertyValueSingle("Modules.WebGui.ServerProcessEnabled", false)
|
||||
-- Remove the frontend endpoint
|
||||
local directories = openspace.getPropertyValue("Modules.WebGui.Directories")
|
||||
local newDirectories;
|
||||
|
||||
openspace.setPropertyValueSingle("Modules.WebGui.DefaultEndpoint", "")
|
||||
|
||||
for i = 0, #directories, 2 do
|
||||
if (string.find(directories[i], "frontend") == nil) then
|
||||
newDirectories[#newDirectories + 1] = directories[i]
|
||||
newDirectories[#newDirectories + 1] = directories[i + 1]
|
||||
end
|
||||
end
|
||||
openspace.setPropertyValueSingle("Modules.WebGui.Directories", newDirectories)
|
||||
end)
|
||||
|
||||
@@ -47,10 +47,10 @@ asset.onInitialize(function ()
|
||||
"Earth", "Voyager 1", "Voyager 2", "Jupiter", "Saturn", "Uranus", "Neptune"
|
||||
})
|
||||
|
||||
openspace.navigation.setCameraState({
|
||||
openspace.navigation.setNavigationState({
|
||||
Anchor = VoyagerAsset.Voyager_1.Identifier,
|
||||
Position = { 526781518487.171326, 257168309890.072144, -1381125204152.817383 },
|
||||
Rotation = { -0.106166, 0.981574, -0.084545, 0.134513 },
|
||||
ReferenceFrame = "Root",
|
||||
Position = { 526781518487.171326, 257168309890.072144, -1381125204152.817383 }
|
||||
})
|
||||
end)
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
|
||||
private:
|
||||
std::function<T(float)> _transferFunction;
|
||||
float _t = 0.f;
|
||||
float _t = 1.f;
|
||||
float _interpolationTime = 1.f;
|
||||
float _scaledDeltaTime = 0.f;
|
||||
};
|
||||
|
||||
@@ -25,13 +25,17 @@
|
||||
#ifndef __OPENSPACE_CORE___NAVIGATIONHANDLER___H__
|
||||
#define __OPENSPACE_CORE___NAVIGATIONHANDLER___H__
|
||||
|
||||
#include <openspace/properties/propertyowner.h>
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/interaction/inputstate.h>
|
||||
#include <openspace/interaction/joystickcamerastates.h>
|
||||
#include <openspace/interaction/orbitalnavigator.h>
|
||||
#include <openspace/interaction/keyframenavigator.h>
|
||||
#include <openspace/properties/propertyowner.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/scalar/boolproperty.h>
|
||||
#include <openspace/util/mouse.h>
|
||||
#include <openspace/util/keys.h>
|
||||
#include <optional>
|
||||
|
||||
namespace openspace {
|
||||
class Camera;
|
||||
@@ -48,6 +52,25 @@ class OrbitalNavigator;
|
||||
|
||||
class NavigationHandler : public properties::PropertyOwner {
|
||||
public:
|
||||
struct NavigationState {
|
||||
NavigationState() = default;
|
||||
NavigationState(const ghoul::Dictionary& dictionary);
|
||||
NavigationState(std::string anchor, std::string aim, std::string referenceFrame,
|
||||
glm::dvec3 position, std::optional<glm::dvec3> up = std::nullopt,
|
||||
double yaw = 0.0, double pitch = 0.0);
|
||||
|
||||
ghoul::Dictionary dictionary() const;
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
std::string anchor;
|
||||
std::string aim;
|
||||
std::string referenceFrame;
|
||||
glm::dvec3 position;
|
||||
std::optional<glm::dvec3> up;
|
||||
double yaw = 0.0;
|
||||
double pitch = 0.0;
|
||||
};
|
||||
|
||||
NavigationHandler();
|
||||
~NavigationHandler();
|
||||
|
||||
@@ -55,10 +78,10 @@ public:
|
||||
void deinitialize();
|
||||
|
||||
// Mutators
|
||||
void setNavigationStateNextFame(NavigationState state);
|
||||
void setCamera(Camera* camera);
|
||||
void setInterpolationTime(float durationInSeconds);
|
||||
|
||||
void setCameraStateFromDictionary(const ghoul::Dictionary& cameraDict);
|
||||
void updateCamera(double deltaTime);
|
||||
void setEnableKeyFrameInteraction();
|
||||
void setDisableKeyFrameInteraction();
|
||||
@@ -66,12 +89,11 @@ public:
|
||||
void stopPlayback();
|
||||
|
||||
// Accessors
|
||||
ghoul::Dictionary cameraStateDictionary();
|
||||
Camera* camera() const;
|
||||
const InputState& inputState() const;
|
||||
const OrbitalNavigator& orbitalNavigator() const;
|
||||
OrbitalNavigator& orbitalNavigator();
|
||||
KeyframeNavigator& keyframeNavigator() const;
|
||||
KeyframeNavigator& keyframeNavigator();
|
||||
bool isKeyFrameInteractionEnabled() const;
|
||||
float interpolationTime() const;
|
||||
|
||||
@@ -100,10 +122,14 @@ public:
|
||||
void clearJoystickButtonCommand(int button);
|
||||
std::vector<std::string> joystickButtonCommand(int button) const;
|
||||
|
||||
NavigationState navigationState(const SceneGraphNode& referenceFrame) const;
|
||||
|
||||
void saveNavigationState(const std::string& filepath,
|
||||
const std::string& referenceFrameIdentifier);
|
||||
|
||||
void saveCameraStateToFile(const std::string& filepath);
|
||||
void restoreCameraStateFromFile(const std::string& filepath);
|
||||
void loadNavigationState(const std::string& filepath);
|
||||
|
||||
void setNavigationStateNextFrame(NavigationState state);
|
||||
|
||||
/**
|
||||
* \return The Lua library that contains all Lua functions available to affect the
|
||||
@@ -112,15 +138,18 @@ public:
|
||||
static scripting::LuaLibrary luaLibrary();
|
||||
|
||||
private:
|
||||
bool _cameraUpdatedFromScript = false;
|
||||
void applyNavigationState(const NavigationHandler::NavigationState& ns);
|
||||
|
||||
bool _playbackModeEnabled = false;
|
||||
|
||||
std::unique_ptr<InputState> _inputState;
|
||||
InputState _inputState;
|
||||
Camera* _camera = nullptr;
|
||||
std::function<void()> _playbackEndCallback;
|
||||
|
||||
std::unique_ptr<OrbitalNavigator> _orbitalNavigator;
|
||||
std::unique_ptr<KeyframeNavigator> _keyframeNavigator;
|
||||
OrbitalNavigator _orbitalNavigator;
|
||||
KeyframeNavigator _keyframeNavigator;
|
||||
|
||||
std::optional<NavigationState> _pendingNavigationState;
|
||||
|
||||
properties::BoolProperty _useKeyFrameInteraction;
|
||||
};
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#include <ghoul/glm.h>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace openspace {
|
||||
class SceneGraphNode;
|
||||
class Camera;
|
||||
@@ -58,6 +60,7 @@ public:
|
||||
|
||||
Camera* camera() const;
|
||||
void setCamera(Camera* camera);
|
||||
void clearPreviousState();
|
||||
|
||||
void setFocusNode(const std::string& focusNode);
|
||||
void setAnchorNode(const std::string& anchorNode);
|
||||
@@ -70,6 +73,7 @@ public:
|
||||
void resetNodeMovements();
|
||||
|
||||
JoystickCameraStates& joystickStates();
|
||||
const JoystickCameraStates& joystickStates() const;
|
||||
|
||||
bool followingNodeRotation() const;
|
||||
const SceneGraphNode* anchorNode() const;
|
||||
@@ -146,10 +150,9 @@ private:
|
||||
const SceneGraphNode* _anchorNode = nullptr;
|
||||
const SceneGraphNode* _aimNode = nullptr;
|
||||
|
||||
glm::dvec3 _previousAnchorNodePosition;
|
||||
glm::dquat _previousAnchorNodeRotation;
|
||||
|
||||
glm::dvec3 _previousAimNodePosition;
|
||||
std::optional<glm::dvec3>_previousAnchorNodePosition;
|
||||
std::optional<glm::dquat> _previousAnchorNodeRotation;
|
||||
std::optional<glm::dvec3> _previousAimNodePosition;
|
||||
|
||||
double _currentCameraToSurfaceDistance = 0.0;
|
||||
bool _directlySetStereoDistance = false;
|
||||
|
||||
@@ -221,7 +221,6 @@ private:
|
||||
double timestamp;
|
||||
};
|
||||
ExternInteraction _externInteract;
|
||||
bool _isRecording = false;
|
||||
double _timestampRecordStarted = 0.0;
|
||||
double _timestampPlaybackStarted_application = 0.0;
|
||||
double _timestampPlaybackStarted_simulation = 0.0;
|
||||
|
||||
@@ -82,7 +82,7 @@ protected:
|
||||
|
||||
void draw(glm::mat4 modelTransform);
|
||||
|
||||
virtual void bindTexture();
|
||||
virtual void bindTexture() = 0;
|
||||
virtual void unbindTexture();
|
||||
|
||||
properties::BoolProperty _enabled;
|
||||
@@ -106,10 +106,8 @@ protected:
|
||||
properties::TriggerProperty _delete;
|
||||
|
||||
glm::ivec2 _objectSize;
|
||||
UniformCache(occlusionDepth, alpha, modelTransform, viewProj, texture) _uniformCache;
|
||||
UniformCache(alpha, modelTransform, viewProj, texture) _uniformCache;
|
||||
std::unique_ptr<ghoul::opengl::ProgramObject> _shader;
|
||||
|
||||
glm::vec2 _originalViewportSize;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
*/
|
||||
static double convertTime(const std::string& time);
|
||||
|
||||
Time(double secondsJ2000 = -1);
|
||||
explicit Time(double secondsJ2000 = -1);
|
||||
Time(const Time& other) = default;
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,7 +44,12 @@ struct KeyframeBase {
|
||||
*/
|
||||
template <typename T>
|
||||
struct Keyframe : public KeyframeBase {
|
||||
Keyframe(size_t i, double t, T p);
|
||||
Keyframe(size_t i, double t, T d);
|
||||
|
||||
Keyframe(Keyframe const&) = default;
|
||||
Keyframe(Keyframe&&) = default;
|
||||
Keyframe& operator=(Keyframe&&) = default;
|
||||
Keyframe& operator=(Keyframe const&) = default;
|
||||
T data;
|
||||
};
|
||||
|
||||
@@ -56,7 +61,8 @@ class Timeline {
|
||||
public:
|
||||
virtual ~Timeline() = default;
|
||||
|
||||
void addKeyframe(double time, T data);
|
||||
void addKeyframe(double time, const T& data);
|
||||
void addKeyframe(double time, T&& data);
|
||||
void clearKeyframes();
|
||||
void removeKeyframe(size_t id);
|
||||
void removeKeyframesBefore(double timestamp, bool inclusive = false);
|
||||
@@ -66,6 +72,7 @@ public:
|
||||
size_t nKeyframes() const;
|
||||
const Keyframe<T>* firstKeyframeAfter(double timestamp, bool inclusive = false) const;
|
||||
const Keyframe<T>* lastKeyframeBefore(double timestamp, bool inclusive = false) const;
|
||||
|
||||
const std::deque<Keyframe<T>>& keyframes() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -25,13 +25,25 @@
|
||||
namespace openspace {
|
||||
|
||||
template <typename T>
|
||||
Keyframe<T>::Keyframe(size_t i, double t, T p)
|
||||
Keyframe<T>::Keyframe(size_t i, double t, T d)
|
||||
: KeyframeBase{ i, t }
|
||||
, data(p)
|
||||
, data(std::move(d))
|
||||
{}
|
||||
|
||||
template <typename T>
|
||||
void Timeline<T>::addKeyframe(double timestamp, T data) {
|
||||
void Timeline<T>::addKeyframe(double timestamp, T&& data) {
|
||||
Keyframe<T> keyframe(++_nextKeyframeId, timestamp, std::move(data));
|
||||
const auto iter = std::upper_bound(
|
||||
_keyframes.cbegin(),
|
||||
_keyframes.cend(),
|
||||
keyframe,
|
||||
&compareKeyframeTimes
|
||||
);
|
||||
_keyframes.insert(iter, std::move(keyframe));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Timeline<T>::addKeyframe(double timestamp, const T& data) {
|
||||
Keyframe<T> keyframe(++_nextKeyframeId, timestamp, data);
|
||||
const auto iter = std::upper_bound(
|
||||
_keyframes.cbegin(),
|
||||
@@ -39,7 +51,7 @@ void Timeline<T>::addKeyframe(double timestamp, T data) {
|
||||
keyframe,
|
||||
&compareKeyframeTimes
|
||||
);
|
||||
_keyframes.insert(iter, keyframe);
|
||||
_keyframes.insert(iter, std::move(keyframe));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -143,7 +155,7 @@ void Timeline<T>::removeKeyframe(size_t id) {
|
||||
std::remove_if(
|
||||
_keyframes.begin(),
|
||||
_keyframes.end(),
|
||||
[id] (Keyframe<T> keyframe) { return keyframe.id == id; }
|
||||
[id] (const Keyframe<T>& keyframe) { return keyframe.id == id; }
|
||||
),
|
||||
_keyframes.end()
|
||||
);
|
||||
@@ -209,7 +221,7 @@ const Keyframe<T>* Timeline<T>::lastKeyframeBefore(double timestamp, bool inclus
|
||||
return &(*it);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
const std::deque<Keyframe<T>>& Timeline<T>::keyframes() const {
|
||||
return _keyframes;
|
||||
}
|
||||
|
||||
@@ -54,8 +54,7 @@ set(HEADER_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceframebuffer.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceimagelocal.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceimageonline.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/translation/luatranslation.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/translation/statictranslation.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rotation/timelinerotation.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rotation/constantrotation.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rotation/fixedrotation.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rotation/luarotation.h
|
||||
@@ -65,6 +64,10 @@ set(HEADER_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scale/timedependentscale.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/timeframe/timeframeinterval.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/timeframe/timeframeunion.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/translation/luatranslation.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/translation/statictranslation.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/translation/timelinetranslation.h
|
||||
|
||||
)
|
||||
source_group("Header Files" FILES ${HEADER_FILES})
|
||||
|
||||
@@ -98,8 +101,7 @@ set(SOURCE_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceframebuffer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceimagelocal.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceimageonline.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/translation/luatranslation.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/translation/statictranslation.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rotation/timelinerotation.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rotation/constantrotation.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rotation/fixedrotation.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rotation/luarotation.cpp
|
||||
@@ -109,6 +111,9 @@ set(SOURCE_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/scale/timedependentscale.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/timeframe/timeframeinterval.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/timeframe/timeframeunion.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/translation/luatranslation.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/translation/statictranslation.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/translation/timelinetranslation.cpp
|
||||
)
|
||||
source_group("Source Files" FILES ${SOURCE_FILES})
|
||||
|
||||
|
||||
@@ -55,9 +55,11 @@
|
||||
#include <modules/base/rotation/fixedrotation.h>
|
||||
#include <modules/base/rotation/luarotation.h>
|
||||
#include <modules/base/rotation/staticrotation.h>
|
||||
#include <modules/base/rotation/timelinerotation.h>
|
||||
#include <modules/base/scale/luascale.h>
|
||||
#include <modules/base/scale/staticscale.h>
|
||||
#include <modules/base/scale/timedependentscale.h>
|
||||
#include <modules/base/translation/timelinetranslation.h>
|
||||
#include <modules/base/translation/luatranslation.h>
|
||||
#include <modules/base/translation/statictranslation.h>
|
||||
#include <modules/base/timeframe/timeframeinterval.h>
|
||||
@@ -131,6 +133,7 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) {
|
||||
auto fTranslation = FactoryManager::ref().factory<Translation>();
|
||||
ghoul_assert(fTranslation, "Ephemeris factory was not created");
|
||||
|
||||
fTranslation->registerClass<TimelineTranslation>("TimelineTranslation");
|
||||
fTranslation->registerClass<LuaTranslation>("LuaTranslation");
|
||||
fTranslation->registerClass<StaticTranslation>("StaticTranslation");
|
||||
|
||||
@@ -141,6 +144,8 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) {
|
||||
fRotation->registerClass<FixedRotation>("FixedRotation");
|
||||
fRotation->registerClass<LuaRotation>("LuaRotation");
|
||||
fRotation->registerClass<StaticRotation>("StaticRotation");
|
||||
fRotation->registerClass<TimelineRotation>("TimelineRotation");
|
||||
|
||||
|
||||
auto fScale = FactoryManager::ref().factory<Scale>();
|
||||
ghoul_assert(fScale, "Scale factory was not created");
|
||||
@@ -198,6 +203,7 @@ std::vector<documentation::Documentation> BaseModule::documentations() const {
|
||||
FixedRotation::Documentation(),
|
||||
LuaRotation::Documentation(),
|
||||
StaticRotation::Documentation(),
|
||||
TimelineRotation::Documentation(),
|
||||
|
||||
LuaScale::Documentation(),
|
||||
StaticScale::Documentation(),
|
||||
@@ -205,6 +211,7 @@ std::vector<documentation::Documentation> BaseModule::documentations() const {
|
||||
|
||||
LuaTranslation::Documentation(),
|
||||
StaticTranslation::Documentation(),
|
||||
TimelineTranslation::Documentation(),
|
||||
|
||||
TimeFrameInterval::Documentation(),
|
||||
TimeFrameUnion::Documentation(),
|
||||
|
||||
@@ -289,7 +289,7 @@ void DashboardItemFramerate::render(glm::vec2& penPosition) {
|
||||
);
|
||||
|
||||
int nLines = output.empty() ? 0 :
|
||||
(std::count(output.begin(), output.end(), '\n') + 1);
|
||||
static_cast<int>((std::count(output.begin(), output.end(), '\n') + 1));
|
||||
|
||||
penPosition.y -= _font->height() * static_cast<float>(nLines);
|
||||
|
||||
|
||||
@@ -226,8 +226,8 @@ void RenderableTrailTrajectory::update(const UpdateData& data) {
|
||||
for (int i = 0; i < nValues; ++i) {
|
||||
const glm::vec3 p = _translation->position({
|
||||
{},
|
||||
_start + i * totalSampleInterval,
|
||||
0.0,
|
||||
Time(_start + i * totalSampleInterval),
|
||||
Time(0.0),
|
||||
false
|
||||
});
|
||||
_vertexArray[i] = { p.x, p.y, p.z };
|
||||
|
||||
@@ -212,7 +212,6 @@ void ScreenSpaceDashboard::update() {
|
||||
if (global::windowDelegate.windowHasResized()) {
|
||||
const glm::ivec2 size = global::windowDelegate.currentWindowResolution();
|
||||
_size = { 0.f, 0.f, size.x, size.y };
|
||||
_originalViewportSize = size;
|
||||
createFramebuffer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,15 +106,15 @@ void ScreenSpaceFramebuffer::render() {
|
||||
const glm::vec2& resolution = global::windowDelegate.currentWindowResolution();
|
||||
const glm::vec4& size = _size.value();
|
||||
|
||||
const float xratio = _originalViewportSize.x / (size.z - size.x);
|
||||
const float yratio = _originalViewportSize.y / (size.w - size.y);;
|
||||
const float xratio = resolution.x / (size.z - size.x);
|
||||
const float yratio = resolution.y / (size.w - size.y);;
|
||||
|
||||
if (!_renderFunctions.empty()) {
|
||||
glViewport(
|
||||
static_cast<GLint>(-size.x * xratio),
|
||||
static_cast<GLint>(-size.y * yratio),
|
||||
static_cast<GLsizei>(_originalViewportSize.x * xratio),
|
||||
static_cast<GLsizei>(_originalViewportSize.y * yratio)
|
||||
static_cast<GLsizei>(resolution.x * xratio),
|
||||
static_cast<GLsizei>(resolution.y * yratio)
|
||||
);
|
||||
GLint defaultFBO = _framebuffer->getActiveObject();
|
||||
_framebuffer->activate();
|
||||
@@ -170,14 +170,16 @@ void ScreenSpaceFramebuffer::removeAllRenderFunctions() {
|
||||
}
|
||||
|
||||
void ScreenSpaceFramebuffer::createFramebuffer() {
|
||||
glm::vec2 resolution = global::windowDelegate.currentWindowResolution();
|
||||
|
||||
_framebuffer = std::make_unique<ghoul::opengl::FramebufferObject>();
|
||||
_framebuffer->activate();
|
||||
_texture = std::make_unique<ghoul::opengl::Texture>(glm::uvec3(
|
||||
_originalViewportSize.x,
|
||||
_originalViewportSize.y,
|
||||
resolution.x,
|
||||
resolution.y,
|
||||
1
|
||||
));
|
||||
_objectSize = glm::ivec2(_originalViewportSize);
|
||||
_objectSize = glm::ivec2(resolution);
|
||||
|
||||
_texture->uploadTexture();
|
||||
_texture->setFilter(ghoul::opengl::Texture::FilterMode::LinearMipMap);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/io/texture/texturereader.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <ghoul/opengl/textureconversion.h>
|
||||
@@ -96,11 +97,30 @@ ScreenSpaceImageLocal::ScreenSpaceImageLocal(const ghoul::Dictionary& dictionary
|
||||
setGuiName("ScreenSpaceImageLocal " + std::to_string(iIdentifier));
|
||||
}
|
||||
|
||||
_texturePath.onChange([this]() { _textureIsDirty = true; });
|
||||
_texturePath.onChange([this]() {
|
||||
if (!FileSys.fileExists(FileSys.absolutePath(_texturePath))) {
|
||||
LWARNINGC(
|
||||
"ScreenSpaceImageLocal",
|
||||
fmt::format("Image {} did not exist for {}", _texturePath, _identifier)
|
||||
);
|
||||
}
|
||||
else {
|
||||
_textureIsDirty = true;
|
||||
}
|
||||
});
|
||||
addProperty(_texturePath);
|
||||
|
||||
if (dictionary.hasKey(TexturePathInfo.identifier)) {
|
||||
_texturePath = dictionary.value<std::string>(TexturePathInfo.identifier);
|
||||
std::string path = dictionary.value<std::string>(TexturePathInfo.identifier);
|
||||
if (!FileSys.fileExists(FileSys.absolutePath(path))) {
|
||||
LWARNINGC(
|
||||
"ScreenSpaceImageLocal",
|
||||
fmt::format("Image {} did not exist for {}", path, _identifier)
|
||||
);
|
||||
}
|
||||
else {
|
||||
_texturePath = path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,12 +150,13 @@ void ScreenSpaceImageLocal::update() {
|
||||
_objectSize = _texture->dimensions();
|
||||
_textureIsDirty = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenSpaceImageLocal::bindTexture() {
|
||||
_texture->bind();
|
||||
if (_texture) {
|
||||
_texture->bind();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -29,10 +29,8 @@ in vec2 vs_st;
|
||||
in vec4 vs_position;
|
||||
|
||||
uniform sampler2D texture1;
|
||||
uniform float OcclusionDepth;
|
||||
uniform float Alpha;
|
||||
|
||||
|
||||
Fragment getFragment() {
|
||||
Fragment frag;
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <modules/cefwebgui/cefwebguimodule.h>
|
||||
|
||||
#include <modules/webbrowser/webbrowsermodule.h>
|
||||
#include <modules/webgui/webguimodule.h>
|
||||
#include <modules/cefwebgui/include/guirenderhandler.h>
|
||||
#include <modules/cefwebgui/include/guikeyboardhandler.h>
|
||||
#include <modules/webbrowser/include/browserinstance.h>
|
||||
@@ -166,7 +165,15 @@ void CefWebGuiModule::internalInitialize(const ghoul::Dictionary& configuration)
|
||||
} else {
|
||||
WebGuiModule* webGuiModule = global::moduleEngine.module<WebGuiModule>();
|
||||
_url = "http://127.0.0.1:" +
|
||||
std::to_string(webGuiModule->port()) + "/#/onscreen";
|
||||
std::to_string(webGuiModule->port()) + "/frontend/#/onscreen";
|
||||
|
||||
_endpointCallback = webGuiModule->addEndpointChangeCallback(
|
||||
[this](const std::string& endpoint, bool exists) {
|
||||
if (exists && endpoint == "frontend" && _instance) {
|
||||
_instance->reloadBrowser();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (configuration.hasValue<float>(GuiScaleInfo.identifier)) {
|
||||
@@ -204,6 +211,11 @@ void CefWebGuiModule::internalInitialize(const ghoul::Dictionary& configuration)
|
||||
});
|
||||
|
||||
global::callback::deinitializeGL.emplace_back([this]() {
|
||||
if (_endpointCallback != -1) {
|
||||
WebGuiModule* webGuiModule = global::moduleEngine.module<WebGuiModule>();
|
||||
webGuiModule->removeEndpointChangeCallback(_endpointCallback);
|
||||
_endpointCallback = -1;
|
||||
}
|
||||
_enabled = false;
|
||||
startOrStopGui();
|
||||
});
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
#include <openspace/util/openspacemodule.h>
|
||||
|
||||
#include <modules/webgui/webguimodule.h>
|
||||
|
||||
#include <openspace/properties/scalar/boolproperty.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/properties/triggerproperty.h>
|
||||
@@ -53,6 +55,8 @@ private:
|
||||
properties::StringProperty _url;
|
||||
properties::FloatProperty _guiScale;
|
||||
std::unique_ptr<BrowserInstance> _instance;
|
||||
|
||||
WebGuiModule::CallbackHandle _endpointCallback = -1;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -39,8 +39,8 @@ public:
|
||||
GUIRenderHandler();
|
||||
virtual ~GUIRenderHandler();
|
||||
|
||||
void draw();
|
||||
void render();
|
||||
void draw() override;
|
||||
void render() override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<ghoul::opengl::ProgramObject> _programObject;
|
||||
|
||||
@@ -31,8 +31,7 @@ uniform mat4 ortho;
|
||||
out vec2 Texcoord;
|
||||
|
||||
void main() {
|
||||
Texcoord = vec2(position.x + 1.0f, position.y - 1.0f) * 0.5;
|
||||
Texcoord.y *= -1.0f;
|
||||
Texcoord = vec2(position.x + 1.0f, position.y + 1.0f) * 0.5;
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
}
|
||||
|
||||
|
||||
@@ -750,7 +750,6 @@ void RenderableBillboardsCloud::renderBillboards(const RenderData& data,
|
||||
|
||||
_program->activate();
|
||||
|
||||
const glm::dmat4 projMatrix = glm::dmat4(data.camera.projectionMatrix());
|
||||
_program->setUniform(
|
||||
"screenSize",
|
||||
glm::vec2(global::renderEngine.renderingResolution())
|
||||
|
||||
@@ -77,19 +77,6 @@ namespace {
|
||||
"all point."
|
||||
};
|
||||
|
||||
//constexpr openspace::properties::Property::PropertyInfo ScaleFactorInfo = {
|
||||
// "ScaleFactor",
|
||||
// "Scale Factor",
|
||||
// "This value is used as a multiplicative factor that is applied to the apparent "
|
||||
// "size of each point."
|
||||
//};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ColorInfo = {
|
||||
"Color",
|
||||
"Color",
|
||||
"This value is used to define the color of the astronomical object."
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo TextColorInfo = {
|
||||
"TextColor",
|
||||
"Text Color",
|
||||
@@ -427,7 +414,7 @@ void RenderableDUMeshes::initializeGL() {
|
||||
}
|
||||
|
||||
void RenderableDUMeshes::deinitializeGL() {
|
||||
for (const std::pair<int, RenderingMesh>& pair : _renderingMeshesMap) {
|
||||
for (const std::pair<const int, RenderingMesh>& pair : _renderingMeshesMap) {
|
||||
for (int i = 0; i < pair.second.numU; ++i) {
|
||||
glDeleteVertexArrays(1, &pair.second.vaoArray[i]);
|
||||
glDeleteBuffers(1, &pair.second.vboArray[i]);
|
||||
@@ -483,7 +470,7 @@ void RenderableDUMeshes::renderMeshes(const RenderData&,
|
||||
_program->setUniform(_uniformCache.alphaValue, _alphaValue);
|
||||
//_program->setUniform(_uniformCache.scaleFactor, _scaleFactor);
|
||||
|
||||
for (const std::pair<int, RenderingMesh>& pair : _renderingMeshesMap) {
|
||||
for (const std::pair<const int, RenderingMesh>& pair : _renderingMeshesMap) {
|
||||
_program->setUniform(_uniformCache.color, _meshColorMap[pair.second.colorIndex]);
|
||||
for (size_t i = 0; i < pair.second.vaoArray.size(); ++i) {
|
||||
glBindVertexArray(pair.second.vaoArray[i]);
|
||||
|
||||
@@ -844,7 +844,7 @@ bool RenderablePlanesCloud::loadData() {
|
||||
|
||||
bool RenderablePlanesCloud::loadTextures() {
|
||||
if (!_textureFileMap.empty()) {
|
||||
for (const std::pair<int, std::string>& pair : _textureFileMap) {
|
||||
for (const std::pair<const int, std::string>& pair : _textureFileMap) {
|
||||
const auto& p = _textureMap.insert(std::make_pair(
|
||||
pair.first,
|
||||
ghoul::io::TextureReader::ref().loadTexture(pair.second)
|
||||
|
||||
@@ -771,7 +771,7 @@ void RenderableFieldlinesSequence::definePropertyCallbackFunctions() {
|
||||
});
|
||||
|
||||
_pJumpToStartBtn.onChange([this] {
|
||||
global::timeManager.setTimeNextFrame(_startTimes[0]);
|
||||
global::timeManager.setTimeNextFrame(Time(_startTimes[0]));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -109,6 +109,11 @@ create_new_module(
|
||||
${HEADER_FILES} ${SOURCE_FILES} ${SHADER_FILES}
|
||||
)
|
||||
|
||||
option(OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION "Instrumentation for GlobeBrowsing Performance" OFF)
|
||||
if (OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION)
|
||||
target_compile_definitions(openspace-module-globebrowsing INTERFACE "OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION")
|
||||
endif ()
|
||||
|
||||
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/gdal_data DESTINATION modules/globebrowsing)
|
||||
|
||||
if (WIN32)
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <openspace/util/factorymanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/fmt.h>
|
||||
#include <ghoul/misc/templatefactory.h>
|
||||
#include <ghoul/misc/assert.h>
|
||||
#include <ghoul/systemcapabilities/generalcapabilitiescomponent.h>
|
||||
@@ -100,6 +101,14 @@ namespace {
|
||||
"The maximum size of the MemoryAwareTileCache, on the CPU and GPU."
|
||||
};
|
||||
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
constexpr const openspace::properties::Property::PropertyInfo InstrumentationInfo = {
|
||||
"SaveInstrumentationInfo",
|
||||
"Save Instrumentation Info",
|
||||
"If enabled, the instrumentation data is saved to disk at the end of the frame."
|
||||
};
|
||||
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
|
||||
|
||||
openspace::GlobeBrowsingModule::Capabilities
|
||||
parseSubDatasets(char** subDatasets, int nSubdatasets)
|
||||
@@ -162,12 +171,24 @@ GlobeBrowsingModule::GlobeBrowsingModule()
|
||||
, _wmsCacheLocation(WMSCacheLocationInfo, "${BASE}/cache_gdal")
|
||||
, _wmsCacheSizeMB(WMSCacheSizeInfo, 1024)
|
||||
, _tileCacheSizeMB(TileCacheSizeInfo, 1024)
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
, _saveInstrumentation(InstrumentationInfo, false)
|
||||
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
{
|
||||
addProperty(_wmsCacheEnabled);
|
||||
addProperty(_offlineMode);
|
||||
addProperty(_wmsCacheLocation);
|
||||
addProperty(_wmsCacheSizeMB);
|
||||
addProperty(_tileCacheSizeMB);
|
||||
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
_saveInstrumentation.onChange([&]() {
|
||||
if (_saveInstrumentation) {
|
||||
_frameInfo.lastSavedFrame = global::renderEngine.frameNumber();
|
||||
}
|
||||
});
|
||||
addProperty(_saveInstrumentation);
|
||||
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
}
|
||||
|
||||
void GlobeBrowsingModule::internalInitialize(const ghoul::Dictionary& dict) {
|
||||
@@ -234,6 +255,43 @@ void GlobeBrowsingModule::internalInitialize(const ghoul::Dictionary& dict) {
|
||||
// Render
|
||||
global::callback::render.emplace_back([&]() { _tileCache->update(); });
|
||||
|
||||
// Postdraw
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
global::callback::postDraw.emplace_back([&]() {
|
||||
// >= as we might have multiple frames per postDraw call (stereo rendering,
|
||||
// fisheye, etc)
|
||||
const uint16_t next = _frameInfo.lastSavedFrame + _frameInfo.saveEveryNthFrame;
|
||||
const bool shouldSave = _saveInstrumentation &&
|
||||
global::renderEngine.frameNumber() >= next;
|
||||
if (shouldSave) {
|
||||
using K = const globebrowsing::RenderableGlobe*;
|
||||
using V = std::vector<FrameInfo>;
|
||||
for (const std::pair<K, V>& i : _frameInfo.frames) {
|
||||
std::string filename = fmt::format(
|
||||
"_inst_globebrowsing_{}_{}_{}.txt",
|
||||
i.first->owner()->identifier(), // Owner of the renderable has a name
|
||||
_frameInfo.lastSavedFrame,
|
||||
_frameInfo.saveEveryNthFrame
|
||||
);
|
||||
std::ofstream file(absPath("${BIN}/" + filename));
|
||||
for (const FrameInfo& f : i.second) {
|
||||
std::string line = fmt::format(
|
||||
"{}\t{}\t{}\t{}",
|
||||
f.iFrame,
|
||||
f.nTilesRenderedLocal,
|
||||
f.nTilesRenderedGlobal,
|
||||
f.nTilesUploaded
|
||||
);
|
||||
file << line << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
_frameInfo.frames.clear();
|
||||
_frameInfo.lastSavedFrame = global::renderEngine.frameNumber();
|
||||
}
|
||||
});
|
||||
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
|
||||
// Deinitialize
|
||||
global::callback::deinitialize.emplace_back([&]() { GdalWrapper::destroy(); });
|
||||
|
||||
@@ -338,16 +396,24 @@ scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
|
||||
"goToGeo",
|
||||
&globebrowsing::luascriptfunctions::goToGeo,
|
||||
{},
|
||||
"number, number, number",
|
||||
"Go to geographic coordinates latitude and longitude"
|
||||
"[string], number, number, [number]",
|
||||
"Go to geographic coordinates of a globe. The first (optional) argument is "
|
||||
"the identifier of a scene graph node that has a RenderableGlobe attached. "
|
||||
"If no globe is passed in, the current anchor will be used. "
|
||||
"The second argument is latitude and the third is longitude (degrees). "
|
||||
"North and East are expressed as positive angles, while South and West are "
|
||||
"negative. The optional fourh argument is the altitude in meters. If no "
|
||||
"altitude is provided, the altitude will be kept as the current distance to "
|
||||
"the surface of the specified globe."
|
||||
},
|
||||
{
|
||||
"getGeoPosition",
|
||||
&globebrowsing::luascriptfunctions::getGeoPosition,
|
||||
{},
|
||||
"name, latitude, longitude, altitude",
|
||||
"Returns the specified surface position on the globe as three floating point "
|
||||
"values"
|
||||
"string, number, number, number",
|
||||
"Returns the specified surface position on the globe identified by the first "
|
||||
"argument, as three floating point values - latitude, longitude and altitude "
|
||||
"(degrees and meters)."
|
||||
},
|
||||
{
|
||||
"getGeoPositionForCamera",
|
||||
@@ -355,7 +421,7 @@ scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
|
||||
{},
|
||||
"void",
|
||||
"Get geographic coordinates of the camera poosition in latitude, "
|
||||
"longitude, and altitude"
|
||||
"longitude, and altitude (degrees and meters)."
|
||||
},
|
||||
{
|
||||
"loadWMSCapabilities",
|
||||
@@ -395,29 +461,29 @@ scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
|
||||
return res;
|
||||
}
|
||||
|
||||
void GlobeBrowsingModule::goToChunk(int x, int y, int level) {
|
||||
Camera* cam = global::navigationHandler.camera();
|
||||
goToChunk(*cam, globebrowsing::TileIndex(x,y,level), glm::vec2(0.5f, 0.5f), true);
|
||||
void GlobeBrowsingModule::goToChunk(const globebrowsing::RenderableGlobe& globe,
|
||||
int x, int y, int level)
|
||||
{
|
||||
goToChunk(globe, globebrowsing::TileIndex(x, y, level), glm::vec2(0.5f, 0.5f), true);
|
||||
}
|
||||
|
||||
void GlobeBrowsingModule::goToGeo(double latitude, double longitude) {
|
||||
void GlobeBrowsingModule::goToGeo(const globebrowsing::RenderableGlobe& globe,
|
||||
double latitude, double longitude)
|
||||
{
|
||||
using namespace globebrowsing;
|
||||
Camera* cam = global::navigationHandler.camera();
|
||||
goToGeodetic2(
|
||||
*cam,
|
||||
globe,
|
||||
Geodetic2{ glm::radians(latitude), glm::radians(longitude) },
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
void GlobeBrowsingModule::goToGeo(double latitude, double longitude,
|
||||
double altitude)
|
||||
void GlobeBrowsingModule::goToGeo(const globebrowsing::RenderableGlobe& globe,
|
||||
double latitude, double longitude, double altitude)
|
||||
{
|
||||
using namespace globebrowsing;
|
||||
|
||||
Camera* cam = global::navigationHandler.camera();
|
||||
goToGeodetic3(
|
||||
*cam,
|
||||
globe,
|
||||
{
|
||||
Geodetic2{ glm::radians(latitude), glm::radians(longitude) },
|
||||
altitude
|
||||
@@ -437,32 +503,15 @@ glm::vec3 GlobeBrowsingModule::cartesianCoordinatesFromGeo(
|
||||
altitude
|
||||
};
|
||||
|
||||
const glm::dvec3 positionModelSpace = globe.ellipsoid().cartesianPosition(pos);
|
||||
//glm::dmat4 modelTransform = globe.modelTransform();
|
||||
//glm::dvec3 positionWorldSpace = glm::dvec3(modelTransform *
|
||||
//glm::dvec4(positionModelSpace, 1.0));
|
||||
|
||||
return glm::vec3(positionModelSpace);
|
||||
return glm::vec3(globe.ellipsoid().cartesianPosition(pos));
|
||||
}
|
||||
|
||||
void GlobeBrowsingModule::goToChunk(Camera& camera, const globebrowsing::TileIndex& ti,
|
||||
void GlobeBrowsingModule::goToChunk(const globebrowsing::RenderableGlobe& globe,
|
||||
const globebrowsing::TileIndex& ti,
|
||||
glm::vec2 uv, bool doResetCameraDirection)
|
||||
{
|
||||
using namespace globebrowsing;
|
||||
|
||||
const RenderableGlobe* globe = castFocusNodeRenderableToGlobe();
|
||||
if (!globe) {
|
||||
LERROR("Focus node must have a RenderableGlobe renderable.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Camera position in model space
|
||||
const glm::dvec3 camPos = camera.positionVec3();
|
||||
const glm::dmat4 inverseModelTransform = glm::inverse(globe->modelTransform());
|
||||
const glm::dvec3 cameraPositionModelSpace = glm::dvec3(
|
||||
inverseModelTransform * glm::dvec4(camPos, 1)
|
||||
);
|
||||
|
||||
const GeodeticPatch patch(ti);
|
||||
const Geodetic2 corner = patch.corner(SOUTH_WEST);
|
||||
Geodetic2 positionOnPatch = patch.size();
|
||||
@@ -473,32 +522,50 @@ void GlobeBrowsingModule::goToChunk(Camera& camera, const globebrowsing::TileInd
|
||||
corner.lon + positionOnPatch.lon
|
||||
};
|
||||
|
||||
const glm::dvec3 positionOnEllipsoid = globe->ellipsoid().geodeticSurfaceProjection(
|
||||
// Compute altitude
|
||||
const glm::dvec3 cameraPosition = global::navigationHandler.camera()->positionVec3();
|
||||
SceneGraphNode* globeSceneGraphNode = dynamic_cast<SceneGraphNode*>(globe.owner());
|
||||
if (!globeSceneGraphNode) {
|
||||
LERROR(
|
||||
"Cannot go to chunk. The renderable is not attached to a scene graph node."
|
||||
);
|
||||
return;
|
||||
}
|
||||
const glm::dmat4 inverseModelTransform = globeSceneGraphNode->inverseModelTransform();
|
||||
const glm::dvec3 cameraPositionModelSpace =
|
||||
glm::dvec3(inverseModelTransform * glm::dvec4(cameraPosition, 1.0));
|
||||
const SurfacePositionHandle posHandle = globe.calculateSurfacePositionHandle(
|
||||
cameraPositionModelSpace
|
||||
);
|
||||
const double altitude = glm::length(cameraPositionModelSpace - positionOnEllipsoid);
|
||||
|
||||
const Geodetic2 geo2 = globe.ellipsoid().cartesianToGeodetic2(
|
||||
posHandle.centerToReferenceSurface
|
||||
);
|
||||
|
||||
goToGeodetic3(camera, {pointPosition, altitude}, doResetCameraDirection);
|
||||
const double altitude = glm::length(
|
||||
cameraPositionModelSpace - posHandle.centerToReferenceSurface
|
||||
);
|
||||
|
||||
goToGeodetic3(globe, { pointPosition, altitude }, doResetCameraDirection);
|
||||
}
|
||||
|
||||
void GlobeBrowsingModule::goToGeodetic2(Camera& camera, globebrowsing::Geodetic2 geo2,
|
||||
void GlobeBrowsingModule::goToGeodetic2(const globebrowsing::RenderableGlobe& globe,
|
||||
globebrowsing::Geodetic2 geo2,
|
||||
bool doResetCameraDirection)
|
||||
{
|
||||
using namespace globebrowsing;
|
||||
|
||||
const RenderableGlobe* globe = castFocusNodeRenderableToGlobe();
|
||||
if (!globe) {
|
||||
LERROR("Focus node must have a RenderableGlobe renderable.");
|
||||
return;
|
||||
const glm::dvec3 cameraPosition = global::navigationHandler.camera()->positionVec3();
|
||||
SceneGraphNode* globeSceneGraphNode = dynamic_cast<SceneGraphNode*>(globe.owner());
|
||||
if (!globeSceneGraphNode) {
|
||||
LERROR("Error when going to Geodetic2");
|
||||
}
|
||||
|
||||
interaction::NavigationHandler& nav = global::navigationHandler;
|
||||
const glm::dvec3 cameraPosition = nav.camera()->positionVec3();
|
||||
const glm::dmat4 inverseModelTransform =
|
||||
nav.orbitalNavigator().anchorNode()->inverseModelTransform();
|
||||
const glm::dmat4 inverseModelTransform = globeSceneGraphNode->inverseModelTransform();
|
||||
|
||||
const glm::dvec3 cameraPositionModelSpace =
|
||||
glm::dvec3(inverseModelTransform * glm::dvec4(cameraPosition, 1.0));
|
||||
const SurfacePositionHandle posHandle = globe->calculateSurfacePositionHandle(
|
||||
const SurfacePositionHandle posHandle = globe.calculateSurfacePositionHandle(
|
||||
cameraPositionModelSpace
|
||||
);
|
||||
|
||||
@@ -506,71 +573,58 @@ void GlobeBrowsingModule::goToGeodetic2(Camera& camera, globebrowsing::Geodetic2
|
||||
posHandle.referenceSurfaceOutDirection * posHandle.heightToSurface;
|
||||
const double altitude = glm::length(cameraPositionModelSpace - centerToActualSurface);
|
||||
|
||||
goToGeodetic3(camera, { geo2, altitude }, doResetCameraDirection);
|
||||
goToGeodetic3(globe, { geo2, altitude }, doResetCameraDirection);
|
||||
}
|
||||
|
||||
void GlobeBrowsingModule::goToGeodetic3(Camera& camera, globebrowsing::Geodetic3 geo3,
|
||||
void GlobeBrowsingModule::goToGeodetic3(const globebrowsing::RenderableGlobe& globe,
|
||||
globebrowsing::Geodetic3 geo3,
|
||||
bool doResetCameraDirection)
|
||||
{
|
||||
using namespace globebrowsing;
|
||||
const glm::dvec3 positionModelSpace = globe.ellipsoid().cartesianPosition(geo3);
|
||||
|
||||
const RenderableGlobe* globe = castFocusNodeRenderableToGlobe();
|
||||
if (!globe) {
|
||||
LERROR("Focus node must have a RenderableGlobe renderable.");
|
||||
return;
|
||||
}
|
||||
|
||||
const glm::dvec3 positionModelSpace = globe->ellipsoid().cartesianPosition(geo3);
|
||||
const glm::dmat4 modelTransform = globe->modelTransform();
|
||||
const glm::dvec3 positionWorldSpace = glm::dvec3(modelTransform *
|
||||
glm::dvec4(positionModelSpace, 1.0));
|
||||
camera.setPositionVec3(positionWorldSpace);
|
||||
const glm::dvec3 slightlyNorth = globe.ellipsoid().cartesianSurfacePosition(
|
||||
Geodetic2{ geo3.geodetic2.lat + 0.001, geo3.geodetic2.lon }
|
||||
);
|
||||
|
||||
if (doResetCameraDirection) {
|
||||
resetCameraDirection(camera, geo3.geodetic2);
|
||||
}
|
||||
interaction::NavigationHandler::NavigationState state;
|
||||
state.anchor = globe.owner()->identifier();
|
||||
state.referenceFrame = globe.owner()->identifier();
|
||||
state.position = positionModelSpace;
|
||||
state.up = slightlyNorth;
|
||||
|
||||
global::navigationHandler.setNavigationStateNextFrame(state);
|
||||
}
|
||||
|
||||
void GlobeBrowsingModule::resetCameraDirection(Camera& camera,
|
||||
globebrowsing::Geodetic2 geo2)
|
||||
glm::dquat GlobeBrowsingModule::lookDownCameraRotation(
|
||||
const globebrowsing::RenderableGlobe& globe,
|
||||
glm::dvec3 cameraModelSpace,
|
||||
globebrowsing::Geodetic2 geo2)
|
||||
{
|
||||
using namespace globebrowsing;
|
||||
|
||||
const RenderableGlobe* globe = castFocusNodeRenderableToGlobe();
|
||||
if (!globe) {
|
||||
LERROR("Focus node must have a RenderableGlobe renderable.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Camera is described in world space
|
||||
const glm::dmat4 modelTransform = globe->modelTransform();
|
||||
const glm::dmat4 modelTransform = globe.modelTransform();
|
||||
|
||||
// Lookup vector
|
||||
const glm::dvec3 positionModelSpace = globe->ellipsoid().cartesianSurfacePosition(
|
||||
const glm::dvec3 positionModelSpace = globe.ellipsoid().cartesianSurfacePosition(
|
||||
geo2
|
||||
);
|
||||
const glm::dvec3 slightlyNorth = globe->ellipsoid().cartesianSurfacePosition(
|
||||
const glm::dvec3 slightlyNorth = globe.ellipsoid().cartesianSurfacePosition(
|
||||
Geodetic2{ geo2.lat + 0.001, geo2.lon }
|
||||
);
|
||||
const glm::dvec3 lookUpModelSpace = glm::normalize(
|
||||
slightlyNorth - positionModelSpace
|
||||
);
|
||||
const glm::dvec3 lookUpWorldSpace = glm::dmat3(modelTransform) * lookUpModelSpace;
|
||||
|
||||
// Lookat vector
|
||||
const glm::dvec3 lookAtWorldSpace = glm::dvec3(
|
||||
modelTransform * glm::dvec4(positionModelSpace, 1.0)
|
||||
);
|
||||
|
||||
// Eye position
|
||||
const glm::dvec3 eye = camera.positionVec3();
|
||||
|
||||
// Matrix
|
||||
const glm::dmat4 lookAtMatrix = glm::lookAt(eye, lookAtWorldSpace, lookUpWorldSpace);
|
||||
const glm::dmat4 lookAtMatrix =
|
||||
glm::lookAt(cameraModelSpace, positionModelSpace, lookUpModelSpace);
|
||||
|
||||
// Set rotation
|
||||
const glm::dquat rotation = glm::quat_cast(inverse(lookAtMatrix));
|
||||
camera.setRotation(rotation);
|
||||
return rotation;
|
||||
}
|
||||
|
||||
const globebrowsing::RenderableGlobe*
|
||||
@@ -732,5 +786,27 @@ uint64_t GlobeBrowsingModule::wmsCacheSize() const {
|
||||
return size * 1024 * 1024;
|
||||
}
|
||||
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
void GlobeBrowsingModule::addFrameInfo(globebrowsing::RenderableGlobe* globe,
|
||||
uint32_t nTilesRenderedLocal,
|
||||
uint32_t nTilesRenderedGlobal,
|
||||
uint32_t nTilesUploaded)
|
||||
{
|
||||
auto it = _frameInfo.frames.find(globe);
|
||||
if (it == _frameInfo.frames.end()) {
|
||||
_frameInfo.frames[globe] = std::vector<FrameInfo>();
|
||||
_frameInfo.frames[globe].reserve(_frameInfo.saveEveryNthFrame);
|
||||
}
|
||||
else {
|
||||
it->second.push_back({
|
||||
global::renderEngine.frameNumber(),
|
||||
nTilesRenderedLocal,
|
||||
nTilesRenderedGlobal,
|
||||
nTilesUploaded
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -53,9 +53,12 @@ public:
|
||||
|
||||
GlobeBrowsingModule();
|
||||
|
||||
void goToChunk(int x, int y, int level);
|
||||
void goToGeo(double latitude, double longitude);
|
||||
void goToGeo(double latitude, double longitude, double altitude);
|
||||
void goToChunk(const globebrowsing::RenderableGlobe& globe, int x, int y, int level);
|
||||
void goToGeo(const globebrowsing::RenderableGlobe& globe,
|
||||
double latitude, double longitude);
|
||||
|
||||
void goToGeo(const globebrowsing::RenderableGlobe& globe,
|
||||
double latitude, double longitude, double altitude);
|
||||
|
||||
glm::vec3 cartesianCoordinatesFromGeo(const globebrowsing::RenderableGlobe& globe,
|
||||
double latitude, double longitude, double altitude);
|
||||
@@ -90,17 +93,26 @@ public:
|
||||
std::string wmsCacheLocation() const;
|
||||
uint64_t wmsCacheSize() const; // bytes
|
||||
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
void addFrameInfo(globebrowsing::RenderableGlobe* globe, uint32_t nTilesRenderedLocal,
|
||||
uint32_t nTilesRenderedGlobal, uint32_t nTilesUploaded);
|
||||
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
|
||||
protected:
|
||||
void internalInitialize(const ghoul::Dictionary&) override;
|
||||
|
||||
private:
|
||||
void goToChunk(Camera& camera, const globebrowsing::TileIndex& ti, glm::vec2 uv,
|
||||
bool doResetCameraDirection);
|
||||
void goToGeodetic2(Camera& camera, globebrowsing::Geodetic2 geo2,
|
||||
bool doResetCameraDirection);
|
||||
void goToGeodetic3(Camera& camera, globebrowsing::Geodetic3 geo3,
|
||||
bool doResetCameraDirection);
|
||||
void resetCameraDirection(Camera& camera, globebrowsing::Geodetic2 geo2);
|
||||
void goToChunk(const globebrowsing::RenderableGlobe& globe,
|
||||
const globebrowsing::TileIndex& ti, glm::vec2 uv, bool doResetCameraDirection);
|
||||
|
||||
void goToGeodetic2(const globebrowsing::RenderableGlobe& globe,
|
||||
globebrowsing::Geodetic2 geo2, bool doResetCameraDirection);
|
||||
|
||||
void goToGeodetic3(const globebrowsing::RenderableGlobe& globe,
|
||||
globebrowsing::Geodetic3 geo3, bool doResetCameraDirection);
|
||||
|
||||
glm::dquat lookDownCameraRotation(const globebrowsing::RenderableGlobe& globe,
|
||||
glm::dvec3 cameraPositionModelSpace, globebrowsing::Geodetic2 geo2);
|
||||
|
||||
/**
|
||||
\return a comma separated list of layer group names.
|
||||
@@ -127,6 +139,26 @@ private:
|
||||
std::map<std::string, Capabilities> _capabilitiesMap;
|
||||
|
||||
std::multimap<std::string, UrlInfo> _urlList;
|
||||
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
struct FrameInfo {
|
||||
uint64_t iFrame = 0;
|
||||
uint32_t nTilesRenderedLocal = 0;
|
||||
uint32_t nTilesRenderedGlobal = 0;
|
||||
uint32_t nTilesUploaded = 0;
|
||||
};
|
||||
|
||||
struct {
|
||||
std::unordered_map<
|
||||
globebrowsing::RenderableGlobe*,
|
||||
std::vector<FrameInfo>
|
||||
> frames;
|
||||
|
||||
uint64_t lastSavedFrame = 0;
|
||||
const uint16_t saveEveryNthFrame = 2048;
|
||||
} _frameInfo;
|
||||
properties::BoolProperty _saveInstrumentation;
|
||||
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -128,31 +128,79 @@ int deleteLayer(lua_State* L) {
|
||||
}
|
||||
|
||||
int goToChunk(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::goToChunk");
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 4, "lua::goToChunk");
|
||||
|
||||
const int x = ghoul::lua::value<int>(L, 1);
|
||||
const int y = ghoul::lua::value<int>(L, 2);
|
||||
const int level = ghoul::lua::value<int>(L, 3);
|
||||
lua_pop(L, 3);
|
||||
const std::string& globeIdentifier = ghoul::lua::value<std::string>(L, 1);
|
||||
const int x = ghoul::lua::value<int>(L, 2);
|
||||
const int y = ghoul::lua::value<int>(L, 3);
|
||||
const int level = ghoul::lua::value<int>(L, 4);
|
||||
lua_pop(L, 4);
|
||||
|
||||
global::moduleEngine.module<GlobeBrowsingModule>()->goToChunk(x, y, level);
|
||||
SceneGraphNode* n = sceneGraphNode(globeIdentifier);
|
||||
if (!n) {
|
||||
return ghoul::lua::luaError(L, "Unknown globe name: " + globeIdentifier);
|
||||
}
|
||||
|
||||
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
|
||||
if (!globe) {
|
||||
return ghoul::lua::luaError(L, "Identifier must be a RenderableGlobe");
|
||||
}
|
||||
|
||||
global::moduleEngine.module<GlobeBrowsingModule>()->goToChunk(*globe, x, y, level);
|
||||
|
||||
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int goToGeo(lua_State* L) {
|
||||
const int nArguments = ghoul::lua::checkArgumentsAndThrow(L, 2, 3, "lua::goToGeo");
|
||||
const int nArguments = ghoul::lua::checkArgumentsAndThrow(L, { 2, 4 }, "lua::goToGeo");
|
||||
|
||||
const double latitude = ghoul::lua::value<double>(L, 1);
|
||||
const double longitude = ghoul::lua::value<double>(L, 2);
|
||||
// Check if the user provided a Scene graph node identifier as the first argument.
|
||||
// lua_isstring returns true for both numbers and strings, so better use !lua_isnumber
|
||||
const bool providedGlobeIdentifier = !lua_isnumber(L, 1);
|
||||
const int parameterOffset = providedGlobeIdentifier ? 1 : 0;
|
||||
|
||||
if (nArguments == 2) {
|
||||
global::moduleEngine.module<GlobeBrowsingModule>()->goToGeo(latitude, longitude);
|
||||
const SceneGraphNode* n;
|
||||
if (providedGlobeIdentifier) {
|
||||
const std::string& globeIdentifier = ghoul::lua::value<std::string>(L, 1);
|
||||
n = sceneGraphNode(globeIdentifier);
|
||||
if (!n) {
|
||||
return ghoul::lua::luaError(L, "Unknown globe name: " + globeIdentifier);
|
||||
}
|
||||
}
|
||||
else if (nArguments == 3) {
|
||||
const double altitude = ghoul::lua::value<double>(L, 3);
|
||||
else {
|
||||
n = global::navigationHandler.orbitalNavigator().anchorNode();
|
||||
if (!n) {
|
||||
return ghoul::lua::luaError(L, "No anchor node is set.");
|
||||
}
|
||||
}
|
||||
|
||||
const double latitude = ghoul::lua::value<double>(L, parameterOffset + 1);
|
||||
const double longitude = ghoul::lua::value<double>(L, parameterOffset + 2);
|
||||
|
||||
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
|
||||
if (!globe) {
|
||||
if (providedGlobeIdentifier) {
|
||||
return ghoul::lua::luaError(L, "Identifier must be a RenderableGlobe");
|
||||
}
|
||||
else {
|
||||
return ghoul::lua::luaError(L,
|
||||
"Current anchor node is not a RenderableGlobe. "
|
||||
"Either change the anchor to a globe, or specify a globe identifier "
|
||||
"as the first argument"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (nArguments == parameterOffset + 2) {
|
||||
global::moduleEngine.module<GlobeBrowsingModule>()->goToGeo(
|
||||
*globe, latitude, longitude
|
||||
);
|
||||
}
|
||||
else if (nArguments == parameterOffset + 3) {
|
||||
const double altitude = ghoul::lua::value<double>(L, parameterOffset + 3);
|
||||
global::moduleEngine.module<GlobeBrowsingModule>()->goToGeo(
|
||||
*globe,
|
||||
latitude,
|
||||
longitude,
|
||||
altitude
|
||||
@@ -168,19 +216,19 @@ int goToGeo(lua_State* L) {
|
||||
int getGeoPosition(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 4, "lua::getGeoPosition");
|
||||
|
||||
const std::string& name = ghoul::lua::value<std::string>(L, 1);
|
||||
const std::string& globeIdentifier = ghoul::lua::value<std::string>(L, 1);
|
||||
const double latitude = ghoul::lua::value<double>(L, 2);
|
||||
const double longitude = ghoul::lua::value<double>(L, 3);
|
||||
const double altitude = ghoul::lua::value<double>(L, 4);
|
||||
lua_pop(L, 4);
|
||||
|
||||
SceneGraphNode* n = sceneGraphNode(name);
|
||||
SceneGraphNode* n = sceneGraphNode(globeIdentifier);
|
||||
if (!n) {
|
||||
return ghoul::lua::luaError(L, "Unknown globe name: " + name);
|
||||
return ghoul::lua::luaError(L, "Unknown globe identifier: " + globeIdentifier);
|
||||
}
|
||||
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
|
||||
if (!globe) {
|
||||
return ghoul::lua::luaError(L, "Name must be a RenderableGlobe");
|
||||
return ghoul::lua::luaError(L, "Identifier must be a RenderableGlobe");
|
||||
}
|
||||
|
||||
GlobeBrowsingModule& mod = *(global::moduleEngine.module<GlobeBrowsingModule>());
|
||||
|
||||
@@ -173,9 +173,16 @@ void DashboardItemGlobeLocation::render(glm::vec2& penPosition) {
|
||||
bool isEast = lon > 0.0;
|
||||
lon = std::abs(lon);
|
||||
|
||||
const double altitude = glm::length(
|
||||
double altitude = glm::length(
|
||||
cameraPositionModelSpace - posHandle.centerToReferenceSurface
|
||||
);
|
||||
|
||||
if (glm::length(cameraPositionModelSpace) <
|
||||
glm::length(posHandle.centerToReferenceSurface))
|
||||
{
|
||||
altitude = -altitude;
|
||||
}
|
||||
|
||||
std::pair<double, std::string> dist = simplifyDistance(altitude);
|
||||
|
||||
penPosition.y -= _font->height();
|
||||
|
||||
@@ -45,11 +45,10 @@
|
||||
#include <locale>
|
||||
|
||||
namespace {
|
||||
constexpr const char* KeyLabels = "Labels";
|
||||
constexpr const char* KeyLabelsFileName = "FileName";
|
||||
|
||||
constexpr const char* _loggerCat = "GlobeLabels";
|
||||
|
||||
constexpr const char* KeyLabelsFileName = "FileName";
|
||||
|
||||
constexpr const double LabelFadeRangeConst = 1500.0;
|
||||
constexpr const double RangeAngularCoefConst = 0.8;
|
||||
constexpr const float MinTransparencyValueConst = 0.009f;
|
||||
@@ -671,19 +670,10 @@ void GlobeLabelsComponent::renderLabels(const RenderData& data,
|
||||
float distToCamera,
|
||||
float fadeInVariable
|
||||
) {
|
||||
constexpr double DIST_EPS = 6000.0;
|
||||
constexpr double SIN_EPS = 0.001;
|
||||
|
||||
glm::vec4 textColor = _labelsColor;
|
||||
textColor.a *= fadeInVariable;
|
||||
|
||||
glm::dmat4 invMP = glm::inverse(_globe->modelTransform());
|
||||
glm::dmat4 invCombinedView = glm::inverse(data.camera.combinedViewMatrix());
|
||||
|
||||
glm::dvec4 cameraPosWorld = invCombinedView * glm::dvec4(0.0, 0.0, 0.0, 1.0);
|
||||
glm::dvec3 cameraPosObj = glm::dvec3(invMP * cameraPosWorld);
|
||||
glm::dvec4 cameraUpVecWorld = glm::dvec4(data.camera.lookUpVectorWorldSpace(), 0.0);
|
||||
glm::dvec3 cameraLookUpObj = glm::dvec3(invMP * cameraUpVecWorld);
|
||||
|
||||
glm::dmat4 VP = glm::dmat4(data.camera.sgctInternal.projectionMatrix()) *
|
||||
data.camera.combinedViewMatrix();
|
||||
@@ -799,7 +789,7 @@ bool GlobeLabelsComponent::isLabelInFrustum(const glm::dmat4& MVMatrix,
|
||||
double bottomDistance = MVMatrix[3][3] + MVMatrix[3][1];
|
||||
double topDistance = MVMatrix[3][3] - MVMatrix[3][1];
|
||||
double nearDistance = MVMatrix[3][3] + MVMatrix[3][2];
|
||||
double farDistance = MVMatrix[3][3] - MVMatrix[3][2];
|
||||
// double farDistance = MVMatrix[3][3] - MVMatrix[3][2];
|
||||
|
||||
// Normalize Planes
|
||||
const double invMagLeft = 1.0 / glm::length(leftNormal);
|
||||
@@ -824,7 +814,7 @@ bool GlobeLabelsComponent::isLabelInFrustum(const glm::dmat4& MVMatrix,
|
||||
|
||||
const double invMagFar = 1.0 / glm::length(farNormal);
|
||||
farNormal *= invMagFar;
|
||||
farDistance *= invMagFar;
|
||||
// farDistance *= invMagFar;
|
||||
|
||||
constexpr const float Radius = 1.0;
|
||||
|
||||
|
||||
@@ -58,20 +58,21 @@ namespace {
|
||||
"globe. The default value is 0.0"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo FixedAltitudeInfo = {
|
||||
"FixedAltitude",
|
||||
"Fixed Altitude",
|
||||
"The altitude in meters of the location on the globe's surface. This value is "
|
||||
"used if the 'UseFixedAltitude' property is 'true'. The default value is 10000km."
|
||||
constexpr openspace::properties::Property::PropertyInfo AltitudeInfo = {
|
||||
"Altitude",
|
||||
"Altitude",
|
||||
"The altitude in meters. "
|
||||
"If the 'UseHeightmap' property is 'true', this is an offset from the actual "
|
||||
"surface of the globe. If not, this is an offset from the reference ellipsoid."
|
||||
"The default value is 0.0"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo UseFixedAltitudeInfo = {
|
||||
"UseFixedAltitude",
|
||||
"Use Fixed Altitude",
|
||||
"If this value is 'true', the altitude specified in 'FixedAltitude' is used for "
|
||||
"this translation. If it is 'false', the altitude will be computed based on the "
|
||||
"height information that is available about the globe to which this translation "
|
||||
"is attached. The default value is 'true'."
|
||||
constexpr openspace::properties::Property::PropertyInfo UseHeightmapInfo = {
|
||||
"UseHeightmap",
|
||||
"Use Heightmap",
|
||||
"If this value is 'true', the altitude specified in 'Altitude' will be treated "
|
||||
"as an offset from the heightmap. Otherwise, it will be an offset from the "
|
||||
"globe's reference ellipsoid. The default value is 'false'."
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@@ -81,8 +82,8 @@ documentation::Documentation GlobeTranslation::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
|
||||
return {
|
||||
"Spice Translation",
|
||||
"space_translation_spicetranslation",
|
||||
"Globe Translation",
|
||||
"space_translation_globetranslation",
|
||||
{
|
||||
{
|
||||
"Type",
|
||||
@@ -110,16 +111,16 @@ documentation::Documentation GlobeTranslation::Documentation() {
|
||||
LatitudeInfo.description,
|
||||
},
|
||||
{
|
||||
FixedAltitudeInfo.identifier,
|
||||
AltitudeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
FixedAltitudeInfo.description
|
||||
AltitudeInfo.description
|
||||
},
|
||||
{
|
||||
UseFixedAltitudeInfo.identifier,
|
||||
UseHeightmapInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
UseFixedAltitudeInfo.description
|
||||
UseHeightmapInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -129,8 +130,8 @@ GlobeTranslation::GlobeTranslation(const ghoul::Dictionary& dictionary)
|
||||
: _globe(GlobeInfo)
|
||||
, _longitude(LongitudeInfo, 0.0, -180.0, 180.0)
|
||||
, _latitude(LatitudeInfo, 0.0, -90.0, 90.0)
|
||||
, _fixedAltitude(FixedAltitudeInfo, 1e8, 0.0, 1e12)
|
||||
, _useFixedAltitude(UseFixedAltitudeInfo, false)
|
||||
, _altitude(AltitudeInfo, 0.0, 0.0, 1e12)
|
||||
, _useHeightmap(UseHeightmapInfo, false)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
@@ -145,11 +146,11 @@ GlobeTranslation::GlobeTranslation(const ghoul::Dictionary& dictionary)
|
||||
if (dictionary.hasKey(LatitudeInfo.identifier)) {
|
||||
_latitude = dictionary.value<double>(LatitudeInfo.identifier);
|
||||
}
|
||||
if (dictionary.hasKey(FixedAltitudeInfo.identifier)) {
|
||||
_fixedAltitude = dictionary.value<double>(FixedAltitudeInfo.identifier);
|
||||
if (dictionary.hasKey(AltitudeInfo.identifier)) {
|
||||
_altitude = dictionary.value<double>(AltitudeInfo.identifier);
|
||||
}
|
||||
if (dictionary.hasKey(UseFixedAltitudeInfo.identifier)) {
|
||||
_useFixedAltitude = dictionary.value<bool>(UseFixedAltitudeInfo.identifier);
|
||||
if (dictionary.hasKey(UseHeightmapInfo.identifier)) {
|
||||
_useHeightmap = dictionary.value<bool>(UseHeightmapInfo.identifier);
|
||||
}
|
||||
|
||||
_globe.onChange([this]() {
|
||||
@@ -159,8 +160,13 @@ GlobeTranslation::GlobeTranslation(const ghoul::Dictionary& dictionary)
|
||||
|
||||
_longitude.onChange([this]() { _positionIsDirty = true; });
|
||||
_latitude.onChange([this]() { _positionIsDirty = true; });
|
||||
_fixedAltitude.onChange([this]() { _positionIsDirty = true; });
|
||||
_useFixedAltitude.onChange([this]() { _positionIsDirty = true; });
|
||||
_altitude.onChange([this]() { _positionIsDirty = true; });
|
||||
_useHeightmap.onChange([this]() { _positionIsDirty = true; });
|
||||
|
||||
addProperty(_longitude);
|
||||
addProperty(_latitude);
|
||||
addProperty(_altitude);
|
||||
addProperty(_useHeightmap);
|
||||
}
|
||||
|
||||
void GlobeTranslation::fillAttachedNode() {
|
||||
@@ -173,8 +179,10 @@ void GlobeTranslation::fillAttachedNode() {
|
||||
"GlobeTranslation",
|
||||
"Could not set attached node as it does not have a RenderableGlobe"
|
||||
);
|
||||
// Reset the globe name to it's previous name
|
||||
_globe = _attachedNode->identifier();
|
||||
if (_attachedNode) {
|
||||
// Reset the globe name to it's previous name
|
||||
_globe = _attachedNode->identifier();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,8 +196,8 @@ glm::dvec3 GlobeTranslation::position(const UpdateData&) const {
|
||||
_positionIsDirty = true;
|
||||
}
|
||||
|
||||
if (!_useFixedAltitude) {
|
||||
// If we don't use the fixed altitude, we have to compute the height every frame
|
||||
if (_useHeightmap) {
|
||||
// If we use the heightmap, we have to compute the height every frame
|
||||
_positionIsDirty = true;
|
||||
}
|
||||
|
||||
@@ -197,33 +205,35 @@ glm::dvec3 GlobeTranslation::position(const UpdateData&) const {
|
||||
return _position;
|
||||
}
|
||||
|
||||
|
||||
GlobeBrowsingModule& mod = *(global::moduleEngine.module<GlobeBrowsingModule>());
|
||||
|
||||
glm::vec3 pos = mod.cartesianCoordinatesFromGeo(
|
||||
*_attachedNode,
|
||||
_latitude,
|
||||
_longitude,
|
||||
_fixedAltitude
|
||||
);
|
||||
|
||||
if (_useFixedAltitude) {
|
||||
_position = glm::dvec3(pos);
|
||||
_positionIsDirty = true;
|
||||
|
||||
return _position;
|
||||
}
|
||||
else {
|
||||
SurfacePositionHandle h = _attachedNode->calculateSurfacePositionHandle(pos);
|
||||
|
||||
pos = mod.cartesianCoordinatesFromGeo(
|
||||
if (_useHeightmap) {
|
||||
glm::vec3 groundPos = mod.cartesianCoordinatesFromGeo(
|
||||
*_attachedNode,
|
||||
_latitude,
|
||||
_longitude,
|
||||
h.heightToSurface
|
||||
0.0
|
||||
);
|
||||
|
||||
_position = glm::dvec3(pos);
|
||||
SurfacePositionHandle h =
|
||||
_attachedNode->calculateSurfacePositionHandle(groundPos);
|
||||
|
||||
_position = mod.cartesianCoordinatesFromGeo(
|
||||
*_attachedNode,
|
||||
_latitude,
|
||||
_longitude,
|
||||
h.heightToSurface + _altitude
|
||||
);
|
||||
return _position;
|
||||
}
|
||||
else {
|
||||
_position = mod.cartesianCoordinatesFromGeo(
|
||||
*_attachedNode,
|
||||
_latitude,
|
||||
_longitude,
|
||||
_altitude
|
||||
);
|
||||
_positionIsDirty = false;
|
||||
return _position;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,8 +49,8 @@ private:
|
||||
properties::StringProperty _globe;
|
||||
properties::DoubleProperty _longitude;
|
||||
properties::DoubleProperty _latitude;
|
||||
properties::DoubleProperty _fixedAltitude;
|
||||
properties::BoolProperty _useFixedAltitude;
|
||||
properties::DoubleProperty _altitude;
|
||||
properties::BoolProperty _useHeightmap;
|
||||
|
||||
RenderableGlobe* _attachedNode = nullptr;
|
||||
|
||||
|
||||
@@ -341,9 +341,12 @@ void Layer::onChange(std::function<void(Layer*)> callback) {
|
||||
_onChangeCallback = std::move(callback);
|
||||
}
|
||||
|
||||
void Layer::update() {
|
||||
int Layer::update() {
|
||||
if (_tileProvider) {
|
||||
tileprovider::update(*_tileProvider);
|
||||
return tileprovider::update(*_tileProvider);
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,8 @@ public:
|
||||
|
||||
void onChange(std::function<void(Layer*)> callback);
|
||||
|
||||
void update();
|
||||
// Return: number of tiles that were updated
|
||||
int update();
|
||||
|
||||
glm::ivec2 tilePixelStartOffset() const;
|
||||
glm::ivec2 tilePixelSizeDifference() const;
|
||||
|
||||
@@ -91,15 +91,18 @@ void LayerGroup::deinitialize() {
|
||||
}
|
||||
}
|
||||
|
||||
void LayerGroup::update() {
|
||||
int LayerGroup::update() {
|
||||
int res = 0;
|
||||
_activeLayers.clear();
|
||||
|
||||
for (const std::unique_ptr<Layer>& layer : _layers) {
|
||||
if (layer->enabled()) {
|
||||
layer->update();
|
||||
res += layer->update();
|
||||
_activeLayers.push_back(layer.get());
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Layer* LayerGroup::addLayer(const ghoul::Dictionary& layerDict) {
|
||||
|
||||
@@ -48,7 +48,8 @@ struct LayerGroup : public properties::PropertyOwner {
|
||||
void deinitialize();
|
||||
|
||||
/// Updates all layers tile providers within this group
|
||||
void update();
|
||||
/// Return: Number of tiles that were updated
|
||||
int update();
|
||||
|
||||
Layer* addLayer(const ghoul::Dictionary& layerDict);
|
||||
void deleteLayer(const std::string& layerName);
|
||||
|
||||
@@ -111,10 +111,12 @@ std::array<LayerGroup*, LayerManager::NumLayerGroups> LayerManager::layerGroups(
|
||||
return res;
|
||||
}
|
||||
|
||||
void LayerManager::update() {
|
||||
int LayerManager::update() {
|
||||
int res = 0;
|
||||
for (std::unique_ptr<LayerGroup>& layerGroup : _layerGroups) {
|
||||
layerGroup->update();
|
||||
res += layerGroup->update();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void LayerManager::reset(bool includeDisabled) {
|
||||
|
||||
@@ -63,7 +63,8 @@ public:
|
||||
|
||||
std::array<LayerGroup*, NumLayerGroups> layerGroups() const;
|
||||
|
||||
void update();
|
||||
// Return: Number of tiles updated
|
||||
int update();
|
||||
void reset(bool includeDisabled = false);
|
||||
|
||||
void onChange(std::function<void(Layer* l)> callback);
|
||||
|
||||
@@ -47,6 +47,13 @@
|
||||
#include <numeric>
|
||||
#include <queue>
|
||||
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
#include <modules/globebrowsing/globebrowsingmodule.h>
|
||||
openspace::GlobeBrowsingModule* _module = nullptr;
|
||||
|
||||
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
|
||||
namespace {
|
||||
// Global flags to modify the RenderableGlobe
|
||||
constexpr const bool LimitLevelByAvailableData = true;
|
||||
@@ -176,7 +183,7 @@ namespace {
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo TargetLodScaleFactorInfo = {
|
||||
"TargetLodScaleFactorInfo",
|
||||
"TargetLodScaleFactor",
|
||||
"Target Level of Detail Scale Factor",
|
||||
"" // @TODO Missing documentation
|
||||
};
|
||||
@@ -595,10 +602,13 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
|
||||
if (dictionary.hasKeyAndValue<ghoul::Dictionary>(KeyLabels)) {
|
||||
_labelsDictionary = dictionary.value<ghoul::Dictionary>(KeyLabels);
|
||||
}
|
||||
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
_module = global::moduleEngine.module<GlobeBrowsingModule>();
|
||||
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
}
|
||||
|
||||
void RenderableGlobe::initializeGL() {
|
||||
|
||||
if (!_labelsDictionary.empty()) {
|
||||
_globeLabelsComponent.initialize(_labelsDictionary, this);
|
||||
addPropertySubOwner(_globeLabelsComponent);
|
||||
@@ -745,7 +755,11 @@ void RenderableGlobe::update(const UpdateData& data) {
|
||||
_layerManager.reset();
|
||||
_debugProperties.resetTileProviders = false;
|
||||
}
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
_nUploadedTiles = _layerManager.update();
|
||||
#else
|
||||
_layerManager.update();
|
||||
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
|
||||
if (_nLayersIsDirty) {
|
||||
std::array<LayerGroup*, LayerManager::NumLayerGroups> lgs =
|
||||
@@ -1034,6 +1048,14 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&) {
|
||||
}
|
||||
_localRenderer.program->deactivate();
|
||||
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
_module->addFrameInfo(
|
||||
this,
|
||||
std::min(localCount, ChunkBufferSize),
|
||||
std::min(globalCount, ChunkBufferSize),
|
||||
_nUploadedTiles
|
||||
);
|
||||
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
|
||||
if (_debugProperties.showChunkBounds || _debugProperties.showChunkAABB) {
|
||||
for (int i = 0; i < std::min(globalCount, ChunkBufferSize); ++i) {
|
||||
|
||||
@@ -274,6 +274,10 @@ private:
|
||||
// Labels
|
||||
GlobeLabelsComponent _globeLabelsComponent;
|
||||
ghoul::Dictionary _labelsDictionary;
|
||||
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
int _nUploadedTiles = 0;
|
||||
#endif // OPENSPACE_MODULE_GLOBEBROWSING_INSTRUMENTATION
|
||||
};
|
||||
|
||||
} // namespace openspace::globebrowsing
|
||||
|
||||
@@ -162,15 +162,17 @@ void initAsyncTileDataReader(DefaultTileProvider& t, TileTextureInitData initDat
|
||||
);
|
||||
}
|
||||
|
||||
void initTexturesFromLoadedData(DefaultTileProvider& t) {
|
||||
bool initTexturesFromLoadedData(DefaultTileProvider& t) {
|
||||
if (t.asyncTextureDataProvider) {
|
||||
std::optional<RawTile> tile = t.asyncTextureDataProvider->popFinishedRawTile();
|
||||
if (tile) {
|
||||
const cache::ProviderTileKey key = { tile->tileIndex, t.uniqueIdentifier };
|
||||
ghoul_assert(!t.tileCache->exist(key), "Tile must not be existing in cache");
|
||||
t.tileCache->createTileAndPut(key, std::move(tile.value()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1073,7 +1075,7 @@ TileDepthTransform depthTransform(TileProvider& tp) {
|
||||
|
||||
|
||||
|
||||
void update(TileProvider& tp) {
|
||||
int update(TileProvider& tp) {
|
||||
switch (tp.type) {
|
||||
case Type::DefaultTileProvider: {
|
||||
DefaultTileProvider& t = static_cast<DefaultTileProvider&>(tp);
|
||||
@@ -1082,7 +1084,7 @@ void update(TileProvider& tp) {
|
||||
}
|
||||
|
||||
t.asyncTextureDataProvider->update();
|
||||
initTexturesFromLoadedData(t);
|
||||
bool hasUploaded = initTexturesFromLoadedData(t);
|
||||
|
||||
if (t.asyncTextureDataProvider->shouldBeDeleted()) {
|
||||
t.asyncTextureDataProvider = nullptr;
|
||||
@@ -1091,6 +1093,9 @@ void update(TileProvider& tp) {
|
||||
tileTextureInitData(t.layerGroupID, t.padTiles, t.tilePixelSize)
|
||||
);
|
||||
}
|
||||
if (hasUploaded) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Type::SingleImageTileProvider:
|
||||
@@ -1123,13 +1128,16 @@ void update(TileProvider& tp) {
|
||||
if (newCurrent) {
|
||||
t.currentTileProvider = newCurrent;
|
||||
}
|
||||
update(*t.currentTileProvider);
|
||||
if (t.currentTileProvider) {
|
||||
update(*t.currentTileProvider);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw ghoul::MissingCaseException();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -222,8 +222,10 @@ TileDepthTransform depthTransform(TileProvider& tp);
|
||||
/**
|
||||
* This method should be called once per frame. Here, TileProviders
|
||||
* are given the opportunity to update their internal state.
|
||||
*
|
||||
* \return The number of tiles that have been updated in this call
|
||||
*/
|
||||
void update(TileProvider& tp);
|
||||
int update(TileProvider& tp);
|
||||
|
||||
/**
|
||||
* Provides a uniform way of all TileProviders to reload or
|
||||
|
||||
+63
-13
@@ -53,32 +53,69 @@ namespace {
|
||||
|
||||
constexpr const std::array<const char*, 2> UniformNames = { "tex", "ortho" };
|
||||
|
||||
void addScreenSpaceRenderableLocal(std::string texturePath) {
|
||||
void addScreenSpaceRenderableLocal(std::string identifier, std::string texturePath) {
|
||||
if (!FileSys.fileExists(absPath(texturePath))) {
|
||||
LWARNING(fmt::format("Could not find image '{}'", texturePath));
|
||||
return;
|
||||
}
|
||||
|
||||
openspace::global::scriptEngine.queueScript(
|
||||
fmt::format(
|
||||
std::string script;
|
||||
if (identifier.empty()) {
|
||||
script = fmt::format(
|
||||
"openspace.addScreenSpaceRenderable({{\
|
||||
Type = 'ScreenSpaceImageLocal',\
|
||||
TexturePath = openspace.absPath('{}')\
|
||||
}});",
|
||||
std::move(texturePath)
|
||||
),
|
||||
texturePath
|
||||
);
|
||||
}
|
||||
else {
|
||||
script = fmt::format(
|
||||
"openspace.addScreenSpaceRenderable({{\
|
||||
Type = 'ScreenSpaceImageLocal',\
|
||||
TexturePath = openspace.absPath('{}'),\
|
||||
Identifier = '{}',\
|
||||
Name = '{}'\
|
||||
}});",
|
||||
texturePath,
|
||||
identifier,
|
||||
identifier
|
||||
);
|
||||
}
|
||||
|
||||
openspace::global::scriptEngine.queueScript(
|
||||
script,
|
||||
openspace::scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
|
||||
void addScreenSpaceRenderableOnline(std::string texturePath) {
|
||||
openspace::global::scriptEngine.queueScript(
|
||||
fmt::format(
|
||||
void addScreenSpaceRenderableOnline(std::string identifier, std::string texturePath) {
|
||||
std::string script;
|
||||
if (identifier.empty()) {
|
||||
script = fmt::format(
|
||||
"openspace.addScreenSpaceRenderable({{\
|
||||
Type = 'ScreenSpaceImageOnline', URL = '{}'\
|
||||
Type = 'ScreenSpaceImageOnline',\
|
||||
URL = '{}'\
|
||||
}});",
|
||||
std::move(texturePath)
|
||||
),
|
||||
texturePath
|
||||
);
|
||||
}
|
||||
else {
|
||||
script = fmt::format(
|
||||
"openspace.addScreenSpaceRenderable({{\
|
||||
Type = 'ScreenSpaceImageOnline',\
|
||||
URL = '{}',\
|
||||
Identifier = '{}',\
|
||||
Name = '{}'\
|
||||
}});",
|
||||
texturePath,
|
||||
identifier,
|
||||
identifier
|
||||
);
|
||||
}
|
||||
|
||||
openspace::global::scriptEngine.queueScript(
|
||||
script,
|
||||
openspace::scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
@@ -616,9 +653,16 @@ void GUI::render() {
|
||||
renderAndUpdatePropertyVisibility();
|
||||
|
||||
static const int addImageBufferSize = 256;
|
||||
static char identifierBuffer[addImageBufferSize];
|
||||
static char addImageLocalBuffer[addImageBufferSize];
|
||||
static char addImageOnlineBuffer[addImageBufferSize];
|
||||
|
||||
ImGui::InputText(
|
||||
"Identifier for Local/Online Images",
|
||||
identifierBuffer,
|
||||
addImageBufferSize
|
||||
);
|
||||
|
||||
bool addImageLocal = ImGui::InputText(
|
||||
"Add Local Image",
|
||||
addImageLocalBuffer,
|
||||
@@ -626,7 +670,10 @@ void GUI::render() {
|
||||
ImGuiInputTextFlags_EnterReturnsTrue
|
||||
);
|
||||
if (addImageLocal) {
|
||||
addScreenSpaceRenderableLocal(std::string(addImageLocalBuffer));
|
||||
addScreenSpaceRenderableLocal(
|
||||
std::string(identifierBuffer),
|
||||
std::string(addImageLocalBuffer)
|
||||
);
|
||||
}
|
||||
|
||||
bool addImageOnline = ImGui::InputText(
|
||||
@@ -637,7 +684,10 @@ void GUI::render() {
|
||||
);
|
||||
|
||||
if (addImageOnline) {
|
||||
addScreenSpaceRenderableOnline(std::string(addImageOnlineBuffer));
|
||||
addScreenSpaceRenderableOnline(
|
||||
std::string(identifierBuffer),
|
||||
std::string(addImageOnlineBuffer)
|
||||
);
|
||||
}
|
||||
|
||||
bool addDashboard = ImGui::Button("Add New Dashboard");
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace {
|
||||
return "[" + formatLuaString(it.key()) + "] = " + formatLua(it);
|
||||
}
|
||||
|
||||
std::string formatLuaTable(const nlohmann::json& json) {
|
||||
std::string formatObjectAsLuaTable(const nlohmann::json& json) {
|
||||
std::string output = "{";
|
||||
auto it = json.begin();
|
||||
for (size_t i = 0; i < json.size(); ++i, ++it) {
|
||||
@@ -81,9 +81,24 @@ namespace {
|
||||
return output + "}";
|
||||
}
|
||||
|
||||
std::string formatArrayAsLuaTable(const nlohmann::json& json) {
|
||||
std::string output = "{";
|
||||
auto it = json.begin();
|
||||
for (size_t i = 0; i < json.size(); ++i, ++it) {
|
||||
output += formatLua(it);
|
||||
if (i < json.size() - 1) {
|
||||
output += ",";
|
||||
}
|
||||
}
|
||||
return output + "}";
|
||||
}
|
||||
|
||||
std::string formatLua(const nlohmann::json::const_iterator& it) {
|
||||
if (it->is_object()) {
|
||||
return formatLuaTable(it->get<nlohmann::json>());
|
||||
return formatObjectAsLuaTable(it->get<nlohmann::json>());
|
||||
}
|
||||
if (it->is_array()) {
|
||||
return formatArrayAsLuaTable(it->get<nlohmann::json>());
|
||||
}
|
||||
if (it->is_number()) {
|
||||
return fmt::format("{:E}", it->get<double>());
|
||||
|
||||
@@ -41,15 +41,29 @@ namespace {
|
||||
|
||||
std::string escapedLuaString(const std::string& str) {
|
||||
std::string luaString;
|
||||
|
||||
for (const char& c : str) {
|
||||
switch (c) {
|
||||
case '\'':
|
||||
luaString += "\'";
|
||||
break;
|
||||
default:
|
||||
luaString += c;
|
||||
case '\t':
|
||||
luaString += "\\t"; // Replace tab with \t.
|
||||
break;
|
||||
case '"':
|
||||
luaString += "\\\""; // Replace " with \".
|
||||
break;
|
||||
case '\\':
|
||||
luaString += "\\\\"; // Replace \ with \\.
|
||||
break;
|
||||
case '\n':
|
||||
luaString += "\\\\n"; // Replace newline with \n.
|
||||
break;
|
||||
case '\r':
|
||||
luaString += "\\r"; // Replace carriage return with \r.
|
||||
break;
|
||||
default:
|
||||
luaString += c;
|
||||
}
|
||||
}
|
||||
|
||||
return luaString;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "TimeTopic";
|
||||
constexpr const char* EventKey = "event";
|
||||
constexpr const char* SubscribeEvent = "start_subscription";
|
||||
constexpr const char* UnsubscribeEvent = "stop_subscription";
|
||||
|
||||
@@ -773,7 +773,6 @@ void RenderableStars::renderPSFToTexture() {
|
||||
GLenum blendDestRGB;
|
||||
GLenum blendSrcAlpha;
|
||||
GLenum blendSrcRGB;
|
||||
GLboolean depthMask;
|
||||
|
||||
glGetIntegerv(GL_BLEND_EQUATION_RGB, &blendEquationRGB);
|
||||
glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blendEquationAlpha);
|
||||
@@ -927,7 +926,6 @@ void RenderableStars::render(const RenderData& data, RendererTasks&) {
|
||||
glm::dmat4(data.modelTransform.rotation) *
|
||||
glm::dmat4(glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)));
|
||||
|
||||
glm::dmat4 modelViewMatrix = data.camera.combinedViewMatrix() * modelMatrix;
|
||||
glm::dmat4 projectionMatrix = glm::dmat4(data.camera.projectionMatrix());
|
||||
|
||||
glm::dmat4 cameraViewProjectionMatrix = projectionMatrix *
|
||||
|
||||
@@ -165,7 +165,6 @@ private:
|
||||
GLuint _psfVao = 0;
|
||||
GLuint _psfVbo = 0;
|
||||
GLuint _psfTexture = 0;
|
||||
GLuint _discTexture = 0;
|
||||
GLuint _convolvedTexture = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ void HorizonsTranslation::readHorizonsTextFile(const std::string& horizonsTextFi
|
||||
);
|
||||
|
||||
// Add position to stored timeline.
|
||||
_timeline.addKeyframe(timeInJ2000, gPos);
|
||||
_timeline.addKeyframe(timeInJ2000, std::move(gPos));
|
||||
|
||||
std::getline(fileStream, line);
|
||||
}
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
|
||||
include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake)
|
||||
|
||||
option(OPENSPACE_MODULE_SYNC_USE_LIBTORRENT "Use libtorrent" OFF)
|
||||
|
||||
set(HEADER_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/syncmodule.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/syncs/httpsynchronization.h
|
||||
@@ -42,48 +40,4 @@ set(SOURCE_FILES
|
||||
)
|
||||
source_group("Source Files" FILES ${SOURCE_FILES})
|
||||
|
||||
if (OPENSPACE_MODULE_SYNC_USE_LIBTORRENT)
|
||||
set(HEADER_FILES
|
||||
${HEADER_FILES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/torrentclient.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/syncs/torrentsynchronization.h
|
||||
)
|
||||
set(SOURCE_FILES
|
||||
${SOURCE_FILES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/torrentclient.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/syncs/torrentsynchronization.cpp
|
||||
)
|
||||
endif ()
|
||||
|
||||
|
||||
create_new_module("Sync" sync_module ${HEADER_FILES} ${SOURCE_FILES})
|
||||
|
||||
#####
|
||||
# Libtorrent
|
||||
#####
|
||||
|
||||
if (OPENSPACE_MODULE_SYNC_USE_LIBTORRENT)
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
set(Boost_USE_MULTITHREADED ON)
|
||||
set(LIBTORRENT_encryption OFF CACHE BOOL "Use OpenSSL Encryption" FORCE)
|
||||
set(LIBTORRENT_shared OFF CACHE BOOL "Use Libtorrent as shared library" FORCE)
|
||||
|
||||
include_external_library(
|
||||
${sync_module}
|
||||
torrent-rasterbar
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ext/libtorrent
|
||||
)
|
||||
target_include_directories(
|
||||
${sync_module}
|
||||
SYSTEM PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ext/libtorrent/include
|
||||
)
|
||||
|
||||
target_compile_definitions(openspace-module-sync PUBLIC SYNC_USE_LIBTORRENT)
|
||||
|
||||
mark_as_advanced(LIBTORRENT_build_examples LIBTORRENT_build_tests
|
||||
LIBTORRENT_deprecated-functions LIBTORRENT_dht LIBTORRENT_encryption
|
||||
LIBTORRENT_exceptions LIBTORRENT_exceptions LIBTORRENT_libiconv
|
||||
LIBTORRENT_logging LIBTORRENT_shared LIBTORRENT_static_runtime
|
||||
)
|
||||
endif () # OPENSPACE_MODULE_SYNC_USE_LIBTORRENT
|
||||
Submodule modules/sync/ext/libtorrent deleted from 22477e7430
@@ -25,7 +25,6 @@
|
||||
#include <modules/sync/syncmodule.h>
|
||||
|
||||
#include <modules/sync/syncs/httpsynchronization.h>
|
||||
#include <modules/sync/syncs/torrentsynchronization.h>
|
||||
#include <modules/sync/syncs/urlsynchronization.h>
|
||||
#include <modules/sync/tasks/syncassettask.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
@@ -87,19 +86,6 @@ void SyncModule::internalInitialize(const ghoul::Dictionary& configuration) {
|
||||
}
|
||||
);
|
||||
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
fSynchronization->registerClass(
|
||||
"TorrentSynchronization",
|
||||
[this](bool, const ghoul::Dictionary& dictionary) {
|
||||
return new TorrentSynchronization(
|
||||
dictionary,
|
||||
_synchronizationRoot,
|
||||
_torrentClient
|
||||
);
|
||||
}
|
||||
);
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
|
||||
fSynchronization->registerClass(
|
||||
"UrlSynchronization",
|
||||
[this](bool, const ghoul::Dictionary& dictionary) {
|
||||
@@ -113,17 +99,6 @@ void SyncModule::internalInitialize(const ghoul::Dictionary& configuration) {
|
||||
auto fTask = FactoryManager::ref().factory<Task>();
|
||||
ghoul_assert(fTask, "No task factory existed");
|
||||
fTask->registerClass<SyncAssetTask>("SyncAssetTask");
|
||||
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
_torrentClient.initialize();
|
||||
global::callback::deinitialize.emplace_back([&]() { _torrentClient.deinitialize(); });
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
}
|
||||
|
||||
void SyncModule::internalDeinitialize() {
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
_torrentClient.deinitialize();
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
}
|
||||
|
||||
std::string SyncModule::synchronizationRoot() const {
|
||||
@@ -140,10 +115,7 @@ std::vector<std::string> SyncModule::httpSynchronizationRepositories() const {
|
||||
|
||||
std::vector<documentation::Documentation> SyncModule::documentations() const {
|
||||
return {
|
||||
HttpSynchronization::Documentation(),
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
TorrentSynchronization::Documentation()
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
HttpSynchronization::Documentation()
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -27,10 +27,6 @@
|
||||
|
||||
#include <openspace/util/openspacemodule.h>
|
||||
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
#include <modules/sync/torrentclient.h>
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class SyncModule : public OpenSpaceModule {
|
||||
@@ -44,20 +40,12 @@ public:
|
||||
void addHttpSynchronizationRepository(std::string repository);
|
||||
std::vector<std::string> httpSynchronizationRepositories() const;
|
||||
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
TorrentClient& torrentClient();
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
|
||||
std::vector<documentation::Documentation> documentations() const override;
|
||||
|
||||
protected:
|
||||
void internalInitialize(const ghoul::Dictionary& configuration) override;
|
||||
void internalDeinitialize() override;
|
||||
|
||||
private:
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
TorrentClient _torrentClient;
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
std::vector<std::string> _synchronizationRepositories;
|
||||
std::string _synchronizationRoot;
|
||||
};
|
||||
|
||||
@@ -1,197 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2019 *
|
||||
* *
|
||||
* 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/sync/syncs/torrentsynchronization.h>
|
||||
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/filesystem/file.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
#include <fstream>
|
||||
|
||||
namespace {
|
||||
constexpr const char* KeyIdentifier = "Identifier";
|
||||
constexpr const char* KeyMagnet = "Magnet";
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation TorrentSynchronization::Documentation() {
|
||||
using namespace openspace::documentation;
|
||||
return {
|
||||
"TorrentSynchronization",
|
||||
"torrent_synchronization",
|
||||
{
|
||||
{
|
||||
KeyIdentifier,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"A unique identifier for this torrent"
|
||||
},
|
||||
{
|
||||
KeyMagnet,
|
||||
new StringVerifier,
|
||||
Optional::No,
|
||||
"A magnet link identifying the torrent"
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TorrentSynchronization::TorrentSynchronization(const ghoul::Dictionary& dict,
|
||||
std::string synchronizationRoot,
|
||||
TorrentClient& torrentClient)
|
||||
: ResourceSynchronization(dict)
|
||||
, _synchronizationRoot(std::move(synchronizationRoot))
|
||||
, _torrentClient(torrentClient)
|
||||
{
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dict,
|
||||
"TorrentSynchronization"
|
||||
);
|
||||
|
||||
_identifier = dict.value<std::string>(KeyIdentifier);
|
||||
_magnetLink = dict.value<std::string>(KeyMagnet);
|
||||
}
|
||||
|
||||
TorrentSynchronization::~TorrentSynchronization() {
|
||||
cancel();
|
||||
}
|
||||
|
||||
std::string TorrentSynchronization::uniformResourceName() const {
|
||||
const size_t begin = _magnetLink.find("=urn") + 1;
|
||||
const size_t end = _magnetLink.find('&', begin);
|
||||
std::string xs = _magnetLink.substr(
|
||||
begin,
|
||||
(end == std::string::npos) ? end : (end - begin)
|
||||
);
|
||||
|
||||
std::transform(
|
||||
xs.begin(),
|
||||
xs.end(),
|
||||
xs.begin(),
|
||||
[](char x) { return (x == ':') ? '.' : x; }
|
||||
);
|
||||
return xs;
|
||||
}
|
||||
|
||||
std::string TorrentSynchronization::directory() {
|
||||
ghoul::filesystem::Directory d(
|
||||
_synchronizationRoot +
|
||||
ghoul::filesystem::FileSystem::PathSeparator +
|
||||
"torrent" +
|
||||
ghoul::filesystem::FileSystem::PathSeparator +
|
||||
_identifier +
|
||||
ghoul::filesystem::FileSystem::PathSeparator +
|
||||
uniformResourceName()
|
||||
);
|
||||
|
||||
return FileSys.absPath(d);
|
||||
}
|
||||
|
||||
void TorrentSynchronization::start() {
|
||||
if (_enabled) {
|
||||
return;
|
||||
}
|
||||
begin();
|
||||
|
||||
if (hasSyncFile()) {
|
||||
resolve();
|
||||
}
|
||||
|
||||
_enabled = true;
|
||||
try {
|
||||
_torrentId = _torrentClient.addMagnetLink(
|
||||
_magnetLink,
|
||||
directory(),
|
||||
[this](TorrentClient::TorrentProgress p) {
|
||||
updateTorrentProgress(p);
|
||||
}
|
||||
);
|
||||
} catch (const TorrentError& e) {
|
||||
LERRORC(name(), e.message);
|
||||
if (!isResolved()) {
|
||||
reject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentSynchronization::cancel() {
|
||||
if (_enabled) {
|
||||
_torrentClient.removeTorrent(_torrentId);
|
||||
_enabled = false;
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
void TorrentSynchronization::clear() {
|
||||
cancel();
|
||||
// TODO: Remove all files from directory.
|
||||
}
|
||||
|
||||
bool TorrentSynchronization::hasSyncFile() {
|
||||
const std::string& path = directory() + ".ossync";
|
||||
return FileSys.fileExists(path);
|
||||
}
|
||||
|
||||
void TorrentSynchronization::createSyncFile() {
|
||||
const std::string& directoryName = directory();
|
||||
const std::string& filepath = directoryName + ".ossync";
|
||||
|
||||
FileSys.createDirectory(directoryName, ghoul::filesystem::FileSystem::Recursive::Yes);
|
||||
|
||||
std::ofstream syncFile(filepath, std::ofstream::out);
|
||||
syncFile << "Synchronized";
|
||||
syncFile.close();
|
||||
}
|
||||
|
||||
size_t TorrentSynchronization::nSynchronizedBytes() {
|
||||
std::lock_guard<std::mutex> g(_progressMutex);
|
||||
return _progress.nDownloadedBytes;
|
||||
}
|
||||
|
||||
size_t TorrentSynchronization::nTotalBytes() {
|
||||
std::lock_guard<std::mutex> g(_progressMutex);
|
||||
return _progress.nTotalBytes;
|
||||
}
|
||||
|
||||
bool TorrentSynchronization::nTotalBytesIsKnown() {
|
||||
std::lock_guard<std::mutex> g(_progressMutex);
|
||||
return _progress.nTotalBytesKnown;
|
||||
}
|
||||
|
||||
void TorrentSynchronization::updateTorrentProgress(
|
||||
TorrentClient::TorrentProgress progress)
|
||||
{
|
||||
std::lock_guard<std::mutex> g(_progressMutex);
|
||||
_progress = progress;
|
||||
if (progress.finished && (state() == State::Syncing)) {
|
||||
createSyncFile();
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
@@ -1,77 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2019 *
|
||||
* *
|
||||
* 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_SYNC___TORRENTSYNCHRONIZATION___H__
|
||||
#define __OPENSPACE_MODULE_SYNC___TORRENTSYNCHRONIZATION___H__
|
||||
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
|
||||
#include <openspace/util/resourcesynchronization.h>
|
||||
|
||||
#include <modules/sync/torrentclient.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class TorrentSynchronizationJob;
|
||||
|
||||
class TorrentSynchronization : public ResourceSynchronization {
|
||||
public:
|
||||
TorrentSynchronization(const ghoul::Dictionary& dict, std::string synchronizationRoot,
|
||||
TorrentClient& client);
|
||||
|
||||
virtual ~TorrentSynchronization();
|
||||
|
||||
std::string directory() override;
|
||||
void start() override;
|
||||
void cancel() override;
|
||||
void clear() override;
|
||||
|
||||
size_t nSynchronizedBytes() override;
|
||||
size_t nTotalBytes() override;
|
||||
bool nTotalBytesIsKnown() override;
|
||||
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
private:
|
||||
void updateTorrentProgress(TorrentClient::TorrentProgress p);
|
||||
std::string uniformResourceName() const;
|
||||
bool hasSyncFile();
|
||||
void createSyncFile();
|
||||
|
||||
std::atomic_bool _enabled = false;
|
||||
|
||||
TorrentClient::TorrentId _torrentId = 0;
|
||||
TorrentClient::TorrentProgress _progress;
|
||||
std::mutex _progressMutex;
|
||||
std::string _identifier;
|
||||
std::string _magnetLink;
|
||||
std::string _synchronizationRoot;
|
||||
TorrentClient& _torrentClient;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
|
||||
#endif // __OPENSPACE_MODULE_SYNC___TORRENTSYNCHRONIZATION___H__
|
||||
@@ -1,271 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2019 *
|
||||
* *
|
||||
* 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/sync/torrentclient.h>
|
||||
|
||||
#include <openspace/openspace.h>
|
||||
#include <ghoul/fmt.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable : 4265)
|
||||
#pragma warning (disable : 4996)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <libtorrent/entry.hpp>
|
||||
#include <libtorrent/bencode.hpp>
|
||||
#include <libtorrent/session.hpp>
|
||||
#include <libtorrent/alert_types.hpp>
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
#include <libtorrent/magnet_uri.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "TorrentClient";
|
||||
constexpr const std::chrono::milliseconds PollInterval(1000);
|
||||
} // namespace
|
||||
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
|
||||
namespace openspace {
|
||||
|
||||
TorrentError::TorrentError(std::string msg)
|
||||
: RuntimeError(std::move(msg), "TorrentClient")
|
||||
{}
|
||||
|
||||
void TorrentClient::initialize() {
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
libtorrent::settings_pack settings;
|
||||
settings.set_str(
|
||||
libtorrent::settings_pack::user_agent,
|
||||
"OpenSpace/" + std::string(OPENSPACE_VERSION_NUMBER)
|
||||
);
|
||||
|
||||
settings.set_str(
|
||||
libtorrent::settings_pack::listen_interfaces,
|
||||
"0.0.0.0:6881,0.0.0.0:20280,0.0.0.0:20285,0.0.0.0:20290"
|
||||
);
|
||||
settings.set_bool(libtorrent::settings_pack::allow_multiple_connections_per_ip, true);
|
||||
settings.set_bool(libtorrent::settings_pack::enable_upnp, true);
|
||||
//settings.set_bool(libtorrent::settings_pack::ignore_limits_on_local_network, true);
|
||||
settings.set_int(libtorrent::settings_pack::connection_speed, 20);
|
||||
settings.set_int(libtorrent::settings_pack::active_downloads, -1);
|
||||
settings.set_int(libtorrent::settings_pack::active_seeds, -1);
|
||||
settings.set_int(libtorrent::settings_pack::active_limit, 30);
|
||||
|
||||
settings.set_str(
|
||||
libtorrent::settings_pack::dht_bootstrap_nodes,
|
||||
"router.utorrent.com,dht.transmissionbt.com,router.bittorrent.com,\
|
||||
router.bitcomet.com"
|
||||
);
|
||||
settings.set_int(libtorrent::settings_pack::dht_announce_interval, 15);
|
||||
|
||||
_session.apply_settings(settings);
|
||||
|
||||
libtorrent::error_code ec;
|
||||
|
||||
_isInitialized = true;
|
||||
_isActive = true;
|
||||
|
||||
_torrentThread = std::thread([this]() {
|
||||
while (_isActive) {
|
||||
pollAlerts();
|
||||
std::unique_lock<std::mutex> lock(_abortMutex);
|
||||
_abortNotifier.wait_for(lock, PollInterval);
|
||||
}
|
||||
});
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
}
|
||||
|
||||
void TorrentClient::deinitialize() {
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
if (!_isActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
_isActive = false;
|
||||
_abortNotifier.notify_all();
|
||||
if (_torrentThread.joinable()) {
|
||||
_torrentThread.join();
|
||||
}
|
||||
|
||||
const std::vector<lt::torrent_handle>& handles = _session.get_torrents();
|
||||
for (const lt::torrent_handle& h : handles) {
|
||||
_session.remove_torrent(h);
|
||||
}
|
||||
_torrents.clear();
|
||||
|
||||
_session.abort();
|
||||
_isInitialized = false;
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
}
|
||||
|
||||
void TorrentClient::pollAlerts() {
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
// Libtorrent does not seem to reliably generate alerts for all added torrents.
|
||||
// To make sure that the program does not keep waiting for already finished
|
||||
// downsloads, we go through the whole list of torrents when polling.
|
||||
// However, in theory, the commented code below should be more efficient:
|
||||
/*
|
||||
std::vector<libtorrent::alert*> alerts;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(_mutex);
|
||||
_session->pop_alerts(&alerts);
|
||||
}
|
||||
for (lt::alert* a : alerts) {
|
||||
if (const lt::torrent_alert* alert =
|
||||
dynamic_cast<lt::torrent_alert*>(a))
|
||||
{
|
||||
notify(alert->handle.id());
|
||||
}
|
||||
}
|
||||
*/
|
||||
std::vector<lt::torrent_handle> handles;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(_mutex);
|
||||
handles = _session.get_torrents();
|
||||
}
|
||||
for (const lt::torrent_handle& h : handles) {
|
||||
notify(h.id());
|
||||
}
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
}
|
||||
|
||||
TorrentClient::TorrentId TorrentClient::addTorrentFile(
|
||||
[[ maybe_unused ]] const std::string& torrentFile,
|
||||
[[maybe_unused]] const std::string& destination,
|
||||
[[maybe_unused]] TorrentProgressCallback cb)
|
||||
{
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
std::lock_guard<std::mutex> guard(_mutex);
|
||||
|
||||
if (!_isInitialized) {
|
||||
LERROR("Torrent session not initialized when adding torrent");
|
||||
return -1;
|
||||
}
|
||||
|
||||
libtorrent::error_code ec;
|
||||
libtorrent::add_torrent_params p;
|
||||
p.save_path = destination;
|
||||
p.ti = std::make_shared<libtorrent::torrent_info>(torrentFile, ec);
|
||||
if (ec) {
|
||||
LERROR(fmt::format("{}: {}", torrentFile, ec.message()));
|
||||
}
|
||||
const libtorrent::torrent_handle h = _session.add_torrent(p, ec);
|
||||
if (ec) {
|
||||
LERROR(fmt::format("{}: {}", torrentFile, ec.message()));
|
||||
}
|
||||
|
||||
TorrentId id = h.id();
|
||||
_torrents.emplace(id, Torrent{ id, h, std::move(cb) });
|
||||
return id;
|
||||
#else // SYNC_USE_LIBTORRENT
|
||||
throw TorrentError("SyncModule is compiled without libtorrent support");
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
}
|
||||
|
||||
TorrentClient::TorrentId TorrentClient::addMagnetLink(
|
||||
[[maybe_unused]] const std::string& magnetLink,
|
||||
[[maybe_unused]] const std::string& destination,
|
||||
[[maybe_unused]] TorrentProgressCallback cb)
|
||||
{
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
std::lock_guard<std::mutex> guard(_mutex);
|
||||
|
||||
// TODO: register callback!
|
||||
if (!_isInitialized) {
|
||||
LERROR("Torrent session not initialized when adding torrent");
|
||||
return -1;
|
||||
}
|
||||
libtorrent::error_code ec;
|
||||
libtorrent::add_torrent_params p = libtorrent::parse_magnet_uri(magnetLink, ec);
|
||||
if (ec) {
|
||||
LERROR(fmt::format("{}: {}", magnetLink, ec.message()));
|
||||
}
|
||||
p.save_path = destination;
|
||||
p.storage_mode = libtorrent::storage_mode_allocate;
|
||||
const libtorrent::torrent_handle h = _session.add_torrent(p, ec);
|
||||
if (ec) {
|
||||
LERROR(fmt::format("{}: {}", magnetLink, ec.message()));
|
||||
}
|
||||
|
||||
TorrentId id = h.id();
|
||||
_torrents.emplace(id, Torrent{ id, h, std::move(cb) });
|
||||
return id;
|
||||
#else // SYNC_USE_LIBTORRENT
|
||||
throw TorrentError("SyncModule is compiled without libtorrent support");
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
}
|
||||
|
||||
void TorrentClient::removeTorrent([[maybe_unused]] TorrentId id) {
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
std::lock_guard<std::mutex> guard(_mutex);
|
||||
|
||||
const auto it = _torrents.find(id);
|
||||
if (it == _torrents.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const libtorrent::torrent_handle h = it->second.handle;
|
||||
_session.remove_torrent(h);
|
||||
|
||||
_torrents.erase(it);
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
}
|
||||
|
||||
void TorrentClient::notify([[maybe_unused]] TorrentId id) {
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
TorrentProgressCallback callback;
|
||||
TorrentProgress progress;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(_mutex);
|
||||
|
||||
const auto it = _torrents.find(id);
|
||||
if (it == _torrents.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const libtorrent::torrent_handle h = it->second.handle;
|
||||
const libtorrent::torrent_status status = h.status();
|
||||
|
||||
progress.finished = status.is_finished;
|
||||
progress.nTotalBytesKnown = status.total_wanted > 0;
|
||||
progress.nTotalBytes = status.total_wanted;
|
||||
progress.nDownloadedBytes = status.total_wanted_done;
|
||||
|
||||
callback = it->second.callback;
|
||||
}
|
||||
|
||||
callback(progress);
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
@@ -1,125 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2019 *
|
||||
* *
|
||||
* 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_SYNC___TORRENTCLIENT___H__
|
||||
#define __OPENSPACE_MODULE_SYNC___TORRENTCLIENT___H__
|
||||
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
|
||||
#include <ghoul/misc/exception.h>
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable : 4265)
|
||||
#pragma warning (disable : 4996)
|
||||
#endif // _MSC_VER
|
||||
|
||||
// libtorrent defines a class with the name 'defer', which messes with out #define of the
|
||||
// defer macro in ghoul/misc/defer.h
|
||||
#undef defer
|
||||
|
||||
#include <libtorrent/torrent_handle.hpp>
|
||||
#include <libtorrent/session.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
#else // SYNC_USE_LIBTORRENT
|
||||
// Dummy definition to make TorrentClient compile, these is not actually used if
|
||||
// SYNC_USE_LIBTORRENT is FALSE
|
||||
namespace libtorrent {
|
||||
using torrent_handle = void*;
|
||||
using session = void*;
|
||||
} // namespace libtorrent
|
||||
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
|
||||
namespace openspace {
|
||||
|
||||
struct TorrentError : public ghoul::RuntimeError {
|
||||
explicit TorrentError(std::string msg);
|
||||
};
|
||||
|
||||
class TorrentClient {
|
||||
public:
|
||||
struct TorrentProgress {
|
||||
bool finished = false;
|
||||
bool nTotalBytesKnown = false;
|
||||
size_t nTotalBytes = 0;
|
||||
size_t nDownloadedBytes = 0;
|
||||
};
|
||||
|
||||
using TorrentProgressCallback = std::function<void(TorrentProgress)>;
|
||||
using TorrentId = int32_t;
|
||||
|
||||
void initialize();
|
||||
void deinitialize();
|
||||
|
||||
TorrentId addTorrentFile(const std::string& torrentFile,
|
||||
const std::string& destination, TorrentProgressCallback cb);
|
||||
|
||||
TorrentId addMagnetLink(const std::string& magnetLink, const std::string& destination,
|
||||
TorrentProgressCallback cb);
|
||||
|
||||
void removeTorrent(TorrentId id);
|
||||
|
||||
private:
|
||||
struct Torrent {
|
||||
TorrentId id;
|
||||
libtorrent::torrent_handle handle;
|
||||
TorrentProgressCallback callback;
|
||||
};
|
||||
|
||||
void notify(TorrentId id);
|
||||
void pollAlerts();
|
||||
|
||||
#ifdef SYNC_USE_LIBTORRENT
|
||||
libtorrent::session _session;
|
||||
bool _isInitialized = false;
|
||||
std::atomic_bool _isActive = false;
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
|
||||
std::thread _torrentThread;
|
||||
std::condition_variable _abortNotifier;
|
||||
std::mutex _abortMutex;
|
||||
std::mutex _mutex;
|
||||
|
||||
std::unordered_map<TorrentId, Torrent> _torrents;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // SYNC_USE_LIBTORRENT
|
||||
|
||||
#endif // __OPENSPACE_MODULE_SYNC___TORRENTCLIENT___H__
|
||||
@@ -426,7 +426,7 @@ RenderableTimeVaryingVolume::Timestep* RenderableTimeVaryingVolume::timestepFrom
|
||||
void RenderableTimeVaryingVolume::jumpToTimestep(int target) {
|
||||
Timestep* t = timestepFromIndex(target);
|
||||
if (t) {
|
||||
global::timeManager.setTimeNextFrame(t->metadata.time);
|
||||
global::timeManager.setTimeNextFrame(Time(t->metadata.time));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,9 +50,6 @@ namespace {
|
||||
constexpr const char* KeyValueFunction = "ValueFunction";
|
||||
constexpr const char* KeyLowerDomainBound = "LowerDomainBound";
|
||||
constexpr const char* KeyUpperDomainBound = "UpperDomainBound";
|
||||
|
||||
constexpr const char* KeyMinValue = "MinValue";
|
||||
constexpr const char* KeyMaxValue = "MaxValue";
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
@@ -35,12 +35,6 @@ namespace {
|
||||
"All the envelopes used in the transfer function"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo HistogramInfo = {
|
||||
"Histogram",
|
||||
"Histogram",
|
||||
"All the data"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo DataUnitInfo = {
|
||||
"DataUnit",
|
||||
"DataUnit",
|
||||
|
||||
@@ -57,9 +57,9 @@ class BrowserInstance;
|
||||
class EventHandler {
|
||||
public:
|
||||
void initialize();
|
||||
void setBrowser(const CefRefPtr<CefBrowser>& browser);
|
||||
void setBrowserInstance(BrowserInstance* browserInstance);
|
||||
void detachBrowser();
|
||||
void resetBrowserInstance();
|
||||
|
||||
void touchPressCallback(const double x, const double y);
|
||||
void touchReleaseCallback(const double x, const double y);
|
||||
bool hasContentCallback(const double, const double);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <modules/webbrowser/include/webrenderhandler.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/vector/vec2property.h>
|
||||
#include <openspace/properties/triggerproperty.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
@@ -62,9 +63,11 @@ class WebKeyboardHandler;
|
||||
class ScreenSpaceBrowser : public ScreenSpaceRenderable {
|
||||
public:
|
||||
ScreenSpaceBrowser(const ghoul::Dictionary& dictionary);
|
||||
virtual ~ScreenSpaceBrowser() = default;
|
||||
|
||||
bool initializeGL() override;
|
||||
bool deinitializeGL() override;
|
||||
|
||||
bool initialize() override;
|
||||
bool deinitialize() override;
|
||||
void render() override;
|
||||
void update() override;
|
||||
bool isReady() const override;
|
||||
@@ -72,14 +75,18 @@ public:
|
||||
private:
|
||||
class ScreenSpaceRenderHandler : public WebRenderHandler {
|
||||
public:
|
||||
void draw();
|
||||
void render();
|
||||
void draw() override;
|
||||
void render() override;
|
||||
|
||||
void setTexture(GLuint t);
|
||||
};
|
||||
|
||||
void bindTexture() override;
|
||||
|
||||
properties::StringProperty _url;
|
||||
properties::Vec2Property _dimensions;
|
||||
properties::TriggerProperty _reload;
|
||||
|
||||
CefRefPtr<ScreenSpaceRenderHandler> _renderHandler;
|
||||
CefRefPtr<WebKeyboardHandler> _keyboardHandler;
|
||||
std::unique_ptr<BrowserInstance> _browserInstance;
|
||||
|
||||
@@ -361,7 +361,7 @@ void EventHandler::setBrowserInstance(BrowserInstance* browserInstance) {
|
||||
_browserInstance = browserInstance;
|
||||
}
|
||||
|
||||
void EventHandler::detachBrowser() {
|
||||
void EventHandler::resetBrowserInstance() {
|
||||
_browserInstance = nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
|
||||
namespace {
|
||||
constexpr const char* KeyIdentifier = "Indentifier";
|
||||
constexpr const char* KeyUrl = "URL";
|
||||
constexpr const char* _loggerCat = "ScreenSpaceBrowser";
|
||||
|
||||
const openspace::properties::Property::PropertyInfo DimensionsInfo = {
|
||||
@@ -44,11 +43,17 @@ namespace {
|
||||
"Set the dimensions of the web browser windows."
|
||||
};
|
||||
const openspace::properties::Property::PropertyInfo UrlInfo = {
|
||||
"Url",
|
||||
"URL",
|
||||
"url",
|
||||
"The URL to load"
|
||||
};
|
||||
|
||||
const openspace::properties::Property::PropertyInfo ReloadInfo = {
|
||||
"Reload",
|
||||
"Reload",
|
||||
"Reload the web browser"
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
@@ -65,6 +70,7 @@ ScreenSpaceBrowser::ScreenSpaceBrowser(const ghoul::Dictionary &dictionary)
|
||||
: ScreenSpaceRenderable(dictionary)
|
||||
, _url(UrlInfo)
|
||||
, _dimensions(DimensionsInfo, glm::vec2(0.f), glm::vec2(0.f), glm::vec2(3000.f))
|
||||
, _reload(ReloadInfo)
|
||||
{
|
||||
if (dictionary.hasKey(KeyIdentifier)) {
|
||||
setIdentifier(dictionary.value<std::string>(KeyIdentifier));
|
||||
@@ -74,17 +80,13 @@ ScreenSpaceBrowser::ScreenSpaceBrowser(const ghoul::Dictionary &dictionary)
|
||||
++id;
|
||||
}
|
||||
|
||||
if (dictionary.hasKeyAndValue<std::string>(KeyUrl)) {
|
||||
_url = dictionary.value<std::string>(KeyUrl);
|
||||
if (dictionary.hasKeyAndValue<std::string>(UrlInfo.identifier)) {
|
||||
_url = dictionary.value<std::string>(UrlInfo.identifier);
|
||||
}
|
||||
|
||||
glm::vec2 windowDimensions = global::windowDelegate.currentSubwindowSize();
|
||||
_dimensions = windowDimensions;
|
||||
|
||||
_texture = std::make_unique<ghoul::opengl::Texture>(
|
||||
glm::uvec3(windowDimensions, 1.0f)
|
||||
);
|
||||
|
||||
_renderHandler = new ScreenSpaceRenderHandler();
|
||||
_keyboardHandler = new WebKeyboardHandler();
|
||||
_browserInstance = std::make_unique<BrowserInstance>(
|
||||
@@ -94,9 +96,11 @@ ScreenSpaceBrowser::ScreenSpaceBrowser(const ghoul::Dictionary &dictionary)
|
||||
|
||||
_url.onChange([this]() { _isUrlDirty = true; });
|
||||
_dimensions.onChange([this]() { _isDimensionsDirty = true; });
|
||||
_reload.onChange([this]() { _browserInstance->reloadBrowser(); });
|
||||
|
||||
addProperty(_url);
|
||||
addProperty(_dimensions);
|
||||
addProperty(_reload);
|
||||
|
||||
WebBrowserModule* webBrowser = global::moduleEngine.module<WebBrowserModule>();
|
||||
if (webBrowser) {
|
||||
@@ -104,17 +108,24 @@ ScreenSpaceBrowser::ScreenSpaceBrowser(const ghoul::Dictionary &dictionary)
|
||||
}
|
||||
}
|
||||
|
||||
bool ScreenSpaceBrowser::initialize() {
|
||||
_originalViewportSize = global::windowDelegate.currentWindowSize();
|
||||
bool ScreenSpaceBrowser::initializeGL() {
|
||||
_texture = std::make_unique<ghoul::opengl::Texture>(
|
||||
glm::uvec3(_dimensions.value(), 1.0f)
|
||||
);
|
||||
|
||||
_renderHandler->setTexture(*_texture);
|
||||
|
||||
createShaders();
|
||||
|
||||
_browserInstance->initialize();
|
||||
_browserInstance->loadUrl(_url);
|
||||
return isReady();
|
||||
}
|
||||
|
||||
bool ScreenSpaceBrowser::deinitialize() {
|
||||
bool ScreenSpaceBrowser::deinitializeGL() {
|
||||
_renderHandler->setTexture(0);
|
||||
_texture = nullptr;
|
||||
|
||||
std::string urlString;
|
||||
_url.getStringValue(urlString);
|
||||
LDEBUG(fmt::format("Deinitializing ScreenSpaceBrowser: {}", urlString));
|
||||
@@ -125,11 +136,12 @@ bool ScreenSpaceBrowser::deinitialize() {
|
||||
if (webBrowser) {
|
||||
webBrowser->removeBrowser(_browserInstance.get());
|
||||
_browserInstance.reset();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
LWARNING("Could not find WebBrowserModule");
|
||||
}
|
||||
|
||||
LWARNING("Could not find WebBrowserModule");
|
||||
return false;
|
||||
return ScreenSpaceRenderable::deinitializeGL();
|
||||
}
|
||||
|
||||
void ScreenSpaceBrowser::render() {
|
||||
@@ -146,6 +158,8 @@ void ScreenSpaceBrowser::render() {
|
||||
}
|
||||
|
||||
void ScreenSpaceBrowser::update() {
|
||||
_objectSize = _texture->dimensions();
|
||||
|
||||
if (_isUrlDirty) {
|
||||
_browserInstance->loadUrl(_url);
|
||||
_isUrlDirty = false;
|
||||
@@ -153,7 +167,6 @@ void ScreenSpaceBrowser::update() {
|
||||
|
||||
if (_isDimensionsDirty) {
|
||||
_browserInstance->reshape(_dimensions.value());
|
||||
_originalViewportSize = _dimensions.value();
|
||||
_isDimensionsDirty = false;
|
||||
}
|
||||
}
|
||||
@@ -162,4 +175,8 @@ bool ScreenSpaceBrowser::isReady() const {
|
||||
return _shader && _texture;
|
||||
}
|
||||
|
||||
void ScreenSpaceBrowser::bindTexture() {
|
||||
_texture->bind();
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -41,10 +41,11 @@ void WebBrowserApp::OnContextCreated(CefRefPtr<CefBrowser>, CefRefPtr<CefFrame>,
|
||||
}
|
||||
|
||||
void WebBrowserApp::OnBeforeCommandLineProcessing(const CefString&,
|
||||
CefRefPtr<CefCommandLine>)
|
||||
CefRefPtr<CefCommandLine> commandLine)
|
||||
{
|
||||
// command_line->AppendSwitch("disable-gpu");
|
||||
// command_line->AppendSwitch("disable-gpu-compositing");
|
||||
commandLine->AppendSwitchWithValue("autoplay-policy", "no-user-gesture-required");
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -78,11 +78,13 @@ void WebRenderHandler::OnPaint(CefRefPtr<CefBrowser>, CefRenderHandler::PaintEle
|
||||
// Copy the updated rectangle line by line.
|
||||
for (int y = lowerUpdatingRectBound.y; y < upperUpdatingRectBound.y; ++y) {
|
||||
int lineOffset = y * w + lowerUpdatingRectBound.x;
|
||||
// Chromium stores image upside down compared to OpenGL, so we flip it:
|
||||
int invLineOffset = (h - y - 1) * w + lowerUpdatingRectBound.x;
|
||||
int rectWidth = upperUpdatingRectBound.x - lowerUpdatingRectBound.x;
|
||||
std::copy(
|
||||
reinterpret_cast<const Pixel*>(buffer) + lineOffset,
|
||||
reinterpret_cast<const Pixel*>(buffer) + lineOffset + rectWidth,
|
||||
_browserBuffer.data() + lineOffset
|
||||
_browserBuffer.data() + invLineOffset
|
||||
);
|
||||
}
|
||||
|
||||
@@ -123,14 +125,15 @@ void WebRenderHandler::updateTexture() {
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
_lowerDirtyRectBound.x,
|
||||
_lowerDirtyRectBound.y,
|
||||
_browserBufferSize.y - _upperDirtyRectBound.y,
|
||||
_upperDirtyRectBound.x - _lowerDirtyRectBound.x,
|
||||
_upperDirtyRectBound.y - _lowerDirtyRectBound.y,
|
||||
GL_BGRA_EXT,
|
||||
GL_UNSIGNED_BYTE,
|
||||
reinterpret_cast<char*>(
|
||||
_browserBuffer.data() +
|
||||
_lowerDirtyRectBound.y * _browserBufferSize.x + _lowerDirtyRectBound.x
|
||||
(_browserBufferSize.y - _upperDirtyRectBound.y) *
|
||||
_browserBufferSize.x + _lowerDirtyRectBound.x
|
||||
)
|
||||
);
|
||||
|
||||
@@ -148,7 +151,7 @@ bool WebRenderHandler::hasContent(int x, int y) {
|
||||
if (_browserBuffer.empty()) {
|
||||
return false;
|
||||
}
|
||||
int index = x + (_browserBufferSize.x * y);
|
||||
int index = x + _browserBufferSize.x * (_browserBufferSize.y - y - 1);
|
||||
index = glm::clamp(index, 0, static_cast<int>(_browserBuffer.size() - 1));
|
||||
return _browserBuffer[index].a;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ void WebBrowserModule::internalDeinitialize() {
|
||||
return;
|
||||
}
|
||||
|
||||
_eventHandler.detachBrowser();
|
||||
_eventHandler.resetBrowserInstance();
|
||||
|
||||
bool forceBrowserShutdown = true;
|
||||
for (BrowserInstance* browser : _browsers) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user