Merge remote-tracking branch 'origin/master' into feature/aurorasaurus

This commit is contained in:
lundkvistarn
2024-09-16 15:32:28 -04:00
656 changed files with 7885 additions and 5214 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
+3 -2
View File
@@ -219,7 +219,8 @@ public:
* The \p identifier must be a name for a sound that was started through the
* #playAudio3d function.
*
* \param handle A valid handle for a track started through the #playAudio3d function
* \param identifier The identifier of a track started through the #playAudio3d
* function
* \param position The new position from which the track originates
*/
void set3dSourcePosition(const std::string& identifier,
@@ -272,7 +273,7 @@ public:
/**
* Sets the position of the speaker for the provided \p channel to the provided
* \position. In general, this is considered an advanced feature to accommodate
* \p position. In general, this is considered an advanced feature to accommodate
* non-standard audio environments.
*
* \param channel The channel whose speaker's position should be changed
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
@@ -187,18 +187,18 @@ RenderableInterpolatedPoints::Interpolation::Interpolation()
);
// No syncing, as this was triggered from a property change (which happened
// based on an already synced script)
global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript({
.code = script,
.synchronized = scripting::ScriptEngine::Script::ShouldBeSynchronized::No,
.sendToRemote = scripting::ScriptEngine::Script::ShouldSendToRemote::No
});
};
interpolateToEnd.onChange([triggerInterpolation, this]() {
float remaining = value.maxValue() - value;
float duration = remaining / speed;
triggerInterpolation(
value.fullyQualifiedIdentifier(),
value.uri(),
value.maxValue(),
duration
);
@@ -206,21 +206,21 @@ RenderableInterpolatedPoints::Interpolation::Interpolation()
interpolateToStart.onChange([triggerInterpolation, this]() {
float duration = value / speed;
triggerInterpolation(value.fullyQualifiedIdentifier(), 0.f, duration);
triggerInterpolation(value.uri(), 0.f, duration);
});
interpolateToNextStep.onChange([triggerInterpolation, this]() {
float prevValue = glm::floor(value);
float newValue = glm::min(prevValue + 1.f, value.maxValue());
float duration = 1.f / speed;
triggerInterpolation(value.fullyQualifiedIdentifier(), newValue, duration);
triggerInterpolation(value.uri(), newValue, duration);
});
interpolateToPrevStep.onChange([triggerInterpolation, this]() {
float prevValue = glm::ceil(value);
float newValue = glm::max(prevValue - 1.f, value.minValue());
float duration = 1.f / speed;
triggerInterpolation(value.fullyQualifiedIdentifier(), newValue, duration);
triggerInterpolation(value.uri(), newValue, duration);
});
addProperty(interpolateToEnd);
@@ -170,10 +170,10 @@ SizeMappingComponent::SizeMappingComponent(const ghoul::Dictionary& dictionary)
const Parameters::ScaleUnit scaleUnit =
std::get<Parameters::ScaleUnit>(*p.scaleFactor);
const DistanceUnit distanceUnit = codegen::map<DistanceUnit>(scaleUnit);
scaleFactor = toMeter(distanceUnit);
scaleFactor = static_cast<float>(toMeter(distanceUnit));
}
else if (std::holds_alternative<double>(*p.scaleFactor)) {
scaleFactor = std::get<double>(*p.scaleFactor);
scaleFactor = static_cast<float>(std::get<double>(*p.scaleFactor));
}
}
+1 -4
View File
@@ -330,10 +330,7 @@ void RenderableSphere::render(const RenderData& data, RendererTasks&) {
glDisable(GL_CULL_FACE);
}
if (renderBin() == Renderable::RenderBin::PreDeferredTransparent) {
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glDepthMask(false);
}
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
_sphere->render();
@@ -28,6 +28,7 @@
#include <openspace/documentation/verifier.h>
#include <openspace/scene/translation.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/timeconversion.h>
#include <openspace/util/updatestructures.h>
#include <optional>
@@ -124,8 +125,13 @@ namespace {
// [[codegen::verbatim(EndTimeInfo.description)]]
std::string endTime [[codegen::annotation("A valid date in ISO 8601 format")]];
// [[codegen::verbatim(SampleIntervalInfo.description)]]
double sampleInterval;
// The interval between samples of the trajectory. This value (together with
// 'TimeStampSubsampleFactor') determines how far apart (in time) the samples are
// spaced along the trajectory. The time interval between 'StartTime' and
// 'EndTime' is split into 'SampleInterval' * 'TimeStampSubsampleFactor' segments.
// If this value is not specified, it will be automatically calculated to produce
// one sample every two day between the 'StartTime' and 'EndTime'.
std::optional<double> sampleInterval;
// [[codegen::verbatim(TimeSubSampleInfo.description)]]
std::optional<int> timeStampSubsampleFactor;
@@ -182,7 +188,13 @@ RenderableTrailTrajectory::RenderableTrailTrajectory(const ghoul::Dictionary& di
_endTime.onChange([this] { reset(); });
addProperty(_endTime);
_sampleInterval = p.sampleInterval;
if (p.sampleInterval.has_value()) {
_sampleInterval = *p.sampleInterval;
}
else {
const double delta = Time::convertTime(_endTime) - Time::convertTime(_startTime);
_sampleInterval = delta / (openspace::SecondsPerYear * 2);
}
_sampleInterval.onChange([this] { reset(); });
addProperty(_sampleInterval);
@@ -85,15 +85,16 @@ ScreenSpaceDashboard::ScreenSpaceDashboard(const ghoul::Dictionary& dictionary)
_useMainDashboard = p.useMainDashboard.value_or(_useMainDashboard);
addProperty(_useMainDashboard);
_scale = 1.f;
_scale.setMaxValue(15.f);
if (_useMainDashboard && p.items.has_value()) {
throw ghoul::RuntimeError("Cannot specify items when using the main dashboard");
}
if (!_useMainDashboard) {
addPropertySubOwner(_dashboard);
}
if (p.items.has_value()) {
ghoul_assert(_useMainDashboard, "Cannot add items to the main dashboard");
ghoul_assert(!_useMainDashboard, "Cannot add items to the main dashboard");
for (const ghoul::Dictionary& item : *p.items) {
std::unique_ptr<DashboardItem> i = DashboardItem::createFromDictionary(item);
_dashboard.addDashboardItem(std::move(i));
+7 -2
View File
@@ -47,7 +47,9 @@ namespace {
struct [[codegen::Dictionary(ConstantRotation)]] Parameters {
// [[codegen::verbatim(RotationInfo.description)]]
std::optional<glm::dvec3> rotationAxis;
std::optional<glm::dvec3> rotationAxis
[[codegen::inrange(glm::dvec3(-1.0), glm::dvec3(1.0))]];
// [[codegen::verbatim(RotationRateInfo.description)]]
std::optional<float> rotationRate;
};
@@ -100,7 +102,10 @@ glm::dmat3 ConstantRotation::matrix(const UpdateData& data) const {
_accumulatedRotation += glm::tau<double>();
}
const glm::dquat q = glm::angleAxis(_accumulatedRotation, _rotationAxis.value());
const glm::dquat q = glm::angleAxis(
_accumulatedRotation,
glm::normalize(_rotationAxis.value())
);
return glm::toMat3(q);
}
-4
View File
@@ -64,10 +64,6 @@ documentation::Documentation LuaRotation::Documentation() {
LuaRotation::LuaRotation(const ghoul::Dictionary& dictionary)
: _luaScriptFile(ScriptInfo)
, _state(
ghoul::lua::LuaState::IncludeStandardLibrary::Yes,
ghoul::lua::LuaState::StrictState::No
)
{
const Parameters p = codegen::bake<Parameters>(dictionary);
-4
View File
@@ -63,10 +63,6 @@ documentation::Documentation LuaScale::Documentation() {
LuaScale::LuaScale(const ghoul::Dictionary& dictionary)
: _luaScriptFile(ScriptInfo)
, _state(
ghoul::lua::LuaState::IncludeStandardLibrary::Yes,
ghoul::lua::LuaState::StrictState::No
)
{
const Parameters p = codegen::bake<Parameters>(dictionary);
+14 -2
View File
@@ -29,6 +29,7 @@ in vec3 vs_normalViewSpace;
in vec4 vs_positionCameraSpace;
in float vs_screenSpaceDepth;
in mat3 vs_TBN;
in vec3 vs_color;
uniform float ambientIntensity = 0.2;
uniform float diffuseIntensity = 1.0;
@@ -36,6 +37,7 @@ uniform float specularIntensity = 1.0;
uniform bool performShading = true;
uniform bool use_forced_color = false;
uniform bool use_vertex_colors = false;
uniform bool has_texture_diffuse;
uniform bool has_texture_normal;
uniform bool has_texture_specular;
@@ -95,7 +97,7 @@ Fragment getFragment() {
}
// Base color
vec4 diffuseAlbedo;
vec4 diffuseAlbedo = vec4(0.0);
if (has_texture_diffuse) {
diffuseAlbedo = texture(texture_diffuse, vs_st);
}
@@ -103,6 +105,16 @@ Fragment getFragment() {
diffuseAlbedo = color_diffuse;
}
// Multiply with vertex color if specified
if (use_vertex_colors) {
diffuseAlbedo.rgb *= vs_color;
// Make sure to not go beyond color range
diffuseAlbedo.r = clamp(diffuseAlbedo.r, 0.0, 1.0);
diffuseAlbedo.g = clamp(diffuseAlbedo.g, 0.0, 1.0);
diffuseAlbedo.b = clamp(diffuseAlbedo.b, 0.0, 1.0);
}
if (performShading) {
// Specular color
vec3 specularAlbedo;
@@ -118,7 +130,7 @@ Fragment getFragment() {
}
}
// Bumb mapping
// Bump mapping
vec3 normal;
if (has_texture_normal) {
vec3 normalAlbedo = texture(texture_normal, vs_st).rgb;
+3
View File
@@ -30,12 +30,14 @@ layout(location = 0) in vec4 in_position;
layout(location = 1) in vec2 in_st;
layout(location = 2) in vec3 in_normal;
layout(location = 3) in vec3 in_tangent;
layout(location = 4) in vec3 in_color;
out vec2 vs_st;
out vec3 vs_normalViewSpace;
out float vs_screenSpaceDepth;
out vec4 vs_positionCameraSpace;
out mat3 vs_TBN;
out vec3 vs_color;
uniform mat4 modelViewTransform;
uniform mat4 projectionTransform;
@@ -51,6 +53,7 @@ void main() {
gl_Position = positionScreenSpace;
vs_st = in_st;
vs_color = in_color;
vs_screenSpaceDepth = positionScreenSpace.w;
vs_normalViewSpace =
+20 -2
View File
@@ -40,12 +40,23 @@ uniform float saturation;
uniform float gamma = 1.0;
uniform vec2 borderWidth = vec2(0.1);
uniform vec3 borderColor = vec3(0.0);
uniform int borderFeather = 0;
// Accelerated rendering can be used for the CEF browser
#define USE_ACCELERATED_RENDERING #{useAcceleratedRendering}
Fragment getFragment() {
Fragment frag;
vec4 originalColor;
#if USE_ACCELERATED_RENDERING
vec2 flippedTexCoords = vec2(vs_st.x, 1.0 - vs_st.y);
// Correcting both orientation and color channels
originalColor = texture(tex, flippedTexCoords).bgra;
#else
originalColor = texture(tex, vs_st);
#endif
vec4 texColor = texture(tex, vs_st) * vec4(color, opacity);
vec4 texColor = originalColor * vec4(color, opacity);
frag.color = texColor.a * texColor + (1.0 - texColor.a) * backgroundColor;
@@ -53,7 +64,14 @@ Fragment getFragment() {
if (vs_st.x < borderWidth.x || vs_st.x > 1 - borderWidth.x ||
vs_st.y < borderWidth.y || vs_st.y > 1 - borderWidth.y)
{
frag.color = vec4(borderColor, 1.0);
frag.color = vec4(borderColor, opacity);
if (borderFeather == 1) {
vec2 f1 = vs_st / borderWidth;
float g1 = min(f1.x, f1.y);
vec2 f2 = (vec2(1) - vs_st) / borderWidth;
float g2 = min(f2.x, f2.y);
frag.color *= min(g1, g2);
}
}
if (frag.color.a == 0.0) {
@@ -64,10 +64,6 @@ documentation::Documentation LuaTranslation::Documentation() {
LuaTranslation::LuaTranslation(const ghoul::Dictionary& dictionary)
: _luaScriptFile(ScriptInfo)
, _state(
ghoul::lua::LuaState::IncludeStandardLibrary::Yes,
ghoul::lua::LuaState::StrictState::No
)
{
const Parameters p = codegen::bake<Parameters>(dictionary);
@@ -33,7 +33,6 @@ namespace {
"Position",
"This value is used as a static offset (in meters) that is applied to the scene "
"graph node that this transformation is attached to relative to its parent.",
// @VISIBILITY(2.25)
openspace::properties::Property::Visibility::User
};
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
+11 -7
View File
@@ -216,6 +216,17 @@ void CefWebGuiModule::internalInitialize(const ghoul::Dictionary& configuration)
startOrStopGui();
});
global::callback::postDraw->emplace_back([this]() {
bool windowChanged = global::windowDelegate->windowHasResized();
if (_instance && (windowChanged || _instance->_shouldReshape)){
const glm::ivec2 res = global::windowDelegate->guiWindowResolution();
_instance->reshape(static_cast<glm::ivec2>(
glm::vec2(res) * global::windowDelegate->dpiScaling()
));
_instance->_shouldReshape = false;
}
});
global::callback::draw2D->emplace_back([this](){
ZoneScopedN("CefWebGuiModule");
@@ -227,13 +238,6 @@ void CefWebGuiModule::internalInitialize(const ghoul::Dictionary& configuration)
const bool isMaster = global::windowDelegate->isMaster();
if (isGuiWindow && isMaster && _instance) {
if (global::windowDelegate->windowHasResized() || _instance->_shouldReshape) {
const glm::ivec2 csws = global::windowDelegate->guiWindowResolution();
_instance->reshape(static_cast<glm::ivec2>(
static_cast<glm::vec2>(csws) * global::windowDelegate->dpiScaling()
));
_instance->_shouldReshape = false;
}
if (_visible) {
_instance->draw();
}
+8 -2
View File
@@ -29,8 +29,14 @@ in vec2 vs_st;
out vec4 outputColor;
uniform sampler2D tex;
#define USE_ACCELERATED_RENDERING #{useAcceleratedRendering}
void main() {
outputColor = texture(tex, vs_st);
#if USE_ACCELERATED_RENDERING
vec2 flippedTexCoords = vec2(vs_st.x, 1.0 - vs_st.y);
vec4 texColor = texture(tex, flippedTexCoords);
outputColor = texColor.bgra; // Correcting both orientation and color channels
#else
outputColor = texture(tex, vs_st);
#endif
}
+5 -2
View File
@@ -38,10 +38,14 @@ namespace openspace {
GUIRenderHandler::GUIRenderHandler() {
LDEBUG("Initializing CEF GL environment...");
ghoul::Dictionary define;
define.setValue("useAcceleratedRendering", _acceleratedRendering);
_programObject = ghoul::opengl::ProgramObject::Build(
"WebGUICEFProgram",
absPath("${MODULE_CEFWEBGUI}/shaders/gui_vs.glsl"),
absPath("${MODULE_CEFWEBGUI}/shaders/gui_fs.glsl")
absPath("${MODULE_CEFWEBGUI}/shaders/gui_fs.glsl"),
define
);
constexpr std::array<float, 12> Vtx = {
-1.f, -1.f, -1.f,
@@ -53,7 +57,6 @@ GUIRenderHandler::GUIRenderHandler() {
glGenVertexArrays(1, &_vao);
glBindVertexArray(_vao);
glGenBuffers(1, &_vbo);
glGenTextures(1, &_texture);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, Vtx.size() * sizeof(float), Vtx.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
+100 -5
View File
@@ -26,7 +26,10 @@
#include <modules/debugging/rendering/renderabledebugplane.h>
#include <openspace/documentation/documentation.h>
#include <openspace/engine/configuration.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/globalscallbacks.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/navigation/path.h>
#include <openspace/navigation/pathnavigator.h>
@@ -37,15 +40,100 @@
#include <openspace/scripting/scriptengine.h>
#include <openspace/scripting/lualibrary.h>
#include <openspace/util/factorymanager.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/font/fontmanager.h>
#include <ghoul/font/fontrenderer.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/assert.h>
#include <ghoul/misc/templatefactory.h>
#include "debuggingmodule_lua.inl"
namespace {
constexpr std::string_view KeyFontMono = "Mono";
constexpr openspace::properties::Property::PropertyInfo ShowStatisticsInfo = {
"ShowStatistics",
"Show Statistics",
"Show updating, rendering, and network statistics on all rendering nodes.",
openspace::properties::Property::Visibility::AdvancedUser
};
constexpr openspace::properties::Property::PropertyInfo StatisticsScaleInfo = {
"StatisticsScale",
"Statistics Scale",
"This value is scaling the statatistics window by the provided amount. For flat "
"projections this is rarely necessary, but it is important when using a setup "
"where the cornders of the image are masked out.",
openspace::properties::Property::Visibility::AdvancedUser
};
constexpr openspace::properties::Property::PropertyInfo ShowFrameNumberInfo = {
"ShowFrameInformation",
"Show Frame Information",
"If this value is enabled, the current frame number and frame times are rendered "
"into the window.",
openspace::properties::Property::Visibility::AdvancedUser
};
} // namespace
namespace openspace {
DebuggingModule::DebuggingModule() : OpenSpaceModule(Name) {}
DebuggingModule::DebuggingModule()
: OpenSpaceModule(Name)
, _showStatistics(ShowStatisticsInfo, false)
, _statisticsScale(StatisticsScaleInfo, 1.f, 0.f, 1.f)
, _showFrameInformation(ShowFrameNumberInfo, false)
{
_showStatistics.onChange([this]() {
global::windowDelegate->showStatistics(_showStatistics);
// We need to reset the scale as it is not updated when the statistics window is
// not currently shown
global::windowDelegate->setStatisticsGraphScale(_statisticsScale);
});
addProperty(_showStatistics);
_statisticsScale.onChange([this]() {
global::windowDelegate->setStatisticsGraphScale(_statisticsScale);
});
addProperty(_statisticsScale);
addProperty(_showFrameInformation);
global::callback::render->push_back([this]() {
if (_showFrameInformation) {
ZoneScopedN("Show Frame Information");
WindowDelegate* del = global::windowDelegate;
glm::vec2 penPosition = glm::vec2(
global::renderEngine->fontResolution().x / 2 - 50,
global::renderEngine->fontResolution().y / 3
);
std::string fn = std::to_string(global::renderEngine->frameNumber());
const WindowDelegate::Frustum frustum = del->frustumMode();
std::string fr = [](WindowDelegate::Frustum f) -> std::string {
switch (f) {
case WindowDelegate::Frustum::Mono: return "";
case WindowDelegate::Frustum::LeftEye: return "(left)";
case WindowDelegate::Frustum::RightEye: return "(right)";
default: throw ghoul::MissingCaseException();
}
}(frustum);
std::string sgFn = std::to_string(del->swapGroupFrameNumber());
std::string dt = std::to_string(del->deltaTime());
std::string avgDt = std::to_string(del->averageDeltaTime());
const std::string res = std::format(
"Frame: {} {}\nSwap group frame: {}\nDt: {}\nAvg Dt: {}",
fn, fr, sgFn, dt, avgDt
);
RenderFont(*_fontFrameInfo, penPosition, res);
}
});
}
void DebuggingModule::internalInitialize(const ghoul::Dictionary&) {
ghoul::TemplateFactory<Renderable>* fRenderable =
@@ -55,6 +143,11 @@ void DebuggingModule::internalInitialize(const ghoul::Dictionary&) {
fRenderable->registerClass<RenderableDebugPlane>("RenderableDebugPlane");
}
void DebuggingModule::internalInitializeGL() {
const Configuration::FontSizes fontSize = global::configuration->fontSize;
_fontFrameInfo = global::fontManager->font(KeyFontMono, fontSize.frameInfo);
}
std::vector<documentation::Documentation> DebuggingModule::documentations() const {
return {
RenderableDebugPlane::Documentation()
@@ -63,13 +156,15 @@ std::vector<documentation::Documentation> DebuggingModule::documentations() cons
scripting::LuaLibrary DebuggingModule::luaLibrary() const {
return {
"debugging",
{
.name = "debugging",
.functions = {
codegen::lua::RenderCameraPath,
codegen::lua::RemoveRenderedCameraPath,
codegen::lua::RenderPathControlPoints,
codegen::lua::RemovePathControlPoints,
codegen::lua::AddCartesianAxes
codegen::lua::RemovePathControlPoints
},
.scripts = {
absPath("${MODULE_DEBUGGING}/scripts/axes.lua")
}
};
}
+12
View File
@@ -27,6 +27,10 @@
#include <openspace/util/openspacemodule.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <ghoul/font/font.h>
namespace openspace {
class DebuggingModule : public OpenSpaceModule {
@@ -41,6 +45,14 @@ public:
protected:
void internalInitialize(const ghoul::Dictionary&) override;
void internalInitializeGL() override;
private:
properties::BoolProperty _showStatistics;
properties::FloatProperty _statisticsScale;
properties::BoolProperty _showFrameInformation;
std::shared_ptr<ghoul::fontrendering::Font> _fontFrameInfo;
};
} // namespace openspace
+11 -83
View File
@@ -64,11 +64,7 @@ constexpr glm::vec3 OrientationLineColor = glm::vec3(0.0, 1.0, 1.0);
RenderedPathIdentifier
);
global::scriptEngine->queueScript(
addParentScript,
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
);
global::scriptEngine->queueScript(addParentScript);
// Get the poses along the path
std::vector<CameraPose> poses;
@@ -98,9 +94,7 @@ constexpr glm::vec3 OrientationLineColor = glm::vec3(0.0, 1.0, 1.0);
"}";
global::scriptEngine->queueScript(
std::format("openspace.addSceneGraphNode({})", pointNode),
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
std::format("openspace.addSceneGraphNode({})", pointNode)
);
};
@@ -121,9 +115,7 @@ constexpr glm::vec3 OrientationLineColor = glm::vec3(0.0, 1.0, 1.0);
"}";
global::scriptEngine->queueScript(
std::format("openspace.addSceneGraphNode({})", lineNode),
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
std::format("openspace.addSceneGraphNode({})", lineNode)
);
};
@@ -158,11 +150,10 @@ constexpr glm::vec3 OrientationLineColor = glm::vec3(0.0, 1.0, 1.0);
// Removes the currently rendered camera path if there is one.
[[codegen::luawrap]] void removeRenderedCameraPath() {
using namespace openspace;
global::scriptEngine->queueScript(
std::format("openspace.removeSceneGraphNode('{}');", RenderedPathIdentifier),
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
const std::string script = std::format(
"openspace.removeSceneGraphNode('{}');", RenderedPathIdentifier
);
global::scriptEngine->queueScript(script);
}
/**
@@ -191,11 +182,7 @@ constexpr glm::vec3 OrientationLineColor = glm::vec3(0.0, 1.0, 1.0);
RenderedPointsIdentifier
);
global::scriptEngine->queueScript(
addParentScript,
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
);
global::scriptEngine->queueScript(addParentScript);
const std::vector<glm::dvec3> points = currentPath->controlPoints();
@@ -230,9 +217,7 @@ constexpr glm::vec3 OrientationLineColor = glm::vec3(0.0, 1.0, 1.0);
"}";
global::scriptEngine->queueScript(
std::format("openspace.addSceneGraphNode({})", node),
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
std::format("openspace.addSceneGraphNode({})", node)
);
}
}
@@ -240,67 +225,10 @@ constexpr glm::vec3 OrientationLineColor = glm::vec3(0.0, 1.0, 1.0);
// Removes the rendered control points.
[[codegen::luawrap]] void removePathControlPoints() {
using namespace openspace;
global::scriptEngine->queueScript(
std::format("openspace.removeSceneGraphNode('{}');", RenderedPointsIdentifier),
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
);
}
/**
* Adds a set of Cartesian axes to the scene graph node identified by the first string, to
* illustrate its local coordinate system. The second (optional) argument is a scale
* value, in meters.
*/
[[codegen::luawrap]] void addCartesianAxes(std::string nodeIdentifier,
std::optional<double> scale)
{
using namespace openspace;
SceneGraphNode* n = global::renderEngine->scene()->sceneGraphNode(nodeIdentifier);
if (!n) {
throw ghoul::lua::LuaError("Unknown scene graph node: " + nodeIdentifier);
}
if (!scale.has_value()) {
scale = 2.0 * n->boundingSphere();
if (n->boundingSphere() <= 0.0) {
LWARNINGC(
"Debugging: Cartesian Axes",
"Using zero bounding sphere for scale of created axes. You need to set "
"the scale manually for them to be visible"
);
scale = 1.0;
}
}
const std::string identifier = makeIdentifier(nodeIdentifier + "_AxesXYZ");
const std::string& axes = "{"
"Identifier = '" + identifier + "',"
"Parent = '" + nodeIdentifier + "',"
"Transform = { "
"Scale = {"
"Type = 'StaticScale',"
"Scale = " + std::to_string(*scale) + ""
"}"
"},"
"Renderable = {"
"Type = 'RenderableCartesianAxes',"
"Enabled = true,"
"XColor = { 1.0, 0.0, 0.0 },"
"YColor = { 0.0, 1.0, 0.0 },"
"ZColor = { 0.0, 0.0, 1.0 }"
"},"
"GUI = {"
"Name = '" + identifier + "',"
"Path = '" + DebuggingGuiPath + "/Coordiante Systems'"
"}"
"}";
global::scriptEngine->queueScript(
std::format("openspace.addSceneGraphNode({});", axes),
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
const std::string script = std::format(
"openspace.removeSceneGraphNode('{}');", RenderedPointsIdentifier
);
global::scriptEngine->queueScript(script);
}
#include "debuggingmodule_lua_codegen.cpp"
+47
View File
@@ -0,0 +1,47 @@
openspace.debugging.documentation = {
{
Name = "createCoordinateAxes",
Arguments = {
{ "nodeIdentifier", "String?" },
{ "scale", "Number?" }
},
Documentation = [[
Creates a new scene graph node that show the coordinate system used for the
currently selected focus node. The first argument specifies the name of the
scene graph node for which the axes should be added. If this parameter is
not specified, the current focus node is used instead. The second argument
provides the length of the coordinate axis in meters. If this value is not
specified 2.5 times the interaction sphere of the selected node is used
instead.
]]
}
}
openspace.debugging.createCoordinateAxes = function (nodeIdentifier, scale)
local node = nodeIdentifier or openspace.navigation.getNavigationState().Anchor
local sphere = openspace.propertyValue("Scene." .. node .. ".EvaluatedInteractionSphere")
if sphere == -1 then
sphere = 1
end
local size = scale or sphere * 2.5
local nodespec = {
Identifier = node .. "_DebugAxes",
Parent = node,
Transform = {
Scale = {
Type = "StaticScale",
Scale = size
}
},
Renderable = {
Type = "RenderableCartesianAxes"
},
GUI = {
Name = node .. " (Debug Axes)",
Path = openspace.propertyValue("Scene." .. node .. ".GuiPath")
}
}
openspace.addSceneGraphNode(nodespec)
end
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
# software and associated documentation files (the "Software"), to deal in the Software #
@@ -34,7 +34,6 @@
namespace openspace {
ghoul::opengl::ProgramObjectManager DigitalUniverseModule::ProgramObjectManager;
ghoul::opengl::TextureManager DigitalUniverseModule::TextureManager;
DigitalUniverseModule::DigitalUniverseModule()
: OpenSpaceModule(DigitalUniverseModule::Name)
@@ -50,7 +49,6 @@ void DigitalUniverseModule::internalInitialize(const ghoul::Dictionary&) {
void DigitalUniverseModule::internalDeinitializeGL() {
ProgramObjectManager.releaseAll(ghoul::opengl::ProgramObjectManager::Warnings::Yes);
TextureManager.releaseAll(ghoul::opengl::TextureManager::Warnings::Yes);
}
std::vector<documentation::Documentation> DigitalUniverseModule::documentations() const {
@@ -28,7 +28,6 @@
#include <openspace/util/openspacemodule.h>
#include <ghoul/opengl/programobjectmanager.h>
#include <ghoul/opengl/texturemanager.h>
namespace openspace {
@@ -41,7 +40,6 @@ public:
std::vector<documentation::Documentation> documentations() const override;
static ghoul::opengl::ProgramObjectManager ProgramObjectManager;
static ghoul::opengl::TextureManager TextureManager;
protected:
void internalInitialize(const ghoul::Dictionary&) override;
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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
View File
@@ -94,6 +94,15 @@ namespace {
openspace::properties::Property::Visibility::AdvancedUser
};
constexpr openspace::properties::Property::PropertyInfo PlanetDefaultTextureInfo = {
"PlanetDefaultTexture",
"Planet Default Texture",
"The path to an image that should be used by default for the planets in all "
"added exoplanet systems. If not specified, the planets are rendered without a "
"texture when added.",
openspace::properties::Property::Visibility::AdvancedUser
};
constexpr openspace::properties::Property::PropertyInfo OrbitDiscTextureInfo = {
"OrbitDiscTexture",
"Orbit Disc Texture",
@@ -182,6 +191,9 @@ namespace {
// [[codegen::verbatim(NoDataTextureInfo.description)]]
std::optional<std::filesystem::path> noDataTexture;
// [[codegen::verbatim(PlanetDefaultTextureInfo.description)]]
std::optional<std::filesystem::path> planetDefaultTexture;
// [[codegen::verbatim(OrbitDiscTextureInfo.description)]]
std::optional<std::filesystem::path> orbitDiscTexture;
@@ -221,6 +233,7 @@ ExoplanetsModule::ExoplanetsModule()
, _starTexturePath(StarTextureInfo)
, _starGlareTexturePath(StarGlareTextureInfo)
, _noDataTexturePath(NoDataTextureInfo)
, _planetDefaultTexturePath(PlanetDefaultTextureInfo)
, _orbitDiscTexturePath(OrbitDiscTextureInfo)
, _habitableZoneTexturePath(HabitableZoneTextureInfo)
, _comparisonCircleColor(
@@ -244,6 +257,7 @@ ExoplanetsModule::ExoplanetsModule()
addProperty(_starTexturePath);
addProperty(_starGlareTexturePath);
addProperty(_noDataTexturePath);
addProperty(_planetDefaultTexturePath);
addProperty(_orbitDiscTexturePath);
addProperty(_habitableZoneTexturePath);
@@ -301,6 +315,10 @@ std::filesystem::path ExoplanetsModule::noDataTexturePath() const {
return _noDataTexturePath.value();
}
std::filesystem::path ExoplanetsModule::planetDefaultTexturePath() const {
return _planetDefaultTexturePath.value();
}
std::filesystem::path ExoplanetsModule::orbitDiscTexturePath() const {
return _orbitDiscTexturePath.value();
}
@@ -354,6 +372,10 @@ void ExoplanetsModule::internalInitialize(const ghoul::Dictionary& dict) {
_starGlareTexturePath = p.starGlareTexture->string();
}
if (p.planetDefaultTexture.has_value()) {
_planetDefaultTexturePath = p.planetDefaultTexture->string();
}
if (p.noDataTexture.has_value()) {
_noDataTexturePath = p.noDataTexture->string();
}
+2
View File
@@ -51,6 +51,7 @@ public:
std::filesystem::path starTexturePath() const;
std::filesystem::path starGlareTexturePath() const;
std::filesystem::path noDataTexturePath() const;
std::filesystem::path planetDefaultTexturePath() const;
std::filesystem::path orbitDiscTexturePath() const;
std::filesystem::path habitableZoneTexturePath() const;
glm::vec3 comparisonCircleColor() const;
@@ -72,6 +73,7 @@ protected:
properties::StringProperty _starTexturePath;
properties::StringProperty _starGlareTexturePath;
properties::StringProperty _noDataTexturePath;
properties::StringProperty _planetDefaultTexturePath;
properties::StringProperty _orbitDiscTexturePath;
properties::StringProperty _habitableZoneTexturePath;
+79 -49
View File
@@ -105,6 +105,17 @@ openspace::exoplanets::ExoplanetSystem findExoplanetSystemInData(
return system;
}
void queueAddSceneGraphNodeScript(const std::string& sgnTableAsString) {
using namespace openspace;
// No sync or send because this will already be called inside a Lua script,
// therefor it has already been synced and sent to the connected nodes and peers
global::scriptEngine->queueScript({
.code = std::format("openspace.addSceneGraphNode({})", sgnTableAsString),
.synchronized = scripting::ScriptEngine::Script::ShouldBeSynchronized::No,
.sendToRemote = scripting::ScriptEngine::Script::ShouldSendToRemote::No
});
}
void createExoplanetSystem(const std::string& starName,
openspace::exoplanets::ExoplanetSystem system)
{
@@ -155,6 +166,14 @@ void createExoplanetSystem(const std::string& starName,
if (!std::isnan(bv)) {
starColor = computeStarColor(bv);
const std::filesystem::path starTexture = module->starTexturePath();
if (!starTexture.empty() && !std::filesystem::is_regular_file(starTexture)) {
LWARNING(std::format(
"Could not find specified star texture set in {} module: '{}'",
module->guiName(), starTexture
));
}
colorLayers =
"{"
"Identifier = 'StarColor',"
@@ -211,15 +230,44 @@ void createExoplanetSystem(const std::string& starName,
"}"
"}";
// No sync or send because this is already inside a Lua script, therefor it has
// already been synced and sent to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.addSceneGraphNode(" + starParent + ");",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
queueAddSceneGraphNodeScript(starParent);
// Add a label for the star.
// The fade values are set based on the values for the Sun label
const std::string starLabel = "{"
"Identifier = '" + starIdentifier + "_Label',"
"Parent = '" + starIdentifier + "',"
"Renderable = {"
"Type = 'RenderableLabel',"
"Enabled = false,"
"Text = '" + sanitizedStarName + "',"
"FontSize = 70.0,"
"Size = 14.17,"
"MinMaxSize = { 1, 50 },"
"EnableFading = true,"
"FadeUnit = 'pc',"
"FadeDistances = { 1.33, 15.0 },"
"FadeWidths = {1.0, 20.0}"
"},"
"Tag = {'exoplanet_system_labels'},"
"GUI = {"
"Name = '" + sanitizedStarName + " Label',"
"Path = '" + guiPath + "'"
"}"
"}";
queueAddSceneGraphNodeScript(starLabel);
// Planets
const std::filesystem::path planetTexture = module->planetDefaultTexturePath();
if (!planetTexture.empty() && !std::filesystem::is_regular_file(planetTexture)) {
LWARNING(std::format(
"Could not find specified planet default texture set in {} module: '{}'",
module->guiName(), planetTexture
));
}
for (size_t i = 0; i < system.planetNames.size(); i++) {
// Note that we are here overriding some invalid parameters in the planet data.
// Use a reference, so that it is changed down the line
@@ -286,6 +334,16 @@ void createExoplanetSystem(const std::string& starName,
"Period = " + std::to_string(periodInSeconds) + ""
"}";
std::string planetLayers = "";
if (!planetTexture.empty()) {
planetLayers = "{"
"Identifier = 'PlanetTexture',"
"FilePath = openspace.absPath('" + formatPathToLua(planetTexture) + "'),"
"BlendMode = 'Color',"
"Enabled = true"
"}";
}
const std::string planetNode = "{"
"Identifier = '" + planetIdentifier + "',"
"Parent = '" + starIdentifier + "',"
@@ -294,7 +352,9 @@ void createExoplanetSystem(const std::string& starName,
"Enabled = " + enabled + ","
"Radii = " + std::to_string(planetRadius) + "," // in meters
"PerformShading = true,"
"Layers = {},"
"Layers = {"
"ColorLayers = {" + planetLayers + "}"
"},"
"LightSourceNode = '" + starIdentifier + "'"
"},"
"Transform = { "
@@ -330,14 +390,8 @@ void createExoplanetSystem(const std::string& starName,
"}"
"}";
// No sync or send because this is already inside a Lua script, therefor it has
// already been synced and sent to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.addSceneGraphNode(" + planetTrailNode + ");"
"openspace.addSceneGraphNode(" + planetNode + ");",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
queueAddSceneGraphNodeScript(planetTrailNode);
queueAddSceneGraphNodeScript(planetNode);
bool hasUpperAUncertainty = !std::isnan(planet.aUpper);
bool hasLowerAUncertainty = !std::isnan(planet.aLower);
@@ -387,13 +441,7 @@ void createExoplanetSystem(const std::string& starName,
"}"
"}";
// No sync or send because this is already inside a Lua script, therefor it
// has already been synced and sent to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.addSceneGraphNode(" + discNode + ");",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
queueAddSceneGraphNodeScript(discNode);
}
}
@@ -437,13 +485,7 @@ void createExoplanetSystem(const std::string& starName,
"}"
"}";
// No sync or send because this is already inside a Lua script, therefor it has
// already been synced and sent to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.addSceneGraphNode(" + circle + ");",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
queueAddSceneGraphNodeScript(circle);
// Habitable Zone
bool hasTeff = !std::isnan(system.starData.teff);
@@ -491,13 +533,7 @@ void createExoplanetSystem(const std::string& starName,
"}"
"}";
// No sync or send because this is already inside a Lua script, therefor it has
// already been synced and sent to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.addSceneGraphNode(" + zoneDiscNode + ");",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
queueAddSceneGraphNodeScript(zoneDiscNode);
// Star glare
if (starColor.has_value()) {
@@ -535,13 +571,7 @@ void createExoplanetSystem(const std::string& starName,
"}"
"}";
// No sync or send because this is already inside a Lua script, therefor it
// has already been synced and sent to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.addSceneGraphNode(" + starGlare + ");",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
queueAddSceneGraphNodeScript(starGlare);
}
}
}
@@ -650,11 +680,11 @@ std::vector<std::string> hostStarsWithSufficientData() {
// No sync or send because this is already inside a Lua script, therefor it has
// already been synced and sent to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.removeSceneGraphNode('" + starIdentifier + "');",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript({
.code = "openspace.removeSceneGraphNode('" + starIdentifier + "');",
.synchronized = scripting::ScriptEngine::Script::ShouldBeSynchronized::No,
.sendToRemote = scripting::ScriptEngine::Script::ShouldSendToRemote::No
});
}
/**
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
+95 -71
View File
@@ -1,102 +1,126 @@
openspace.gaia.documentation = {
{
Name = "addClippingBox",
Arguments = {{ "name", "String" },{ "size", "vec3" }, { "position", "vec3" }},
Documentation = "Creates a clipping box for the Gaia renderable in the first argument"
{
Name = "addClippingBox",
Arguments = {
{ "name", "String" },
{ "size", "vec3" },
{ "position", "vec3" }
},
{
Name = "removeClippingBox",
Arguments = {},
Documentation = ""
Documentation = "Creates a clipping box for the Gaia renderable in the first argument"
},
{
Name = "removeClippingBox",
Arguments = {},
Documentation = ""
},
{
Name = "addClippingSphere",
Arguments = {
{ "name", "String" },
{ "radius", "Number" }
},
{
Name = "addClippingSphere",
Arguments = {{ "name", "String" }, { "radius", "Number" }},
Documentation = "Creates a clipping sphere for the Gaia renderable in the first argument"
}
Documentation = "Creates a clipping sphere for the Gaia renderable in the first argument"
}
}
openspace.gaia.addClippingBox = function (name, size, position)
local grid_identifier = "Filtering_Box"
local kilo_parsec_in_meter = 30856775814913700000
local grid_identifier = "Filtering_Box"
local kilo_parsec_in_meter = 30856775814913700000
if openspace.hasSceneGraphNode(grid_identifier) then
openspace.removeSceneGraphNode(grid_identifier)
end
if openspace.hasSceneGraphNode(grid_identifier) then
openspace.removeSceneGraphNode(grid_identifier)
end
local grid = {
Identifier = grid_identifier,
Transform = {
Translation = {
Type = "StaticTranslation",
Position = { position[1] * kilo_parsec_in_meter, position[2] * kilo_parsec_in_meter, position[3] * kilo_parsec_in_meter }
}
},
Renderable = {
Type = "RenderableBoxGrid",
Color = { 0.6, 0.5, 0.7 },
LineWidth = 2.0,
Size = { size[1] * kilo_parsec_in_meter, size[2] * kilo_parsec_in_meter, size[3] * kilo_parsec_in_meter}
},
GUI = {
Name = "Filtering Grid",
Path = "/Other/Grids"
local grid = {
Identifier = grid_identifier,
Transform = {
Translation = {
Type = "StaticTranslation",
Position = {
position[1] * kilo_parsec_in_meter,
position[2] * kilo_parsec_in_meter,
position[3] * kilo_parsec_in_meter
}
}
},
Renderable = {
Type = "RenderableBoxGrid",
Color = { 0.6, 0.5, 0.7 },
LineWidth = 2.0,
Size = {
size[1] * kilo_parsec_in_meter,
size[2] * kilo_parsec_in_meter,
size[3] * kilo_parsec_in_meter
}
},
GUI = {
Name = "Filtering Grid",
Path = "/Other/Grids"
}
}
openspace.addSceneGraphNode(grid)
openspace.addSceneGraphNode(grid)
openspace.setPropertyValue('Scene.' .. name .. '.renderable.FilterPosX', { (position[1] - size[1] / 2) * kilo_parsec_in_meter, (position[1] + size[1] / 2) * kilo_parsec_in_meter })
openspace.setPropertyValue('Scene.' .. name .. '.renderable.FilterPosY', { (position[2] - size[2] / 2) * kilo_parsec_in_meter, (position[2] + size[2] / 2) * kilo_parsec_in_meter })
openspace.setPropertyValue('Scene.' .. name .. '.renderable.FilterPosZ', { (position[3] - size[3] / 2) * kilo_parsec_in_meter, (position[3] + size[3] / 2) * kilo_parsec_in_meter })
openspace.setPropertyValue(
"Scene." .. name .. ".renderable.FilterPosX",
{ (position[1] - size[1] / 2) * kilo_parsec_in_meter, (position[1] + size[1] / 2) * kilo_parsec_in_meter }
)
openspace.setPropertyValue(
"Scene." .. name .. ".renderable.FilterPosY",
{ (position[2] - size[2] / 2) * kilo_parsec_in_meter, (position[2] + size[2] / 2) * kilo_parsec_in_meter }
)
openspace.setPropertyValue(
"Scene." .. name .. ".renderable.FilterPosZ",
{ (position[3] - size[3] / 2) * kilo_parsec_in_meter, (position[3] + size[3] / 2) * kilo_parsec_in_meter }
)
end
openspace.gaia.removeClippingBox = function()
local grid_identifier = "Filtering_Box"
local grid_identifier = "Filtering_Box"
if openspace.hasSceneGraphNode(grid_identifier) then
openspace.removeSceneGraphNode(grid_identifier)
end
if openspace.hasSceneGraphNode(grid_identifier) then
openspace.removeSceneGraphNode(grid_identifier)
end
end
openspace.gaia.addClippingSphere = function (name, radius)
local grid_identifier = "Filtering_Sphere"
local kilo_parsec_in_meter = 30856775814913700000
local grid_identifier = "Filtering_Sphere"
local kilo_parsec_in_meter = 30856775814913700000
if openspace.hasSceneGraphNode(grid_identifier) then
openspace.removeSceneGraphNode(grid_identifier)
end
if openspace.hasSceneGraphNode(grid_identifier) then
openspace.removeSceneGraphNode(grid_identifier)
end
local grid = {
Identifier = grid_identifier,
Transform = {
Scale = {
Type = "StaticScale",
Scale = radius * kilo_parsec_in_meter
}
},
Renderable = {
Type = "RenderableSphericalGrid",
Color = { 0.6, 0.5, 0.7 },
LineWidth = 1.0,
},
GUI = {
Name = "Filtering Sphere",
Path = "/Other/Grids"
}
local grid = {
Identifier = grid_identifier,
Transform = {
Scale = {
Type = "StaticScale",
Scale = radius * kilo_parsec_in_meter
}
},
Renderable = {
Type = "RenderableSphericalGrid",
Color = { 0.6, 0.5, 0.7 },
LineWidth = 1.0,
},
GUI = {
Name = "Filtering Sphere",
Path = "/Other/Grids"
}
}
openspace.addSceneGraphNode(grid)
openspace.addSceneGraphNode(grid)
openspace.setPropertyValue('Scene.' .. name .. '.renderable.FilterDist', radius * kilo_parsec_in_meter)
openspace.setPropertyValue("Scene." .. name .. ".renderable.FilterDist", radius * kilo_parsec_in_meter)
end
openspace.gaia.removeClippingSphere = function()
local grid_identifier = "Filtering_Sphere"
local grid_identifier = "Filtering_Sphere"
if openspace.hasSceneGraphNode(grid_identifier) then
openspace.removeSceneGraphNode(grid_identifier)
end
if openspace.hasSceneGraphNode(grid_identifier) then
openspace.removeSceneGraphNode(grid_identifier)
end
end
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
+3 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
@@ -74,6 +74,7 @@ set(HEADER_FILES
src/tileprovider/texttileprovider.h
src/tileprovider/tileindextileprovider.h
src/tileprovider/tileprovider.h
src/tileprovider/tileproviderbydate.h
src/tileprovider/tileproviderbyindex.h
src/tileprovider/tileproviderbylevel.h
)
@@ -120,6 +121,7 @@ set(SOURCE_FILES
src/tileprovider/texttileprovider.cpp
src/tileprovider/tileindextileprovider.cpp
src/tileprovider/tileprovider.cpp
src/tileprovider/tileproviderbydate.cpp
src/tileprovider/tileproviderbyindex.cpp
src/tileprovider/tileproviderbylevel.cpp
)
@@ -48,6 +48,7 @@
#include <modules/globebrowsing/src/tileprovider/temporaltileprovider.h>
#include <modules/globebrowsing/src/tileprovider/tileindextileprovider.h>
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
#include <modules/globebrowsing/src/tileprovider/tileproviderbydate.h>
#include <modules/globebrowsing/src/tileprovider/tileproviderbyindex.h>
#include <modules/globebrowsing/src/tileprovider/tileproviderbylevel.h>
#include <openspace/camera/camera.h>
@@ -310,6 +311,7 @@ void GlobeBrowsingModule::internalInitialize(const ghoul::Dictionary& dict) {
fTileProvider->registerClass<TemporalTileProvider>("TemporalTileProvider");
fTileProvider->registerClass<TileIndexTileProvider>("TileIndexTileProvider");
fTileProvider->registerClass<SizeReferenceTileProvider>("SizeReferenceTileProvider");
fTileProvider->registerClass<TileProviderByDate>("TileProviderByDate");
fTileProvider->registerClass<TileProviderByLevel>("TileProviderByLevel");
fTileProvider->registerClass<TileProviderByIndex>("TileProviderByIndex");
@@ -338,6 +340,7 @@ std::vector<documentation::Documentation> GlobeBrowsingModule::documentations()
globebrowsing::SizeReferenceTileProvider::Documentation(),
globebrowsing::TemporalTileProvider::Documentation(),
globebrowsing::TileIndexTileProvider::Documentation(),
globebrowsing::TileProviderByDate::Documentation(),
globebrowsing::TileProviderByIndex::Documentation(),
globebrowsing::TileProviderByLevel::Documentation(),
globebrowsing::GeoJsonManager::Documentation(),
@@ -284,7 +284,8 @@ namespace {
* \param y The y value of the tile index
* \param level The level of the tile index
*/
[[codegen::luawrap]] void goToChunk(std::string globeIdentifier, int x, int y, int level) {
[[codegen::luawrap]] void goToChunk(std::string globeIdentifier, int x, int y, int level)
{
using namespace openspace;
using namespace globebrowsing;
@@ -495,8 +496,8 @@ void flyToGeoInternal(std::string globe, double latitude,
}
/**
* Fly the camera to a geographic coordinate (latitude, longitude and altitude) on a globe,
* using the path navigation system.
* Fly the camera to a geographic coordinate (latitude, longitude and altitude) on a
* globe, using the path navigation system.
*
* \param globe The identifier of a scene graph node that has a RenderableGlobe attached.
* If an empty string is provided, the current anchor node is used
+370 -333
View File
@@ -1,396 +1,433 @@
openspace.globebrowsing.documentation = {
{
Name = "createTemporalGibsGdalXml",
Arguments = {{ "layerName", "String" }, { "resolution", "String" }, { "format", "String" }},
Documentation = [[
Creates an XML configuration for a temporal GIBS dataset to be used in
a TemporalTileprovider
]]
{
Name = "createTemporalGibsGdalXml",
Arguments = {
{ "layerName", "String" },
{ "resolution", "String" },
{ "format", "String" }
},
{
Name = "createGibsGdalXml",
Arguments = {{ "layerName", "String" }, { "date", "String" }, { "resolution", "String" }, { "format", "String" }},
Documentation =
"Creates an XML configuration for a GIBS dataset." ..
"Arguments are: layerName, date, resolution, format." ..
"For all specifications, see " ..
"https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+Available+Imagery+Products" ..
"Usage:" ..
"openspace.globebrowsing.addLayer(" ..
"\"Earth\"," ..
"\"ColorLayers\"," ..
"{" ..
"Name = \"MODIS_Terra_Chlorophyll_A\"," ..
"FilePath = openspace.globebrowsing.createGibsGdalXml(" ..
"\"MODIS_Terra_Chlorophyll_A\"," ..
"\"2013-07-02\"," ..
"\"1km\"," ..
"\"png\"" ..
")" ..
"}" ..
")"
Documentation = [[
Creates an XML configuration for a temporal GIBS dataset to be used in a
TemporalTileprovider
]]
},
{
Name = "createGibsGdalXml",
Arguments = {
{ "layerName", "String" },
{ "date", "String" },
{ "resolution", "String" },
{ "format", "String" }
},
{
Name = "addGibsLayer",
Arguments = {{ "layer", "String" }, { "resolution", "String" }, { "format", "String" }, { "startDate", "String" }, { "endDate", "String" }},
Documentation = "Adds a new layer from NASA GIBS to the Earth globe. Arguments " ..
"are: imagery layer name, imagery resolution, start date, end date, format. " ..
"For all specifications, see " ..
"https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+Available+Imagery+Products" ..
"Usage:" ..
"openspace.globebrowsing.addGibsLayer('AIRS_Temperature_850hPa_Night', '2km', '2013-07-15', 'Present', 'png')"
Documentation = [[
Creates an XML configuration for a GIBS dataset.
Arguments are: layerName, date, resolution, format.
For all specifications, see
https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+Available+Imagery+Products
Usage:
openspace.globebrowsing.addLayer(
"Earth",
"ColorLayers",
{
Name = "MODIS_Terra_Chlorophyll_A",
FilePath = openspace.globebrowsing.createGibsGdalXml(
"MODIS_Terra_Chlorophyll_A",
"2013-07-02",
"1km",
"png"
)
}
)
]]
},
{
Name = "addGibsLayer",
Arguments = {
{ "layer", "String" },
{ "resolution", "String" },
{ "format", "String" },
{ "startDate", "String" },
{ "endDate", "String" }
},
{
Name = "parseInfoFile",
Arguments = {{ "file", "String" }},
Documentation =
"Parses the passed info file and return the table with the information " ..
"provided in the info file. The return table contains the optional keys: " ..
"'Color', 'Height', 'Node', 'Location', 'Identifier'." ..
"Usage: local t = openspace.globebrowsing.parseInfoFile(file)" ..
"openspace.globebrowsing.addLayer(\"Earth\", \"ColorLayers\", t.color)" ..
"openspace.globebrowsing.addLayer(\"Earth\", \"HeightLayers\", t.height)"
Documentation = [[
Adds a new layer from NASA GIBS to the Earth globe. Arguments are: imagery layer
name, imagery resolution, start date, end date, format.
For all specifications, see
https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+Available+Imagery+Products
Usage:
openspace.globebrowsing.addGibsLayer(
"AIRS_Temperature_850hPa_Night", "2km", "2013-07-15", "Present", "png"
)
]]
},
{
Name = "parseInfoFile",
Arguments = {
{ "file", "String" }
},
{
Name = "addBlendingLayersFromDirectory",
Arguments = {{ "directory", "String" }, { "nodeName", "String" }},
Documentation =
"Retrieves all info files recursively in the directory passed as the first " ..
"argument to this function. The color and height tables retrieved from these " ..
"info files are then added to the RenderableGlobe identified by name passed " ..
"to the second argument." ..
"Usage: openspace.globebrowsing.addBlendingLayersFromDirectory(directory, \"Earth\")"
Documentation = [[
Parses the passed info file and return the table with the information provided in
the info file. The return table contains the optional keys:
'Color', 'Height', 'Node', 'Location', 'Identifier'.
Usage:
local t = openspace.globebrowsing.parseInfoFile(file)
openspace.globebrowsing.addLayer("Earth", "ColorLayers", t.color)
openspace.globebrowsing.addLayer("Earth", "HeightLayers", t.height)
]]
},
{
Name = "addBlendingLayersFromDirectory",
Arguments = {
{ "directory", "String" },
{ "nodeName", "String" }
},
{
Name = "addFocusNodesFromDirectory",
Arguments = {{ "directory", "String" }, { "nodeName", "String" }},
Documentation =
"Retrieves all info files recursively in the directory passed as the first " ..
"argument to this function. The name and location retrieved from these info " ..
"files are then used to create new SceneGraphNodes that can be used as " ..
"focus nodes. " ..
"Usage: openspace.globebrowsing.addFocusNodesFromDirectory(directory, \"Mars\")"
Documentation = [[
Retrieves all info files recursively in the directory passed as the first argument
to this function. The color and height tables retrieved from these info files are
then added to the RenderableGlobe identified by name passed to the second argument.
Usage:
openspace.globebrowsing.addBlendingLayersFromDirectory(directory, "Earth")
]]
},
{
Name = "addFocusNodesFromDirectory",
Arguments = {
{ "directory", "String" },
{ "nodeName", "String" }
},
{
Name = "addFocusNodeFromLatLong",
Arguments = {{ "name", "String" }, { "globeIdentifier", "String" }, { "latitude", "Number" }, { "longitude", "Number" }, { "altitude", "Number" }},
Documentation =
"Creates a new SceneGraphNode that can be used as focus node. " ..
"Usage: openspace.globebrowsing.addFocusNodeFromLatLong(" ..
"\"Olympus Mons\", \"Mars\", -18.65, 226.2, optionalAltitude)"
Documentation = [[
Retrieves all info files recursively in the directory passed as the first argument
to this function. The name and location retrieved from these info files are then
used to create new SceneGraphNodes that can be used as focus nodes.
Usage:
openspace.globebrowsing.addFocusNodesFromDirectory(directory, "Mars")
]]
},
{
Name = "addFocusNodeFromLatLong",
Arguments = {
{ "name", "String" },
{ "globeIdentifier", "String" },
{ "latitude", "Number" },
{ "longitude", "Number" },
{ "altitude", "Number" }
},
{
Name = "loadWMSServersFromFile",
Arguments = {{ "filePath", "String" }},
Documentation =
"Loads all WMS servers from the provided file and passes them to the " ..
"'openspace.globebrowsing.loadWMSCapabilities' file."
}
Documentation = [[
Creates a new SceneGraphNode that can be used as focus node.
Usage:
openspace.globebrowsing.addFocusNodeFromLatLong(
"Olympus Mons", "Mars", -18.65, 226.2, optionalAltitude
)
]]
},
{
Name = "loadWMSServersFromFile",
Arguments = {
{ "filePath", "String" }
},
Documentation = [[
Loads all WMS servers from the provided file and passes them to the
'openspace.globebrowsing.loadWMSCapabilities' file.
]]
}
}
openspace.globebrowsing.addGibsLayer = function(layerName, resolution, format, startDate, endDate)
if endDate == 'Present' then
endDate = ''
end
if endDate == "Present" then
endDate = ""
end
local layer = {
Identifier = layerName,
Type = "TemporalTileLayer",
Mode = "Prototyped",
Prototyped = {
Time = {
Start = startDate,
End = endDate
},
TemporalResolution = "1d",
TimeFormat = "YYYY-MM-DD",
Prototype = openspace.globebrowsing.createTemporalGibsGdalXml(layerName, resolution, format)
}
local layer = {
Identifier = layerName,
Type = "TemporalTileLayer",
Mode = "Prototyped",
Prototyped = {
Time = {
Start = startDate,
End = endDate
},
TemporalResolution = "1d",
TimeFormat = "YYYY-MM-DD",
Prototype = openspace.globebrowsing.createTemporalGibsGdalXml(layerName, resolution, format)
}
}
openspace.globebrowsing.addLayer(
'Earth',
'ColorLayers',
layer
)
openspace.globebrowsing.addLayer("Earth", "ColorLayers", layer)
end
openspace.globebrowsing.createGibsGdalXml = function (layerName, date, resolution, format)
local tileLevel = 5
-- These resolutions are defined by GIBS: https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+API+for+Developers#GIBSAPIforDevelopers-Script-levelAccessviaGDAL
if resolution == "2km" then
tileLevel = 5
elseif resolution == "1km" then
tileLevel = 6
elseif resolution == "500m" then
tileLevel = 7
elseif resolution == "250m" then
tileLevel = 8
elseif resolution == "125m" then
tileLevel = 9
elseif resolution == "62.5m" then
tileLevel = 10
elseif resolution == "31.25m" then
tileLevel = 11
elseif resolution == "15.625m" then
tileLevel = 12
else
openspace.printError("Unknown resolution: " .. resolution)
return ""
end
local tileLevel = 5
-- These resolutions are defined by GIBS: https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+API+for+Developers#GIBSAPIforDevelopers-Script-levelAccessviaGDAL
if resolution == "2km" then
tileLevel = 5
elseif resolution == "1km" then
tileLevel = 6
elseif resolution == "500m" then
tileLevel = 7
elseif resolution == "250m" then
tileLevel = 8
elseif resolution == "125m" then
tileLevel = 9
elseif resolution == "62.5m" then
tileLevel = 10
elseif resolution == "31.25m" then
tileLevel = 11
elseif resolution == "15.625m" then
tileLevel = 12
else
openspace.printError("Unknown resolution: " .. resolution)
return ""
end
local rasterCount = 3
if format == "jpg" then
if layerName == "ASTER_GDEM_Greyscale_Shaded_Relief" then
rasterCount = 1
else
rasterCount = 3
end
elseif format == "png" then
rasterCount = 4
local rasterCount = 3
if format == "jpg" then
if layerName == "ASTER_GDEM_Greyscale_Shaded_Relief" then
rasterCount = 1
else
openspace.printError("Unknown format \"" .. format .. "\". Use 'jpg' or 'png'")
return ""
rasterCount = 3
end
elseif format == "png" then
rasterCount = 4
else
openspace.printError("Unknown format \"" .. format .. "\". Use 'jpg' or 'png'")
return ""
end
local gdalWmsTemplate =
local gdalWmsTemplate =
"<GDAL_WMS>" ..
"<Service name=\"TMS\">" ..
"<ServerUrl>https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/" ..
layerName .. "/default/" .. date .. "/" .. resolution ..
"/${z}/${y}/${x}." .. format .. "</ServerUrl>" ..
"</Service>" ..
"<DataWindow>" ..
"<UpperLeftX>-180.0</UpperLeftX>" ..
"<UpperLeftY>90</UpperLeftY>" ..
"<LowerRightX>396.0</LowerRightX>" ..
"<LowerRightY>-198</LowerRightY>" ..
"<TileLevel>" .. tileLevel .. "</TileLevel>" ..
"<TileCountX>2</TileCountX>" ..
"<TileCountY>1</TileCountY>" ..
"<YOrigin>top</YOrigin>" ..
"</DataWindow>" ..
"<Projection>EPSG:4326</Projection>" ..
"<BlockSizeX>512</BlockSizeX>" ..
"<BlockSizeY>512</BlockSizeY>" ..
"<BandsCount>" .. rasterCount .. "</BandsCount>" ..
"<UnsafeSSL>true</UnsafeSSL>" ..
"<ZeroBlockHttpCodes>400,204,404</ZeroBlockHttpCodes>" ..
"<ZeroBlockOnServerException>true</ZeroBlockOnServerException>" ..
"<Timeout>5</Timeout>" ..
"<Service name=\"TMS\">" ..
"<ServerUrl>https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/" ..
layerName .. "/default/" .. date .. "/" .. resolution ..
"/${z}/${y}/${x}." .. format .. "</ServerUrl>" ..
"</Service>" ..
"<DataWindow>" ..
"<UpperLeftX>-180.0</UpperLeftX>" ..
"<UpperLeftY>90</UpperLeftY>" ..
"<LowerRightX>396.0</LowerRightX>" ..
"<LowerRightY>-198</LowerRightY>" ..
"<TileLevel>" .. tileLevel .. "</TileLevel>" ..
"<TileCountX>2</TileCountX>" ..
"<TileCountY>1</TileCountY>" ..
"<YOrigin>top</YOrigin>" ..
"</DataWindow>" ..
"<Projection>EPSG:4326</Projection>" ..
"<BlockSizeX>512</BlockSizeX>" ..
"<BlockSizeY>512</BlockSizeY>" ..
"<BandsCount>" .. rasterCount .. "</BandsCount>" ..
"<UnsafeSSL>true</UnsafeSSL>" ..
"<ZeroBlockHttpCodes>400,204,404</ZeroBlockHttpCodes>" ..
"<ZeroBlockOnServerException>true</ZeroBlockOnServerException>" ..
"<Timeout>5</Timeout>" ..
"</GDAL_WMS>"
return gdalWmsTemplate
return gdalWmsTemplate
end
openspace.globebrowsing.createTemporalGibsGdalXml = function (layerName, resolution, format)
return openspace.globebrowsing.createGibsGdalXml(layerName, "${OpenSpaceTimeId}", resolution, format)
return openspace.globebrowsing.createGibsGdalXml(layerName, "${OpenSpaceTimeId}", resolution, format)
end
openspace.globebrowsing.parseInfoFile = function (file)
-- We are loading these values from an external info file and since we are switching
-- to a strict Lua, we need to predefine these global variables
local function declare(name)
rawset(_G, name, "")
end
-- We are loading these values from an external info file and since we are switching
-- to a strict Lua, we need to predefine these global variables
local function declare(name)
rawset(_G, name, "")
end
declare("Name")
declare("Identifier")
declare("Description")
declare("ColorFile")
declare("HeightFile")
declare("Location")
declare("ZIndex")
declare("BlendMode")
declare("Name")
declare("Identifier")
declare("Description")
declare("ColorFile")
declare("HeightFile")
declare("Location")
declare("ZIndex")
declare("BlendMode")
local dir = openspace.directoryForPath(file)
local file_func, error = loadfile(file)
if file_func then
file_func()
else
openspace.printError('Error loading file "' .. file .. '": '.. error)
return nil
end
local dir = openspace.directoryForPath(file)
local file_func, error = loadfile(file)
if file_func then
file_func()
else
openspace.printError('Error loading file "' .. file .. '": '.. error)
return nil
end
-- Hoist the global variables into local space
local Name = rawget(_G, "Name")
local Identifier = rawget(_G, "Identifier")
local Description = rawget(_G, "Description")
local ColorFile = rawget(_G, "ColorFile")
local HeightFile = rawget(_G, "HeightFile")
local Location = rawget(_G, "Location")
local ZIndex = rawget(_G, "ZIndex")
local BlendMode = rawget(_G, "BlendMode")
-- Hoist the global variables into local space
local Name = rawget(_G, "Name")
local Identifier = rawget(_G, "Identifier")
local Description = rawget(_G, "Description")
local ColorFile = rawget(_G, "ColorFile")
local HeightFile = rawget(_G, "HeightFile")
local Location = rawget(_G, "Location")
local ZIndex = rawget(_G, "ZIndex")
local BlendMode = rawget(_G, "BlendMode")
-- Now we can start
local name = Name or Identifier
local identifier = Identifier
local zIndex = ZIndex
local blendMode = BlendMode
if zIndex == "" then
zIndex = nil
end
if blendMode == "" then
-- Color blending is the default for .info files if nothing else is specified
blendMode = "Color"
end
-- Now we can start
local name = Name or Identifier
local identifier = Identifier
local zIndex = ZIndex
local blendMode = BlendMode
if zIndex == "" then
zIndex = nil
end
if blendMode == "" then
-- Color blending is the default for .info files if nothing else is specified
blendMode = "Color"
end
if identifier == "" then
openspace.printError('Error loading file "' .. file .. '": No "Identifier" found')
return nil
end
if identifier == "" then
openspace.printError('Error loading file "' .. file .. '": No "Identifier" found')
return nil
end
local color = nil
if ColorFile and ColorFile ~= "" then
color = {
Identifier = identifier,
Name = name,
Description = Description or "",
FilePath = dir .. '/' .. ColorFile,
BlendMode = blendMode,
ZIndex = zIndex
}
end
local height = nil
if HeightFile and HeightFile ~= "" then
height = {
Identifier = identifier,
Name = name,
Description = Description or "",
FilePath = dir .. '/' .. HeightFile,
TilePixelSize = 65,
ZIndex = zIndex
}
end
local location = nil
if Location then
location = Location
end
return {
Color = color,
Height = height,
Name = name,
Location = location,
Identifier = identifier
local color = nil
if ColorFile and ColorFile ~= "" then
color = {
Identifier = identifier,
Name = name,
Description = Description or "",
FilePath = dir .. "/" .. ColorFile,
BlendMode = blendMode,
ZIndex = zIndex
}
end
local height = nil
if HeightFile and HeightFile ~= "" then
height = {
Identifier = identifier,
Name = name,
Description = Description or "",
FilePath = dir .. "/" .. HeightFile,
TilePixelSize = 65,
ZIndex = zIndex
}
end
local location = nil
if Location then
location = Location
end
return {
Color = color,
Height = height,
Name = name,
Location = location,
Identifier = identifier
}
end
openspace.globebrowsing.addBlendingLayersFromDirectory = function (dir, node_name)
local function ends_with(str, ending)
return ending == '' or str:sub(-#ending) == ending
end
-- Walking the directory with an empty string will cause the current working directory
-- to be walked recursively. This is probably not what the users expects (and it is
-- also one of the default values in the globebrowsing customization script), so we
-- ignore the empty string here
if dir == nil or dir == '' then
openspace.printError("No directory specified")
return
end
if node_name == nil or node_name == '' then
openspace.printError("No node name specified")
return
end
local files = openspace.walkDirectoryFiles(dir, true, true)
for _, file in pairs(files) do
if file and file:find('.info') and ends_with(file, '.info') then
local t = openspace.globebrowsing.parseInfoFile(file)
if t and t.Color then
openspace.printInfo("Adding color layer '" .. t.Color["Identifier"] .. "'")
openspace.globebrowsing.addLayer(node_name, "ColorLayers", t.Color)
end
if t and t.Height then
openspace.printInfo("Adding height layer '" .. t.Height["Identifier"] .. "'")
openspace.globebrowsing.addLayer(node_name, "HeightLayers", t.Height)
end
end
local function ends_with(str, ending)
return ending == "" or str:sub(-#ending) == ending
end
-- Walking the directory with an empty string will cause the current working directory
-- to be walked recursively. This is probably not what the users expects (and it is
-- also one of the default values in the globebrowsing customization script), so we
-- ignore the empty string here
if dir == nil or dir == "" then
openspace.printError("No directory specified")
return
end
if node_name == nil or node_name == "" then
openspace.printError("No node name specified")
return
end
local files = openspace.walkDirectoryFiles(dir, true, true)
for _, file in pairs(files) do
if file and file:find(".info") and ends_with(file, ".info") then
local t = openspace.globebrowsing.parseInfoFile(file)
if t and t.Color then
openspace.printInfo("Adding color layer '" .. t.Color["Identifier"] .. "'")
openspace.globebrowsing.addLayer(node_name, "ColorLayers", t.Color)
end
if t and t.Height then
openspace.printInfo("Adding height layer '" .. t.Height["Identifier"] .. "'")
openspace.globebrowsing.addLayer(node_name, "HeightLayers", t.Height)
end
end
end
end
openspace.globebrowsing.addFocusNodesFromDirectory = function (dir, node_name)
local files = openspace.walkDirectoryFiles(dir, true, true)
local files = openspace.walkDirectoryFiles(dir, true, true)
for _, file in pairs(files) do
if file and file:find('.info') then
local t = openspace.globebrowsing.parseInfoFile(file)
for _, file in pairs(files) do
if file and file:find(".info") then
local t = openspace.globebrowsing.parseInfoFile(file)
if node_name and t and t.Location then
openspace.printInfo("Creating focus node for '" .. node_name .. "'")
if node_name and t and t.Location then
openspace.printInfo("Creating focus node for '" .. node_name .. "'")
local lat = t.Location.Center[1]
local long = t.Location.Center[2]
local lat = t.Location.Center[1]
local long = t.Location.Center[2]
local identifier = node_name .. " - " .. t.Identifier
local name = node_name .. " - " .. t.Name
local identifier = node_name .. " - " .. t.Identifier
local name = node_name .. " - " .. t.Name
openspace.addSceneGraphNode({
Identifier = identifier,
Parent = node_name,
Transform = {
Translation = {
Type = "GlobeTranslation",
Globe = node_name,
Latitude = lat,
Longitude = long,
UseHeightmap = true
}
},
GUI = {
Path = "/Other/Bookmarks",
Name = name
}
})
end
end
openspace.addSceneGraphNode({
Identifier = identifier,
Parent = node_name,
Transform = {
Translation = {
Type = "GlobeTranslation",
Globe = node_name,
Latitude = lat,
Longitude = long,
UseHeightmap = true
}
},
GUI = {
Path = "/Other/Bookmarks",
Name = name
}
})
end
end
end
end
openspace.globebrowsing.addFocusNodeFromLatLong = function (name, globe_identifier, lat, long, altitude)
altitude = altitude or 0;
altitude = altitude or 0;
local identifier = globe_identifier .. "-" .. name
local identifier = globe_identifier .. "-" .. name
openspace.addSceneGraphNode({
Identifier = identifier,
Parent = globe_identifier,
Transform = {
Translation = {
Type = "GlobeTranslation",
Globe = globe_identifier,
Latitude = lat,
Longitude = long,
FixedAltitude = altitude
}
},
GUI = {
Path = "/Other/Bookmarks",
Name = identifier
}
})
openspace.addSceneGraphNode({
Identifier = identifier,
Parent = globe_identifier,
Transform = {
Translation = {
Type = "GlobeTranslation",
Globe = globe_identifier,
Latitude = lat,
Longitude = long,
FixedAltitude = altitude
}
},
GUI = {
Path = "/Other/Bookmarks",
Name = identifier
}
})
return identifier
return identifier
end
openspace.globebrowsing.loadWMSServersFromFile = function (file_path)
local servers = dofile(file_path)
local servers = dofile(file_path)
for key, value in pairs(servers) do
local globe = key
for _,val in pairs(value) do
openspace.globebrowsing.loadWMSCapabilities(
val["Name"],
globe,
val["URL"]
)
end
for key, value in pairs(servers) do
local globe = key
for _,val in pairs(value) do
openspace.globebrowsing.loadWMSCapabilities(val["Name"], globe, val["URL"] )
end
end
end
+43 -28
View File
@@ -1,35 +1,50 @@
openspace.globebrowsing.documentation = {
{
Name = "setNodePosition",
Arguments = {{ "nodeIdentifer", "String" }, { "globeIdentifier", "String" }, { "latitude", "Number" }, { "longitude", "Number" }, { "altitude", "Number" }},
Documentation =
"Sets the position of a SceneGraphNode that has GlobeTranslation/GlobeRotations. " ..
"Usage: openspace.globebrowsing.setNodePosition(" ..
"\"Scale_StatueOfLiberty\", \"Earth\", 40.000, -117.5, optionalAltitude)"
Arguments = {
{ "nodeIdentifer", "String" },
{ "globeIdentifier", "String" },
{ "latitude", "Number" },
{ "longitude", "Number" },
{ "altitude", "Number" }
},
Documentation = [[
Sets the position of a SceneGraphNode that has GlobeTranslation/GlobeRotations.
Usage:
openspace.globebrowsing.setNodePosition(
"Scale_StatueOfLiberty", "Earth", 40.000, -117.5, optionalAltitude
)
]]
},
{
Name = "setNodePositionFromCamera",
Arguments = {{ "nodeIdentifer", "String" }, { "useAltitude", "Boolean" }},
Documentation =
"Sets the position of a SceneGraphNode that has GlobeTranslation/GlobeRotations" ..
" to match the camera. Only uses camera position not rotation. If useAltitude" ..
" is true, then the position will also be updated to the camera's altitude." ..
"Usage: openspace.globebrowsing.setNodePositionFromCamera(" ..
"\"Scale_StatueOfLiberty\", optionalUseAltitude)"
Arguments = {
{ "nodeIdentifer", "String" },
{ "useAltitude", "Boolean" }
},
Documentation = [[
Sets the position of a SceneGraphNode that has GlobeTranslation/GlobeRotations to
match the camera. Only uses camera position not rotation. If useAltitude is true,
then the position will also be updated to the camera's altitude.
Usage:
openspace.globebrowsing.setNodePositionFromCamera(
"Scale_StatueOfLiberty", optionalUseAltitude
)
]]
}
}
openspace.globebrowsing.setNodePosition = function (node_identifer, globe_identifier, lat, lon, altitude)
openspace.setParent(node_identifer, globe_identifier)
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Globe', globe_identifier);
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Latitude', lat);
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Longitude', lon);
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Rotation.Globe', globe_identifier);
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Rotation.Latitude', lat);
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Rotation.Longitude', lon);
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Globe", globe_identifier);
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Latitude", lat);
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Longitude", lon);
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Rotation.Globe", globe_identifier);
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Rotation.Latitude", lat);
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Rotation.Longitude", lon);
if (altitude) then
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Altitude', altitude);
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Altitude', altitude);
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Altitude", altitude);
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Altitude", altitude);
end
end
@@ -37,14 +52,14 @@ openspace.globebrowsing.setNodePositionFromCamera = function (node_identifer, us
local lat, lon, alt = openspace.globebrowsing.geoPositionForCamera();
local camera = openspace.navigation.getNavigationState();
openspace.setParent(node_identifer, camera.Anchor)
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Globe', camera.Anchor);
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Latitude', lat);
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Longitude', lon);
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Rotation.Globe', camera.Anchor);
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Rotation.Latitude', lat);
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Rotation.Longitude', lon);
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Globe", camera.Anchor);
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Latitude", lat);
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Longitude", lon);
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Rotation.Globe", camera.Anchor);
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Rotation.Latitude", lat);
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Rotation.Longitude", lon);
if (use_altitude) then
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Altitude', alt);
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Altitude', alt);
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Altitude", alt);
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Altitude", alt);
end
end
@@ -151,15 +151,17 @@ vec4 getSample#{layerGroup}#{i}(vec2 uv, vec3 levelWeights,
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
#elif (#{#{layerGroup}#{i}LayerType} == 5) // TileIndexTileProvider
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
#elif (#{#{layerGroup}#{i}LayerType} == 6) // TileProviderByIndex
#elif (#{#{layerGroup}#{i}LayerType} == 6) // TileProviderByDate
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
#elif (#{#{layerGroup}#{i}LayerType} == 7) // TileProviderByLevel
#elif (#{#{layerGroup}#{i}LayerType} == 7) // TileProviderByIndex
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
#elif (#{#{layerGroup}#{i}LayerType} == 8) // SolidColor
#elif (#{#{layerGroup}#{i}LayerType} == 8) // TileProviderByLevel
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
#elif (#{#{layerGroup}#{i}LayerType} == 9) // SolidColor
c.rgb = #{layerGroup}[#{i}].color;
#elif (#{#{layerGroup}#{i}LayerType} == 9) // SpoutImageProvider
#elif (#{#{layerGroup}#{i}LayerType} == 10) // SpoutImageProvider
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
#elif (#{#{layerGroup}#{i}LayerType} == 10) // VideoTileProvider
#elif (#{#{layerGroup}#{i}LayerType} == 11) // VideoTileProvider
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
#endif
@@ -860,25 +860,19 @@ void GeoJsonComponent::flyToFeature(std::optional<int> index) const {
float lat = centroidLat + _latLongOffset.value().x;
float lon = centroidLon + _latLongOffset.value().y;
global::scriptEngine->queueScript(
std::format(
"openspace.globebrowsing.flyToGeo([[{}]], {}, {}, {})",
_globeNode.owner()->identifier(), lat, lon, d
),
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
const std::string script = std::format(
"openspace.globebrowsing.flyToGeo([[{}]], {}, {}, {})",
_globeNode.owner()->identifier(), lat, lon, d
);
global::scriptEngine->queueScript(script);
}
void GeoJsonComponent::triggerDeletion() const {
global::scriptEngine->queueScript(
std::format(
"openspace.globebrowsing.deleteGeoJson([[{}]], [[{}]])",
_globeNode.owner()->identifier(), _identifier
),
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
const std::string script = std::format(
"openspace.globebrowsing.deleteGeoJson([[{}]], [[{}]])",
_globeNode.owner()->identifier(), _identifier
);
global::scriptEngine->queueScript(script);
}
} // namespace openspace::globebrowsing
+10 -10
View File
@@ -49,7 +49,7 @@ namespace {
"Latitude",
"The latitude of the location on the globe's surface. The value can range from "
"-90 to 90, with negative values representing the southern hemisphere of the "
"globe. The default value is 0.0.",
"globe.",
openspace::properties::Property::Visibility::User
};
@@ -58,15 +58,15 @@ namespace {
"Longitude",
"The longitude of the location on the globe's surface. The value can range from "
"-180 to 180, with negative values representing the western hemisphere of the "
"globe. The default value is 0.0.",
"globe.",
openspace::properties::Property::Visibility::User
};
constexpr openspace::properties::Property::PropertyInfo AngleInfo = {
"Angle",
"Angle",
"A rotation angle that can be used to rotate the object around its own y-axis, "
"which will be pointing out of the globe's surface.",
"A rotation angle (in degrees) that can be used to rotate the object around its "
"own y-axis, which will be pointing out of the globe's surface.",
openspace::properties::Property::Visibility::AdvancedUser
};
@@ -82,7 +82,8 @@ namespace {
constexpr openspace::properties::Property::PropertyInfo UseCameraInfo = {
"UseCamera",
"Use Camera",
"If this value is 'true', the lat and lon are updated to match the camera.",
"If this value is 'true', the latitute and longitude are updated each frame "
"to match the location of the camera.",
openspace::properties::Property::Visibility::AdvancedUser
};
@@ -92,10 +93,10 @@ namespace {
[[codegen::annotation("A valid scene graph node with a RenderableGlobe")]];
// [[codegen::verbatim(LatitudeInfo.description)]]
std::optional<double> latitude;
double latitude [[codegen::inrange(-90.0, 90.0)]];
// [[codegen::verbatim(LongitudeInfo.description)]]
std::optional<double> longitude;
double longitude [[codegen::inrange(-180.0, 180.0)]];
// [[codegen::verbatim(AngleInfo.description)]]
std::optional<double> angle;
@@ -132,11 +133,11 @@ GlobeRotation::GlobeRotation(const ghoul::Dictionary& dictionary)
});
addProperty(_globe);
_latitude = p.latitude.value_or(_latitude);
_latitude = p.latitude;
_latitude.onChange([this]() { setUpdateVariables(); });
addProperty(_latitude);
_longitude = p.longitude.value_or(_longitude);
_longitude = p.longitude;
_longitude.onChange([this]() { setUpdateVariables(); });
addProperty(_longitude);
@@ -151,7 +152,6 @@ GlobeRotation::GlobeRotation(const ghoul::Dictionary& dictionary)
_useCamera = p.useCamera.value_or(_useCamera);
_useCamera.onChange([this]() { setUpdateVariables(); });
addProperty(_useCamera);
}
void GlobeRotation::findGlobe() {
@@ -74,6 +74,7 @@ void GPULayerGroup::setValue(ghoul::opengl::ProgramObject& program,
case layers::Layer::ID::SizeReferenceTileProvider:
case layers::Layer::ID::TemporalTileProvider:
case layers::Layer::ID::TileIndexTileProvider:
case layers::Layer::ID::TileProviderByDate:
case layers::Layer::ID::TileProviderByIndex:
case layers::Layer::ID::TileProviderByLevel: {
const ChunkTilePile& ctp = al.chunkTilePile(
@@ -146,6 +147,7 @@ void GPULayerGroup::bind(ghoul::opengl::ProgramObject& p, const LayerGroup& laye
case layers::Layer::ID::SizeReferenceTileProvider:
case layers::Layer::ID::TemporalTileProvider:
case layers::Layer::ID::TileIndexTileProvider:
case layers::Layer::ID::TileProviderByDate:
case layers::Layer::ID::TileProviderByIndex:
case layers::Layer::ID::TileProviderByLevel: {
gal.gpuChunkTiles.resize(pileSize);
+8 -3
View File
@@ -26,6 +26,8 @@
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/globals.h>
#include <openspace/scripting/scriptengine.h>
#include <modules/globebrowsing/src/layergroup.h>
#include <modules/globebrowsing/src/layermanager.h>
#include <modules/globebrowsing/src/tileindex.h>
@@ -130,8 +132,8 @@ namespace {
std::optional<std::string> type [[codegen::inlist("DefaultTileProvider",
"SingleImageProvider", "ImageSequenceTileProvider",
"SizeReferenceTileProvider", "TemporalTileProvider", "TileIndexTileProvider",
"TileProviderByIndex", "TileProviderByLevel", "SolidColor",
"SpoutImageProvider", "VideoTileProvider")]];
"TileProviderByDate", "TileProviderByIndex", "TileProviderByLevel",
"SolidColor", "SpoutImageProvider", "VideoTileProvider")]];
// Determine whether the layer is enabled or not. If this value is not specified,
// the layer is disabled
@@ -320,7 +322,7 @@ Layer::Layer(layers::Group::ID id, const ghoul::Dictionary& layerDict, LayerGrou
_remove.onChange([this]() {
if (_tileProvider) {
_tileProvider->reset();
_parent.deleteLayer(identifier());
_parent.scheduleDeleteLayer(identifier());
}
});
@@ -342,6 +344,7 @@ Layer::Layer(layers::Group::ID id, const ghoul::Dictionary& layerDict, LayerGrou
case layers::Layer::ID::SizeReferenceTileProvider:
case layers::Layer::ID::TemporalTileProvider:
case layers::Layer::ID::TileIndexTileProvider:
case layers::Layer::ID::TileProviderByDate:
case layers::Layer::ID::TileProviderByIndex:
case layers::Layer::ID::TileProviderByLevel:
case layers::Layer::ID::VideoTileProvider:
@@ -513,6 +516,7 @@ void Layer::initializeBasedOnType(layers::Layer::ID id, ghoul::Dictionary initDi
case layers::Layer::ID::SizeReferenceTileProvider:
case layers::Layer::ID::TemporalTileProvider:
case layers::Layer::ID::TileIndexTileProvider:
case layers::Layer::ID::TileProviderByDate:
case layers::Layer::ID::TileProviderByIndex:
case layers::Layer::ID::TileProviderByLevel:
case layers::Layer::ID::VideoTileProvider:
@@ -546,6 +550,7 @@ void Layer::addVisibleProperties() {
case layers::Layer::ID::SizeReferenceTileProvider:
case layers::Layer::ID::TemporalTileProvider:
case layers::Layer::ID::TileIndexTileProvider:
case layers::Layer::ID::TileProviderByDate:
case layers::Layer::ID::TileProviderByIndex:
case layers::Layer::ID::TileProviderByLevel:
case layers::Layer::ID::VideoTileProvider:
+13 -24
View File
@@ -89,6 +89,11 @@ void LayerGroup::deinitialize() {
void LayerGroup::update() {
ZoneScoped;
for (const std::string& layer : _layersToDelete) {
deleteLayer(layer);
}
_layersToDelete.clear();
_activeLayers.clear();
for (const std::unique_ptr<Layer>& layer : _layers) {
@@ -159,23 +164,6 @@ Layer* LayerGroup::addLayer(const ghoul::Dictionary& layerDict) {
std::stable_sort(_subOwners.begin(), _subOwners.end(), compareZIndexSubOwners);
_levelBlendingEnabled.setVisibility(properties::Property::Visibility::User);
properties::PropertyOwner* layerGroup = ptr->owner();
properties::PropertyOwner* layerManager = layerGroup->owner();
// @TODO (emmbr, 2021-11-03) If the layer is added as part of the globe's
// dictionary during construction this function is called in the LayerManager's
// initialize function. This means that the layerManager does not exists yet, and
// we cannot find which SGN it belongs to... Want to avoid doing this check, so
// this should be fixed (probably as part of a cleanup/rewite of the LayerManager)
if (layerManager) {
properties::PropertyOwner* globe = layerManager->owner();
properties::PropertyOwner* sceneGraphNode = globe->owner();
global::eventEngine->publishEvent<events::EventLayerAdded>(
ptr->uri()
);
}
return ptr;
}
@@ -189,13 +177,7 @@ void LayerGroup::deleteLayer(const std::string& layerName) {
// which will no longer be valid once it is deleted
removePropertySubOwner(it->get());
(*it)->deinitialize();
properties::PropertyOwner* layerGroup = it->get()->owner();
properties::PropertyOwner* layerManager = layerGroup->owner();
properties::PropertyOwner* globe = layerManager->owner();
properties::PropertyOwner* sceneGraphNode = globe->owner();
global::eventEngine->publishEvent<events::EventLayerRemoved>(
it->get()->uri()
);
// We need to keep the name of the layer since we only get it as a reference
// and the name needs to survive the deletion
const std::string lName = layerName;
@@ -217,6 +199,10 @@ void LayerGroup::deleteLayer(const std::string& layerName) {
LERROR("Could not find layer " + layerName);
}
void LayerGroup::scheduleDeleteLayer(const std::string& layerName) {
_layersToDelete.push_back(layerName);
}
void LayerGroup::moveLayer(int oldPosition, int newPosition) {
if (_layers.size() == 1) {
ghoul_assert(
@@ -292,6 +278,9 @@ void LayerGroup::moveLayer(int oldPosition, int newPosition) {
RenderableGlobe* renderable = dynamic_cast<RenderableGlobe*>(manager->owner());
ghoul_assert(manager, "Hierarchy error: LayerManager. Owner is not RenderableGlobe");
renderable->invalidateShader();
// Notify that the layers are in a different order
global::eventEngine->publishEvent<events::EventPropertyTreeUpdated>(uri());
}
std::vector<Layer*> LayerGroup::layers() const {
+5
View File
@@ -53,6 +53,9 @@ struct LayerGroup : public properties::PropertyOwner {
Layer* addLayer(const ghoul::Dictionary& layerDict);
void deleteLayer(const std::string& layerName);
// The same as `deleteLayer` but executed later before the next frame
void scheduleDeleteLayer(const std::string& layerName);
void moveLayer(int oldPosition, int newPosition);
/**
@@ -81,6 +84,8 @@ private:
std::vector<std::unique_ptr<Layer>> _layers;
std::vector<Layer*> _activeLayers;
std::vector<std::string> _layersToDelete;
properties::BoolProperty _levelBlendingEnabled;
std::function<void(Layer*)> _onChangeCallback;
};
+6 -1
View File
@@ -84,6 +84,7 @@ struct Layer {
SizeReferenceTileProvider,
TemporalTileProvider,
TileIndexTileProvider,
TileProviderByDate,
TileProviderByIndex,
TileProviderByLevel,
SolidColor,
@@ -95,7 +96,7 @@ struct Layer {
std::string_view identifier;
};
constexpr std::array<Layer, 11> Layers = {
constexpr std::array<Layer, 12> Layers = {
Layer {
.id = Layer::ID::DefaultTileProvider,
.identifier = "DefaultTileProvider"
@@ -120,6 +121,10 @@ constexpr std::array<Layer, 11> Layers = {
.id = Layer::ID::TileIndexTileProvider,
.identifier = "TileIndexTileProvider"
},
Layer {
.id = Layer::ID::TileProviderByDate,
.identifier = "TileProviderByDate"
},
Layer {
.id = Layer::ID::TileProviderByIndex,
.identifier = "TileProviderByIndex"
+133 -116
View File
@@ -176,6 +176,13 @@ namespace {
openspace::properties::Property::Visibility::AdvancedUser
};
constexpr openspace::properties::Property::PropertyInfo AmbientIntensityInfo = {
"AmbientIntensity",
"Ambient Intensity",
"The intensity factor for the ambient light used for light shading.",
openspace::properties::Property::Visibility::User
};
constexpr openspace::properties::Property::PropertyInfo LightSourceNodeInfo = {
"LightSourceNode",
"Light Source",
@@ -253,13 +260,6 @@ namespace {
openspace::properties::Property::Visibility::Developer
};
constexpr openspace::properties::Property::PropertyInfo AmbientIntensityInfo = {
"AmbientIntensity",
"Ambient Intensity",
"The intensity factor for the ambient light used for light shading.",
openspace::properties::Property::Visibility::User
};
constexpr openspace::properties::Property::PropertyInfo NActiveLayersInfo = {
"NActiveLayers",
"Number of active layers",
@@ -276,9 +276,24 @@ namespace {
// [[codegen::verbatim(PerformShadingInfo.description)]]
std::optional<bool> performShading;
// [[codegen::verbatim(AccurateNormalsInfo.description)]]
std::optional<bool> useAccurateNormals;
// [[codegen::verbatim(AmbientIntensityInfo.description)]]
std::optional<float> ambientIntensity;
// [[codegen::verbatim(LightSourceNodeInfo.description)]]
std::optional<std::string> lightSourceNode;
// [[codegen::verbatim(RenderAtDistanceInfo.description)]]
std::optional<bool> renderAtDistance;
// [[codegen::verbatim(TargetLodScaleFactorInfo.description)]]
std::optional<float> targetLodScaleFactor;
// [[codegen::verbatim(OrenNayarRoughnessInfo.description)]]
std::optional<float> orenNayarRoughness;
// A list of layers that should be added to the globe.
std::optional<std::map<std::string, ghoul::Dictionary>> layers
[[codegen::reference("globebrowsing_layermanager")]];
@@ -314,9 +329,6 @@ namespace {
std::optional<ghoul::Dictionary> shadows
[[codegen::reference("globebrowsing_shadows_component")]];
// [[codegen::verbatim(LightSourceNodeInfo.description)]]
std::optional<std::string> lightSourceNode;
};
#include "renderableglobe_codegen.cpp"
} // namespace
@@ -570,6 +582,17 @@ documentation::Documentation RenderableGlobe::Documentation() {
RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _performShading(PerformShadingInfo, true)
, _useAccurateNormals(AccurateNormalsInfo, false)
, _ambientIntensity(AmbientIntensityInfo, 0.05f, 0.f, 1.f)
, _lightSourceNodeName(LightSourceNodeInfo)
, _renderAtDistance(RenderAtDistanceInfo, false)
, _eclipseShadowsEnabled(EclipseInfo, false)
, _eclipseHardShadows(EclipseHardShadowsInfo, false)
, _targetLodScaleFactor(TargetLodScaleFactorInfo, 15.f, 1.f, 50.f)
, _currentLodScaleFactor(CurrentLodScaleFactorInfo, 15.f, 1.f, 50.f)
, _orenNayarRoughness(OrenNayarRoughnessInfo, 0.f, 0.f, 1.f)
, _nActiveLayers(NActiveLayersInfo, 0, 0, OpenGLCap.maxTextureUnits() / 3)
, _debugProperties({
BoolProperty(ShowChunkEdgeInfo, false),
BoolProperty(LevelProjectedAreaInfo, true),
@@ -578,31 +601,20 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
IntProperty(ModelSpaceRenderingInfo, 14, 1, 22),
IntProperty(DynamicLodIterationCountInfo, 16, 4, 128)
})
, _generalProperties({
BoolProperty(PerformShadingInfo, true),
BoolProperty(AccurateNormalsInfo, false),
BoolProperty(EclipseInfo, false),
BoolProperty(EclipseHardShadowsInfo, false),
BoolProperty(ShadowMappingInfo, false),
BoolProperty(RenderAtDistanceInfo, false),
FloatProperty(ZFightingPercentageInfo, 0.995f, 0.000001f, 1.f),
IntProperty(NumberShadowSamplesInfo, 5, 1, 7),
FloatProperty(TargetLodScaleFactorInfo, 15.f, 1.f, 50.f),
FloatProperty(CurrentLodScaleFactorInfo, 15.f, 1.f, 50.f),
FloatProperty(OrenNayarRoughnessInfo, 0.f, 0.f, 1.f),
FloatProperty(AmbientIntensityInfo, 0.05f, 0.f, 1.f),
IntProperty(NActiveLayersInfo, 0, 0, OpenGLCap.maxTextureUnits() / 3)
})
, _debugPropertyOwner({ "Debug" })
, _shadowMappingPropertyOwner({ "ShadowMapping" })
, _shadowMappingProperties({
BoolProperty(ShadowMappingInfo, false),
FloatProperty(ZFightingPercentageInfo, 0.995f, 0.000001f, 1.f),
IntProperty(NumberShadowSamplesInfo, 5, 1, 7)
})
, _shadowMappingPropertyOwner({ "ShadowMapping", "Shadow Mapping"})
, _grid(DefaultSkirtedGridSegments, DefaultSkirtedGridSegments)
, _leftRoot(Chunk(LeftHemisphereIndex))
, _rightRoot(Chunk(RightHemisphereIndex))
, _lightSourceNodeName(LightSourceNodeInfo)
{
const Parameters p = codegen::bake<Parameters>(dictionary);
_generalProperties.currentLodScaleFactor.setReadOnly(true);
_currentLodScaleFactor.setReadOnly(true);
// Read the radii in to its own dictionary
if (p.radii.has_value()) {
@@ -623,12 +635,6 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
// For globes, the interaction sphere is always the same as the bounding sphere
setInteractionSphere(boundingSphere());
_generalProperties.performShading =
p.performShading.value_or(_generalProperties.performShading);
_generalProperties.renderAtDistance =
p.renderAtDistance.value_or(_generalProperties.renderAtDistance);
// Init layer manager
// @TODO (abock, 2021-03-25) The layermanager should be changed to take a
// std::map<std::string, ghoul::Dictionary> instead and then we don't need to get it
@@ -642,9 +648,18 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
}
addProperty(Fadeable::_opacity);
addProperty(_generalProperties.performShading);
addProperty(_generalProperties.useAccurateNormals);
addProperty(_generalProperties.renderAtDistance);
_performShading = p.performShading.value_or(_performShading);
addProperty(_performShading);
_useAccurateNormals = p.useAccurateNormals.value_or(_useAccurateNormals);
addProperty(_useAccurateNormals);
_renderAtDistance = p.renderAtDistance.value_or(_renderAtDistance);
addProperty(_renderAtDistance);
_ambientIntensity = p.ambientIntensity.value_or(_ambientIntensity);
addProperty(_ambientIntensity);
_lightSourceNodeName.onChange([this]() {
if (_lightSourceNodeName.value().empty()) {
@@ -678,29 +693,33 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
}
_ellipsoid.setShadowConfigurationArray(shadowConfArray);
addProperty(_generalProperties.eclipseShadowsEnabled);
addProperty(_generalProperties.eclipseHardShadows);
// TODO: Missing value from parameters
addProperty(_eclipseShadowsEnabled);
addProperty(_eclipseHardShadows);
}
_shadowMappingPropertyOwner.addProperty(_generalProperties.shadowMapping);
_shadowMappingPropertyOwner.addProperty(_generalProperties.zFightingPercentage);
_shadowMappingPropertyOwner.addProperty(_generalProperties.nShadowSamples);
_generalProperties.nShadowSamples.onChange([this]() {
_shadowMappingPropertyOwner.addProperty(_shadowMappingProperties.shadowMapping);
_shadowMappingPropertyOwner.addProperty(_shadowMappingProperties.zFightingPercentage);
_shadowMappingPropertyOwner.addProperty(_shadowMappingProperties.nShadowSamples);
_shadowMappingProperties.nShadowSamples.onChange([this]() {
_shadersNeedRecompilation = true;
});
addPropertySubOwner(_shadowMappingPropertyOwner);
_generalProperties.targetLodScaleFactor.onChange([this]() {
const float sf = _generalProperties.targetLodScaleFactor;
_generalProperties.currentLodScaleFactor = sf;
_targetLodScaleFactor = p.targetLodScaleFactor.value_or(_targetLodScaleFactor);
_targetLodScaleFactor.onChange([this]() {
const float sf = _targetLodScaleFactor;
_currentLodScaleFactor = sf;
_lodScaleFactorDirty = true;
});
addProperty(_generalProperties.targetLodScaleFactor);
addProperty(_generalProperties.currentLodScaleFactor);
addProperty(_generalProperties.orenNayarRoughness);
addProperty(_generalProperties.ambientIntensity);
_generalProperties.nActiveLayers.setReadOnly(true);
addProperty(_generalProperties.nActiveLayers);
addProperty(_targetLodScaleFactor);
addProperty(_currentLodScaleFactor);
_orenNayarRoughness = p.orenNayarRoughness.value_or(_orenNayarRoughness);
addProperty(_orenNayarRoughness);
_nActiveLayers.setReadOnly(true);
addProperty(_nActiveLayers);
_debugPropertyOwner.addProperty(_debugProperties.showChunkEdges);
_debugPropertyOwner.addProperty(_debugProperties.levelByProjectedAreaElseDistance);
@@ -708,15 +727,17 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
_debugPropertyOwner.addProperty(_debugProperties.performFrustumCulling);
_debugPropertyOwner.addProperty(_debugProperties.modelSpaceRenderingCutoffLevel);
_debugPropertyOwner.addProperty(_debugProperties.dynamicLodIterationCount);
addPropertySubOwner(_debugPropertyOwner);
auto notifyShaderRecompilation = [this]() {
_shadersNeedRecompilation = true;
};
_generalProperties.useAccurateNormals.onChange(notifyShaderRecompilation);
_generalProperties.eclipseShadowsEnabled.onChange(notifyShaderRecompilation);
_generalProperties.eclipseHardShadows.onChange(notifyShaderRecompilation);
_generalProperties.performShading.onChange(notifyShaderRecompilation);
_useAccurateNormals.onChange(notifyShaderRecompilation);
_eclipseShadowsEnabled.onChange(notifyShaderRecompilation);
_eclipseHardShadows.onChange(notifyShaderRecompilation);
_performShading.onChange(notifyShaderRecompilation);
_debugProperties.showChunkEdges.onChange(notifyShaderRecompilation);
_shadowMappingProperties.shadowMapping.onChange(notifyShaderRecompilation);
_layerManager.onChange([this](Layer* l) {
_shadersNeedRecompilation = true;
@@ -724,8 +745,6 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
_nLayersIsDirty = true;
_lastChangedLayer = l;
});
addPropertySubOwner(_debugPropertyOwner);
addPropertySubOwner(_layerManager);
_globalChunkBuffer.resize(2048);
@@ -733,6 +752,11 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
_traversalMemory.resize(512);
_labelsDictionary = p.labels.value_or(_labelsDictionary);
if (!_labelsDictionary.isEmpty()) {
// Fading of the labels should also depend on the fading of the globe
_globeLabelsComponent.setParentFadeable(this);
addPropertySubOwner(_globeLabelsComponent);
}
// Init geojson manager
_geoJsonManager.initialize(this);
@@ -750,9 +774,8 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
_shadowComponent = std::make_unique<ShadowComponent>(dictionary);
_shadowComponent->initialize();
addPropertySubOwner(_shadowComponent.get());
_generalProperties.shadowMapping = true;
_shadowMappingProperties.shadowMapping = true;
}
_generalProperties.shadowMapping.onChange(notifyShaderRecompilation);
// Use a secondary renderbin for labels, and other things that we want to be able to
// render with transparency, on top of the globe, after the atmosphere step
@@ -762,10 +785,6 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
void RenderableGlobe::initializeGL() {
if (!_labelsDictionary.isEmpty()) {
_globeLabelsComponent.initialize(_labelsDictionary, this);
addPropertySubOwner(_globeLabelsComponent);
// Fading of the labels should also depend on the fading of the globe
_globeLabelsComponent.setParentFadeable(this);
}
_layerManager.update();
@@ -831,7 +850,7 @@ void RenderableGlobe::render(const RenderData& data, RendererTasks& rendererTask
constexpr int res = 2880;
const double distance = res * boundingSphere() / tfov;
if ((distanceToCamera < distance) || (_generalProperties.renderAtDistance)) {
if ((distanceToCamera < distance) || (_renderAtDistance)) {
try {
if (_shadowComponent && _shadowComponent->isEnabled()) {
// Set matrices and other GL states
@@ -1055,7 +1074,7 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
if (_nLayersIsDirty) {
std::array<LayerGroup*, LayerManager::NumLayerGroups> lgs =
_layerManager.layerGroups();
_generalProperties.nActiveLayers = std::accumulate(
_nActiveLayers = std::accumulate(
lgs.begin(),
lgs.end(),
0,
@@ -1076,7 +1095,7 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
if (_layerManager.hasAnyBlendingLayersEnabled()) {
if (_lodScaleFactorDirty) {
const float dsf = static_cast<float>(
_generalProperties.currentLodScaleFactor * _ellipsoid.minimumRadius()
_currentLodScaleFactor * _ellipsoid.minimumRadius()
);
// We are setting the setIgnoreUniformLocationError as it is not super trivial
@@ -1098,12 +1117,12 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
}
}
if (_generalProperties.performShading) {
const float onr = _generalProperties.orenNayarRoughness;
if (_performShading) {
const float onr = _orenNayarRoughness;
_localRenderer.program->setUniform("orenNayarRoughness", onr);
_globalRenderer.program->setUniform("orenNayarRoughness", onr);
const float amb = _generalProperties.ambientIntensity;
const float amb = _ambientIntensity;
_localRenderer.program->setUniform("ambientIntensity", amb);
_globalRenderer.program->setUniform("ambientIntensity", amb);
}
@@ -1124,7 +1143,7 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
}
const float dsf = static_cast<float>(
_generalProperties.currentLodScaleFactor * _ellipsoid.minimumRadius()
_currentLodScaleFactor * _ellipsoid.minimumRadius()
);
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
_globalRenderer.program->setIgnoreUniformLocationError(IgnoreError::Yes);
@@ -1146,7 +1165,7 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
}
const float dsf = static_cast<float>(
_generalProperties.currentLodScaleFactor * _ellipsoid.minimumRadius()
_currentLodScaleFactor * _ellipsoid.minimumRadius()
);
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
_localRenderer.program->setIgnoreUniformLocationError(IgnoreError::Yes);
@@ -1183,7 +1202,13 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
_cachedInverseModelTransform * glm::dvec4(data.camera.positionVec3(), 1.0)
);
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
_globalRenderer.program->setIgnoreUniformLocationError(IgnoreError::Yes);
// The cameraPosition is not used if a globe only has a solid color, but it would
// be costlier to figure that out and will only trigger rarely, so instead we just
// ignore the location error
_globalRenderer.program->setUniform("cameraPosition", glm::vec3(cameraPosition));
_globalRenderer.program->setIgnoreUniformLocationError(IgnoreError::No);
}
const glm::mat4 modelViewTransform = glm::mat4(viewTransform * _cachedModelTransform);
@@ -1200,7 +1225,7 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
const bool hasHeightLayer =
!_layerManager.layerGroup(layers::Group::ID::HeightLayers).activeLayers().empty();
if (_generalProperties.useAccurateNormals && hasHeightLayer) {
if (_useAccurateNormals && hasHeightLayer) {
// Apply an extra scaling to the height if the object is scaled
_globalRenderer.program->setUniform(
"heightScale",
@@ -1216,7 +1241,7 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
const bool waterLayersActive =
!_layerManager.layerGroup(Group::ID::WaterMasks).activeLayers().empty();
if (nightLayersActive || waterLayersActive || _generalProperties.performShading) {
if (nightLayersActive || waterLayersActive || _performShading) {
const glm::dvec3 directionToSunWorldSpace =
directionToLightSource(data.modelTransform.translation, _lightSourceNode);
@@ -1242,7 +1267,7 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
data.camera.sgctInternal.projectionMatrix()
);
if (nightLayersActive || waterLayersActive || _generalProperties.performShading) {
if (nightLayersActive || waterLayersActive || _performShading) {
const glm::dvec3 directionToSunWorldSpace =
directionToLightSource(data.modelTransform.translation, _lightSourceNode);
@@ -1343,21 +1368,19 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
const int iterCount = _debugProperties.dynamicLodIterationCount;
const bool exceededIterations =
static_cast<int>(_iterationsOfUnavailableData) > iterCount;
const float clf = _generalProperties.currentLodScaleFactor;
const float clfMin = _generalProperties.currentLodScaleFactor.minValue();
const float targetLod = _generalProperties.targetLodScaleFactor;
const float clf = _currentLodScaleFactor;
const float clfMin = _currentLodScaleFactor.minValue();
const float targetLod = _targetLodScaleFactor;
const bool validLodFactor = clf > clfMin;
if (exceededIterations && validLodFactor) {
_generalProperties.currentLodScaleFactor =
_generalProperties.currentLodScaleFactor - 0.1f;
_currentLodScaleFactor = _currentLodScaleFactor - 0.1f;
_iterationsOfUnavailableData = 0;
_lodScaleFactorDirty = true;
} // Make 2 times the iterations with available data to move it up again
else if (static_cast<int>(_iterationsOfAvailableData) >
(iterCount * 2) && clf < targetLod)
{
_generalProperties.currentLodScaleFactor =
_generalProperties.currentLodScaleFactor + 0.1f;
_currentLodScaleFactor = _currentLodScaleFactor + 0.1f;
_iterationsOfAvailableData = 0;
_lodScaleFactorDirty = true;
}
@@ -1410,15 +1433,13 @@ void RenderableGlobe::renderChunkGlobally(const Chunk& chunk, const RenderData&
setCommonUniforms(program, chunk, data);
if (_generalProperties.eclipseShadowsEnabled &&
!_ellipsoid.shadowConfigurationArray().empty())
{
if (_eclipseShadowsEnabled && !_ellipsoid.shadowConfigurationArray().empty()) {
calculateEclipseShadows(program, data, ShadowCompType::GLOBAL_SHADOW);
}
// Shadow Mapping
ghoul::opengl::TextureUnit shadowMapUnit;
if (_generalProperties.shadowMapping && shadowData.shadowDepthTexture != 0) {
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.
@@ -1431,9 +1452,12 @@ void RenderableGlobe::renderChunkGlobally(const Chunk& chunk, const RenderData&
glBindTexture(GL_TEXTURE_2D, shadowData.shadowDepthTexture);
program.setUniform("shadowMapTexture", shadowMapUnit);
program.setUniform("zFightingPercentage", _generalProperties.zFightingPercentage);
program.setUniform(
"zFightingPercentage",
_shadowMappingProperties.zFightingPercentage
);
}
else if (_generalProperties.shadowMapping) {
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.
@@ -1549,15 +1573,13 @@ void RenderableGlobe::renderChunkLocally(const Chunk& chunk, const RenderData& d
setCommonUniforms(program, chunk, data);
if (_generalProperties.eclipseShadowsEnabled &&
!_ellipsoid.shadowConfigurationArray().empty())
{
if (_eclipseShadowsEnabled && !_ellipsoid.shadowConfigurationArray().empty()) {
calculateEclipseShadows(program, data, ShadowCompType::LOCAL_SHADOW);
}
// Shadow Mapping
ghoul::opengl::TextureUnit shadowMapUnit;
if (_generalProperties.shadowMapping && shadowData.shadowDepthTexture != 0) {
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.
@@ -1570,9 +1592,12 @@ void RenderableGlobe::renderChunkLocally(const Chunk& chunk, const RenderData& d
glBindTexture(GL_TEXTURE_2D, shadowData.shadowDepthTexture);
program.setUniform("shadowMapTexture", shadowMapUnit);
program.setUniform("zFightingPercentage", _generalProperties.zFightingPercentage);
program.setUniform(
"zFightingPercentage",
_shadowMappingProperties.zFightingPercentage
);
}
else if (_generalProperties.shadowMapping) {
else if (_shadowMappingProperties.shadowMapping) {
shadowMapUnit.activate();
// JCC: Avoiding a to recompiling the shaders or having more than one
// set of shaders for this step.
@@ -1636,7 +1661,7 @@ void RenderableGlobe::setCommonUniforms(ghoul::opengl::ProgramObject& programObj
ZoneScoped;
if (_generalProperties.useAccurateNormals &&
if (_useAccurateNormals &&
!_layerManager.layerGroup(Group::ID::HeightLayers).activeLayers().empty())
{
const glm::dvec3 corner00 = _ellipsoid.cartesianSurfacePosition(
@@ -1737,31 +1762,22 @@ void RenderableGlobe::recompileShaders() {
const bool hasHeightLayer =
!_layerManager.layerGroup(layers::Group::ID::HeightLayers).activeLayers().empty();
pairs.emplace_back("useAccurateNormals",
std::to_string(_generalProperties.useAccurateNormals && hasHeightLayer)
);
pairs.emplace_back(
"performShading",
std::to_string(_generalProperties.performShading)
);
pairs.emplace_back(
"useEclipseShadows",
std::to_string(_generalProperties.eclipseShadowsEnabled)
);
pairs.emplace_back(
"useEclipseHardShadows",
std::to_string(_generalProperties.eclipseHardShadows)
"useAccurateNormals",
std::to_string(_useAccurateNormals && hasHeightLayer)
);
pairs.emplace_back("performShading", std::to_string(_performShading));
pairs.emplace_back("useEclipseShadows", std::to_string(_eclipseShadowsEnabled));
pairs.emplace_back("useEclipseHardShadows", std::to_string(_eclipseHardShadows));
pairs.emplace_back(
"enableShadowMapping",
std::to_string(_generalProperties.shadowMapping)
std::to_string(_shadowMappingProperties.shadowMapping && _shadowComponent)
);
pairs.emplace_back("showChunkEdges", std::to_string(_debugProperties.showChunkEdges));
pairs.emplace_back("showHeightResolution", "0");
pairs.emplace_back("showHeightIntensities", "0");
pairs.emplace_back("defaultHeight", std::to_string(DefaultHeight));
//
// Create dictionary from layerpreprocessing data
//
@@ -1850,7 +1866,10 @@ void RenderableGlobe::recompileShaders() {
}
// Shadow Mapping Samples
shaderDictionary.setValue("nShadowSamples", _generalProperties.nShadowSamples - 1);
shaderDictionary.setValue(
"nShadowSamples",
_shadowMappingProperties.nShadowSamples - 1
);
// Exclise Shadow Samples
const int nEclipseShadows = static_cast<int>(
@@ -2274,7 +2293,7 @@ void RenderableGlobe::calculateEclipseShadows(ghoul::opengl::ProgramObject& prog
// JCC: Removed in favor of: #define USE_ECLIPSE_HARD_SHADOWS #{useEclipseHardShadows}
/*programObject.setUniform(
"hardShadows",
_generalProperties.eclipseHardShadows
_eclipseHardShadows
);*/
//programObject.setUniform("calculateEclipseShadows", true);
}
@@ -2312,8 +2331,7 @@ int RenderableGlobe::desiredLevelByDistance(const Chunk& chunk,
const double distanceToPatch = glm::length(cameraToChunk);
const double distance = distanceToPatch;
const double scaleFactor = _generalProperties.currentLodScaleFactor *
_ellipsoid.minimumRadius();
const double scaleFactor = _currentLodScaleFactor * _ellipsoid.minimumRadius();
const double projectedScaleFactor = scaleFactor / distance;
const int desiredLevel = static_cast<int>(ceil(log2(projectedScaleFactor)));
return desiredLevel;
@@ -2399,8 +2417,7 @@ int RenderableGlobe::desiredLevelByProjectedArea(const Chunk& chunk,
const double areaABC = 0.5 * glm::length(glm::cross(AC, AB));
const double projectedChunkAreaApprox = 8 * areaABC;
const double scaledArea = _generalProperties.currentLodScaleFactor *
projectedChunkAreaApprox;
const double scaledArea = _currentLodScaleFactor * projectedChunkAreaApprox;
return chunk.tileIndex.level + static_cast<int>(round(scaledArea - 1));
}
+35 -36
View File
@@ -128,38 +128,6 @@ public:
static documentation::Documentation Documentation();
private:
static constexpr int MinSplitDepth = 2;
static constexpr int MaxSplitDepth = 22;
struct {
properties::BoolProperty showChunkEdges;
properties::BoolProperty levelByProjectedAreaElseDistance;
properties::BoolProperty resetTileProviders;
properties::BoolProperty performFrustumCulling;
properties::IntProperty modelSpaceRenderingCutoffLevel;
properties::IntProperty dynamicLodIterationCount;
} _debugProperties;
struct {
properties::BoolProperty performShading;
properties::BoolProperty useAccurateNormals;
properties::BoolProperty eclipseShadowsEnabled;
properties::BoolProperty eclipseHardShadows;
properties::BoolProperty shadowMapping;
properties::BoolProperty renderAtDistance;
properties::FloatProperty zFightingPercentage;
properties::IntProperty nShadowSamples;
properties::FloatProperty targetLodScaleFactor;
properties::FloatProperty currentLodScaleFactor;
properties::FloatProperty orenNayarRoughness;
properties::FloatProperty ambientIntensity;
properties::IntProperty nActiveLayers;
} _generalProperties;
properties::PropertyOwner _debugPropertyOwner;
properties::PropertyOwner _shadowMappingPropertyOwner;
/**
* Test if a specific chunk can safely be culled without affecting the rendered image.
*
@@ -245,16 +213,49 @@ private:
void setCommonUniforms(ghoul::opengl::ProgramObject& programObject,
const Chunk& chunk, const RenderData& data);
void recompileShaders();
void splitChunkNode(Chunk& cn, int depth);
void mergeChunkNode(Chunk& cn);
bool updateChunkTree(Chunk& cn, const RenderData& data, const glm::dmat4& mvp);
void updateChunk(Chunk& chunk, const RenderData& data, const glm::dmat4& mvp) const;
void freeChunkNode(Chunk* n);
static constexpr int MinSplitDepth = 2;
static constexpr int MaxSplitDepth = 22;
properties::BoolProperty _performShading;
properties::BoolProperty _useAccurateNormals;
properties::FloatProperty _ambientIntensity;
properties::StringProperty _lightSourceNodeName;
properties::BoolProperty _renderAtDistance;
properties::BoolProperty _eclipseShadowsEnabled;
properties::BoolProperty _eclipseHardShadows;
properties::FloatProperty _targetLodScaleFactor;
properties::FloatProperty _currentLodScaleFactor;
properties::FloatProperty _orenNayarRoughness;
properties::IntProperty _nActiveLayers;
struct {
properties::BoolProperty showChunkEdges;
properties::BoolProperty levelByProjectedAreaElseDistance;
properties::BoolProperty resetTileProviders;
properties::BoolProperty performFrustumCulling;
properties::IntProperty modelSpaceRenderingCutoffLevel;
properties::IntProperty dynamicLodIterationCount;
} _debugProperties;
properties::PropertyOwner _debugPropertyOwner;
struct {
properties::BoolProperty shadowMapping;
properties::FloatProperty zFightingPercentage;
properties::IntProperty nShadowSamples;
} _shadowMappingProperties;
properties::PropertyOwner _shadowMappingPropertyOwner;
Ellipsoid _ellipsoid;
SkirtedGrid _grid;
LayerManager _layerManager;
@@ -270,7 +271,6 @@ private:
std::vector<const Chunk*> _localChunkBuffer;
std::vector<const Chunk*> _traversalMemory;
Chunk _leftRoot; // Covers all negative longitudes
Chunk _rightRoot; // Covers all positive longitudes
@@ -293,7 +293,6 @@ private:
} _localRenderer;
SceneGraphNode* _lightSourceNode = nullptr;
properties::StringProperty _lightSourceNodeName;
bool _shadersNeedRecompilation = true;
bool _lodScaleFactorDirty = true;
@@ -200,11 +200,11 @@ TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary)
const Time start = Time(p.prototyped->time.start);
Time end = Time::now();
_prototyped.startTimeJ2000 = start.j2000Seconds();
_prototyped.endTimeJ2000 = Time(p.prototyped->time.end).j2000Seconds();
if (p.prototyped->time.end == "Yesterday") {
end.advanceTime(-60.0 * 60.0 * 24.0); // Go back one day
}
else if (p.prototyped->time.end != "Today") {
_prototyped.endTimeJ2000 = Time(p.prototyped->time.end).j2000Seconds();
end.setTime(p.prototyped->time.end);
}
@@ -97,6 +97,8 @@ Tile TextTileProvider::renderTile(const TileIndex& tileIndex, const std::string&
fontRenderer->render(*font, position, text, color);
texture->setFilter(ghoul::opengl::Texture::FilterMode::LinearMipMap);
tile = Tile{ texture, std::nullopt, Tile::Status::OK };
tileCache->put(key, initData.hashKey, tile);
@@ -0,0 +1,190 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2024 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/globebrowsing/src/tileprovider/tileproviderbydate.h>
#include <openspace/documentation/documentation.h>
#include <openspace/engine/globals.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/timemanager.h>
#include <functional>
namespace {
struct [[codegen::Dictionary(TileProviderByDate)]] Parameters {
// Specifies the list of tile providers and for which times they are used for. The
// tile provider with the earliest time will be used for all dates prior to that
// date and the provider with the latest time will be used for all dates
// afterwards. In between, a provider is used from the specified time until the
// time of the next provider
std::map<std::string, ghoul::Dictionary> providers;
};
#include "tileproviderbydate_codegen.cpp"
} // namespace
namespace openspace::globebrowsing {
documentation::Documentation TileProviderByDate::Documentation() {
return codegen::doc<Parameters>("globebrowsing_tileproviderbydate");
}
TileProviderByDate::TileProviderByDate(const ghoul::Dictionary& dictionary) {
ZoneScoped;
Parameters p = codegen::bake<Parameters>(dictionary);
// For now we need to inject the LayerGroupID this way. We don't want it to be part of
// the parameters struct as that would mean it would be visible to the end user, which
// we don't want since this value just comes from whoever creates it, not the user
ghoul_assert(dictionary.hasValue<int>("LayerGroupID"), "No Layer Group ID provided");
const layers::Group::ID group = static_cast<layers::Group::ID>(
dictionary.value<int>("LayerGroupID")
);
for (std::pair<const std::string, ghoul::Dictionary>& prov : p.providers) {
prov.second.setValue("LayerGroupID", static_cast<int>(group));
// Pass down the caching information from the enclosing dictionary
if (dictionary.hasValue<std::string>("GlobeName")) {
prov.second.setValue("GlobeName", dictionary.value<std::string>("GlobeName"));
}
layers::Layer::ID typeID = layers::Layer::ID::DefaultTileProvider;
if (prov.second.hasValue<std::string>("Type")) {
const std::string type = prov.second.value<std::string>("Type");
typeID = ghoul::from_string<layers::Layer::ID>(type);
}
std::unique_ptr<TileProvider> tp = createFromDictionary(typeID, prov.second);
const std::string provId = prov.second.value<std::string>("Identifier");
tp->setIdentifier(provId);
const std::string providerName = prov.second.value<std::string>("Name");
tp->setGuiName(providerName);
addPropertySubOwner(tp.get());
const double time = SpiceManager::ref().ephemerisTimeFromDate(prov.first);
_tileProviders.emplace_back(time, std::move(tp));
}
// After we added all tile providers, we need to sort them as they might have been
// given in an arbitrary order
std::sort(
_tileProviders.begin(),
_tileProviders.end(),
[](const Provider& lhs, const Provider& rhs) {
return lhs.startTime < rhs.startTime;
}
);
}
void TileProviderByDate::internalInitialize() {
for (const Provider& p : _tileProviders) {
p.tileProvider->initialize();
}
}
void TileProviderByDate::internalDeinitialize() {
for (const Provider& p : _tileProviders) {
p.tileProvider->deinitialize();
}
}
Tile TileProviderByDate::tile(const TileIndex& tileIndex) {
ZoneScoped;
return _currentTileProvider ? _currentTileProvider->tile(tileIndex) : Tile();
}
Tile::Status TileProviderByDate::tileStatus(const TileIndex& index) {
return
_currentTileProvider ?
_currentTileProvider->tileStatus(index) :
Tile::Status::Unavailable;
}
TileDepthTransform TileProviderByDate::depthTransform() {
return _currentTileProvider ?
_currentTileProvider->depthTransform() :
TileDepthTransform(0.f, 1.f);
}
void TileProviderByDate::update() {
if (_tileProviders.empty()) {
// If there are no tile providers, then there is no work to be done
_currentTileProvider = nullptr;
return;
}
// First update all tile providers
for (const Provider& p : _tileProviders) {
p.tileProvider->update();
}
// Then check update our current tile provider pointer
const double time = global::timeManager->time().j2000Seconds();
ghoul_assert(!_tileProviders.empty(), "There should be tile providers at this point");
// We use the first tileprovider for all times before the beginning start
if (time < _tileProviders.begin()->startTime) {
_currentTileProvider = _tileProviders.begin()->tileProvider.get();
return;
}
// And the last tileprovider for all times after the end
if (time > _tileProviders.back().startTime) {
_currentTileProvider = _tileProviders.back().tileProvider.get();
return;
}
_currentTileProvider = _tileProviders.begin()->tileProvider.get();
for (const Provider& p : _tileProviders) {
if (p.startTime > time) {
// We have found the first entry that is larger than the current time, which
// means that we are done
return;
}
_currentTileProvider = p.tileProvider.get();
}
}
void TileProviderByDate::reset() {
for (const Provider& p : _tileProviders) {
p.tileProvider->reset();
}
}
int TileProviderByDate::minLevel() {
return _currentTileProvider ? _currentTileProvider->minLevel() : 1;
}
int TileProviderByDate::maxLevel() {
return _currentTileProvider ? _currentTileProvider->maxLevel() : 1;
}
float TileProviderByDate::noDataValueAsFloat() {
return _currentTileProvider ? _currentTileProvider->noDataValueAsFloat() : 1;
}
} // namespace openspace::globebrowsing
@@ -0,0 +1,65 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2024 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDERBYDATE___H__
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDERBYDATE___H__
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
#include <vector>
namespace openspace::globebrowsing {
class TileProviderByDate : public TileProvider {
public:
TileProviderByDate(const ghoul::Dictionary& dictionary);
Tile tile(const TileIndex& tileIndex) override final;
Tile::Status tileStatus(const TileIndex& index) override final;
TileDepthTransform depthTransform() override final;
void update() override final;
void reset() override final;
int minLevel() override final;
int maxLevel() override final;
float noDataValueAsFloat() override final;
static documentation::Documentation Documentation();
private:
struct Provider {
// The time at which this provider becomes valid
double startTime = 0.0;
std::unique_ptr<TileProvider> tileProvider;
};
std::vector<Provider> _tileProviders;
TileProvider* _currentTileProvider = nullptr;
void internalInitialize() override final;
void internalDeinitialize() override final;
};
} // namespace openspace::globebrowsing
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDERBYDATE___H__
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
@@ -62,7 +62,6 @@ protected:
std::function<std::vector<properties::PropertyOwner*>()> _propertyOwnerFunction;
properties::BoolProperty _useTreeLayout;
properties::StringListProperty _treeOrdering;
};
} // namespace openspace::gui
+4 -2
View File
@@ -58,7 +58,8 @@ void GuiActionComponent::render() {
global::actionManager->triggerAction(
p.second,
ghoul::Dictionary(),
interaction::ActionManager::ShouldBeSynchronized::Yes
interaction::ActionManager::ShouldBeSynchronized::Yes,
interaction::ActionManager::ShouldBeLogged::Yes
);
}
ImGui::SameLine();
@@ -85,7 +86,8 @@ void GuiActionComponent::render() {
global::actionManager->triggerAction(
action.command,
ghoul::Dictionary(),
interaction::ActionManager::ShouldBeSynchronized::Yes
interaction::ActionManager::ShouldBeSynchronized::Yes,
interaction::ActionManager::ShouldBeLogged::Yes
);
}
ImGui::SameLine();
+1 -5
View File
@@ -145,11 +145,7 @@ void GuiGIBSComponent::render() {
"openspace.globebrowsing.addLayer('Earth', 'ColorLayers', {})",
layerScript
);
global::scriptEngine->queueScript(
std::move(script),
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
);
global::scriptEngine->queueScript(std::move(script));
}
ImGui::End();
@@ -329,9 +329,8 @@ void GuiGlobeBrowsingComponent::render() {
std::remove(layerName.begin(), layerName.end(), ' '),
layerName.end()
);
global::scriptEngine->queueScript(
std::format(
"openspace.globebrowsing.addLayer(\
const std::string script = std::format(
"openspace.globebrowsing.addLayer(\
'{}', \
'{}', \
{{ \
@@ -341,15 +340,13 @@ void GuiGlobeBrowsingComponent::render() {
Enabled = true\
}}\
);",
n,
type,
layerName,
l.name,
l.url
),
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
n,
type,
layerName,
l.name,
l.url
);
global::scriptEngine->queueScript(script);
};
if (addColor) {
+3 -48
View File
@@ -46,15 +46,6 @@ namespace {
openspace::properties::Property::Visibility::AdvancedUser
};
constexpr openspace::properties::Property::PropertyInfo OrderingInfo = {
"Ordering",
"Tree Ordering",
"This list determines the order of the first tree layer if it is used. Elements "
"present in this list will be shown first, with an alphabetical ordering for "
"elements not listed.",
openspace::properties::Property::Visibility::AdvancedUser
};
int nVisibleProperties(const std::vector<openspace::properties::Property*>& props)
{
using namespace openspace;
@@ -185,10 +176,8 @@ GuiPropertyComponent::GuiPropertyComponent(std::string identifier, std::string g
UseTreeLayout useTree)
: GuiComponent(std::move(identifier), std::move(guiName))
, _useTreeLayout(UseTreeInfo, useTree)
, _treeOrdering(OrderingInfo)
{
addProperty(_useTreeLayout);
addProperty(_treeOrdering);
}
void GuiPropertyComponent::setPropertyOwners(
@@ -303,14 +292,11 @@ void GuiPropertyComponent::render() {
(void)owner; // using [[maybe_unused]] in the for loop gives an error
}
// Sort:
// if guigrouping, sort by name and shortest first, but respect the user specified
// ordering then all w/o guigroup
const std::vector<std::string>& ordering = _treeOrdering;
// Sort: by name and shortest first
std::stable_sort(
owners.begin(),
owners.end(),
[&ordering](PropertyOwner* lhs, PropertyOwner* rhs) {
[](PropertyOwner* lhs, PropertyOwner* rhs) {
const std::string lhsGrp = dynamic_cast<SceneGraphNode*>(lhs)->guiPath();
const std::string rhsGrp = dynamic_cast<SceneGraphNode*>(rhs)->guiPath();
@@ -321,38 +307,7 @@ void GuiPropertyComponent::render() {
return true;
}
if (ordering.empty()) {
return lhsGrp < rhsGrp;
}
std::vector<std::string> lhsToken = ghoul::tokenizeString(lhsGrp, '/');
// The first token is always empty
auto lhsIt = std::find(ordering.begin(), ordering.end(), lhsToken[1]);
std::vector<std::string> rhsToken = ghoul::tokenizeString(rhsGrp, '/');
// The first token is always empty
auto rhsIt = std::find(ordering.begin(), ordering.end(), rhsToken[1]);
if (lhsIt != ordering.end() && rhsIt != ordering.end()) {
if (lhsToken[1] != rhsToken[1]) {
// If both top-level groups are in the ordering list, the
// order of the iterators gives us the order of the groups
return lhsIt < rhsIt;
}
else {
return lhsGrp < rhsGrp;
}
}
else if (lhsIt != ordering.end() && rhsIt == ordering.end()) {
// If only one of them is in the list, we have a sorting
return true;
}
else if (lhsIt == ordering.end() && rhsIt != ordering.end()) {
return false;
}
else {
return lhsGrp < rhsGrp;
}
return lhsGrp < rhsGrp;
}
);
}
+62 -119
View File
@@ -32,6 +32,7 @@
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/scene/scene.h>
#include <openspace/util/timeconversion.h>
#include <openspace/util/timemanager.h>
#include <openspace/scripting/scriptengine.h>
@@ -105,19 +106,12 @@ void GuiSpaceTimeComponent::render() {
const bool pressed = ImGui::Button(n->guiName().c_str());
ImGui::SameLine();
if (pressed) {
global::scriptEngine->queueScript(
"openspace.setPropertyValue('" +
std::string(AnchorProperty) + "', '" +
n->identifier() + "');",
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
);
global::scriptEngine->queueScript(
"openspace.setPropertyValue('" +
std::string(RetargetAnchorProperty) + "', nil);",
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
const std::string script = std::format(
"openspace.setPropertyValue('{}', '{}');"
"openspace.setPropertyValue('{}', nil);",
AnchorProperty, n->identifier(), RetargetAnchorProperty
);
global::scriptEngine->queueScript(script);
}
}
}
@@ -143,29 +137,21 @@ void GuiSpaceTimeComponent::render() {
const bool hasChanged = ImGui::Combo("", &currentPosition, nodeNames.c_str());
if (hasChanged) {
global::scriptEngine->queueScript(
"openspace.setPropertyValue('" + std::string(AnchorProperty) + "', '" +
nodes[currentPosition]->identifier() + "');",
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
);
global::scriptEngine->queueScript(
"openspace.setPropertyValue('" +
std::string(RetargetAnchorProperty) + "', nil);",
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
const std::string script = std::format(
"openspace.setPropertyValue('{}', '{}');"
"openspace.setPropertyValue('{}', nil);",
AnchorProperty, nodes[currentPosition]->identifier(), RetargetAnchorProperty
);
global::scriptEngine->queueScript(script);
}
ImGui::SameLine();
const bool pressed = ImGui::Button("Refocus");
if (pressed) {
global::scriptEngine->queueScript(
"openspace.setPropertyValue('" +
std::string(RetargetAnchorProperty) + "', nil);",
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
const std::string script = std::format(
"openspace.setPropertyValue('{}', nil);", RetargetAnchorProperty
);
global::scriptEngine->queueScript(script);
}
float interpolationTime = global::navigationHandler->interpolationTime();
@@ -210,11 +196,10 @@ void GuiSpaceTimeComponent::render() {
if (dateChanged) {
// No sync or send because time settings are always synced and sent to the
// connected nodes and peers
global::scriptEngine->queueScript(
std::format("openspace.time.setTime([[{}]])", std::string_view(Buffer)),
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
const std::string script = std::format(
"openspace.time.setTime([[{}]])", std::string_view(Buffer)
);
global::scriptEngine->queueScript(script);
}
showTooltip(
@@ -239,29 +224,23 @@ void GuiSpaceTimeComponent::render() {
std::chrono::hours(24) * std::abs(days)
).count();
const double newTime = days < 0 ?
j2000 - seconds :
j2000 + seconds;
const double newTime = days < 0.f ? j2000 - seconds : j2000 + seconds;
if (shift) {
// If any shift key is pressed we want to always jump to the time.
// No sync or send because time settings are always synced and sent
// to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.time.setTime(" + std::to_string(newTime) + ")",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
"openspace.time.setTime(" + std::to_string(newTime) + ")"
);
}
else {
// No sync or send because time settings are always synced and sent
// to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.time.interpolateTime(" + std::to_string(newTime) + ", " +
std::to_string(duration) + ")",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
const std::string script = std::format(
"openspace.time.interpolateTime({}, {})", newTime, duration
);
global::scriptEngine->queueScript(script);
}
};
@@ -300,11 +279,8 @@ void GuiSpaceTimeComponent::render() {
// No sync or send because time settings are always synced and sent
// to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.time.setTime(\"" + nowTime + "\")",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
std::format("openspace.time.setTime('{}')", nowTime)
);
}
ImGui::SameLine();
@@ -386,11 +362,9 @@ void GuiSpaceTimeComponent::render() {
// No sync or send because time settings are always synced and sent
// to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.time.interpolateDeltaTime(" + std::to_string(newDt) + ")",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript(std::format(
"openspace.time.interpolateDeltaTime({})", newDt
));
}
if (unitChanged) {
// If only the unit changes, we keep the delta time, but need to convert the
@@ -437,22 +411,22 @@ void GuiSpaceTimeComponent::render() {
// No sync or send because time settings are always synced and sent
// to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.time.setDeltaTime(" + std::to_string(newDeltaTime) + ")",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
const std::string s = std::format(
"openspace.time.setDeltaTime({})", newDeltaTime
);
global::scriptEngine->queueScript(s);
}
if (!ImGui::IsItemActive() && !ImGui::IsItemClicked()) {
if (_slidingDelta != 0.f) {
// No sync or send because time settings are always synced and sent
// to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.time.setDeltaTime(" + std::to_string(_oldDeltaTime) + ")",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
const std::string script = std::format(
"openspace.time.setDeltaTime({})", _oldDeltaTime
);
using Script = scripting::ScriptEngine::Script;
global::scriptEngine->queueScript(script);
}
_slidingDelta = 0.f;
}
@@ -477,11 +451,10 @@ void GuiSpaceTimeComponent::render() {
// No sync or send because time settings are always synced and sent
// to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.time.setDeltaTime(" + std::to_string(newDeltaTime) + ")",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
const std::string script = std::format(
"openspace.time.setDeltaTime({})", newDeltaTime
);
global::scriptEngine->queueScript(script);
}
else {
_accelerationDelta = 0.f;
@@ -496,11 +469,7 @@ void GuiSpaceTimeComponent::render() {
{ ImGui::GetWindowWidth() / 2 - 7.5f, 0.f }
);
if (pauseChanged) {
global::scriptEngine->queueScript(
"openspace.time.interpolateTogglePause()",
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
);
global::scriptEngine->queueScript("openspace.time.interpolateTogglePause()");
}
ImGui::SameLine();
const bool invert = ImGui::Button(
@@ -510,22 +479,18 @@ void GuiSpaceTimeComponent::render() {
if (invert) {
// No sync or send because time settings are always synced and sent
// to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.time.interpolateDeltaTime(-1 * openspace.time.deltaTime());",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
const std::string script =
"openspace.time.interpolateDeltaTime(-1 * openspace.time.deltaTime());";
global::scriptEngine->queueScript(script);
}
const bool minusDs = ImGui::Button("-1d/s");
if (minusDs) {
// No sync or send because time settings are always synced and sent
// to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.time.interpolateDeltaTime(" + std::to_string(-24 * 60 * 60) + ")",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript(std::format(
"openspace.time.interpolateDeltaTime(-{})", SecondsPerDay
));
}
ImGui::SameLine();
@@ -533,11 +498,9 @@ void GuiSpaceTimeComponent::render() {
if (minusHs) {
// No sync or send because time settings are always synced and sent
// to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.time.interpolateDeltaTime(" + std::to_string(-60 * 60) + ")",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript(std::format(
"openspace.time.interpolateDeltaTime(-{})", SecondsPerHour
));
}
ImGui::SameLine();
@@ -545,11 +508,9 @@ void GuiSpaceTimeComponent::render() {
if (minusMs) {
// No sync or send because time settings are always synced and sent
// to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.time.interpolateDeltaTime(" + std::to_string(-60) + ")",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript(std::format(
"openspace.time.interpolateDeltaTime(-{})", SecondsPerMinute
));
}
ImGui::SameLine();
@@ -557,11 +518,7 @@ void GuiSpaceTimeComponent::render() {
if (minusSs) {
// No sync or send because time settings are always synced and sent
// to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.time.interpolateDeltaTime(" + std::to_string(-1) + ")",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript("openspace.time.interpolateDeltaTime(-1)");
}
ImGui::SameLine();
@@ -569,11 +526,7 @@ void GuiSpaceTimeComponent::render() {
if (zero) {
// No sync or send because time settings are always synced and sent
// to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.time.interpolateDeltaTime(" + std::to_string(0) + ")",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript("openspace.time.interpolateDeltaTime(0)");
}
ImGui::SameLine();
@@ -582,11 +535,7 @@ void GuiSpaceTimeComponent::render() {
if (plusSs) {
// No sync or send because time settings are always synced and sent
// to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.time.interpolateDeltaTime(" + std::to_string(1) + ")",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript("openspace.time.interpolateDeltaTime(1)");
}
ImGui::SameLine();
@@ -594,11 +543,9 @@ void GuiSpaceTimeComponent::render() {
if (plusMs) {
// No sync or send because time settings are always synced and sent
// to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.time.interpolateDeltaTime(" + std::to_string(60) + ")",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript(std::format(
"openspace.time.interpolateDeltaTime({})", SecondsPerMinute
));
}
ImGui::SameLine();
@@ -606,11 +553,9 @@ void GuiSpaceTimeComponent::render() {
if (plusHs) {
// No sync or send because time settings are always synced and sent
// to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.time.interpolateDeltaTime(" + std::to_string(60 * 60) + ")",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript(std::format(
"openspace.time.interpolateDeltaTime({})", SecondsPerHour
));
}
ImGui::SameLine();
@@ -618,11 +563,9 @@ void GuiSpaceTimeComponent::render() {
if (plusDs) {
// No sync or send because time settings are always synced and sent
// to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.time.interpolateDeltaTime(" + std::to_string(24 * 60 * 60) + ")",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript(std::format(
"openspace.time.interpolateDeltaTime({})", SecondsPerDay
));
}
ImGui::End();
+25 -27
View File
@@ -65,7 +65,7 @@ void renderTooltip(Property* prop, double delay) {
}
ImGui::Text(
"%s",
(std::string("Identifier: ") + prop->fullyQualifiedIdentifier()).c_str()
(std::string("Identifier: ") + prop->uri()).c_str()
);
ImGui::EndTooltip();
}
@@ -73,9 +73,7 @@ void renderTooltip(Property* prop, double delay) {
void executeSetPropertyScript(const std::string& id, const std::string& value) {
global::scriptEngine->queueScript(
std::format("openspace.setPropertyValueSingle('{}', {});", id, value),
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
std::format("openspace.setPropertyValueSingle('{}', {});", id, value)
);
}
@@ -95,7 +93,7 @@ void renderBoolProperty(Property* prop, const std::string& ownerName,
}
if (value != p->value()) {
executeSetPropertyScript(p->fullyQualifiedIdentifier(), value ? "true" : "false");
executeSetPropertyScript(p->uri(), value ? "true" : "false");
}
ImGui::PopID();
}
@@ -158,7 +156,7 @@ void renderOptionProperty(Property* prop, const std::string& ownerName,
}
}
if (value != p->value() && !isReadOnly) {
executeSetPropertyScript(p->fullyQualifiedIdentifier(), std::to_string(value));
executeSetPropertyScript(p->uri(), std::to_string(value));
}
ImGui::PopID();
}
@@ -200,7 +198,7 @@ void renderSelectionProperty(Property* prop, const std::string& ownerName,
parameters.pop_back();
}
parameters += "}";
executeSetPropertyScript(p->fullyQualifiedIdentifier(), parameters);
executeSetPropertyScript(p->uri(), parameters);
}
ImGui::TreePop();
}
@@ -231,7 +229,7 @@ void renderStringProperty(Property* prop, const std::string& ownerName,
if (hasNewValue) {
executeSetPropertyScript(
p->fullyQualifiedIdentifier(),
p->uri(),
"[[" + std::string(buffer.data()) + "]]"
);
}
@@ -283,7 +281,7 @@ void renderDoubleListProperty(Property* prop, const std::string& ownerName,
ImGui::PushID((ownerName + '.' + name).c_str());
const std::string value = p->stringValue();
renderListProperty(name, p->fullyQualifiedIdentifier(), value);
renderListProperty(name, p->uri(), value);
if (showTooltip) {
renderTooltip(prop, tooltipDelay);
@@ -301,7 +299,7 @@ void renderIntListProperty(Property* prop, const std::string& ownerName,
ImGui::PushID((ownerName + '.' + name).c_str());
const std::string value = p->stringValue();
renderListProperty(name, p->fullyQualifiedIdentifier(), value);
renderListProperty(name, p->uri(), value);
if (showTooltip) {
renderTooltip(prop, tooltipDelay);
@@ -319,7 +317,7 @@ void renderStringListProperty(Property* prop, const std::string& ownerName,
ImGui::PushID((ownerName + '.' + name).c_str());
const std::string value = p->stringValue();
renderListProperty(name, p->fullyQualifiedIdentifier(), value);
renderListProperty(name, p->uri(), value);
if (showTooltip) {
renderTooltip(prop, tooltipDelay);
@@ -358,7 +356,7 @@ void renderDoubleProperty(properties::Property* prop, const std::string& ownerNa
}
if (changed) {
executeSetPropertyScript(p->fullyQualifiedIdentifier(), std::to_string(value));
executeSetPropertyScript(p->uri(), std::to_string(value));
}
ImGui::PopID();
@@ -382,7 +380,7 @@ void renderIntProperty(Property* prop, const std::string& ownerName,
}
if (changed) {
executeSetPropertyScript(p->fullyQualifiedIdentifier(), std::to_string(value));
executeSetPropertyScript(p->uri(), std::to_string(value));
}
ImGui::PopID();
@@ -405,7 +403,7 @@ void renderIVec2Property(Property* prop, const std::string& ownerName,
}
if (changed) {
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
}
ImGui::PopID();
@@ -428,7 +426,7 @@ void renderIVec3Property(Property* prop, const std::string& ownerName,
}
if (changed) {
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
}
ImGui::PopID();
}
@@ -450,7 +448,7 @@ void renderIVec4Property(Property* prop, const std::string& ownerName,
}
if (changed) {
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
}
ImGui::PopID();
}
@@ -479,7 +477,7 @@ void renderFloatProperty(Property* prop, const std::string& ownerName,
}
if (changed) {
executeSetPropertyScript(p->fullyQualifiedIdentifier(), std::to_string(value));
executeSetPropertyScript(p->uri(), std::to_string(value));
}
ImGui::PopID();
@@ -509,7 +507,7 @@ void renderVec2Property(Property* prop, const std::string& ownerName,
}
if (changed) {
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
}
ImGui::PopID();
@@ -545,7 +543,7 @@ void renderVec3Property(Property* prop, const std::string& ownerName,
}
if (changed) {
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
}
ImGui::PopID();
@@ -581,7 +579,7 @@ void renderVec4Property(Property* prop, const std::string& ownerName,
}
if (changed) {
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
}
ImGui::PopID();
@@ -611,7 +609,7 @@ void renderDVec2Property(Property* prop, const std::string& ownerName,
}
if (changed) {
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
}
ImGui::PopID();
@@ -641,7 +639,7 @@ void renderDVec3Property(Property* prop, const std::string& ownerName,
}
if (changed) {
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
}
ImGui::PopID();
@@ -671,7 +669,7 @@ void renderDVec4Property(Property* prop, const std::string& ownerName,
}
if (changed) {
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
}
ImGui::PopID();
@@ -723,7 +721,7 @@ void renderDMat2Property(Property* prop, const std::string& ownerName,
}
if (changed) {
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
}
ImGui::PopID();
@@ -785,7 +783,7 @@ void renderDMat3Property(Property* prop, const std::string& ownerName,
}
if (changed) {
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
}
ImGui::PopID();
@@ -857,7 +855,7 @@ void renderDMat4Property(Property* prop, const std::string& ownerName,
}
if (changed) {
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
}
ImGui::PopID();
@@ -872,7 +870,7 @@ void renderTriggerProperty(Property* prop, const std::string& ownerName,
const bool pressed = ImGui::Button(name.c_str());
if (pressed) {
executeSetPropertyScript(prop->fullyQualifiedIdentifier(), "nil");
executeSetPropertyScript(prop->uri(), "nil");
}
if (showTooltip) {
renderTooltip(prop, tooltipDelay);
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
+4 -8
View File
@@ -137,11 +137,9 @@ void IswaCygnet::initializeGL() {
else {
_delete.onChange([this]() {
deinitialize();
global::scriptEngine->queueScript(
"openspace.removeSceneGraphNode('" + identifier() + "')",
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
);
global::scriptEngine->queueScript(std::format(
"openspace.removeSceneGraphNode('{}')", identifier()
));
});
}
@@ -306,9 +304,7 @@ void IswaCygnet::initializeGroup() {
[this](ghoul::Dictionary) {
LDEBUG(identifier() + " Event clearGroup");
global::scriptEngine->queueScript(
"openspace.removeSceneGraphNode('" + identifier() + "')",
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
"openspace.removeSceneGraphNode('" + identifier() + "')"
);
}
);
+6 -8
View File
@@ -152,11 +152,10 @@ void IswaKameleonGroup::updateFieldlineSeeds() {
if (it == options.end() && std::get<2>(seedPath.second)) {
LDEBUG("Removed fieldlines: " + std::get<0>(seedPath.second));
global::scriptEngine->queueScript(
"openspace.removeSceneGraphNode('" + std::get<0>(seedPath.second) + "')",
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
const std::string script = std::format(
"openspace.removeSceneGraphNode('{}')", std::get<0>(seedPath.second)
);
global::scriptEngine->queueScript(script);
std::get<2>(seedPath.second) = false;
// if this option was turned on
}
@@ -180,11 +179,10 @@ void IswaKameleonGroup::clearFieldlines() {
if (std::get<2>(seedPath.second)) {
LDEBUG("Removed fieldlines: " + std::get<0>(seedPath.second));
global::scriptEngine->queueScript(
"openspace.removeSceneGraphNode('" + std::get<0>(seedPath.second) + "')",
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
const std::string script = std::format(
"openspace.removeSceneGraphNode('{}')", std::get<0>(seedPath.second)
);
global::scriptEngine->queueScript(script);
std::get<2>(seedPath.second) = false;
}
}
+3 -4
View File
@@ -290,11 +290,10 @@ void KameleonPlane::updateFieldlineSeeds() {
}
LDEBUG("Removed fieldlines: " + std::get<0>(seedPath.second));
global::scriptEngine->queueScript(
"openspace.removeSceneGraphNode('" + std::get<0>(seedPath.second) + "')",
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
const std::string script = std::format(
"openspace.removeSceneGraphNode('{}')", std::get<0>(seedPath.second)
);
global::scriptEngine->queueScript(script);
std::get<2>(seedPath.second) = false;
// if this option was turned on
}
+3 -4
View File
@@ -53,11 +53,10 @@ ScreenSpaceCygnet::ScreenSpaceCygnet(const ghoul::Dictionary& dictionary)
_minRealTimeUpdateInterval = 100;
_delete.onChange([this]() {
global::scriptEngine->queueScript(
"openspace.iswa.removeScreenSpaceCygnet("+std::to_string(_cygnetId)+");",
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
const std::string script = std::format(
"openspace.iswa.removeScreenSpaceCygnet({});", _cygnetId
);
global::scriptEngine->queueScript(script);
});
}
+7 -24
View File
@@ -85,11 +85,10 @@ namespace {
}
void createScreenSpace(int id) {
using namespace openspace;
std::string idStr = std::to_string(id);
openspace::global::scriptEngine->queueScript(
"openspace.iswa.addScreenSpaceCygnet({CygnetId =" + idStr + "});",
openspace::scripting::ScriptEngine::ShouldBeSynchronized::Yes,
openspace::scripting::ScriptEngine::ShouldSendToRemote::Yes
global::scriptEngine->queueScript(
"openspace.iswa.addScreenSpaceCygnet({CygnetId =" + idStr + "});"
);
}
} // namespace
@@ -546,11 +545,7 @@ void IswaManager::createPlane(MetadataFuture& data) {
std::string luaTable = jsonPlaneToLuaTable(data);
if (!luaTable.empty()) {
std::string script = "openspace.addSceneGraphNode(" + luaTable + ");";
global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
);
global::scriptEngine->queueScript(script);
}
}
@@ -580,11 +575,7 @@ void IswaManager::createSphere(MetadataFuture& data) {
std::string luaTable = jsonSphereToLuaTable(data);
if (luaTable != "") {
std::string script = "openspace.addSceneGraphNode(" + luaTable + ");";
global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
);
global::scriptEngine->queueScript(script);
}
}
@@ -614,11 +605,7 @@ void IswaManager::createKameleonPlane(CdfInfo info, std::string cut) {
std::string luaTable = parseKWToLuaTable(info, cut);
if (!luaTable.empty()) {
std::string script = "openspace.addSceneGraphNode(" + luaTable + ");";
global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
);
global::scriptEngine->queueScript(script);
}
}
else {
@@ -656,11 +643,7 @@ void IswaManager::createFieldline(std::string name, std::filesystem::path cdfPat
"}";
if (!luaTable.empty()) {
std::string script = "openspace.addSceneGraphNode(" + luaTable + ");";
global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
);
global::scriptEngine->queueScript(script);
}
}
else {
+3 -11
View File
@@ -68,11 +68,8 @@ namespace {
// Remove a Cygnets.
[[codegen::luawrap]] void removeCygnet(std::string name) {
using namespace openspace;
global::scriptEngine->queueScript(
"openspace.removeSceneGraphNode('" + name + "')",
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
openspace::global::scriptEngine->queueScript(
"openspace.removeSceneGraphNode('" + name + "')"
);
}
@@ -94,12 +91,7 @@ namespace {
std::string script = std::format(
"openspace.unregisterScreenSpaceRenderable('{}');", cygnetInformation[id]->name
);
global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
);
global::scriptEngine->queueScript(script);
}
// Remove a group of Cygnets.
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
@@ -104,7 +104,6 @@ namespace {
"LowerValueBound",
"Lower Value Bound",
"", // @TODO Missing documentation
// @VISIBILITY(?)
openspace::properties::Property::Visibility::AdvancedUser
};
@@ -112,7 +111,6 @@ namespace {
"UpperValueBound",
"Upper Value Bound",
"", // @TODO Missing documentation
// @VISIBILITY(?)
openspace::properties::Property::Visibility::AdvancedUser
};
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
@@ -79,7 +79,6 @@ namespace {
"CurrentTime",
"Current Time",
"", // @TODO Missing documentation
// @VISIBILITY(2.5)
openspace::properties::Property::Visibility::User
};
@@ -87,7 +86,6 @@ namespace {
"MemoryBudget",
"Memory Budget",
"", // @TODO Missing documentation
// @VISIBILITY(3.5)
openspace::properties::Property::Visibility::AdvancedUser
};
@@ -95,7 +93,6 @@ namespace {
"StreamingBudget",
"Streaming Budget",
"", // @TODO Missing documentation
// @VISIBILITY(3.5)
openspace::properties::Property::Visibility::AdvancedUser
};
@@ -103,7 +100,6 @@ namespace {
"UseGlobalTime",
"Global Time",
"", // @TODO Missing documentation
// @VISIBILITY(2.5)
openspace::properties::Property::Visibility::User
};
@@ -118,7 +114,6 @@ namespace {
"Selector",
"Brick Selector",
"", // @TODO Missing documentation
// @VISIBILITY(3.5)
openspace::properties::Property::Visibility::AdvancedUser
};
+2 -2
View File
@@ -571,11 +571,11 @@ bool TSP::writeCache() {
}
float TSP::spatialError(unsigned int brickIndex) const {
return *reinterpret_cast<const float*>(_data[brickIndex*NUM_DATA + SPATIAL_ERR]);
return *reinterpret_cast<const float*>(&_data[brickIndex*NUM_DATA + SPATIAL_ERR]);
}
float TSP::temporalError(unsigned int brickIndex) const {
return *reinterpret_cast<const float*>(_data[brickIndex*NUM_DATA + TEMPORAL_ERR]);
return *reinterpret_cast<const float*>(&_data[brickIndex*NUM_DATA + TEMPORAL_ERR]);
}
unsigned int TSP::firstOctreeChild(unsigned int brickIndex) const {
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
+1 -1
View File
@@ -72,7 +72,7 @@ void to_json(json& j, const PropertyOwner* p) {
namespace ghoul {
void to_json(json& j, const Dictionary& d) {
json object;
json object = json::object();
for (const std::string_view k : d.keys()) {
const std::string key = std::string(k);
if (d.hasValue<glm::dvec4>(key)) {
@@ -446,11 +446,7 @@ void FlightControllerTopic::processInputState(const nlohmann::json& json) {
void FlightControllerTopic::processLua(const nlohmann::json &json) {
const std::string script = json[LuaScript];
global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
);
global::scriptEngine->queueScript(script);
}
} // namespace openspace
+9 -7
View File
@@ -190,7 +190,9 @@ void LuaScriptTopic::handleJson(const nlohmann::json& json) {
void LuaScriptTopic::runScript(std::string script, bool shouldReturn,
bool shouldBeSynchronized)
{
scripting::ScriptEngine::ScriptCallback callback;
using namespace scripting;
ScriptEngine::Script::Callback callback;
if (shouldReturn) {
callback = [this](const ghoul::Dictionary& data) {
if (_connection) {
@@ -205,12 +207,12 @@ void LuaScriptTopic::runScript(std::string script, bool shouldReturn,
_waitingForReturnValue = false;
}
global::scriptEngine->queueScript(
std::move(script),
scripting::ScriptEngine::ShouldBeSynchronized(shouldBeSynchronized),
scripting::ScriptEngine::ShouldSendToRemote(shouldBeSynchronized),
callback
);
global::scriptEngine->queueScript({
.code = std::move(script),
.synchronized = ScriptEngine::Script::ShouldBeSynchronized(shouldBeSynchronized),
.sendToRemote = ScriptEngine::Script::ShouldSendToRemote(shouldBeSynchronized),
.callback = callback
});
}
bool LuaScriptTopic::isDone() const {
@@ -122,13 +122,10 @@ void SetPropertyTopic::handleJson(const nlohmann::json& json) {
const nlohmann::json value = json.at("value");
std::string literal = luaLiteralFromJson(value);
global::scriptEngine->queueScript(
std::format(
"openspace.setPropertyValueSingle(\"{}\", {})", propertyKey, literal
),
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
);
const std::string script = std::format(
"openspace.setPropertyValueSingle(\"{}\", {})", propertyKey, literal
);
global::scriptEngine->queueScript(script);
}
}
catch (const std::out_of_range& e) {
@@ -58,7 +58,6 @@ std::vector<nlohmann::json> ShortcutTopic::shortcutsJson() const {
const nlohmann::json shortcutJson = {
{ "identifier", action.identifier },
{ "name", action.name },
{ "script", action.command },
{ "synchronization", static_cast<bool>(!action.isLocal) },
{ "documentation", action.documentation },
{ "guiPath", action.guiPath },
@@ -121,7 +120,6 @@ nlohmann::json ShortcutTopic::shortcutJson(const std::string& identifier) const
json.push_back({
{ "identifier", action.identifier },
{ "name", action.name },
{ "script", action.command },
{ "synchronization", static_cast<bool>(!action.isLocal) },
{ "documentation", action.documentation },
{ "guiPath", action.guiPath },
@@ -40,13 +40,10 @@ namespace openspace {
void TriggerPropertyTopic::handleJson(const nlohmann::json& json) {
try {
const std::string& propertyKey = json.at("property").get<std::string>();
global::scriptEngine->queueScript(
std::format(
"openspace.setPropertyValueSingle(\"{}\", nil)", propertyKey
),
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
const std::string script = std::format(
"openspace.setPropertyValueSingle(\"{}\", nil)", propertyKey
);
global::scriptEngine->queueScript(script);
}
catch (const std::out_of_range& e) {
LERROR("Could not trigger property -- key or value is missing in payload");
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
+3
View File
@@ -94,6 +94,9 @@ protected:
private:
class RenderHandler : public WebRenderHandler {
public:
RenderHandler()
: WebRenderHandler(false)
{}
void draw() override;
void render() override;
+4 -17
View File
@@ -345,14 +345,9 @@ void SkyBrowserModule::moveHoverCircle(const std::string& imageUrl, bool useScri
// Show the circle
if (useScript) {
const std::string script = std::format(
"openspace.setPropertyValueSingle('Scene.{}.Renderable.Fade', 1.0);",
id
);
global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
"openspace.setPropertyValueSingle('Scene.{}.Renderable.Fade', 1.0);", id
);
global::scriptEngine->queueScript(script);
}
else {
Renderable* renderable = _hoverCircle->renderable();
@@ -372,11 +367,7 @@ void SkyBrowserModule::moveHoverCircle(const std::string& imageUrl, bool useScri
"openspace.setPropertyValueSingle('Scene.{}.Translation.Position', {});",
id, ghoul::to_string(pos)
);
global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
);
global::scriptEngine->queueScript(script);
}
void SkyBrowserModule::disableHoverCircle(bool useScript) {
@@ -386,11 +377,7 @@ void SkyBrowserModule::disableHoverCircle(bool useScript) {
"openspace.setPropertyValueSingle('Scene.{}.Renderable.Fade', 0.0);",
_hoverCircle->identifier()
);
global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
);
global::scriptEngine->queueScript(script);
}
else {
_hoverCircle->renderable()->property("Fade")->set(0.f);
+31 -43
View File
@@ -249,21 +249,21 @@ std::string prunedIdentifier(std::string identifier) {
// No sync or send because this is already inside a Lua script, therefor it
// has already been synced and sent to the connected nodes and peers
global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript({
.code = script,
.synchronized = scripting::ScriptEngine::Script::ShouldBeSynchronized::No,
.sendToRemote = scripting::ScriptEngine::Script::ShouldSendToRemote::No
});
}
}
// To ensure each node in a cluster calls its own instance of the wwt application
// Do not send this script to the other nodes. (Note malej 2023-AUG-23: Due to this
// already being inside a Lua function that have already been synced out)
global::scriptEngine->queueScript(
"openspace.skybrowser.sendOutIdsToBrowsers()",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript({
.code = "openspace.skybrowser.sendOutIdsToBrowsers()",
.synchronized = scripting::ScriptEngine::Script::ShouldBeSynchronized::No,
.sendToRemote = scripting::ScriptEngine::Script::ShouldSendToRemote::No
});
}
/**
@@ -607,30 +607,18 @@ ghoul::Dictionary wwtImageCollectionUrlDeprecated()
// No sync or send because this is already inside a Lua script, therefor it has
// already been synced and sent to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.addScreenSpaceRenderable(" + browser + ");",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript(
"openspace.addSceneGraphNode(" + target + ");",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript(
"openspace.skybrowser.addPairToSkyBrowserModule('" + idTarget + "','"
+ idBrowser + "');",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript(
"openspace.skybrowser.setSelectedBrowser('" + idBrowser + "');",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
const std::string script = std::format(
"openspace.addScreenSpaceRenderable({0});"
"openspace.addSceneGraphNode({1});"
"openspace.skybrowser.addPairToSkyBrowserModule('{2}','{3}');"
"openspace.skybrowser.setSelectedBrowser('{3}')",
browser, target, idTarget, idBrowser
);
global::scriptEngine->queueScript({
.code = script,
.synchronized = scripting::ScriptEngine::Script::ShouldBeSynchronized::No,
.sendToRemote = scripting::ScriptEngine::Script::ShouldSendToRemote::No
});
}
/**
@@ -650,17 +638,17 @@ ghoul::Dictionary wwtImageCollectionUrlDeprecated()
// Remove from engine.
// No sync or send because this is already inside a Lua script, therefor it has
// already been synced and sent to the connected nodes and peers
global::scriptEngine->queueScript(
"openspace.removeScreenSpaceRenderable('" + browser + "');",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript({
.code = "openspace.removeScreenSpaceRenderable('" + browser + "');",
.synchronized = scripting::ScriptEngine::Script::ShouldBeSynchronized::No,
.sendToRemote = scripting::ScriptEngine::Script::ShouldSendToRemote::No
});
global::scriptEngine->queueScript(
"openspace.removeSceneGraphNode('" + target + "');",
scripting::ScriptEngine::ShouldBeSynchronized::No,
scripting::ScriptEngine::ShouldSendToRemote::No
);
global::scriptEngine->queueScript({
.code = "openspace.removeSceneGraphNode('" + target + "');",
.synchronized = scripting::ScriptEngine::Script::ShouldBeSynchronized::No,
.sendToRemote = scripting::ScriptEngine::Script::ShouldSendToRemote::No
});
}
}
+2 -1
View File
@@ -109,7 +109,8 @@ Browser::Browser(const ghoul::Dictionary& dictionary)
// Create browser and render handler
_browserInstance = std::make_unique<BrowserInstance>(
_renderHandler.get(),
_keyboardHandler.get()
_keyboardHandler.get(),
false
);
WebBrowserModule* webBrowser = global::moduleEngine->module<WebBrowserModule>();
@@ -193,7 +193,10 @@ ScreenSpaceSkyBrowser::~ScreenSpaceSkyBrowser() {
bool ScreenSpaceSkyBrowser::initializeGL() {
WwtCommunicator::initializeGL();
ScreenSpaceRenderable::initializeGL();
// @TODO (ylvse, 2024-08-23) Remove this once the skybrowser has been rewritten
ghoul::Dictionary dict;
dict.setValue("useAcceleratedRendering", false);
createShaders(dict);
return true;
}
+2 -10
View File
@@ -49,11 +49,7 @@ namespace {
"openspace.setPropertyValueSingle('Scene.{}.Translation.Position', {});",
id, ghoul::to_string(positionCelestial)
);
openspace::global::scriptEngine->queueScript(
script,
openspace::scripting::ScriptEngine::ShouldBeSynchronized::Yes,
openspace::scripting::ScriptEngine::ShouldSendToRemote::Yes
);
openspace::global::scriptEngine->queueScript(script);
}
} // namespace
@@ -328,11 +324,7 @@ void TargetBrowserPair::startFading(float goal, float fadeTime) {
_targetNode->identifier(), _browser->identifier(), goal, fadeTime
);
global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
scripting::ScriptEngine::ShouldSendToRemote::Yes
);
global::scriptEngine->queueScript(script);
}
void TargetBrowserPair::stopAnimations() {
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
@@ -287,9 +287,6 @@ void RenderableTravelSpeed::update(const UpdateData& data) {
else { // in case we've reached the target
reinitiateTravel();
}
_shaderProgram->setUniform("lineColor", _lineColor);
_shaderProgram->setUniform("opacity", opacity());
}
void RenderableTravelSpeed::render(const RenderData& data, RendererTasks&) {
@@ -304,6 +301,9 @@ void RenderableTravelSpeed::render(const RenderData& data, RendererTasks&) {
);
_shaderProgram->setUniform("projectionTransform", data.camera.projectionMatrix());
_shaderProgram->setUniform("lineColor", _lineColor);
_shaderProgram->setUniform("opacity", opacity());
#ifndef __APPLE__
glLineWidth(_lineWidth);
#else
+9 -7
View File
@@ -1,15 +1,17 @@
openspace.space.documentation = {
{
Name = "tleToSpiceTranslation",
Arguments = {{ "tlePath", "String" }},
Return = "{ Translation, SpiceKernel }",
Arguments = {
{ "tlePath", "String" }
},
Return = "( Translation, SpiceKernel )",
Documentation = [[
Takes the provided TLE file, converts it into a SPICE kernel and returns a
SpiceTranslation instance that can be used to access the information in the TLE
file using SPICE's superior integral solver.
Takes the provided TLE file, converts it into a SPICE kernel and returns a
SpiceTranslation instance that can be used to access the information in the TLE
file using SPICE's superior integral solver.
The second return value is the spice kernel that should be loaded and unloaded by
whoever called this function.
The second return value is the spice kernel that should be loaded and unloaded by
whoever called this function.
]]
}
}
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #
+1 -1
View File
@@ -2,7 +2,7 @@
# #
# OpenSpace #
# #
# Copyright (c) 2014-2023 #
# Copyright (c) 2014-2024 #
# #
# 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 #

Some files were not shown because too many files have changed in this diff Show More