diff --git a/data/assets/examples/nodearrow.asset b/data/assets/examples/nodearrow.asset deleted file mode 100644 index ef851baa48..0000000000 --- a/data/assets/examples/nodearrow.asset +++ /dev/null @@ -1,77 +0,0 @@ -local earth = asset.require("scene/solarsystem/planets/earth/earth") -local moon = asset.require("scene/solarsystem/planets/earth/moon/moon") -local mars = asset.require("scene/solarsystem/planets/mars/mars") - - - -local EarthRadius = 6371000.0 - -local ArrowExample = { - Identifier = "RenderableNodeArrowExample", - Parent = earth.Earth.Identifier, - Renderable = { - Type = "RenderableNodeArrow", - StartNode = earth.Earth.Identifier, - EndNode = mars.Mars.Identifier, - Color = { 0.8, 1.0, 0.8 }, - Offset = 2 * EarthRadius, - Length = 5 * EarthRadius, - Width = 900000.0 - }, - GUI = { - Name = "Node Arrow Example", - Path = "/Example", - Description = [[Example node direction arrow, using absolute sizes]] - } -} - --- Relative values: Multiplied with bounding sphere -local ArrowExample_RelativeUnits = { - Identifier = "RenderableNodeArrowExample_Relative", - Parent = earth.Earth.Identifier, - Renderable = { - Type = "RenderableNodeArrow", - StartNode = earth.Earth.Identifier, - EndNode = moon.Moon.Identifier, - Color = { 0.78, 0.0, 1.0 }, - UseRelativeOffset = true, - UseRelativeLength = true, - Offset = 2.0, - Length = 5.0, - Width = 900000.0, - Invert = true -- Point to start node instead of end node - }, - GUI = { - Name = "Node Arrow Example (relative units)", - Path = "/Example", - Description = [[Example node direction arrow, using relative sizes]] - } -} - - -asset.onInitialize(function() - openspace.addSceneGraphNode(ArrowExample) - openspace.addSceneGraphNode(ArrowExample_RelativeUnits) -end) - -asset.onDeinitialize(function() - openspace.removeSceneGraphNode(ArrowExample_RelativeUnits) - openspace.removeSceneGraphNode(ArrowExample) -end) - -asset.export(ArrowExample) -asset.export(ArrowExample_RelativeUnits) - - - -asset.meta = { - Name = "RenderableNodeArrow Example asset", - Version = "1.0", - Description = [[Examples of the RenderableNodeArrow renderable, that can be used to draw - an arrow pointing from one scene graph node in the direction of another. Note that - the arrows are generated as objects in 3D space and need to have a size that is - suitable for their 3D context.]], - Author = "OpenSpace Team", - URL = "http://openspaceproject.com", - License = "MIT license" -} diff --git a/data/assets/examples/renderable/renderablenodearrow/nodearrow.asset b/data/assets/examples/renderable/renderablenodearrow/nodearrow.asset new file mode 100644 index 0000000000..0e659ca4b7 --- /dev/null +++ b/data/assets/examples/renderable/renderablenodearrow/nodearrow.asset @@ -0,0 +1,39 @@ +-- Basic +-- This example shows an arrow pointing from one scene graph node in the direction of +-- another. Here, it points from Earth to Mars. +-- +-- Note that the arrows are generated as objects in 3D space and need to have a size +-- that is suitable for the scene graph nodes they refer to. Here it is set based on +-- the size of the Earth. + +local earth = asset.require("scene/solarsystem/planets/earth/earth") +local mars = asset.require("scene/solarsystem/planets/mars/mars") + +local Node = { + Identifier = "RenderableNodeArrow_Example", + -- Parent to the start node, so that when we focus on the arrow this is where we end up + Parent = earth.Earth.Identifier, + Renderable = { + Type = "RenderableNodeArrow", + StartNode = earth.Earth.Identifier, + EndNode = mars.Mars.Identifier, + -- How far away from the start node should the arrow start (meters) + Offset = 2 * 6371000.0, + -- How long should the arrow be (meters) + Length = 5 * 6371000.0, + -- How wide should the arrow be (meters) + Width = 900000.0 + }, + GUI = { + Name = "Basic", + Path = "/Examples/RenderableNodeArrow" + } +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(Node) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(Node) +end) diff --git a/data/assets/examples/renderable/renderablenodearrow/nodearrow_appearance.asset b/data/assets/examples/renderable/renderablenodearrow/nodearrow_appearance.asset new file mode 100644 index 0000000000..38e9f6238c --- /dev/null +++ b/data/assets/examples/renderable/renderablenodearrow/nodearrow_appearance.asset @@ -0,0 +1,41 @@ +-- Custom Appearance (Colored & Inverted) +-- This example shows an arrow pointing from one scene graph node in the direction of +-- another. Here, it is created with the Solar System barycenter as start node and +-- Earth as end node, but the arrow direction is inverted so that it points towards +-- the Solar System barycenter. Some appearance related properties are also changed to +-- customize the look of the arrow, but default values are used for its size. + +local earth = asset.require("scene/solarsystem/planets/earth/earth") +local sunTransforms = asset.require("scene/solarsystem/sun/transforms") + +local Node = { + Identifier = "RenderableNodeArrow_Example_Appearance", + -- Parent to the start node, so that when we focus on the arrow this is where we end up + Parent = sunTransforms.SolarSystemBarycenter.Identifier, + Renderable = { + Type = "RenderableNodeArrow", + StartNode = sunTransforms.SolarSystemBarycenter.Identifier, + EndNode = earth.Earth.Identifier, + -- Point to start node instead of end node + Invert = true, + -- Give the arrow a custom color (here a dark red) + Color = { 0.5, 0.0, 0.0 }, + -- Set the arrow head size so that it takes up a quarter (25%) of the full length of + -- the arrow + ArrowHeadSize = 0.25, + -- Set the arrow head width. A value of 1 makes it as wide as the body of the arrow + ArrowHeadWidthFactor = 1.0 + }, + GUI = { + Name = "Custom Appearance (Colored & Inverted)", + Path = "/Examples/RenderableNodeArrow" + } +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(Node) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(Node) +end) diff --git a/data/assets/examples/renderable/renderablenodearrow/nodearrow_relativevalues.asset b/data/assets/examples/renderable/renderablenodearrow/nodearrow_relativevalues.asset new file mode 100644 index 0000000000..1f1fb74c3a --- /dev/null +++ b/data/assets/examples/renderable/renderablenodearrow/nodearrow_relativevalues.asset @@ -0,0 +1,42 @@ +-- Relative Units for Offset and Length +-- This example shows an arrow pointing from one scene graph node in the direction of +-- another, but where the size is specified using relative values (based on the bounding +-- sphere of the start node). Here it points from Earth to the Moon. +-- +-- Note that the arrows are generated as objects in 3D space and need to have a size +-- that is suitable for the scene graph nodes they refer to. Here it is set based on +-- the size of the start node, i.e. Earth. + +local earth = asset.require("scene/solarsystem/planets/earth/earth") +local moon = asset.require("scene/solarsystem/planets/earth/moon/moon") + +local Node = { + Identifier = "RenderableNodeArrow_Example_Relative", + -- Parent to the start node, so that when we focus on the arrow this is where we end up + Parent = earth.Earth.Identifier, + Renderable = { + Type = "RenderableNodeArrow", + StartNode = earth.Earth.Identifier, + EndNode = moon.Moon.Identifier, + -- Use relative values for offset and length + UseRelativeOffset = true, + UseRelativeLength = true, + -- Specify relative values (times the size of Earth, in this case) + Offset = 2.0, + Length = 5.0, + -- Width is in meters + Width = 900000.0 + }, + GUI = { + Name = "Relative Units", + Path = "/Examples/RenderableNodeArrow", + } +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(Node) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(Node) +end) diff --git a/data/assets/examples/renderable/renderableplaneimageonline/planeimageonline.asset b/data/assets/examples/renderable/renderableplaneimageonline/planeimageonline.asset new file mode 100644 index 0000000000..40607a837c --- /dev/null +++ b/data/assets/examples/renderable/renderableplaneimageonline/planeimageonline.asset @@ -0,0 +1,24 @@ +-- Basic +-- This example shows how to create a textured plane in 3D space, where the texture is +-- loaded from the internet though a web URL. + +local Node = { + Identifier = "RenderablePlaneImageOnline_Example", + Renderable = { + Type = "RenderablePlaneImageOnline", + Size = 3.0E11, + URL = "http://data.openspaceproject.com/examples/renderableplaneimageonline.jpg" + }, + GUI = { + Name = "Basic", + Path = "/Examples/RenderablePlaneImageOnline" + } +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(Node) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(Node) +end) diff --git a/data/assets/examples/renderable/renderableplaneimageonline/planeimageonline_billboarded.asset b/data/assets/examples/renderable/renderableplaneimageonline/planeimageonline_billboarded.asset new file mode 100644 index 0000000000..67808307e6 --- /dev/null +++ b/data/assets/examples/renderable/renderableplaneimageonline/planeimageonline_billboarded.asset @@ -0,0 +1,26 @@ +-- Billboarded Image +-- This example shows how to create a textured plane in 3D space, where the texture is +-- loaded from the internet though a web URL and the plane is billboarded to always +-- face the camera. + +local Node = { + Identifier = "RenderablePlaneImageOnline_Example_Billboarded", + Renderable = { + Type = "RenderablePlaneImageOnline", + Size = 3.0E11, + URL = "http://data.openspaceproject.com/examples/renderableplaneimageonline.jpg", + Billboarded = true + }, + GUI = { + Name = "Billboarded", + Path = "/Examples/RenderablePlaneImageOnline" + } +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(Node) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(Node) +end) diff --git a/data/assets/examples/renderableplaneimageonline.asset b/data/assets/examples/renderableplaneimageonline.asset deleted file mode 100644 index 6e48992e23..0000000000 --- a/data/assets/examples/renderableplaneimageonline.asset +++ /dev/null @@ -1,41 +0,0 @@ -local transforms = asset.require("scene/solarsystem/sun/transforms") - - - -local RenderablePlaneImageOnline = { - Identifier = "RenderablePlaneImageOnline", - Parent = transforms.SolarSystemBarycenter.Identifier, - Renderable = { - Type = "RenderablePlaneImageOnline", - Size = 3.0E11, - Origin = "Center", - Billboard = true, - URL = "http://data.openspaceproject.com/examples/renderableplaneimageonline.jpg" - }, - GUI = { - Description = "A plane that loads a texture from the internet.", - Path = "/Examples" - } -} - - -asset.onInitialize(function() - openspace.addSceneGraphNode(RenderablePlaneImageOnline) -end) - -asset.onDeinitialize(function() - openspace.removeSceneGraphNode(RenderablePlaneImageOnline) -end) - -asset.export(RenderablePlaneImageOnline) - - -asset.meta = { - Name = "RenderablePlaneImageOnline Example", - Version = "1.0", - Description = [[Example of how to create a textured plane in 3D space, where the - texture is loaded from a web URL]], - Author = "OpenSpace Team", - URL = "http://openspaceproject.com", - License = "MIT license" -} diff --git a/modules/base/rendering/renderablenodearrow.cpp b/modules/base/rendering/renderablenodearrow.cpp index fa8e432a43..805f77dfba 100644 --- a/modules/base/rendering/renderablenodearrow.cpp +++ b/modules/base/rendering/renderablenodearrow.cpp @@ -169,12 +169,20 @@ namespace { openspace::properties::Property::Visibility::User }; + // A RenderableNodeArrow can be used to create a 3D arrow pointing in the direction + // of one scene graph node to another. + // + // The arrow will be placed at the `StartNode` at a distance of the provided + // `Offset` value. Per default, the `Length` and `Offset` of the arrow is specified + // in meters, but they may also be specified as a multiplier of the bounding sphere + // of the `StartNode`. The look of the arrow can be customized to change the width + // and length of both the arrow body and head. struct [[codegen::Dictionary(RenderableNodeArrow)]] Parameters { // [[codegen::verbatim(StartNodeInfo.description)]] - std::string startNode [[codegen::notempty]]; + std::string startNode [[codegen::identifier()]]; // [[codegen::verbatim(EndNodeInfo.description)]] - std::string endNode [[codegen::notempty]]; + std::string endNode [[codegen::identifier()]]; // [[codegen::verbatim(ColorInfo.description)]] std::optional color [[codegen::color()]]; @@ -454,6 +462,8 @@ void RenderableNodeArrow::updateShapeTransforms(const RenderData& data) { // Rotation to point at the end node const glm::quat rotQuat = glm::rotation(glm::dvec3(0.0, 0.0, 1.0), arrowDirection); _pointDirectionRotation = glm::dmat4(glm::toMat4(rotQuat)); + + setBoundingSphere(length + offset); } void RenderableNodeArrow::render(const RenderData& data, RendererTasks&) { diff --git a/modules/base/rendering/renderableplane.cpp b/modules/base/rendering/renderableplane.cpp index 0903fdb943..e698c9fe59 100644 --- a/modules/base/rendering/renderableplane.cpp +++ b/modules/base/rendering/renderableplane.cpp @@ -103,6 +103,9 @@ namespace { // [[codegen::verbatim(SizeInfo.description)]] std::variant size; + // [[codegen::verbatim(AutoScaleInfo.description)]] + std::optional autoScale; + enum class [[codegen::map(BlendMode)]] BlendMode { Normal, Additive @@ -133,6 +136,11 @@ RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary) { Parameters p = codegen::bake(dictionary); + _opacity.onChange([this]() { + if (_blendMode == static_cast(BlendMode::Normal)) { + setRenderBinFromOpacity(); + } + }); addProperty(Fadeable::_opacity); if (std::holds_alternative(p.size)) { @@ -141,9 +149,9 @@ RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary) else { _size = std::get(p.size); } - - _billboard = p.billboard.value_or(_billboard); - _mirrorBackside = p.mirrorBackside.value_or(_mirrorBackside); + _size.setExponent(15.f); + _size.onChange([this]() { _planeIsDirty = true; }); + addProperty(_size); _blendMode.addOptions({ { static_cast(BlendMode::Normal), "Normal" }, @@ -161,27 +169,22 @@ RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary) } }); - _opacity.onChange([this]() { - if (_blendMode == static_cast(BlendMode::Normal)) { - setRenderBinFromOpacity(); - } - }); - if (p.blendMode.has_value()) { _blendMode = codegen::map(*p.blendMode); } + addProperty(_blendMode); + + _billboard = p.billboard.value_or(_billboard); + addProperty(_billboard); + + _mirrorBackside = p.mirrorBackside.value_or(_mirrorBackside); + addProperty(_mirrorBackside); + + _autoScale = p.autoScale.value_or(_autoScale); + addProperty(_autoScale); _multiplyColor = p.multiplyColor.value_or(_multiplyColor); _multiplyColor.setViewOption(properties::Property::ViewOptions::Color); - - addProperty(_billboard); - - _size.setExponent(15.f); - addProperty(_size); - _size.onChange([this](){ _planeIsDirty = true; }); - - addProperty(_autoScale); - addProperty(_multiplyColor); setBoundingSphere(glm::compMax(_size.value())); diff --git a/modules/base/rendering/renderableplaneimagelocal.cpp b/modules/base/rendering/renderableplaneimagelocal.cpp index b0e49da674..93a4d7b435 100644 --- a/modules/base/rendering/renderableplaneimagelocal.cpp +++ b/modules/base/rendering/renderableplaneimagelocal.cpp @@ -73,8 +73,6 @@ RenderablePlaneImageLocal::RenderablePlaneImageLocal(const ghoul::Dictionary& di { const Parameters p = codegen::bake(dictionary); - addProperty(_blendMode); - _texturePath = absPath(p.texture).string(); _textureFile = std::make_unique(_texturePath.value()); diff --git a/modules/base/rendering/renderableplaneimageonline.cpp b/modules/base/rendering/renderableplaneimageonline.cpp index d9d0acb796..39fe94d583 100644 --- a/modules/base/rendering/renderableplaneimageonline.cpp +++ b/modules/base/rendering/renderableplaneimageonline.cpp @@ -43,6 +43,8 @@ namespace { openspace::properties::Property::Visibility::User }; + // A RenderablePlaneImageOnline creates a textured 3D plane, where the texture image + // is loaded from the internet though a web URL. struct [[codegen::Dictionary(RenderablePlaneImageOnline)]] Parameters { // [[codegen::verbatim(TextureInfo.description)]] std::string url [[codegen::key("URL")]];