mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-02 08:49:20 -05:00
Merge remote-tracking branch 'origin/master' into feature/postprocessing-effects
This commit is contained in:
@@ -37,7 +37,6 @@ set(OPENSPACE_RELEASE_BUILD OFF)
|
||||
set(OPENSPACE_VERSION_MAJOR)
|
||||
set(OPENSPACE_VERSION_MINOR)
|
||||
set(OPENSPACE_VERSION_PATCH)
|
||||
set(OPENSPACE_VERSION_STRING)
|
||||
|
||||
include(${PROJECT_SOURCE_DIR}/support/cmake/module_common.cmake)
|
||||
include(${PROJECT_SOURCE_DIR}/ext/ghoul/support/cmake/message_macros.cmake)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2022 #
|
||||
# Copyright (c) 2014-2025 #
|
||||
# #
|
||||
# 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 #
|
||||
@@ -22,7 +22,6 @@
|
||||
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #
|
||||
##########################################################################################
|
||||
|
||||
include(${PROJECT_SOURCE_DIR}/ext/ghoul/support/cmake/copy_shared_libraries.cmake)
|
||||
include(${PROJECT_SOURCE_DIR}/support/cmake/application_definition.cmake)
|
||||
include(${PROJECT_SOURCE_DIR}/support/cmake/global_variables.cmake)
|
||||
|
||||
@@ -50,7 +49,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 PUBLIC openspace-core MinVR)
|
||||
target_link_libraries(OpenSpace-MinVR PUBLIC openspace-core openspace-module-collection MinVR)
|
||||
|
||||
# Web Browser and Web gui
|
||||
# Why not put these in the module's path? Because they do not have access to the
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <openspace/engine/configuration.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/engine/settings.h>
|
||||
#include <openspace/engine/windowdelegate.h>
|
||||
#include <openspace/util/keys.h>
|
||||
#include <openspace/util/mouse.h>
|
||||
@@ -36,8 +37,8 @@
|
||||
#include <ghoul/logging/consolelog.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/logging/visualstudiooutputlog.h>
|
||||
#include <ghoul/opengl/ghoul_gl.h>
|
||||
#include <api/MinVR.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <numeric>
|
||||
|
||||
// @TODO: Add Spout support
|
||||
@@ -115,7 +116,7 @@ void Handler::onVREvent(const VRDataIndex& eventData) {
|
||||
const VRAnalogEvent& event = static_cast<const VRAnalogEvent&>(eventData);
|
||||
}
|
||||
else if (isButtonEvent) {
|
||||
if (!global::windowDelegate.isMaster()) {
|
||||
if (!global::windowDelegate->isMaster()) {
|
||||
return;
|
||||
}
|
||||
const VRButtonEvent& event = static_cast<const VRButtonEvent&>(eventData);
|
||||
@@ -130,7 +131,7 @@ void Handler::onVREvent(const VRDataIndex& eventData) {
|
||||
std::string keyName = buttonName.substr(beg, sep - beg);
|
||||
std::string actionName = buttonName.substr(sep + 1);
|
||||
|
||||
Key key = KeyMapping.find(keyName)->second;
|
||||
Key key = stringToKey(keyName).key;
|
||||
|
||||
KeyAction action;
|
||||
if (actionName == "Up") {
|
||||
@@ -157,12 +158,12 @@ void Handler::onVREvent(const VRDataIndex& eventData) {
|
||||
}
|
||||
|
||||
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;
|
||||
KM mod = KM::None;
|
||||
mod |= keyboardState.modifierShift ? KM::Shift : KM::None;
|
||||
mod |= keyboardState.modifierCtrl ? KM::Control : KM::None;
|
||||
mod |= keyboardState.modifierAlt ? KM::Alt : KM::None;
|
||||
|
||||
openspace::global::openSpaceEngine.keyboardCallback(key, mod, action);
|
||||
global::openSpaceEngine->keyboardCallback(key, mod, action, IsGuiWindow::Yes);
|
||||
}
|
||||
|
||||
if (buttonName.size() >= 8 && buttonName.substr(0, 8) == "MouseBtn") {
|
||||
@@ -203,24 +204,29 @@ void Handler::onVREvent(const VRDataIndex& eventData) {
|
||||
}
|
||||
|
||||
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;
|
||||
KM mod = KM::None;
|
||||
mod |= keyboardState.modifierShift ? KM::Shift : KM::None;
|
||||
mod |= keyboardState.modifierCtrl ? KM::Control : KM::None;
|
||||
mod |= keyboardState.modifierAlt ? KM::Alt : KM::None;
|
||||
|
||||
global::openSpaceEngine.mouseButtonCallback(button, action, mod);
|
||||
global::openSpaceEngine->mouseButtonCallback(
|
||||
button,
|
||||
action,
|
||||
mod,
|
||||
IsGuiWindow::Yes
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
else if (type == "CursorMove") {
|
||||
if (!global::windowDelegate.isMaster()) {
|
||||
if (!global::windowDelegate->isMaster()) {
|
||||
return;
|
||||
}
|
||||
const VRCursorEvent& event = static_cast<const VRCursorEvent&>(eventData);
|
||||
|
||||
const float* pos = event.getPos();
|
||||
windowingGlobals.mousePosition = glm::vec2(pos[0], pos[1]);
|
||||
openspace::global::openSpaceEngine.mousePositionCallback(pos[0], pos[1]);
|
||||
global::openSpaceEngine->mousePositionCallback(pos[0], pos[1], IsGuiWindow::Yes);
|
||||
|
||||
// @TODO(abock): Support mouse wheel
|
||||
//openspace::global::openSpaceEngine.mouseScrollWheelCallback(posX, posY);
|
||||
@@ -229,19 +235,19 @@ void Handler::onVREvent(const VRDataIndex& eventData) {
|
||||
const VRTrackerEvent& event = static_cast<const VRTrackerEvent&>(eventData);
|
||||
}
|
||||
else if (type == "OpenSpaceMessage") {
|
||||
if (global::windowDelegate.isMaster()) {
|
||||
if (global::windowDelegate->isMaster()) {
|
||||
// We don't want the message if we are the master as we already have the state
|
||||
return;
|
||||
}
|
||||
const int frameNumber = eventData.getValue("FrameNumber");
|
||||
const int nBytes = eventData.getValue("NBytes");
|
||||
std::vector<int> intData = eventData.getValue("SynchronizationData");
|
||||
char* data = reinterpret_cast<char*>(intData.data());
|
||||
std::byte* data = reinterpret_cast<std::byte*>(intData.data());
|
||||
|
||||
std::vector<char> synchronizationBuffer(nBytes);
|
||||
std::vector<std::byte> synchronizationBuffer(nBytes);
|
||||
std::copy(data, data + nBytes, synchronizationBuffer.begin());
|
||||
|
||||
global::openSpaceEngine.decode(std::move(synchronizationBuffer));
|
||||
global::openSpaceEngine->decode(std::move(synchronizationBuffer));
|
||||
}
|
||||
else {
|
||||
LERRORC("onVREvent()", std::format("Received an event of unknown type {}", type));
|
||||
@@ -263,7 +269,7 @@ void Handler::onVRRenderContext(const VRDataIndex& stateData) {
|
||||
windowingGlobals.framebufferSize.x = stateData.getValue("FramebufferWidth");
|
||||
windowingGlobals.framebufferSize.y = stateData.getValue("FramebufferHeight");
|
||||
|
||||
global::openSpaceEngine.initializeGL();
|
||||
global::openSpaceEngine->initializeGL();
|
||||
|
||||
HasInitializedGL = true;
|
||||
}
|
||||
@@ -279,14 +285,14 @@ void Handler::onVRRenderScene(const VRDataIndex& stateData) {
|
||||
glm::mat4 projectionMatrix = glm::make_mat4(state.getProjectionMatrix());
|
||||
glm::mat4 viewMatrix = glm::make_mat4(state.getViewMatrix());
|
||||
try {
|
||||
openspace::global::openSpaceEngine.render(
|
||||
openspace::global::openSpaceEngine->render(
|
||||
// @TODO(abock) we should probably use the user position here?
|
||||
glm::mat4(1.f),
|
||||
viewMatrix,
|
||||
projectionMatrix
|
||||
);
|
||||
openspace::global::openSpaceEngine.drawOverlays();
|
||||
openspace::global::openSpaceEngine.postDraw();
|
||||
openspace::global::openSpaceEngine->drawOverlays();
|
||||
openspace::global::openSpaceEngine->postDraw();
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
@@ -301,29 +307,22 @@ void Handler::appendNewInputEventsSinceLastCall(VRDataQueue* queue) {
|
||||
|
||||
void setupMinVrDelegateFunctions(VRMain& main) {
|
||||
// Sets up the OpenSpace WindowDelegate callback functions
|
||||
WindowDelegate& delegate = global::windowDelegate;
|
||||
WindowDelegate* delegate = global::windowDelegate;
|
||||
|
||||
delegate.nWindows = []() { return windowingGlobals.nWindows; };
|
||||
delegate.currentWindowSize = []() { return windowingGlobals.windowSize; };
|
||||
delegate.currentWindowResolution = delegate.currentWindowSize;
|
||||
delegate.currentDrawBufferResolution = delegate.currentWindowResolution;
|
||||
delegate.currentViewportSize = delegate.currentWindowResolution;
|
||||
delegate->nWindows = []() { return windowingGlobals.nWindows; };
|
||||
delegate->currentWindowSize = []() { return windowingGlobals.windowSize; };
|
||||
delegate->currentDrawBufferResolution = delegate->currentWindowSize;
|
||||
delegate->currentViewportSize = delegate->currentWindowSize;
|
||||
|
||||
delegate.averageDeltaTime = []() -> double {
|
||||
delegate->averageDeltaTime = []() -> double {
|
||||
return windowingGlobals.averageDeltatime;
|
||||
};
|
||||
delegate.deltaTime = []() -> double { return windowingGlobals.deltaTime; };
|
||||
delegate->deltaTime = []() -> double { return windowingGlobals.deltaTime; };
|
||||
|
||||
delegate.mousePosition = []() {
|
||||
return windowingGlobals.mousePosition;
|
||||
};
|
||||
delegate.mouseButtons = [](int) {
|
||||
return windowingGlobals.mouseButtons;
|
||||
};
|
||||
|
||||
delegate.isMaster = []() { return IsMasterNode; };
|
||||
delegate->isMaster = []() { return IsMasterNode; };
|
||||
|
||||
delegate.openGLProcedureAddress = [](const char* func) {
|
||||
delegate->openGLProcedureAddress = [](const char* func) {
|
||||
VRWindowToolkit* wtk = engine.getWindowToolkit("VRGLFWWindowToolkit");
|
||||
VRglproc procAddress = wtk->getProcAddress(func);
|
||||
return procAddress;
|
||||
@@ -348,12 +347,13 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
ghoul::initialize();
|
||||
global::create();
|
||||
|
||||
// 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(),
|
||||
absPath(argv[0]).parent_path(),
|
||||
ghoul::filesystem::FileSystem::Override::Yes
|
||||
);
|
||||
|
||||
@@ -362,22 +362,42 @@ int main(int argc, char** argv) {
|
||||
try {
|
||||
// Find configuration
|
||||
//std::string configurationFilePath = commandlineArguments.configurationName;
|
||||
//if (commandlineArguments.configurationName.empty()) {
|
||||
LDEBUG("Finding configuration");
|
||||
std::string configurationFilePath = configuration::findConfiguration();
|
||||
//}
|
||||
std::filesystem::path configurationFilePath = findConfiguration();
|
||||
configurationFilePath = absPath(configurationFilePath);
|
||||
|
||||
if (!FileSys.fileExists(configurationFilePath)) {
|
||||
LFATALC("main", "Could not find configuration: " + configurationFilePath);
|
||||
if (!std::filesystem::exists(configurationFilePath)) {
|
||||
LFATALC(
|
||||
"main",
|
||||
std::format("Could not find configuration: {}", configurationFilePath)
|
||||
);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
LINFO(std::format("Configuration Path: '{}'", configurationFilePath));
|
||||
|
||||
// Register the base path as the directory where the configuration file lives
|
||||
std::filesystem::path base = configurationFilePath.parent_path();
|
||||
FileSys.registerPathToken("${BASE}", std::move(base));
|
||||
|
||||
#ifdef WIN32
|
||||
glm::ivec2 size = glm::ivec2(1920, 1080);
|
||||
DEVMODEW dm = { 0 };
|
||||
dm.dmSize = sizeof(DEVMODEW);
|
||||
BOOL success = EnumDisplaySettingsW(nullptr, ENUM_CURRENT_SETTINGS, &dm);
|
||||
if (success) {
|
||||
size.x = dm.dmPelsWidth;
|
||||
size.y = dm.dmPelsHeight;
|
||||
}
|
||||
#else // ^^^^ WIN32 // !WIN32 vvvv
|
||||
const glm::ivec2 size = glm::ivec2(1920, 1080);
|
||||
#endif // WIN32
|
||||
|
||||
// Loading configuration from disk
|
||||
LDEBUG("Loading configuration from disk");
|
||||
global::configuration = configuration::loadConfigurationFromFile(
|
||||
configurationFilePath
|
||||
*global::configuration = loadConfigurationFromFile(
|
||||
configurationFilePath,
|
||||
findSettings(),
|
||||
size
|
||||
);
|
||||
|
||||
// If the user requested a commandline-based configuation script that should
|
||||
@@ -393,9 +413,9 @@ int main(int argc, char** argv) {
|
||||
//}
|
||||
|
||||
// Determining MinVR configuration file
|
||||
LDEBUG("MinVR Configuration file: " + global::configuration.windowConfiguration);
|
||||
LDEBUG("MinVR Configuration file: " + global::configuration->windowConfiguration);
|
||||
|
||||
windowConfiguration = global::configuration.windowConfiguration;
|
||||
windowConfiguration = global::configuration->windowConfiguration;
|
||||
}
|
||||
catch (const documentation::SpecificationError& e) {
|
||||
LFATALC("main", "Loading of configuration file failed");
|
||||
@@ -416,12 +436,12 @@ int main(int argc, char** argv) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
global::openSpaceEngine.registerPathTokens();
|
||||
global::openSpaceEngine.initialize();
|
||||
global::openSpaceEngine->registerPathTokens();
|
||||
global::openSpaceEngine->initialize();
|
||||
|
||||
engine.addEventHandler(&handler);
|
||||
engine.addRenderHandler(&handler);
|
||||
engine.loadConfig(global::configuration.windowConfiguration);
|
||||
engine.loadConfig(global::configuration->windowConfiguration);
|
||||
// Yes, this still contains the OpenSpace-specific commandline arguments, but no one
|
||||
// will ever know if we use the remaining arguments or not; both commandline parsers
|
||||
// just ignore the arguments they don't understand
|
||||
@@ -432,7 +452,7 @@ int main(int argc, char** argv) {
|
||||
const std::string& name = engine.getName();
|
||||
IsMasterNode = (name == MasterNode);
|
||||
|
||||
if (global::windowDelegate.isMaster()) {
|
||||
if (global::windowDelegate->isMaster()) {
|
||||
engine.addInputDevice(&handler);
|
||||
}
|
||||
|
||||
@@ -460,10 +480,10 @@ int main(int argc, char** argv) {
|
||||
|
||||
|
||||
|
||||
global::openSpaceEngine.preSynchronization();
|
||||
global::openSpaceEngine->preSynchronization();
|
||||
|
||||
if (global::windowDelegate.isMaster()) {
|
||||
std::vector<char> syncBuffer = global::openSpaceEngine.encode();
|
||||
if (global::windowDelegate->isMaster()) {
|
||||
std::vector<std::byte> syncBuffer = global::openSpaceEngine->encode();
|
||||
VRDataIndex e("OpenSpace_Sync");
|
||||
|
||||
e.addData("EventType", "OpenSpaceMessage");
|
||||
@@ -489,7 +509,7 @@ int main(int argc, char** argv) {
|
||||
engine.updateAllModels();
|
||||
|
||||
// @TODO(abock): Not sure if this should be before updateAllModels or here
|
||||
global::openSpaceEngine.postSynchronizationPreDraw();
|
||||
global::openSpaceEngine->postSynchronizationPreDraw();
|
||||
|
||||
++FrameNumber;
|
||||
}
|
||||
@@ -497,12 +517,12 @@ int main(int argc, char** argv) {
|
||||
engine.renderOnAllDisplays();
|
||||
} while (!engine.getShutdown());
|
||||
|
||||
global::openSpaceEngine.deinitializeGL();
|
||||
global::openSpaceEngine->deinitializeGL();
|
||||
|
||||
// This assumes that `shutdown` destroys the OpenGL state and thus have to happen
|
||||
// after the deinitializeGL function
|
||||
engine.shutdown();
|
||||
global::openSpaceEngine.deinitialize();
|
||||
global::openSpaceEngine->deinitialize();
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -382,9 +382,7 @@ LauncherWindow::LauncherWindow(bool profileEnabled, const Configuration& globalC
|
||||
{
|
||||
QLabel* versionLabel = new QLabel(centralWidget);
|
||||
versionLabel->setVisible(true);
|
||||
versionLabel->setText(
|
||||
QString::fromStdString(std::string(OPENSPACE_VERSION_STRING_FULL))
|
||||
);
|
||||
versionLabel->setText(QString::fromStdString(std::string(OPENSPACE_VERSION)));
|
||||
versionLabel->setObjectName("version-info");
|
||||
versionLabel->setGeometry(geometry::VersionString);
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ NotificationWindow::NotificationWindow(QWidget* parent)
|
||||
std::string URL = std::format(
|
||||
"https://raw.githubusercontent.com/OpenSpace/Notifications/refs/heads/master/"
|
||||
"{}.txt",
|
||||
OPENSPACE_IS_RELEASE_BUILD ? OPENSPACE_VERSION_NUMBER : "master"
|
||||
OPENSPACE_IS_RELEASE_BUILD ? OPENSPACE_VERSION : "master"
|
||||
);
|
||||
|
||||
_request = std::make_unique<HttpMemoryDownload>(
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
local LockCurrent = {
|
||||
Identifier = "os.temporalLayer.LockCurrent",
|
||||
Name = "Lock Focus Node Temporal Layers",
|
||||
Command = [[
|
||||
local j2000 = openspace.time.currentTime()
|
||||
local dateTime = openspace.time.convertTime(j2000)
|
||||
local focusName = openspace.propertyValue("NavigationHandler.OrbitalNavigator.Anchor")
|
||||
openspace.setPropertyValue("Scene." .. focusName .. ".*.FixedTime", dateTime)
|
||||
openspace.setPropertyValue("Scene." .. focusName .. ".*.UseFixedTime", true)
|
||||
]],
|
||||
Documentation = [[Set fixed date for all temporal layers for the currently
|
||||
focused node.]],
|
||||
GuiPath = "/Solar System",
|
||||
IsLocal = false
|
||||
}
|
||||
|
||||
local UnlockCurrent = {
|
||||
Identifier = "os.temporalLayer.UnlockCurrent",
|
||||
Name = "Unlock Focus Node Temporal Layers",
|
||||
Command = [[
|
||||
local j2000 = openspace.time.currentTime()
|
||||
local dateTime = openspace.time.convertTime(j2000)
|
||||
local focusName = openspace.propertyValue("NavigationHandler.OrbitalNavigator.Anchor")
|
||||
openspace.setPropertyValue("Scene." .. focusName .. ".*.UseFixedTime", false)
|
||||
openspace.setPropertyValue("Scene." .. focusName .. ".*.FixedTime", "")
|
||||
]],
|
||||
Documentation = [[Removes fixed date for all temporal layers for the currently
|
||||
focused node.]],
|
||||
GuiPath = "/Solar System",
|
||||
IsLocal = false
|
||||
}
|
||||
|
||||
local LockAll = {
|
||||
Identifier = "os.temporalLayer.LockAll",
|
||||
Name = "Lock All Temporal Layers",
|
||||
Command = [[
|
||||
local j2000 = openspace.time.currentTime()
|
||||
local dateTime = openspace.time.convertTime(j2000)
|
||||
openspace.setPropertyValue("Scene.*.FixedTime", dateTime)
|
||||
openspace.setPropertyValue("Scene.*.UseFixedTime", true)
|
||||
]],
|
||||
Documentation = "Set fixed date for all temporal layers in the scene.",
|
||||
GuiPath = "/Solar System",
|
||||
IsLocal = false
|
||||
}
|
||||
|
||||
local UnlockAll = {
|
||||
Identifier = "os.temporalLayer.UnlockAll",
|
||||
Name = "Unlock All Temporal Layers",
|
||||
Command = [[
|
||||
openspace.setPropertyValue("Scene.*.UseFixedTime", false)
|
||||
openspace.setPropertyValue("Scene.*.FixedTime", "")
|
||||
]],
|
||||
Documentation = "Removes fixed date for all temporal layers in the scene.",
|
||||
GuiPath = "/Solar System",
|
||||
IsLocal = false
|
||||
}
|
||||
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.action.registerAction(LockCurrent);
|
||||
openspace.action.registerAction(UnlockCurrent);
|
||||
openspace.action.registerAction(LockAll);
|
||||
openspace.action.registerAction(UnlockAll);
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.action.removeAction(UnlockAll);
|
||||
openspace.action.removeAction(LockAll);
|
||||
openspace.action.removeAction(UnlockCurrent);
|
||||
openspace.action.removeAction(LockCurrent);
|
||||
end)
|
||||
|
||||
|
||||
asset.meta = {
|
||||
Name = "Temporal Layers - Lock Date",
|
||||
Version = "1.0",
|
||||
Description = [[Provides actions for locking and unlocking temporal layers to the
|
||||
current date.]],
|
||||
Author = "OpenSpace Team",
|
||||
URL = "http://openspaceproject.com",
|
||||
License = "MIT license"
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
local earth = asset.require("scene/solarsystem/planets/earth/earth")
|
||||
|
||||
|
||||
|
||||
-- These two files are downloaded from the servers when the asset gets loaded. Specifying
|
||||
-- these two URLs in this way will cause them to be downloaded into the same folder on the
|
||||
-- harddisk. For this example this is important as the points-relative.geojson will ask
|
||||
-- for the image.png in the same folder by specifying "./image.png"
|
||||
local data = asset.resource({
|
||||
Name = "GeoJSON Example Relative Texture Path",
|
||||
Type = "UrlSynchronization",
|
||||
Identifier = "geojson_example_points_relative_path",
|
||||
Url = {
|
||||
"http://liu-se.cdn.openspaceproject.com/files/examples/geojson/points-relative.geojson",
|
||||
"http://liu-se.cdn.openspaceproject.com/files/examples/geojson/image.png"
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
local ExamplePoints = {
|
||||
Identifier = "Points-Example-RelativeTexturePath",
|
||||
File = data .. "points-relative.geojson",
|
||||
HeightOffset = 20000.0,
|
||||
DefaultProperties = {
|
||||
PointSize = 10.0
|
||||
},
|
||||
Name = "Example Points (Relative Texture Path)"
|
||||
}
|
||||
|
||||
|
||||
asset.onInitialize(function()
|
||||
openspace.globebrowsing.addGeoJson(earth.Earth.Identifier, ExamplePoints)
|
||||
end)
|
||||
|
||||
asset.onDeinitialize(function()
|
||||
openspace.globebrowsing.deleteGeoJson(earth.Earth.Identifier, ExamplePoints)
|
||||
end)
|
||||
|
||||
asset.export(ExamplePoints)
|
||||
|
||||
|
||||
|
||||
asset.meta = {
|
||||
Name = "GeoJson Example - Points (Relative Texture Path)",
|
||||
Description = [[GeoJson example asset with points that are facing the camera
|
||||
(default). This example is using a relative path to specify the location of the image
|
||||
that is to be used.]],
|
||||
Author = "OpenSpace Team",
|
||||
URL = "http://openspaceproject.com",
|
||||
License = "MIT license"
|
||||
}
|
||||
+1
-2
@@ -15,8 +15,7 @@ local Layer = {
|
||||
Name = "LAMO [Local]",
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 5,
|
||||
FilePath = textures .. "ceres_lamo_4096x2048.png",
|
||||
CacheSettings = { Enabled = false }
|
||||
FilePath = textures .. "ceres_lamo_4096x2048.png"
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -51,8 +51,7 @@ local Charon = {
|
||||
"moon_major_pluto"
|
||||
},
|
||||
GUI = {
|
||||
Path = "/Solar System/Dwarf Planets/Pluto/Charon",
|
||||
Focusable = false
|
||||
Path = "/Solar System/Dwarf Planets/Pluto/Charon"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,8 +43,7 @@ asset.onInitialize(function()
|
||||
Description = "",
|
||||
FilePath = imagename,
|
||||
Enabled = false,
|
||||
ZIndex = 100,
|
||||
CacheSettings = { Enabled = false }
|
||||
ZIndex = 100
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
@@ -16,8 +16,7 @@ local Layer = {
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 5,
|
||||
FilePath = texturesPath .. "earth_bluemarble.jpg",
|
||||
Description = "Earth image from Blue Marble Next Generation",
|
||||
CacheSettings = { Enabled = false }
|
||||
Description = "Earth image from Blue Marble Next Generation"
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -21,8 +21,7 @@ local Layer = {
|
||||
Settings = {
|
||||
Multiplier = 40,
|
||||
Offset = -600
|
||||
},
|
||||
CacheSettings = { Enabled = false }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<BlockSizeY>512</BlockSizeY>
|
||||
<BandsCount>1</BandsCount>
|
||||
<DataType>Float32</DataType>
|
||||
<DataValues NoData="0" Min="-11000" Max="8500"/>
|
||||
<DataValues NoData="-3.40282347e+38" Min="-11000" Max="8500"/>
|
||||
<MaxConnections>5</MaxConnections>
|
||||
<ZeroBlockHttpCodes>404,400</ZeroBlockHttpCodes>
|
||||
</GDAL_WMS>
|
||||
|
||||
+1
-2
@@ -16,8 +16,7 @@ local Layer = {
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 5,
|
||||
FilePath = texturesPath .. "earth_night.png",
|
||||
Description = "Earth's city lights are clearly visible from space",
|
||||
CacheSettings = { Enabled = false }
|
||||
Description = "Earth's city lights are clearly visible from space"
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -16,8 +16,7 @@ local Layer = {
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 5,
|
||||
FilePath = texturesPath .. "WAC_GLOBAL_E000N0000_032P.png",
|
||||
Description = "Lower Resolution offline version of WAC layer",
|
||||
CacheSettings = { Enabled = false }
|
||||
Description = "Lower Resolution offline version of WAC layer"
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -31,8 +31,7 @@ local Layer = {
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 100,
|
||||
FilePath = syncedDirectory .. "4096.jpg",
|
||||
Description = Description,
|
||||
CacheSettings = { Enabled = false }
|
||||
Description = Description
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -14,8 +14,7 @@ local Layer = {
|
||||
Identifier = "Texture",
|
||||
FilePath = texturesPath .. "ganymede.jpg",
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 5,
|
||||
CacheSettings = { Enabled = false }
|
||||
ZIndex = 5
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -14,8 +14,7 @@ local Layer = {
|
||||
Identifier = "Texture",
|
||||
FilePath = texturesPath .. "io.jpg",
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 5,
|
||||
CacheSettings = { Enabled = false }
|
||||
ZIndex = 5
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -16,8 +16,7 @@ local Layer = {
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 5,
|
||||
FilePath = texturesPath .. "mars.png",
|
||||
Description = "Default jpg texture for Mars",
|
||||
CacheSettings = { Enabled = false }
|
||||
Description = "Default jpg texture for Mars"
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -16,8 +16,7 @@ local Layer = {
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 100,
|
||||
FilePath = texturesPath .. "alsimap_02122015.png",
|
||||
BlendMode = "Multiply",
|
||||
CacheSettings = { Enabled = false }
|
||||
BlendMode = "Multiply"
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -16,8 +16,7 @@ local Layer = {
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 100,
|
||||
FilePath = texturesPath .. "casimap_02122015.png",
|
||||
BlendMode = "Multiply",
|
||||
CacheSettings = { Enabled = false }
|
||||
BlendMode = "Multiply"
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -16,8 +16,7 @@ local Layer = {
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 100,
|
||||
FilePath = texturesPath .. "fesimap_02122015.png",
|
||||
BlendMode = "Multiply",
|
||||
CacheSettings = { Enabled = false }
|
||||
BlendMode = "Multiply"
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -17,8 +17,7 @@ local Layer = {
|
||||
ZIndex = 5,
|
||||
Description = [[The Map Projected Basemap RDR (BDR) data set consists of a global
|
||||
monochrome map of reflectance at a resolution of 256 pixels per degree (~166 m/p).
|
||||
This is an offline version with lower resoution than the Messenger BDR layer.]],
|
||||
CacheSettings = { Enabled = false }
|
||||
This is an offline version with lower resoution than the Messenger BDR layer.]]
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -20,8 +20,7 @@ local Layer = {
|
||||
Gamma = 1.33,
|
||||
Multiplier = 1.15
|
||||
},
|
||||
BlendMode = "Multiply",
|
||||
CacheSettings = { Enabled = false }
|
||||
BlendMode = "Multiply"
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -16,8 +16,7 @@ local Layer = {
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 100,
|
||||
FilePath = texturesPath .. "ssimap_02122015.png",
|
||||
BlendMode = "Multiply",
|
||||
CacheSettings = { Enabled = false }
|
||||
BlendMode = "Multiply"
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -14,8 +14,7 @@ local Layer = {
|
||||
Identifier = "Texture",
|
||||
FilePath = texturesPath .. "neptune.jpg",
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 5,
|
||||
CacheSettings = { Enabled = false }
|
||||
ZIndex = 5
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -20,8 +20,7 @@ local Layer = {
|
||||
Triton. This map has a resolution of 1,970 feet (600 meters per pixel [m]). Color was
|
||||
synthesized by combining high-resolution images taken through orange, violet, and
|
||||
ultraviolet filters; these images were displayed as red, green, and blue images and
|
||||
combined to create this color version (Smith et al., 1989).]],
|
||||
CacheSettings = { Enabled = false }
|
||||
combined to create this color version (Smith et al., 1989).]]
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -14,8 +14,7 @@ local Layer = {
|
||||
Identifier = "Texture",
|
||||
FilePath = texturesPath .. "dione.jpg",
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 5,
|
||||
CacheSettings = { Enabled = false }
|
||||
ZIndex = 5
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -14,8 +14,7 @@ local Layer = {
|
||||
Identifier = "Texture",
|
||||
FilePath = texturesPath .. "enceladus.jpg",
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 5,
|
||||
CacheSettings = { Enabled = false }
|
||||
ZIndex = 5
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -14,8 +14,7 @@ local layer = {
|
||||
Identifier = "Texture",
|
||||
FilePath = texturesPath .. "iapetus.jpg",
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 5,
|
||||
CacheSettings = { Enabled = false }
|
||||
ZIndex = 5
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -14,8 +14,7 @@ local Layer = {
|
||||
Identifier = "Texture",
|
||||
FilePath = texturesPath .. "saturn.jpg",
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 5,
|
||||
CacheSettings = { Enabled = false }
|
||||
ZIndex = 5
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -14,8 +14,7 @@ local Layer = {
|
||||
Identifier = "Texture",
|
||||
FilePath = texturesPath .. "mimas.jpg",
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 5,
|
||||
CacheSettings = { Enabled = false }
|
||||
ZIndex = 5
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -14,8 +14,7 @@ local Layer = {
|
||||
Identifier = "Texture",
|
||||
FilePath = texturesPath .. "rhea.jpg",
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 5,
|
||||
CacheSettings = { Enabled = false }
|
||||
ZIndex = 5
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ local Saturn = {
|
||||
TextureUnlit = texturesPath .. "unlit_original_single.png",
|
||||
TextureColor = texturesPath .. "color_original_single.png",
|
||||
TextureTransparency = texturesPath .. "trans_original_single.png",
|
||||
ColorFilter = 0.8,
|
||||
ColorFilter = 0.9,
|
||||
|
||||
NightFactor = 1.0,
|
||||
Size = 140445000,
|
||||
|
||||
+1
-2
@@ -14,8 +14,7 @@ local Layer = {
|
||||
Identifier = "Texture",
|
||||
FilePath = texturesPath .. "tethys.jpg",
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 5,
|
||||
CacheSettings = { Enabled = false }
|
||||
ZIndex = 5
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -14,8 +14,7 @@ local Layer = {
|
||||
Identifier = "Texture",
|
||||
FilePath = texturesPath .. "uranus.jpg",
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 5,
|
||||
CacheSettings = { Enabled = false }
|
||||
ZIndex = 5
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -22,8 +22,7 @@ local Layer = {
|
||||
TileProvider = {
|
||||
Identifier = "Clouds",
|
||||
Name = "Clouds",
|
||||
FilePath = texturesPath .. "venus_clouds.jpg",
|
||||
CacheSettings = { Enabled = false }
|
||||
FilePath = texturesPath .. "venus_clouds.jpg"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
+1
-2
@@ -22,8 +22,7 @@ local Layer = {
|
||||
TileProvider = {
|
||||
Identifier = "Clouds",
|
||||
Name = "Clouds",
|
||||
FilePath = texturesPath .. "venus_clouds.jpg",
|
||||
CacheSettings = { Enabled = false }
|
||||
FilePath = texturesPath .. "venus_clouds.jpg"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -14,8 +14,7 @@ local Clouds = {
|
||||
Identifier = "Clouds",
|
||||
FilePath = texturesPath .. "venus_clouds.jpg",
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 20,
|
||||
CacheSettings = { Enabled = false }
|
||||
ZIndex = 20
|
||||
}
|
||||
|
||||
local Layer = {
|
||||
@@ -26,8 +25,7 @@ local Layer = {
|
||||
Settings = {
|
||||
Opacity = 0.48,
|
||||
Gamma = 0.48
|
||||
},
|
||||
CacheSettings = { Enabled = false }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -14,8 +14,7 @@ local Layer = {
|
||||
Identifier = "Texture",
|
||||
FilePath = texturesPath .. "sun.jpg",
|
||||
Enabled = asset.enabled,
|
||||
ZIndex = 5,
|
||||
CacheSettings = { Enabled = false }
|
||||
ZIndex = 5
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ local guiCustomization = asset.require("customization/gui")
|
||||
|
||||
|
||||
-- Select which commit hashes to use for the UI frontend
|
||||
local frontendHash = "8e0c43cc406cc56dea3c5e1f0b4c45b1216927a5"
|
||||
local frontendHash = "baabd171ecbe61b2758970a2cdafb43fbcd1a23b"
|
||||
|
||||
-- The name of the file to download from the server
|
||||
local frontendFile = "frontend.zip"
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"base_keybindings",
|
||||
"events/toggle_sun",
|
||||
"scene/solarsystem/planets/earth/earth",
|
||||
"scene/solarsystem/planets/earth/satellites/satellites"
|
||||
"scene/solarsystem/planets/earth/satellites/satellites",
|
||||
"scene/solarsystem/planets/earth/noaa-sos/overlays/latlon_grid-white"
|
||||
],
|
||||
"camera": {
|
||||
"altitude": 17000000.0,
|
||||
@@ -70,6 +71,11 @@
|
||||
"name": "{earth_satellites~space_stations}.Renderable.Enabled",
|
||||
"type": "setPropertyValue",
|
||||
"value": "false"
|
||||
},
|
||||
{
|
||||
"name": "Scene.Earth.Renderable.Layers.Overlays.noaa-sos-overlays-latlon_grid-white.Enabled",
|
||||
"type": "setPropertyValueSingle",
|
||||
"value": "false"
|
||||
}
|
||||
],
|
||||
"time": {
|
||||
@@ -81,4 +87,4 @@
|
||||
"major": 1,
|
||||
"minor": 4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ constexpr KeyModifier operator|(KeyModifier lhs, KeyModifier rhs) {
|
||||
return static_cast<KeyModifier>(
|
||||
static_cast<std::underlying_type_t<KeyModifier>>(lhs) |
|
||||
static_cast<std::underlying_type_t<KeyModifier>>(rhs)
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
constexpr KeyModifier operator|=(KeyModifier& lhs, KeyModifier rhs) {
|
||||
|
||||
@@ -201,8 +201,7 @@ function addExoplanetSystem(data)
|
||||
Identifier = "StarTexture",
|
||||
FilePath = openspace.absPath(starTexture),
|
||||
BlendMode = "Color",
|
||||
Enabled = true,
|
||||
CacheSettings = { Enabled = false }
|
||||
Enabled = true
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -211,8 +210,7 @@ function addExoplanetSystem(data)
|
||||
Identifier = "NoDataStarTexture",
|
||||
FilePath = openspace.absPath(starNoDataTexture),
|
||||
BlendMode = "Color",
|
||||
Enabled = true,
|
||||
CacheSettings = { Enabled = false }
|
||||
Enabled = true
|
||||
}
|
||||
}
|
||||
end
|
||||
@@ -506,8 +504,7 @@ function addExoplanetSystem(data)
|
||||
Identifier = "PlanetTexture",
|
||||
Name = "Planet Texture",
|
||||
FilePath = openspace.absPath(defaultPlanetTexture),
|
||||
Enabled = true,
|
||||
CacheSettings = { Enabled = false }
|
||||
Enabled = true
|
||||
}
|
||||
table.insert(planetColorLayers, PlanetTextureLayer)
|
||||
ambientIntensity = 0.15
|
||||
|
||||
@@ -496,8 +496,8 @@ bool GlobeBrowsingModule::hasDefaultGeoPointTexture() const {
|
||||
return _hasDefaultGeoPointTexture;
|
||||
}
|
||||
|
||||
std::string_view GlobeBrowsingModule::defaultGeoPointTexture() const {
|
||||
return _defaultGeoPointTexturePath;
|
||||
std::filesystem::path GlobeBrowsingModule::defaultGeoPointTexture() const {
|
||||
return _defaultGeoPointTexturePath.value();
|
||||
}
|
||||
|
||||
scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
|
||||
|
||||
@@ -90,7 +90,7 @@ public:
|
||||
std::string mrfCacheLocation() const;
|
||||
|
||||
bool hasDefaultGeoPointTexture() const;
|
||||
std::string_view defaultGeoPointTexture() const;
|
||||
std::filesystem::path defaultGeoPointTexture() const;
|
||||
|
||||
protected:
|
||||
void internalInitialize(const ghoul::Dictionary&) override;
|
||||
|
||||
@@ -34,11 +34,11 @@ in vec4 shadowCoords;
|
||||
in vec3 vs_normal;
|
||||
|
||||
uniform sampler2DShadow shadowMapTexture;
|
||||
uniform sampler1D ringTextureFwrd;
|
||||
uniform sampler1D ringTextureBckwrd;
|
||||
uniform sampler1D ringTextureUnlit;
|
||||
uniform sampler1D ringTextureColor;
|
||||
uniform sampler1D ringTextureTransparency;
|
||||
uniform sampler1D textureForwards;
|
||||
uniform sampler1D textureBackwards;
|
||||
uniform sampler1D textureUnlit;
|
||||
uniform sampler1D textureColor;
|
||||
uniform sampler1D textureTransparency;
|
||||
uniform vec2 textureOffset;
|
||||
uniform float colorFilterValue;
|
||||
uniform vec3 sunPosition;
|
||||
@@ -70,19 +70,19 @@ Fragment getFragment() {
|
||||
discard;
|
||||
}
|
||||
|
||||
vec4 colorBckwrd = texture(ringTextureBckwrd, texCoord);
|
||||
vec4 colorFwrd = texture(ringTextureFwrd, texCoord);
|
||||
vec4 colorMult = texture(ringTextureColor, texCoord);
|
||||
vec4 transparency = texture(ringTextureTransparency, texCoord);
|
||||
vec4 colorBckwrd = texture(textureBackwards, texCoord);
|
||||
vec4 colorFwrd = texture(textureForwards, texCoord);
|
||||
vec4 colorMult = texture(textureColor, texCoord);
|
||||
float transparency = 1.0 - texture(textureTransparency, texCoord).r;
|
||||
|
||||
float lerpFactor = dot(camPositionObj, sunPositionObj);
|
||||
|
||||
// Jon Colors:
|
||||
//vec4 diffuse = mix(colorFwrd * vec4(1, 0.88, 0.82, 1.0), colorBckwrd * vec4(1, 0.88, 0.82, 1.0), lerpFactor);
|
||||
vec4 diffuse = mix(colorFwrd * colorMult, colorBckwrd * colorMult, lerpFactor);
|
||||
diffuse.a = colorFilterValue * transparency.a;
|
||||
vec4 diffuse = mix(colorFwrd, colorBckwrd, lerpFactor) * colorMult;
|
||||
diffuse.a = colorFilterValue * transparency;
|
||||
float colorValue = length(diffuse.rgb) / 0.57735026919;
|
||||
if (colorValue < 0.1) {
|
||||
if (colorValue < 0.001) {
|
||||
discard;
|
||||
}
|
||||
|
||||
@@ -103,10 +103,10 @@ Fragment getFragment() {
|
||||
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( 0, NSSamples - #{i}));
|
||||
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( NSSamples - #{i}, -NSSamples + #{i}));
|
||||
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( NSSamples - #{i}, 0));
|
||||
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( NSSamples - #{i}, NSSamples - #{i}));
|
||||
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(NSSamples - #{i}, NSSamples - #{i}));
|
||||
#endfor
|
||||
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(0, 0));
|
||||
shadow = clamp(sum / (8.0 * NSSamples + 1.f), 0.35, 1.0);
|
||||
shadow = clamp(sum / (8.0 * NSSamples + 1.f), 0.05, 1.0);
|
||||
}
|
||||
|
||||
// The normal for the one plane depends on whether we are dealing
|
||||
@@ -119,13 +119,13 @@ Fragment getFragment() {
|
||||
// if we are facing away from the Sun
|
||||
if (dot(sunPosition, normal) < 0.0) {
|
||||
diffuse.xyz =
|
||||
vec3(1.0, 0.97075, 0.952) * texture(ringTextureUnlit, texCoord).xyz * nightFactor;
|
||||
vec3(1.0, 0.97075, 0.952) * texture(textureUnlit, texCoord).xyz * nightFactor;
|
||||
}
|
||||
|
||||
Fragment frag;
|
||||
|
||||
frag.color = diffuse * shadow;
|
||||
frag.color.a *= opacity;
|
||||
frag.color.a = frag.color.a * opacity + (1.0 - shadow) * 0.5;
|
||||
frag.depth = vs_screenSpaceDepth;
|
||||
frag.gPosition = vec4(1e30, 1e30, 1e30, 1.0);
|
||||
frag.gNormal = vec4(normal, 1.0);
|
||||
|
||||
@@ -37,25 +37,20 @@ out vec2 fs_uv;
|
||||
out vec3 ellipsoidNormalCameraSpace;
|
||||
out vec3 levelWeights;
|
||||
out vec3 positionCameraSpace;
|
||||
out vec3 posObjSpace;
|
||||
out vec3 normalObjSpace;
|
||||
|
||||
#if USE_ACCURATE_NORMALS
|
||||
out vec3 ellipsoidTangentThetaCameraSpace;
|
||||
out vec3 ellipsoidTangentPhiCameraSpace;
|
||||
#endif // USE_ACCURATE_NORMALS
|
||||
|
||||
uniform dmat4 modelTransform;
|
||||
|
||||
#if USE_ECLIPSE_SHADOWS
|
||||
out vec3 positionWorldSpace;
|
||||
uniform dmat4 modelTransform;
|
||||
#endif // USE_ECLIPSE_SHADOWS
|
||||
|
||||
#if SHADOW_MAPPING_ENABLED
|
||||
// ShadowMatrix is the matrix defined by:
|
||||
// textureCoordsMatrix * projectionMatrix * combinedViewMatrix * modelMatrix
|
||||
// where textureCoordsMatrix is just a scale and bias computation: [-1,1] to [0,1]
|
||||
uniform dmat4 shadowMatrix;
|
||||
out vec4 shadowCoords;
|
||||
#endif // SHADOW_MAPPING_ENABLED
|
||||
|
||||
uniform mat4 modelViewProjectionTransform;
|
||||
uniform mat4 modelViewTransform;
|
||||
uniform vec3 radiiSquared;
|
||||
@@ -134,12 +129,10 @@ void main() {
|
||||
gl_Position = fs_position;
|
||||
ellipsoidNormalCameraSpace = mat3(modelViewTransform) * pair.normal;
|
||||
positionCameraSpace = vec3(modelViewTransform * vec4(pair.position, 1.0));
|
||||
posObjSpace = pair.position;
|
||||
normalObjSpace = pair.normal;
|
||||
|
||||
#if USE_ECLIPSE_SHADOWS
|
||||
positionWorldSpace = vec3(modelTransform * dvec4(pair.position, 1.0));
|
||||
#endif // USE_ECLIPSE_SHADOWS
|
||||
|
||||
#if SHADOW_MAPPING_ENABLED
|
||||
shadowCoords = vec4(shadowMatrix * dvec4(pair.position, 1.0));
|
||||
#endif // SHADOW_MAPPING_ENABLED
|
||||
}
|
||||
|
||||
@@ -37,24 +37,21 @@ out vec4 fs_position;
|
||||
out vec3 ellipsoidNormalCameraSpace;
|
||||
out vec3 levelWeights;
|
||||
out vec3 positionCameraSpace;
|
||||
out vec3 posObjSpace;
|
||||
out vec3 normalObjSpace;
|
||||
|
||||
#if USE_ACCURATE_NORMALS
|
||||
out vec3 ellipsoidTangentThetaCameraSpace;
|
||||
out vec3 ellipsoidTangentPhiCameraSpace;
|
||||
#endif // USE_ACCURATE_NORMALS
|
||||
|
||||
#if USE_ECLIPSE_SHADOWS
|
||||
out vec3 positionWorldSpace;
|
||||
uniform dmat4 inverseViewTransform;
|
||||
#endif // USE_ECLIPSE_SHADOWS
|
||||
uniform dmat4 modelTransform;
|
||||
|
||||
#if SHADOW_MAPPING_ENABLED
|
||||
// ShadowMatrix is the matrix defined by:
|
||||
// textureCoordsMatrix * projectionMatrix * combinedViewMatrix * modelMatrix
|
||||
// where textureCoordsMatrix is just a scale and bias computation: [-1,1] to [0,1]
|
||||
uniform dmat4 shadowMatrix;
|
||||
out vec4 shadowCoords;
|
||||
#endif // SHADOW_MAPPING_ENABLED
|
||||
#if USE_ECLIPSE_SHADOWS
|
||||
// Position in world space
|
||||
out vec3 positionWorldSpace;
|
||||
#endif // USE_ECLIPSE_SHADOWS
|
||||
|
||||
uniform mat4 projectionTransform;
|
||||
// Input points in camera space
|
||||
@@ -118,12 +115,9 @@ void main() {
|
||||
gl_Position = fs_position;
|
||||
ellipsoidNormalCameraSpace = patchNormalCameraSpace;
|
||||
positionCameraSpace = p;
|
||||
posObjSpace = vec3(inverseViewTransform * dvec4(p, 1.0));
|
||||
|
||||
#if USE_ECLIPSE_SHADOWS
|
||||
positionWorldSpace = vec3(inverseViewTransform * dvec4(p, 1.0));
|
||||
positionWorldSpace = vec3(modelTransform * dvec4(p, 1.0));
|
||||
#endif // USE_ECLIPSE_SHADOWS
|
||||
|
||||
#if SHADOW_MAPPING_ENABLED
|
||||
shadowCoords = vec4(shadowMatrix * dvec4(p, 1.0));
|
||||
#endif // SHADOW_MAPPING_ENABLED
|
||||
}
|
||||
|
||||
@@ -52,6 +52,9 @@ uniform vec2 vertexResolution;
|
||||
#endif // SHOW_HEIGHT_RESOLUTION
|
||||
|
||||
uniform vec3 lightDirectionCameraSpace;
|
||||
uniform vec3 lightDirectionObjSpace;
|
||||
uniform mat4 modelViewTransform;
|
||||
uniform float ringSize;
|
||||
|
||||
#if PERFORM_SHADING
|
||||
uniform float orenNayarRoughness;
|
||||
@@ -59,13 +62,16 @@ uniform float ambientIntensity;
|
||||
#endif // PERFORM_SHADING
|
||||
|
||||
#if SHADOW_MAPPING_ENABLED
|
||||
#if USE_RING_SHADOWS
|
||||
// Fragment position in object space
|
||||
in vec3 posObjSpace;
|
||||
|
||||
#define NSSamplesMinusOne #{nShadowSamples}
|
||||
#define NSSamples (NSSamplesMinusOne + 1)
|
||||
|
||||
in vec4 shadowCoords;
|
||||
uniform sampler2DShadow shadowMapTexture;
|
||||
uniform float zFightingPercentage;
|
||||
// Color of the rings
|
||||
uniform sampler1D ringTextureColor;
|
||||
// Transparency of the rings
|
||||
uniform sampler1D ringTextureTransparency;
|
||||
uniform vec2 textureOffset;
|
||||
#endif // USE_RING_SHADOWS
|
||||
#endif // SHADOW_MAPPING_ENABLED
|
||||
|
||||
#if USE_ECLIPSE_SHADOWS
|
||||
@@ -137,11 +143,29 @@ vec4 calcShadow(const ShadowRenderingStruct shadowInfoArray[NSEclipseShadows],
|
||||
}
|
||||
#endif
|
||||
|
||||
float rayPlaneIntersection(vec3 rayOrigin, vec3 rayDirection, vec3 planePoint,
|
||||
vec3 planeNormal)
|
||||
{
|
||||
float denom = dot(planeNormal, rayDirection);
|
||||
|
||||
// Check if ray is parallel to plane (or nearly parallel)
|
||||
if (abs(denom) < 1e-6) {
|
||||
return -1.0; // No intersection or ray lies in plane
|
||||
}
|
||||
|
||||
vec3 p0l0 = planePoint - rayOrigin;
|
||||
float t = dot(p0l0, planeNormal) / denom;
|
||||
|
||||
// Return negative if intersection is behind ray origin
|
||||
return t >= 0.0 ? t : -1.0;
|
||||
}
|
||||
|
||||
in vec4 fs_position;
|
||||
in vec2 fs_uv;
|
||||
in vec3 ellipsoidNormalCameraSpace;
|
||||
in vec3 levelWeights;
|
||||
in vec3 positionCameraSpace;
|
||||
in vec3 normalObjSpace;
|
||||
|
||||
#if USE_ACCURATE_NORMALS
|
||||
in vec3 ellipsoidTangentThetaCameraSpace;
|
||||
@@ -149,7 +173,7 @@ in vec3 positionCameraSpace;
|
||||
#endif // USE_ACCURATE_NORMALS
|
||||
|
||||
#if USE_ECLIPSE_SHADOWS
|
||||
in vec3 positionWorldSpace;
|
||||
in vec3 positionWorldSpace;
|
||||
#endif // USE_ECLIPSE_SHADOWS
|
||||
|
||||
uniform float opacity;
|
||||
@@ -201,6 +225,7 @@ Fragment getFragment() {
|
||||
#endif // USE_NIGHTTEXTURE
|
||||
|
||||
#if PERFORM_SHADING
|
||||
vec3 preShadedColor = frag.color.rgb;
|
||||
frag.color = calculateShadedColor(
|
||||
frag.color,
|
||||
normal,
|
||||
@@ -268,29 +293,47 @@ Fragment getFragment() {
|
||||
#endif // SHOW_CHUNK_EDGES
|
||||
|
||||
#if SHADOW_MAPPING_ENABLED
|
||||
// 0.0 is full shadow, 1.0 is no shadow
|
||||
float shadow = 1.0;
|
||||
if (shadowCoords.w > 1) {
|
||||
vec4 normalizedShadowCoords = shadowCoords;
|
||||
normalizedShadowCoords.z = normalizeFloat(zFightingPercentage * normalizedShadowCoords.w);
|
||||
normalizedShadowCoords.xy = normalizedShadowCoords.xy / normalizedShadowCoords.w;
|
||||
normalizedShadowCoords.w = 1.0;
|
||||
// Light through rings is colored, default full white
|
||||
vec3 lightColor = vec3(1.0);
|
||||
|
||||
#if USE_RING_SHADOWS
|
||||
// Calculate ring shadow by projecting ring texture directly onto surface
|
||||
// Assume ring lies in the XZ plane (Y=0) in object space
|
||||
vec3 surfaceToSun = -normalize(lightDirectionObjSpace); // Use world coordinates
|
||||
vec3 p = posObjSpace;
|
||||
vec3 ringPlaneNormal = vec3(0.0, 0.0, 1.0);
|
||||
|
||||
if (abs(surfaceToSun.y) > 1e-8 && dot(normalObjSpace, lightDirectionObjSpace) < 0.0) {
|
||||
float t = rayPlaneIntersection(p, surfaceToSun, vec3(0.0), ringPlaneNormal);
|
||||
|
||||
vec3 ringIntersection = p + t * surfaceToSun;
|
||||
|
||||
// Calculate distance from ring center
|
||||
float tx = length(ringIntersection.xy) / ringSize;
|
||||
// See advanced_rings_fs.glsl for explanation of textureOffset
|
||||
float texCoord = (tx - textureOffset.x) / (textureOffset.y - textureOffset.x);
|
||||
|
||||
float sum = 0;
|
||||
#for i in 0..#{nShadowSamples}
|
||||
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(-NSSamples + #{i}, -NSSamples + #{i}));
|
||||
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(-NSSamples + #{i}, 0));
|
||||
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(-NSSamples + #{i}, NSSamples - #{i}));
|
||||
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( 0, -NSSamples + #{i}));
|
||||
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( 0, NSSamples - #{i}));
|
||||
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( NSSamples - #{i}, -NSSamples + #{i}));
|
||||
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( NSSamples - #{i}, 0));
|
||||
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2( NSSamples - #{i}, NSSamples - #{i}));
|
||||
#endfor
|
||||
sum += textureProjOffset(shadowMapTexture, normalizedShadowCoords, ivec2(0, 0));
|
||||
shadow = sum / (8.0 * NSSamples + 1.f);
|
||||
}
|
||||
frag.color.xyz *= shadow < 0.99 ? clamp(shadow + 0.3, 0.0, 1.0) : shadow;
|
||||
#endif
|
||||
if (texCoord >= 0.0 && texCoord <= 1.0) {
|
||||
// Sample ring transparency texture
|
||||
float ringOpacity = texture(ringTextureTransparency, texCoord).r;
|
||||
|
||||
// Increase the shadow darkness factor with low angle to simulate the light having
|
||||
// to pass through more material
|
||||
float angleFactor = clamp(abs(-dot(ringPlaneNormal, surfaceToSun)) / 2.0, 0.0, 0.3);
|
||||
// Calculate shadow factor based on ring opacity
|
||||
shadow = clamp(ringOpacity + angleFactor, 0.05, 1.0);
|
||||
lightColor = texture(ringTextureColor, texCoord).rgb;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_RING_SHADOWS
|
||||
|
||||
// Blend the light color passing through the rings with the pre-shaded color
|
||||
frag.color.rgb = mix(preShadedColor * lightColor * ambientIntensity, frag.color.rgb, shadow);
|
||||
|
||||
#endif // SHADOW_MAPPING_ENABLED
|
||||
|
||||
frag.color.a *= opacity;
|
||||
frag.color = clamp(frag.color, 0.0, 1.0);
|
||||
|
||||
@@ -64,7 +64,11 @@
|
||||
#define SHOW_CHUNK_EDGES #{showChunkEdges}
|
||||
#define SHOW_HEIGHT_RESOLUTION #{showHeightResolution}
|
||||
#define SHOW_HEIGHT_INTENSITIES #{showHeightIntensities}
|
||||
|
||||
// Show shadow from globe onto rings
|
||||
#define SHADOW_MAPPING_ENABLED #{enableShadowMapping}
|
||||
// Show shadow from rings onto globe
|
||||
#define USE_RING_SHADOWS #{useRingShadows}
|
||||
|
||||
const vec3 DefaultLevelWeights = vec3(1.0, 0.0, 0.0);
|
||||
|
||||
|
||||
@@ -587,7 +587,7 @@ void GeoJsonComponent::update() {
|
||||
}
|
||||
|
||||
void GeoJsonComponent::readFile() {
|
||||
std::ifstream file(_geoJsonFile);
|
||||
std::ifstream file = std::ifstream(_geoJsonFile);
|
||||
|
||||
if (!file.good()) {
|
||||
LERROR(std::format("Failed to open GeoJSON file: {}", _geoJsonFile.value()));
|
||||
@@ -601,6 +601,14 @@ void GeoJsonComponent::readFile() {
|
||||
std::istreambuf_iterator<char>()
|
||||
);
|
||||
|
||||
// For the loading, we want to assume that the current working directory is where the
|
||||
// GeoJSON file is located
|
||||
const std::filesystem::path cwd = std::filesystem::current_path();
|
||||
std::filesystem::path jsonDir =
|
||||
std::filesystem::path(_geoJsonFile.value()).parent_path();
|
||||
std::filesystem::current_path(jsonDir);
|
||||
defer { std::filesystem::current_path(cwd); };
|
||||
|
||||
// Parse GeoJSON string into GeoJSON objects
|
||||
try {
|
||||
const geos::io::GeoJSONReader reader;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <modules/globebrowsing/src/renderableglobe.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <geos/io/GeoJSON.h>
|
||||
#include <scn/scan.h>
|
||||
@@ -527,7 +528,8 @@ GeoJsonOverrideProperties propsFromGeoJson(const geos::io::GeoJSONFeature& featu
|
||||
result.pointSize = static_cast<float>(value.getNumber());
|
||||
}
|
||||
else if (keyMatches(key, propertykeys::Texture, PointTextureInfo)) {
|
||||
result.pointTexture = value.getString();
|
||||
std::string texture = value.getString();
|
||||
result.pointTexture = absPath(texture);
|
||||
}
|
||||
else if (keyMatches(key, propertykeys::PointTextureAnchor, PointAnchorOptionInfo))
|
||||
{
|
||||
@@ -628,8 +630,8 @@ float PropertySet::pointSize() const {
|
||||
return overrideValues.pointSize.value_or(defaultValues.pointSize);
|
||||
}
|
||||
|
||||
std::string PropertySet::pointTexture() const {
|
||||
return overrideValues.pointTexture.value_or(defaultValues.pointTexture);
|
||||
std::filesystem::path PropertySet::pointTexture() const {
|
||||
return overrideValues.pointTexture.value_or(defaultValues.pointTexture.value());
|
||||
}
|
||||
|
||||
GeoJsonProperties::PointTextureAnchor PropertySet::pointTextureAnchor() const {
|
||||
|
||||
@@ -107,7 +107,7 @@ struct GeoJsonOverrideProperties {
|
||||
std::optional<float> lineWidth;
|
||||
|
||||
std::optional<float> pointSize;
|
||||
std::optional<std::string> pointTexture;
|
||||
std::optional<std::filesystem::path> pointTexture;
|
||||
std::optional<GeoJsonProperties::PointTextureAnchor> pointTextureAnchor;
|
||||
|
||||
std::optional<bool> extrude;
|
||||
@@ -135,7 +135,7 @@ struct PropertySet {
|
||||
float lineWidth() const;
|
||||
|
||||
float pointSize() const;
|
||||
std::string pointTexture() const;
|
||||
std::filesystem::path pointTexture() const;
|
||||
GeoJsonProperties::PointTextureAnchor pointTextureAnchor() const;
|
||||
|
||||
bool extrude() const;
|
||||
|
||||
@@ -115,7 +115,7 @@ bool GlobeGeometryFeature::useHeightMap() const {
|
||||
}
|
||||
|
||||
void GlobeGeometryFeature::updateTexture(bool isInitializeStep) {
|
||||
std::string texture;
|
||||
std::filesystem::path texture;
|
||||
GlobeBrowsingModule* m = global::moduleEngine->module<GlobeBrowsingModule>();
|
||||
|
||||
if (!isInitializeStep && _properties.hasOverrideTexture()) {
|
||||
@@ -144,15 +144,14 @@ void GlobeGeometryFeature::updateTexture(bool isInitializeStep) {
|
||||
_pointTexture->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToEdge);
|
||||
}
|
||||
|
||||
std::filesystem::path texturePath = absPath(texture);
|
||||
if (std::filesystem::is_regular_file(texturePath)) {
|
||||
if (std::filesystem::is_regular_file(texture)) {
|
||||
_hasTexture = true;
|
||||
_pointTexture->loadFromFile(texture);
|
||||
_pointTexture->uploadToGpu();
|
||||
}
|
||||
else {
|
||||
LERROR(std::format(
|
||||
"Trying to use texture file that does not exist: {}", texturePath
|
||||
"Trying to use texture file that does not exist: {}", texture
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,7 +266,7 @@ std::optional<std::string> RawTileDataReader::mrfCache() {
|
||||
// We don't support these formats as they will typically lack
|
||||
// crucial imformation such as GeoTags. It also makes little sense to
|
||||
// cache them as they are already local files.
|
||||
// If it is crucial to cache a dataset of this type, convert it to geotiff.
|
||||
// If it is crucial to cache a dataset of this type, convert it to GeoTIFF.
|
||||
constexpr std::array<std::string_view, 11> Unsupported = {
|
||||
"jpeg", "jpg",
|
||||
"png",
|
||||
@@ -281,10 +281,6 @@ std::optional<std::string> RawTileDataReader::mrfCache() {
|
||||
|
||||
for (std::string_view fmt : Unsupported) {
|
||||
if (_datasetFilePath.ends_with(fmt)) {
|
||||
LWARNING(std::format(
|
||||
"Unsupported file format for MRF caching: '{}', Dataset: '{}'",
|
||||
fmt, _datasetFilePath
|
||||
));
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -773,7 +773,24 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
|
||||
_ringsComponent = std::make_unique<RingsComponent>(*p.rings);
|
||||
_ringsComponent->setParentFadeable(this);
|
||||
_ringsComponent->initialize();
|
||||
_ringsComponent->onReadinessChange([this]() {
|
||||
_shadersNeedRecompilation = true;
|
||||
});
|
||||
addPropertySubOwner(_ringsComponent.get());
|
||||
|
||||
auto* enabledProperty = static_cast<properties::BoolProperty*>(
|
||||
_ringsComponent->property("Enabled")
|
||||
);
|
||||
if (enabledProperty) {
|
||||
enabledProperty->onChange([this]() {
|
||||
_shadersNeedRecompilation = true;
|
||||
});
|
||||
}
|
||||
|
||||
// Set up notification for shader recompilation when rings readiness changes
|
||||
_ringsComponent->onReadinessChange([this]() {
|
||||
_shadersNeedRecompilation = true;
|
||||
});
|
||||
}
|
||||
|
||||
if (p.shadows.has_value()) {
|
||||
@@ -865,15 +882,8 @@ void RenderableGlobe::render(const RenderData& data, RendererTasks& rendererTask
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
// Render from light source point of view
|
||||
// (Rings are skipped because the shadow is drawn directly onto the globe)
|
||||
renderChunks(lightRenderData, rendererTask, {}, true);
|
||||
if (_ringsComponent && _ringsComponent->isEnabled() &&
|
||||
_ringsComponent->isVisible())
|
||||
{
|
||||
_ringsComponent->draw(
|
||||
lightRenderData,
|
||||
RingsComponent::RenderPass::GeometryOnly
|
||||
);
|
||||
}
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
@@ -884,11 +894,7 @@ void RenderableGlobe::render(const RenderData& data, RendererTasks& rendererTask
|
||||
if (_ringsComponent && _ringsComponent->isEnabled() &&
|
||||
_ringsComponent->isVisible())
|
||||
{
|
||||
_ringsComponent->draw(
|
||||
data,
|
||||
RingsComponent::RenderPass::GeometryAndShading,
|
||||
_shadowComponent->shadowMapData()
|
||||
);
|
||||
_ringsComponent->draw(data, _shadowComponent->shadowMapData());
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -896,10 +902,7 @@ void RenderableGlobe::render(const RenderData& data, RendererTasks& rendererTask
|
||||
if (_ringsComponent && _ringsComponent->isEnabled() &&
|
||||
_ringsComponent->isVisible())
|
||||
{
|
||||
_ringsComponent->draw(
|
||||
data,
|
||||
RingsComponent::RenderPass::GeometryAndShading
|
||||
);
|
||||
_ringsComponent->draw(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1247,24 +1250,14 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
|
||||
const bool waterLayersActive =
|
||||
!_layerManager.layerGroup(Group::ID::WaterMasks).activeLayers().empty();
|
||||
|
||||
if (nightLayersActive || waterLayersActive || _performShading) {
|
||||
const glm::dvec3 directionToSunWorldSpace =
|
||||
directionToLightSource(data.modelTransform.translation, _lightSourceNode);
|
||||
|
||||
const glm::vec3 directionToSunCameraSpace = glm::vec3(viewTransform *
|
||||
glm::dvec4(directionToSunWorldSpace, 0));
|
||||
// @TODO (abock, 2020-04-14); This is just a bandaid for issue #1136. The better
|
||||
// way is to figure out with the uniform is optimized away. I assume that it is
|
||||
// because the shader doesn't get recompiled when the last layer of the night
|
||||
// or water is disabled; so the shader thinks it has to do the calculation, but
|
||||
// there are actually no layers left
|
||||
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
|
||||
_localRenderer.program->setIgnoreUniformLocationError(IgnoreError::Yes);
|
||||
if (_useAccurateNormals && hasHeightLayer) {
|
||||
// Apply an extra scaling to the height if the object is scaled
|
||||
_localRenderer.program->setUniform(
|
||||
"lightDirectionCameraSpace",
|
||||
-glm::normalize(directionToSunCameraSpace)
|
||||
"heightScale",
|
||||
static_cast<float>(
|
||||
glm::compMax(data.modelTransform.scale) * data.camera.scaling()
|
||||
)
|
||||
);
|
||||
_localRenderer.program->setIgnoreUniformLocationError(IgnoreError::Yes);
|
||||
}
|
||||
|
||||
// Local shader
|
||||
@@ -1273,24 +1266,35 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
|
||||
data.camera.sgctInternal.projectionMatrix()
|
||||
);
|
||||
|
||||
// Light direction uniforms, only used in fragment shader
|
||||
if (nightLayersActive || waterLayersActive || _performShading) {
|
||||
const glm::dvec3 directionToSunWorldSpace =
|
||||
directionToLightSource(data.modelTransform.translation, _lightSourceNode);
|
||||
const glm::vec3 directionToSunCameraSpace(viewTransform *
|
||||
glm::dvec4(directionToSunWorldSpace, 0.0));
|
||||
const glm::vec3 directionToSunObjSpace(_cachedInverseModelTransform *
|
||||
glm::dvec4(directionToSunWorldSpace, 0.0));
|
||||
|
||||
const glm::vec3 directionToSunCameraSpace = glm::vec3(viewTransform *
|
||||
glm::dvec4(directionToSunWorldSpace, 0));
|
||||
// @TODO (abock, 2020-04-14); This is just a bandaid for issue #1136. The better
|
||||
// way is to figure out with the uniform is optimized away. I assume that it is
|
||||
// because the shader doesn't get recompiled when the last layer of the night
|
||||
// or water is disabled; so the shader thinks it has to do the calculation, but
|
||||
// there are actually no layers left
|
||||
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
|
||||
_globalRenderer.program->setIgnoreUniformLocationError(IgnoreError::Yes);
|
||||
// Set the light direction uniforms for local renderer
|
||||
_globalRenderer.program->setUniform(
|
||||
"lightDirectionCameraSpace",
|
||||
-glm::normalize(directionToSunCameraSpace)
|
||||
);
|
||||
_globalRenderer.program->setIgnoreUniformLocationError(IgnoreError::Yes);
|
||||
_localRenderer.program->setUniform(
|
||||
"lightDirectionCameraSpace",
|
||||
-glm::normalize(directionToSunCameraSpace)
|
||||
);
|
||||
|
||||
if (_ringsComponent) {
|
||||
_localRenderer.program->setUniform(
|
||||
"lightDirectionObjSpace",
|
||||
-glm::normalize(directionToSunObjSpace)
|
||||
);
|
||||
_globalRenderer.program->setUniform(
|
||||
"lightDirectionObjSpace",
|
||||
-glm::normalize(directionToSunObjSpace)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
int globalCount = 0;
|
||||
@@ -1452,31 +1456,27 @@ void RenderableGlobe::renderChunkGlobally(const Chunk& chunk, const RenderData&
|
||||
}
|
||||
|
||||
// Shadow Mapping
|
||||
ghoul::opengl::TextureUnit shadowMapUnit;
|
||||
if (_shadowMappingProperties.shadowMapping && shadowData.shadowDepthTexture != 0) {
|
||||
// Adding the model transformation to the final shadow matrix so we have a
|
||||
// complete transformation from the model coordinates to the clip space of the
|
||||
// light position.
|
||||
program.setUniform(
|
||||
"shadowMatrix",
|
||||
shadowData.shadowMatrix * modelTransform()
|
||||
);
|
||||
if (_shadowMappingProperties.shadowMapping) {
|
||||
// Bind ring textures for direct projection when rings component is available
|
||||
if (_ringsComponent && _ringsComponent->isEnabled()) {
|
||||
ghoul::opengl::TextureUnit ringTextureColorUnit;
|
||||
ghoul::opengl::TextureUnit ringTextureTransparencyUnit;
|
||||
|
||||
shadowMapUnit.activate();
|
||||
glBindTexture(GL_TEXTURE_2D, shadowData.shadowDepthTexture);
|
||||
if (_ringsComponent->textureColor()) {
|
||||
ringTextureColorUnit.activate();
|
||||
_ringsComponent->textureColor()->bind();
|
||||
program.setUniform("ringTextureColor", ringTextureColorUnit);
|
||||
}
|
||||
|
||||
program.setUniform("shadowMapTexture", shadowMapUnit);
|
||||
program.setUniform(
|
||||
"zFightingPercentage",
|
||||
_shadowMappingProperties.zFightingPercentage
|
||||
);
|
||||
}
|
||||
else if (_shadowMappingProperties.shadowMapping && _shadowComponent) {
|
||||
shadowMapUnit.activate();
|
||||
// JCC: Avoiding a to recompiling the shaders or having more than one
|
||||
// set of shaders for this step.
|
||||
glBindTexture(GL_TEXTURE_2D, _shadowComponent->dDepthTexture());
|
||||
program.setUniform("shadowMapTexture", shadowMapUnit);
|
||||
if (_ringsComponent->textureTransparency()) {
|
||||
ringTextureTransparencyUnit.activate();
|
||||
_ringsComponent->textureTransparency()->bind();
|
||||
program.setUniform("ringTextureTransparency", ringTextureTransparencyUnit);
|
||||
}
|
||||
|
||||
program.setUniform("textureOffset", _ringsComponent->textureOffset());
|
||||
program.setUniform("ringSize", (float)_ringsComponent->size());
|
||||
}
|
||||
}
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
@@ -1590,33 +1590,29 @@ void RenderableGlobe::renderChunkLocally(const Chunk& chunk, const RenderData& d
|
||||
if (_eclipseShadowsEnabled && !_ellipsoid.shadowConfigurationArray().empty()) {
|
||||
calculateEclipseShadows(program, data, ShadowCompType::LOCAL_SHADOW);
|
||||
}
|
||||
|
||||
|
||||
// Shadow Mapping
|
||||
ghoul::opengl::TextureUnit shadowMapUnit;
|
||||
if (_shadowMappingProperties.shadowMapping && shadowData.shadowDepthTexture != 0) {
|
||||
// Adding the model transformation to the final shadow matrix so we have a
|
||||
// complete transformation from the model coordinates to the clip space of the
|
||||
// light position.
|
||||
program.setUniform(
|
||||
"shadowMatrix",
|
||||
shadowData.shadowMatrix * modelTransform()
|
||||
);
|
||||
// Bind ring textures for direct projection when rings component is available
|
||||
if (_ringsComponent && _ringsComponent->isEnabled()) {
|
||||
ghoul::opengl::TextureUnit ringTextureColorUnit;
|
||||
ghoul::opengl::TextureUnit ringTextureTransparencyUnit;
|
||||
|
||||
shadowMapUnit.activate();
|
||||
glBindTexture(GL_TEXTURE_2D, shadowData.shadowDepthTexture);
|
||||
if (_ringsComponent->textureColor()) {
|
||||
ringTextureColorUnit.activate();
|
||||
_ringsComponent->textureColor()->bind();
|
||||
program.setUniform("ringTextureColor", ringTextureColorUnit);
|
||||
}
|
||||
|
||||
program.setUniform("shadowMapTexture", shadowMapUnit);
|
||||
program.setUniform(
|
||||
"zFightingPercentage",
|
||||
_shadowMappingProperties.zFightingPercentage
|
||||
);
|
||||
}
|
||||
else if (_shadowMappingProperties.shadowMapping) {
|
||||
shadowMapUnit.activate();
|
||||
// JCC: Avoiding a to recompiling the shaders or having more than one
|
||||
// set of shaders for this step.
|
||||
glBindTexture(GL_TEXTURE_2D, _shadowComponent->dDepthTexture());
|
||||
program.setUniform("shadowMapTexture", shadowMapUnit);
|
||||
if (_ringsComponent->textureTransparency()) {
|
||||
ringTextureTransparencyUnit.activate();
|
||||
_ringsComponent->textureTransparency()->bind();
|
||||
program.setUniform("ringTextureTransparency", ringTextureTransparencyUnit);
|
||||
}
|
||||
|
||||
program.setUniform("textureOffset", _ringsComponent->textureOffset());
|
||||
program.setUniform("ringSize", (float)_ringsComponent->size());
|
||||
}
|
||||
}
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
@@ -1718,6 +1714,12 @@ void RenderableGlobe::setCommonUniforms(ghoul::opengl::ProgramObject& programObj
|
||||
programObject.setUniform("deltaPhi1", glm::length(deltaPhi1));
|
||||
programObject.setUniform("tileDelta", TileDelta);
|
||||
}
|
||||
|
||||
// Used by local and global renderer, as well as geojson
|
||||
using ghoul::opengl::ProgramObject;
|
||||
programObject.setIgnoreUniformLocationError(ProgramObject::IgnoreError::Yes);
|
||||
programObject.setUniform("modelTransform", _cachedModelTransform);
|
||||
programObject.setIgnoreUniformLocationError(ProgramObject::IgnoreError::No);
|
||||
}
|
||||
|
||||
void RenderableGlobe::recompileShaders() {
|
||||
@@ -1787,6 +1789,10 @@ void RenderableGlobe::recompileShaders() {
|
||||
"enableShadowMapping",
|
||||
std::to_string(_shadowMappingProperties.shadowMapping && _shadowComponent)
|
||||
);
|
||||
pairs.emplace_back(
|
||||
"useRingShadows",
|
||||
std::to_string(_shadowMappingProperties.shadowMapping && _ringsComponent)
|
||||
);
|
||||
pairs.emplace_back("showChunkEdges", std::to_string(_debugProperties.showChunkEdges));
|
||||
pairs.emplace_back("showHeightResolution", "0");
|
||||
pairs.emplace_back("showHeightIntensities", "0");
|
||||
@@ -2492,7 +2498,6 @@ bool RenderableGlobe::isCullableByHorizon(const Chunk& chunk,
|
||||
);
|
||||
|
||||
const glm::dvec3& globeToCamera = cameraPos;
|
||||
|
||||
const Geodetic2 camPosOnGlobe = _ellipsoid.cartesianToGeodetic2(globeToCamera);
|
||||
const Geodetic2 closestPatchPoint = patch.closestPoint(camPosOnGlobe);
|
||||
glm::dvec3 objectPos = _ellipsoid.cartesianSurfacePosition(closestPatchPoint);
|
||||
|
||||
@@ -351,6 +351,9 @@ void RingsComponent::initializeGL() {
|
||||
glGenBuffers(1, &_vertexPositionBuffer);
|
||||
|
||||
createPlane();
|
||||
|
||||
// Check if readiness state has changed after shader compilation
|
||||
checkAndNotifyReadinessChange();
|
||||
}
|
||||
|
||||
void RingsComponent::deinitializeGL() {
|
||||
@@ -377,15 +380,10 @@ void RingsComponent::deinitializeGL() {
|
||||
_geometryOnlyShader = nullptr;
|
||||
}
|
||||
|
||||
void RingsComponent::draw(const RenderData& data, RenderPass renderPass,
|
||||
void RingsComponent::draw(const RenderData& data,
|
||||
const ShadowComponent::ShadowMapData& shadowData)
|
||||
{
|
||||
if (renderPass == RenderPass::GeometryAndShading) {
|
||||
_shader->activate();
|
||||
}
|
||||
else if (renderPass == RenderPass::GeometryOnly) {
|
||||
_geometryOnlyShader->activate();
|
||||
}
|
||||
_shader->activate();
|
||||
|
||||
const glm::dmat4 modelTransform =
|
||||
glm::translate(glm::dmat4(1.0), data.modelTransform.translation) *
|
||||
@@ -402,165 +400,142 @@ void RingsComponent::draw(const RenderData& data, RenderPass renderPass,
|
||||
ghoul::opengl::TextureUnit ringTextureUnlitUnit;
|
||||
ghoul::opengl::TextureUnit ringTextureColorUnit;
|
||||
ghoul::opengl::TextureUnit ringTextureTransparencyUnit;
|
||||
if (renderPass == RenderPass::GeometryAndShading) {
|
||||
if (_isAdvancedTextureEnabled) {
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.modelViewProjectionMatrix,
|
||||
modelViewProjectionTransform
|
||||
);
|
||||
_shader->setUniform(_uniformCacheAdvancedRings.textureOffset, _offset);
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.colorFilterValue,
|
||||
_colorFilter
|
||||
);
|
||||
_shader->setUniform(_uniformCacheAdvancedRings.nightFactor, _nightFactor);
|
||||
_shader->setUniform(_uniformCacheAdvancedRings.sunPosition, _sunPosition);
|
||||
if (_isAdvancedTextureEnabled) {
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.modelViewProjectionMatrix,
|
||||
modelViewProjectionTransform
|
||||
);
|
||||
_shader->setUniform(_uniformCacheAdvancedRings.textureOffset, _offset);
|
||||
_shader->setUniform(_uniformCacheAdvancedRings.colorFilterValue, _colorFilter);
|
||||
_shader->setUniform(_uniformCacheAdvancedRings.nightFactor, _nightFactor);
|
||||
_shader->setUniform(_uniformCacheAdvancedRings.sunPosition, _sunPosition);
|
||||
|
||||
const glm::dmat4 inverseModelTransform = glm::inverse(modelTransform);
|
||||
const glm::dmat4 inverseModelTransform = glm::inverse(modelTransform);
|
||||
|
||||
const glm::vec3 sunPositionObjectSpace = glm::normalize(
|
||||
glm::vec3(inverseModelTransform * glm::vec4(_sunPosition, 0.f))
|
||||
);
|
||||
const glm::vec3 sunPositionObjectSpace = glm::normalize(
|
||||
glm::vec3(inverseModelTransform * glm::vec4(_sunPosition, 0.f))
|
||||
);
|
||||
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.sunPositionObj,
|
||||
sunPositionObjectSpace
|
||||
);
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.zFightingPercentage,
|
||||
_zFightingPercentage
|
||||
);
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.modelViewProjectionMatrix,
|
||||
modelViewProjectionTransform
|
||||
);
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.sunPositionObj,
|
||||
sunPositionObjectSpace
|
||||
);
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.zFightingPercentage,
|
||||
_zFightingPercentage
|
||||
);
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.modelViewProjectionMatrix,
|
||||
modelViewProjectionTransform
|
||||
);
|
||||
|
||||
ringTextureFwrdUnit.activate();
|
||||
_textureForwards->bind();
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.ringTextureFwrd,
|
||||
ringTextureFwrdUnit
|
||||
);
|
||||
ringTextureFwrdUnit.activate();
|
||||
_textureForwards->bind();
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.textureForwards,
|
||||
ringTextureFwrdUnit
|
||||
);
|
||||
|
||||
ringTextureBckwrdUnit.activate();
|
||||
_textureBackwards->bind();
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.ringTextureBckwrd,
|
||||
ringTextureBckwrdUnit
|
||||
);
|
||||
ringTextureBckwrdUnit.activate();
|
||||
_textureBackwards->bind();
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.textureBackwards,
|
||||
ringTextureBckwrdUnit
|
||||
);
|
||||
|
||||
ringTextureUnlitUnit.activate();
|
||||
_textureUnlit->bind();
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.ringTextureUnlit,
|
||||
ringTextureUnlitUnit
|
||||
);
|
||||
ringTextureUnlitUnit.activate();
|
||||
_textureUnlit->bind();
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.textureUnlit,
|
||||
ringTextureUnlitUnit
|
||||
);
|
||||
|
||||
ringTextureColorUnit.activate();
|
||||
_textureColor->bind();
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.ringTextureColor,
|
||||
ringTextureColorUnit
|
||||
);
|
||||
ringTextureColorUnit.activate();
|
||||
_textureColor->bind();
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.textureColor,
|
||||
ringTextureColorUnit
|
||||
);
|
||||
|
||||
ringTextureTransparencyUnit.activate();
|
||||
_textureTransparency->bind();
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.ringTextureTransparency,
|
||||
ringTextureTransparencyUnit
|
||||
);
|
||||
_shader->setUniform(_uniformCacheAdvancedRings.opacity, opacity());
|
||||
ringTextureTransparencyUnit.activate();
|
||||
_textureTransparency->bind();
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.textureTransparency,
|
||||
ringTextureTransparencyUnit
|
||||
);
|
||||
_shader->setUniform(_uniformCacheAdvancedRings.opacity, opacity());
|
||||
|
||||
// Adding the model transformation to the final shadow matrix so we have a
|
||||
// complete transformation from the model coordinates to the clip space of
|
||||
// the light position.
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.shadowMatrix,
|
||||
shadowData.shadowMatrix * modelTransform
|
||||
);
|
||||
// Adding the model transformation to the final shadow matrix so we have a
|
||||
// complete transformation from the model coordinates to the clip space of
|
||||
// the light position.
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.shadowMatrix,
|
||||
shadowData.shadowMatrix * modelTransform
|
||||
);
|
||||
|
||||
const glm::dmat4 camToObjectTransform = glm::inverse(
|
||||
data.camera.combinedViewMatrix()
|
||||
* modelTransform
|
||||
);
|
||||
const glm::dmat4 camToObjectTransform = glm::inverse(
|
||||
data.camera.combinedViewMatrix() * modelTransform
|
||||
);
|
||||
|
||||
_camPositionObjectSpace = glm::normalize(
|
||||
glm::vec3(camToObjectTransform * glm::dvec4(0.0, 0.0, 0.0, 1.0))
|
||||
);
|
||||
_camPositionObjectSpace = glm::normalize(
|
||||
glm::vec3(camToObjectTransform * glm::dvec4(0.0, 0.0, 0.0, 1.0))
|
||||
);
|
||||
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.camPositionObj,
|
||||
_camPositionObjectSpace
|
||||
);
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.camPositionObj,
|
||||
_camPositionObjectSpace
|
||||
);
|
||||
|
||||
ghoul::opengl::TextureUnit shadowMapUnit;
|
||||
shadowMapUnit.activate();
|
||||
glBindTexture(GL_TEXTURE_2D, shadowData.shadowDepthTexture);
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.shadowMapTexture,
|
||||
shadowMapUnit
|
||||
);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnablei(GL_BLEND, 0);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
else {
|
||||
_shader->setUniform(
|
||||
_uniformCache.modelViewProjectionMatrix,
|
||||
modelViewProjectionTransform
|
||||
);
|
||||
_shader->setUniform(_uniformCache.textureOffset, _offset);
|
||||
_shader->setUniform(_uniformCache.colorFilterValue, _colorFilter);
|
||||
_shader->setUniform(_uniformCache.nightFactor, _nightFactor);
|
||||
_shader->setUniform(_uniformCache.sunPosition, _sunPosition);
|
||||
_shader->setUniform(_uniformCache.zFightingPercentage, _zFightingPercentage);
|
||||
_shader->setUniform(
|
||||
_uniformCache.modelViewProjectionMatrix,
|
||||
modelViewProjectionTransform
|
||||
);
|
||||
_shader->setUniform(_uniformCache.opacity, opacity());
|
||||
|
||||
ringTextureUnit.activate();
|
||||
_texture->bind();
|
||||
_shader->setUniform(_uniformCache.ringTexture, ringTextureUnit);
|
||||
|
||||
// Adding the model transformation to the final shadow matrix so we have a
|
||||
// complete transformation from the model coordinates to the clip space of
|
||||
// the light position.
|
||||
_shader->setUniform(
|
||||
_uniformCache.shadowMatrix,
|
||||
shadowData.shadowMatrix * modelTransform
|
||||
);
|
||||
|
||||
ghoul::opengl::TextureUnit shadowMapUnit;
|
||||
shadowMapUnit.activate();
|
||||
glBindTexture(GL_TEXTURE_2D, shadowData.shadowDepthTexture);
|
||||
_shader->setUniform(_uniformCache.shadowMapTexture, shadowMapUnit);
|
||||
}
|
||||
ghoul::opengl::TextureUnit shadowMapUnit;
|
||||
shadowMapUnit.activate();
|
||||
glBindTexture(GL_TEXTURE_2D, shadowData.shadowDepthTexture);
|
||||
_shader->setUniform(
|
||||
_uniformCacheAdvancedRings.shadowMapTexture,
|
||||
shadowMapUnit
|
||||
);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnablei(GL_BLEND, 0);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
else if (renderPass == RenderPass::GeometryOnly) {
|
||||
_geometryOnlyShader->setUniform(
|
||||
_geomUniformCache.modelViewProjectionMatrix,
|
||||
else {
|
||||
_shader->setUniform(
|
||||
_uniformCache.modelViewProjectionMatrix,
|
||||
modelViewProjectionTransform
|
||||
);
|
||||
_geometryOnlyShader->setUniform(_geomUniformCache.textureOffset, _offset);
|
||||
_shader->setUniform(_uniformCache.textureOffset, _offset);
|
||||
_shader->setUniform(_uniformCache.colorFilterValue, _colorFilter);
|
||||
_shader->setUniform(_uniformCache.nightFactor, _nightFactor);
|
||||
_shader->setUniform(_uniformCache.sunPosition, _sunPosition);
|
||||
_shader->setUniform(_uniformCache.zFightingPercentage, _zFightingPercentage);
|
||||
_shader->setUniform(
|
||||
_uniformCache.modelViewProjectionMatrix,
|
||||
modelViewProjectionTransform
|
||||
);
|
||||
_shader->setUniform(_uniformCache.opacity, opacity());
|
||||
|
||||
ringTextureUnit.activate();
|
||||
if (_isAdvancedTextureEnabled) {
|
||||
_textureForwards->bind();
|
||||
}
|
||||
else {
|
||||
_texture->bind();
|
||||
}
|
||||
_texture->bind();
|
||||
_shader->setUniform(_uniformCache.ringTexture, ringTextureUnit);
|
||||
|
||||
_geometryOnlyShader->setUniform(_geomUniformCache.ringTexture, ringTextureUnit);
|
||||
// Adding the model transformation to the final shadow matrix so we have a
|
||||
// complete transformation from the model coordinates to the clip space of
|
||||
// the light position.
|
||||
_shader->setUniform(
|
||||
_uniformCache.shadowMatrix,
|
||||
shadowData.shadowMatrix * modelTransform
|
||||
);
|
||||
|
||||
ghoul::opengl::TextureUnit shadowMapUnit;
|
||||
shadowMapUnit.activate();
|
||||
glBindTexture(GL_TEXTURE_2D, shadowData.shadowDepthTexture);
|
||||
_shader->setUniform(_uniformCache.shadowMapTexture, shadowMapUnit);
|
||||
}
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnablei(GL_BLEND, 0);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
@@ -569,13 +544,8 @@ void RingsComponent::draw(const RenderData& data, RenderPass renderPass,
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
if (renderPass == RenderPass::GeometryAndShading) {
|
||||
_shader->deactivate();
|
||||
global::renderEngine->openglStateCache().resetBlendState();
|
||||
}
|
||||
else if (renderPass == RenderPass::GeometryOnly) {
|
||||
_geometryOnlyShader->deactivate();
|
||||
}
|
||||
_shader->deactivate();
|
||||
global::renderEngine->openglStateCache().resetBlendState();
|
||||
}
|
||||
|
||||
void RingsComponent::update(const UpdateData& data) {
|
||||
@@ -645,17 +615,14 @@ void RingsComponent::loadTexture() {
|
||||
);
|
||||
|
||||
if (textureForwards) {
|
||||
LDEBUG(
|
||||
std::format(
|
||||
"Loaded forwards scattering texture from '{}'",
|
||||
absPath(_textureFwrdPath)
|
||||
)
|
||||
);
|
||||
LDEBUG(std::format(
|
||||
"Loaded forwards scattering texture from '{}'",
|
||||
absPath(_textureFwrdPath)
|
||||
));
|
||||
_textureForwards = std::move(textureForwards);
|
||||
|
||||
_textureForwards->uploadTexture();
|
||||
_textureForwards->setFilter(
|
||||
ghoul::opengl::Texture::FilterMode::AnisotropicMipMap);
|
||||
_textureForwards->setFilter(Texture::FilterMode::AnisotropicMipMap);
|
||||
|
||||
_textureFileForwards = std::make_unique<ghoul::filesystem::File>(
|
||||
_textureFwrdPath.value()
|
||||
@@ -671,17 +638,14 @@ void RingsComponent::loadTexture() {
|
||||
);
|
||||
|
||||
if (textureBackwards) {
|
||||
LDEBUG(
|
||||
std::format(
|
||||
"Loaded backwards scattering texture from '{}'",
|
||||
absPath(_textureBckwrdPath)
|
||||
)
|
||||
);
|
||||
LDEBUG(std::format(
|
||||
"Loaded backwards scattering texture from '{}'",
|
||||
absPath(_textureBckwrdPath)
|
||||
));
|
||||
_textureBackwards = std::move(textureBackwards);
|
||||
|
||||
_textureBackwards->uploadTexture();
|
||||
_textureBackwards->setFilter(
|
||||
ghoul::opengl::Texture::FilterMode::AnisotropicMipMap);
|
||||
_textureBackwards->setFilter(Texture::FilterMode::AnisotropicMipMap);
|
||||
|
||||
_textureFileBackwards = std::make_unique<ghoul::filesystem::File>(
|
||||
_textureBckwrdPath.value()
|
||||
@@ -697,9 +661,9 @@ void RingsComponent::loadTexture() {
|
||||
);
|
||||
|
||||
if (textureUnlit) {
|
||||
LDEBUG(
|
||||
std::format("Loaded unlit texture from '{}'", absPath(_textureUnlitPath))
|
||||
);
|
||||
LDEBUG(std::format(
|
||||
"Loaded unlit texture from '{}'", absPath(_textureUnlitPath)
|
||||
));
|
||||
_textureUnlit = std::move(textureUnlit);
|
||||
|
||||
_textureUnlit->uploadTexture();
|
||||
@@ -741,15 +705,13 @@ void RingsComponent::loadTexture() {
|
||||
);
|
||||
|
||||
if (textureTransparency) {
|
||||
LDEBUG(
|
||||
std::format("Loaded unlit texture from '{}'", absPath(_textureUnlitPath))
|
||||
);
|
||||
LDEBUG(std::format(
|
||||
"Loaded transparency texture from '{}'", absPath(_textureTransparencyPath)
|
||||
));
|
||||
_textureTransparency = std::move(textureTransparency);
|
||||
|
||||
|
||||
_textureTransparency->uploadTexture();
|
||||
_textureTransparency->setFilter(
|
||||
ghoul::opengl::Texture::FilterMode::AnisotropicMipMap
|
||||
);
|
||||
_textureTransparency->setFilter(Texture::FilterMode::AnisotropicMipMap);
|
||||
|
||||
_textureFileTransparency = std::make_unique<ghoul::filesystem::File>(
|
||||
_textureTransparencyPath.value()
|
||||
@@ -759,6 +721,9 @@ void RingsComponent::loadTexture() {
|
||||
}
|
||||
|
||||
_isAdvancedTextureEnabled = _textureForwards && _textureBackwards && _textureUnlit;
|
||||
|
||||
// Check if readiness state has changed after loading textures
|
||||
checkAndNotifyReadinessChange();
|
||||
}
|
||||
|
||||
void RingsComponent::createPlane() {
|
||||
@@ -821,14 +786,6 @@ void RingsComponent::compileShadowShader() {
|
||||
|
||||
try {
|
||||
global::renderEngine->removeRenderProgram(_shader.get());
|
||||
// _shader = global::renderEngine->buildRenderProgram(
|
||||
// "RingsProgram",
|
||||
// absPath("${MODULE_GLOBEBROWSING}/shaders/rings_vs.glsl"),
|
||||
// absPath("${MODULE_GLOBEBROWSING}/shaders/rings_fs.glsl"),
|
||||
// dict
|
||||
// );
|
||||
|
||||
// ghoul::opengl::updateUniformLocations(*_shader, _uniformCache);
|
||||
|
||||
// Uses multiple textures for the Rings
|
||||
// See https://bjj.mmedia.is/data/s_rings/index.html for theory behind it
|
||||
@@ -857,6 +814,9 @@ void RingsComponent::compileShadowShader() {
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERROR(e.message);
|
||||
}
|
||||
|
||||
// Check if readiness state has changed after shader compilation
|
||||
checkAndNotifyReadinessChange();
|
||||
}
|
||||
|
||||
bool RingsComponent::isEnabled() const {
|
||||
@@ -867,4 +827,50 @@ double RingsComponent::size() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
ghoul::opengl::Texture* RingsComponent::textureForwards() const {
|
||||
return _textureForwards.get();
|
||||
}
|
||||
|
||||
ghoul::opengl::Texture* RingsComponent::textureBackwards() const {
|
||||
return _textureBackwards.get();
|
||||
}
|
||||
|
||||
ghoul::opengl::Texture* RingsComponent::textureUnlit() const {
|
||||
return _textureUnlit.get();
|
||||
}
|
||||
|
||||
ghoul::opengl::Texture* RingsComponent::textureColor() const {
|
||||
return _textureColor.get();
|
||||
}
|
||||
|
||||
ghoul::opengl::Texture* RingsComponent::textureTransparency() const {
|
||||
return _textureTransparency.get();
|
||||
}
|
||||
|
||||
glm::vec2 RingsComponent::textureOffset() const {
|
||||
return _offset;
|
||||
}
|
||||
|
||||
glm::vec3 RingsComponent::sunPositionObj() const {
|
||||
return _sunPosition;
|
||||
}
|
||||
|
||||
glm::vec3 RingsComponent::camPositionObj() const {
|
||||
return _camPositionObjectSpace;
|
||||
}
|
||||
|
||||
void RingsComponent::onReadinessChange(ReadinessChangeCallback callback) {
|
||||
_readinessChangeCallback = std::move(callback);
|
||||
}
|
||||
|
||||
void RingsComponent::checkAndNotifyReadinessChange() {
|
||||
const bool currentlyReady = isReady();
|
||||
if (currentlyReady != _wasReady) {
|
||||
_wasReady = currentlyReady;
|
||||
if (_readinessChangeCallback) {
|
||||
_readinessChangeCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -51,10 +51,8 @@ namespace documentation { struct Documentation; }
|
||||
|
||||
class RingsComponent : public properties::PropertyOwner, public Fadeable {
|
||||
public:
|
||||
enum class RenderPass {
|
||||
GeometryOnly,
|
||||
GeometryAndShading
|
||||
};
|
||||
// Callback for when readiness state changes
|
||||
using ReadinessChangeCallback = std::function<void()>;
|
||||
|
||||
explicit RingsComponent(const ghoul::Dictionary& dictionary);
|
||||
|
||||
@@ -64,20 +62,33 @@ public:
|
||||
|
||||
bool isReady() const;
|
||||
|
||||
void draw(const RenderData& data, RenderPass renderPass,
|
||||
void draw(const RenderData& data,
|
||||
const ShadowComponent::ShadowMapData& shadowData = {}
|
||||
);
|
||||
void update(const UpdateData& data);
|
||||
bool isEnabled() const;
|
||||
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
bool isEnabled() const;
|
||||
double size() const;
|
||||
|
||||
// Readiness change callback
|
||||
void onReadinessChange(ReadinessChangeCallback callback);
|
||||
|
||||
// Texture access methods for globe rendering
|
||||
ghoul::opengl::Texture* textureForwards() const;
|
||||
ghoul::opengl::Texture* textureBackwards() const;
|
||||
ghoul::opengl::Texture* textureUnlit() const;
|
||||
ghoul::opengl::Texture* textureColor() const;
|
||||
ghoul::opengl::Texture* textureTransparency() const;
|
||||
glm::vec2 textureOffset() const;
|
||||
glm::vec3 sunPositionObj() const;
|
||||
glm::vec3 camPositionObj() const;
|
||||
|
||||
private:
|
||||
void loadTexture();
|
||||
void createPlane();
|
||||
void compileShadowShader();
|
||||
void checkAndNotifyReadinessChange();
|
||||
|
||||
properties::StringProperty _texturePath;
|
||||
properties::StringProperty _textureFwrdPath;
|
||||
@@ -100,8 +111,8 @@ private:
|
||||
opacity
|
||||
) _uniformCache;
|
||||
UniformCache(modelViewProjectionMatrix, textureOffset, colorFilterValue, nightFactor,
|
||||
sunPosition, sunPositionObj, camPositionObj, ringTextureFwrd, ringTextureBckwrd,
|
||||
ringTextureUnlit, ringTextureColor, ringTextureTransparency, shadowMatrix,
|
||||
sunPosition, sunPositionObj, camPositionObj, textureForwards, textureBackwards,
|
||||
textureUnlit, textureColor, textureTransparency, shadowMatrix,
|
||||
shadowMapTexture, zFightingPercentage, opacity
|
||||
) _uniformCacheAdvancedRings;
|
||||
UniformCache(modelViewProjectionMatrix, textureOffset, ringTexture) _geomUniformCache;
|
||||
@@ -128,6 +139,10 @@ private:
|
||||
|
||||
glm::vec3 _sunPosition = glm::vec3(0.f);
|
||||
glm::vec3 _camPositionObjectSpace = glm::vec3(0.f);
|
||||
|
||||
// Callback for readiness state changes
|
||||
ReadinessChangeCallback _readinessChangeCallback;
|
||||
bool _wasReady = false;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -77,7 +77,7 @@ void KameleonDocumentationTask::perform(const Task::ProgressCallback & progressC
|
||||
|
||||
ghoul::Dictionary dictionary;
|
||||
dictionary.setValue("kameleon", std::move(kameleonDictionary));
|
||||
dictionary.setValue("version", std::string(OPENSPACE_VERSION_NUMBER));
|
||||
dictionary.setValue("version", std::string(OPENSPACE_VERSION));
|
||||
dictionary.setValue("input", _inputPath.string());
|
||||
|
||||
std::string json = ghoul::formatJson(dictionary);
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
|
||||
<!--The compatibility section will be merged from build/win/compatibility.manifest -->
|
||||
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity type="Win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<requestedExecutionLevel level="asInvoker" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
|
||||
</assembly>
|
||||
@@ -420,7 +420,7 @@ void OpenSpaceEngine::initialize() {
|
||||
}
|
||||
|
||||
|
||||
LINFOC("OpenSpace Version", std::string(OPENSPACE_VERSION_STRING_FULL));
|
||||
LINFOC("OpenSpace Version", std::string(OPENSPACE_VERSION));
|
||||
LINFOC("Commit", std::string(OPENSPACE_GIT_FULL));
|
||||
|
||||
// Register modules
|
||||
|
||||
@@ -168,7 +168,7 @@ LabelsComponent::LabelsComponent(const ghoul::Dictionary& dictionary)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_labelFile = absPath(p.file.value_or(""));
|
||||
_labelFile = p.file.has_value() ? absPath(*p.file) : "";
|
||||
_useCache = p.useCaching.value_or(true);
|
||||
|
||||
if (p.unit.has_value()) {
|
||||
|
||||
@@ -1238,7 +1238,7 @@ void RenderEngine::renderVersionInformation() {
|
||||
if (global::versionChecker->hasLatestVersionInfo()) {
|
||||
VersionChecker::SemanticVersion ver = global::versionChecker->latestVersion();
|
||||
|
||||
std::string versionString = std::string(OPENSPACE_VERSION_STRING_FULL);
|
||||
std::string versionString = std::string(OPENSPACE_VERSION);
|
||||
const VersionChecker::SemanticVersion current {
|
||||
OPENSPACE_VERSION_MAJOR,
|
||||
OPENSPACE_VERSION_MINOR,
|
||||
@@ -1259,11 +1259,11 @@ void RenderEngine::renderVersionInformation() {
|
||||
);
|
||||
}
|
||||
else {
|
||||
versionBox = _fontVersionInfo->boundingBox(OPENSPACE_VERSION_STRING_FULL);
|
||||
versionBox = _fontVersionInfo->boundingBox(OPENSPACE_VERSION);
|
||||
FR::defaultRenderer().render(
|
||||
*_fontVersionInfo,
|
||||
glm::vec2(fontResolution().x - versionBox.x - 10.f, 5.f),
|
||||
OPENSPACE_VERSION_STRING_FULL,
|
||||
OPENSPACE_VERSION,
|
||||
glm::vec4(0.5f, 0.5f, 0.5f, 1.f)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -94,18 +94,12 @@ void TextureComponent::loadFromFile(const std::filesystem::path& path) {
|
||||
using namespace ghoul::io;
|
||||
using namespace ghoul::opengl;
|
||||
|
||||
std::filesystem::path absolutePath = absPath(path);
|
||||
std::unique_ptr<Texture> tex = TextureReader::ref().loadTexture(path, _nDimensions);
|
||||
if (tex) {
|
||||
LDEBUG(std::format("Loaded texture from '{}'", path));
|
||||
_texture = std::move(tex);
|
||||
|
||||
std::unique_ptr<Texture> texture = TextureReader::ref().loadTexture(
|
||||
absolutePath,
|
||||
_nDimensions
|
||||
);
|
||||
|
||||
if (texture) {
|
||||
LDEBUG(std::format("Loaded texture from '{}'", absolutePath));
|
||||
_texture = std::move(texture);
|
||||
|
||||
_textureFile = std::make_unique<ghoul::filesystem::File>(absolutePath);
|
||||
_textureFile = std::make_unique<ghoul::filesystem::File>(path);
|
||||
if (_shouldWatchFile) {
|
||||
_textureFile->setCallback([this]() { _fileIsDirty = true; });
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ void VersionChecker::requestLatestVersion(const std::string& url) {
|
||||
|
||||
std::string fullUrl = std::format(
|
||||
"{}?client_version={}&commit_hash={}&operating_system={}&profile={}",
|
||||
url, OPENSPACE_VERSION_NUMBER, OPENSPACE_GIT_COMMIT, operatingSystem, profile
|
||||
url, OPENSPACE_VERSION, OPENSPACE_GIT_COMMIT, operatingSystem, profile
|
||||
);
|
||||
|
||||
if (_request) {
|
||||
|
||||
@@ -41,9 +41,7 @@ constexpr uint8_t OPENSPACE_VERSION_MAJOR = @OPENSPACE_VERSION_MAJOR@;
|
||||
constexpr uint8_t OPENSPACE_VERSION_MINOR = @OPENSPACE_VERSION_MINOR@;
|
||||
constexpr uint8_t OPENSPACE_VERSION_PATCH = @OPENSPACE_VERSION_PATCH@;
|
||||
|
||||
constexpr std::string_view OPENSPACE_VERSION_NUMBER = "@OPENSPACE_VERSION_MAJOR@.@OPENSPACE_VERSION_MINOR@.@OPENSPACE_VERSION_PATCH@";
|
||||
constexpr std::string_view OPENSPACE_VERSION_STRING = "@OPENSPACE_VERSION_STRING@";
|
||||
constexpr std::string_view OPENSPACE_VERSION_STRING_FULL = "@OPENSPACE_VERSION_MAJOR@.@OPENSPACE_VERSION_MINOR@.@OPENSPACE_VERSION_PATCH@ (@OPENSPACE_VERSION_STRING@)";
|
||||
constexpr std::string_view OPENSPACE_VERSION = "@OPENSPACE_VERSION_MAJOR@.@OPENSPACE_VERSION_MINOR@.@OPENSPACE_VERSION_PATCH@";
|
||||
|
||||
#else // ^^^^ OPENSPACE_RELEASE_BUILD || !OPENSPACE_RELEASE_BUILD vvvv
|
||||
|
||||
@@ -53,9 +51,7 @@ constexpr uint8_t OPENSPACE_VERSION_MAJOR = std::numeric_limits<uint8_t>::max();
|
||||
constexpr uint8_t OPENSPACE_VERSION_MINOR = std::numeric_limits<uint8_t>::max();
|
||||
constexpr uint8_t OPENSPACE_VERSION_PATCH = std::numeric_limits<uint8_t>::max();
|
||||
|
||||
constexpr std::string_view OPENSPACE_VERSION_NUMBER = "";
|
||||
constexpr std::string_view OPENSPACE_VERSION_STRING = "";
|
||||
constexpr std::string_view OPENSPACE_VERSION_STRING_FULL = "";
|
||||
constexpr std::string_view OPENSPACE_VERSION = "";
|
||||
|
||||
#endif // OPENSPACE_RELEASE_BUILD
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ set(OPENSPACE_VERSION_NUMBER
|
||||
)
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "OpenSpace ${OPENSPACE_VERSION_NUMBER}")
|
||||
set(CPACK_PACKAGE_FILE_NAME
|
||||
"${CPACK_PACKAGE_NAME} ${OPENSPACE_VERSION_NUMBER} ${OPENSPACE_VERSION_STRING}"
|
||||
"${CPACK_PACKAGE_NAME} ${OPENSPACE_VERSION_NUMBER}"
|
||||
)
|
||||
set(CPACK_STRIP_FILES 1)
|
||||
|
||||
@@ -74,11 +74,11 @@ if (WIN32)
|
||||
set(CPACK_GENERATOR ZIP)
|
||||
# Need backslash for correct subdirectory paths
|
||||
set(CPACK_PACKAGE_ICON "${PROJECT_SOURCE_DIR}\\\\apps\\\\OpenSpace\\\\openspace.png")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}\\\\${OPENSPACE_VERSION_NUMBER} ${OPENSPACE_VERSION_STRING}")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}\\\\${OPENSPACE_VERSION_NUMBER}")
|
||||
else ()
|
||||
set(CPACK_GENERATOR TGZ)
|
||||
set(CPACK_PACKAGE_ICON "${PROJECT_SOURCE_DIR}/apps/OpenSpace/openspace.png")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}/${OPENSPACE_VERSION_NUMBER} ${OPENSPACE_VERSION_STRING}")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}/${OPENSPACE_VERSION_NUMBER}")
|
||||
endif ()
|
||||
|
||||
option(OPENSPACE_CREATE_INSTALLER "Create an OpenSpace installer from the package" OFF)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"profile": "empty",
|
||||
"commands": [
|
||||
{
|
||||
"type": "navigationstate",
|
||||
"value": {
|
||||
"anchor": "Saturn",
|
||||
"position": [
|
||||
208667642.45051652,
|
||||
54126259.932879746,
|
||||
57439831.8163157
|
||||
],
|
||||
"pitch": -0.017233194146801384,
|
||||
"up": [
|
||||
-0.26992564740141767,
|
||||
0.01898840930203355,
|
||||
0.9626939208217241
|
||||
],
|
||||
"yaw": -0.003697938774824961,
|
||||
"timestamp": "2025 JUL 13 12:13:12"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "asset",
|
||||
"value": "scene/solarsystem/planets/saturn/default_layers.asset"
|
||||
},
|
||||
{
|
||||
"type": "asset",
|
||||
"value": "scene/solarsystem/planets/saturn/saturn.asset"
|
||||
},
|
||||
{
|
||||
"type": "wait",
|
||||
"value": 10.0
|
||||
},
|
||||
{
|
||||
"type": "screenshot"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"profile": "empty",
|
||||
"commands": [
|
||||
{
|
||||
"type": "navigationstate",
|
||||
"value": {
|
||||
"anchor": "Saturn",
|
||||
"position": [
|
||||
208667642.45118257,
|
||||
54126259.93271133,
|
||||
57439831.8162123
|
||||
],
|
||||
"pitch": -0.017233193591973957,
|
||||
"up": [
|
||||
-0.26992564738826463,
|
||||
0.018988409251575723,
|
||||
0.9626939208264074
|
||||
],
|
||||
"yaw": -0.003697934996467431,
|
||||
"timestamp": "2028 MAY 14 12:13:12"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "asset",
|
||||
"value": "scene/solarsystem/planets/saturn/default_layers.asset"
|
||||
},
|
||||
{
|
||||
"type": "asset",
|
||||
"value": "scene/solarsystem/planets/saturn/saturn.asset"
|
||||
},
|
||||
{
|
||||
"type": "wait",
|
||||
"value": 10.0
|
||||
},
|
||||
{
|
||||
"type": "screenshot"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"profile": "empty",
|
||||
"commands": [
|
||||
{
|
||||
"type": "navigationstate",
|
||||
"value": {
|
||||
"anchor": "Saturn",
|
||||
"position": [
|
||||
-141360298.68091586,
|
||||
-166699069.69779366,
|
||||
-45551858.24393063
|
||||
],
|
||||
"pitch": 0.0064781942863547555,
|
||||
"up": [
|
||||
-0.14567322634534205,
|
||||
-0.14393621312449992,
|
||||
0.9788062513477921
|
||||
],
|
||||
"yaw": -0.0046432197348252,
|
||||
"timestamp": "2020 MAY 14 12:12:49"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "asset",
|
||||
"value": "scene/solarsystem/planets/saturn/default_layers.asset"
|
||||
},
|
||||
{
|
||||
"type": "asset",
|
||||
"value": "scene/solarsystem/planets/saturn/saturn.asset"
|
||||
},
|
||||
{
|
||||
"type": "wait",
|
||||
"value": 10.0
|
||||
},
|
||||
{
|
||||
"type": "screenshot"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user