diff --git a/data/assets/base.asset b/data/assets/base.asset index 73e2db77ab..6ef26ab294 100644 --- a/data/assets/base.asset +++ b/data/assets/base.asset @@ -63,6 +63,22 @@ local Keybindings = { GuiPath = "/Rendering", Local = false }, + { + Key = "l", + Name = "Turn on labels", + Command = "openspace.setPropertyValue('{solarsystem_labels}.Renderable.Enabled', true)", + Documentation = "Turns on visibility for all solar system labels", + GuiPath = "/Rendering", + Local = false + }, + { + Key = "Shift+l", + Name = "Turn off labels", + Command = "openspace.setPropertyValue('{solarsystem_labels}.Renderable.Enabled', false)", + Documentation = "Turns off visibility for all solar system labels", + GuiPath = "/Rendering", + Local = false + } } asset.onInitialize(function () diff --git a/data/assets/scene/digitaluniverse/2dF.asset b/data/assets/scene/digitaluniverse/2dF.asset index 2b09ab91ff..2da1fb619d 100644 --- a/data/assets/scene/digitaluniverse/2dF.asset +++ b/data/assets/scene/digitaluniverse/2dF.asset @@ -6,7 +6,7 @@ local textures = asset.syncedResource({ Name = "2dF Textures", Type = "HttpSynchronization", Identifier = "digitaluniverse_2dF_textures", - Version = 1 + Version = 2 }) local speck = asset.syncedResource({ @@ -24,7 +24,7 @@ local object = { Color = { 1.0, 1.0, 1.0 }, Opacity = 1.0, File = speck .. "/2dF.speck", - Texture = textures .. "/point3.png", + Texture = textures .. "/point3A.png", ColorMap = speck .. "/2dF.cmap", ColorOption = { "redshift", "proximity" }, ColorRange = { { 0.0, 0.075 }, { 1.0, 25.0 } }, diff --git a/data/assets/scene/digitaluniverse/2mass.asset b/data/assets/scene/digitaluniverse/2mass.asset index b27311229a..c27557c282 100644 --- a/data/assets/scene/digitaluniverse/2mass.asset +++ b/data/assets/scene/digitaluniverse/2mass.asset @@ -6,7 +6,7 @@ local textures = asset.syncedResource({ Name = "2MASS Textures", Type = "HttpSynchronization", Identifier = "digitaluniverse_2mass_textures", - Version = 1 + Version = 2 }) local speck = asset.syncedResource({ @@ -24,7 +24,7 @@ local object = { Color = { 1.0, 0.4, 0.2 }, Opacity = 1.0, File = speck .. "/2MASS.speck", - Texture = textures .. "/point3.png", + Texture = textures .. "/point3A.png", ColorMap = speck .. "/lss.cmap", ColorOption = { "redshift", "prox5Mpc" }, ColorRange = { { 0.0, 0.075 }, { 1.0, 50.0 } }, diff --git a/data/assets/scene/digitaluniverse/6dF.asset b/data/assets/scene/digitaluniverse/6dF.asset index 3f9b74256c..2843b142d4 100644 --- a/data/assets/scene/digitaluniverse/6dF.asset +++ b/data/assets/scene/digitaluniverse/6dF.asset @@ -6,7 +6,7 @@ local textures = asset.syncedResource({ Name = "6dF Textures", Type = "HttpSynchronization", Identifier = "digitaluniverse_6dF_textures", - Version = 1 + Version = 2 }) local speck = asset.syncedResource({ @@ -24,7 +24,7 @@ local object = { Color = { 1.0, 1.0, 0.0 }, Opacity = 1.0, File = speck .. "/6dF.speck", - Texture = textures .. "/point3.png", + Texture = textures .. "/point3A.png", ColorMap = speck .. "/6dF.cmap", ColorOption = { "redshift", "proximity" }, ColorRange = { { 0.0, 0.075 }, { 1.0, 10.0 } }, diff --git a/data/assets/scene/digitaluniverse/abell.asset b/data/assets/scene/digitaluniverse/abell.asset index 673f2f57ac..287eab6c52 100644 --- a/data/assets/scene/digitaluniverse/abell.asset +++ b/data/assets/scene/digitaluniverse/abell.asset @@ -6,7 +6,7 @@ local textures = asset.syncedResource({ Name = "Abell Textures", Type = "HttpSynchronization", Identifier = "digitaluniverse_abell_textures", - Version = 1 + Version = 2 }) local speck = asset.syncedResource({ @@ -25,7 +25,7 @@ local object = { Opacity = 1.0, --ColorMap = speck .. "/abell.cmap", File = speck .. "/abell.speck", - Texture = textures .. "/point3.png", + Texture = textures .. "/point3A.png", LabelFile = speck .. "/abell.label", TextColor = { 0.0, 0.8, 0.0, 1.0 }, TextSize = 22, diff --git a/data/assets/scene/digitaluniverse/quasars.asset b/data/assets/scene/digitaluniverse/quasars.asset index b24f034f7d..be9b11e59b 100644 --- a/data/assets/scene/digitaluniverse/quasars.asset +++ b/data/assets/scene/digitaluniverse/quasars.asset @@ -6,7 +6,7 @@ local textures = asset.syncedResource({ Name = "Quasars Textures", Type = "HttpSynchronization", Identifier = "digitaluniverse_quasars_textures", - Version = 1 + Version = 2 }) local speck = asset.syncedResource({ @@ -24,7 +24,7 @@ local object = { Color = { 1.0, 0.4, 0.2 }, Opacity = 0.95, File = speck .. "/quasars.speck", - Texture = textures .. "/point3.png", + Texture = textures .. "/point3A.png", Unit = "Mpc", ScaleFactor = 540.9, -- Fade in value in the same unit as "Unit" diff --git a/data/assets/scene/digitaluniverse/sdss.asset b/data/assets/scene/digitaluniverse/sdss.asset index 38563ed859..56d92df264 100644 --- a/data/assets/scene/digitaluniverse/sdss.asset +++ b/data/assets/scene/digitaluniverse/sdss.asset @@ -6,7 +6,7 @@ local textures = asset.syncedResource({ Name = "Sloan Digital Sky Survey Textures", Type = "HttpSynchronization", Identifier = "digitaluniverse_sloandss_textures", - Version = 1 + Version = 2 }) local speck = asset.syncedResource({ @@ -28,7 +28,7 @@ local object = { ColorMap = speck .. "/SDSSgals.cmap", ColorOption = { "redshift", "proximity" }, ColorRange = { { 0.0, 0.075 }, { 1.0, 50.0 } }, - Texture = textures .. "/point3.png", + Texture = textures .. "/point3A.png", Unit = "Mpc", -- Fade in value in the same unit as "Unit" FadeInDistances = { 220.0, 650.0 }, diff --git a/data/assets/scene/digitaluniverse/superclusters.asset b/data/assets/scene/digitaluniverse/superclusters.asset index d51868d921..5ce754caa7 100644 --- a/data/assets/scene/digitaluniverse/superclusters.asset +++ b/data/assets/scene/digitaluniverse/superclusters.asset @@ -6,7 +6,7 @@ local textures = asset.syncedResource({ Name = "Galaxy Superclusters Textures", Type = "HttpSynchronization", Identifier = "digitaluniverse_superclusters_textures", - Version = 1 + Version = 2 }) local speck = asset.syncedResource({ @@ -25,7 +25,7 @@ local object = { Color = { 1.0, 1.0, 1.0 }, Opacity = 0.65, File = speck .. "/superclust.speck", - Texture = textures .. "/point3.png", + Texture = textures .. "/point3A.png", LabelFile = speck .. "/superclust.label", TextColor = { 0.9, 0.9, 0.9, 1.0 }, ScaleFactor = 531.0, diff --git a/data/assets/scene/digitaluniverse/tully.asset b/data/assets/scene/digitaluniverse/tully.asset index 59d750c728..e8e515e22b 100644 --- a/data/assets/scene/digitaluniverse/tully.asset +++ b/data/assets/scene/digitaluniverse/tully.asset @@ -6,7 +6,7 @@ local textures = asset.syncedResource({ Name = "Tully Textures", Type = "HttpSynchronization", Identifier = "digitaluniverse_tully_textures", - Version = 2 + Version = 3 }) local speck = asset.syncedResource({ @@ -25,7 +25,7 @@ local tullyPoints = { Opacity = 0.99, ScaleFactor = 500.0, File = speck .. "/tully.speck", - Texture = textures .. "/point3.png", + Texture = textures .. "/point3A.png", --ColorMap = speck .. "/tully.cmap", ColorMap = speck .. "/lss.cmap", --ColorOption = { "proximity" }, diff --git a/data/assets/scene/milkyway/milkyway/volume.asset b/data/assets/scene/milkyway/milkyway/volume.asset index f4ad4a9385..2ae420e931 100644 --- a/data/assets/scene/milkyway/milkyway/volume.asset +++ b/data/assets/scene/milkyway/milkyway/volume.asset @@ -21,7 +21,7 @@ local MilkyWayVolumeGalaxy = { -- The center of the Milky Way is approximately 8 kiloparsec from the Sun. -- The x-axis of galactic coordinates points from the sun towards the center -- of the galaxy. - Position = {8 * kiloparsec, 0, 0} + Position = { 8 * kiloparsec, 0, 0 } } }, Renderable = { @@ -29,12 +29,13 @@ local MilkyWayVolumeGalaxy = { StepSize = 0.01, AbsorptionMultiply = 200, EmissionMultiply = 250, - Rotation = {3.1415926, 3.1248, 4.45741}, + Rotation = { 3.1415926, 3.1248, 4.45741 }, Volume = { Type = "Volume", Filename = data .. "/MilkyWayRGBAVolume1024x1024x128.raw", - Dimensions = {1024, 1024, 128}, - Size = {1.2E21, 1.2E21, 0.15E21} + Dimensions = { 1024, 1024, 128 }, + Size = { 1.2E21, 1.2E21, 0.15E21 }, + Downscale = 0.4, }, Points = { Type = "Points", diff --git a/data/assets/scene/solarsystem/dwarf_planets/pluto/charon.asset b/data/assets/scene/solarsystem/dwarf_planets/pluto/charon.asset index c9c58a820f..87139c2b9e 100644 --- a/data/assets/scene/solarsystem/dwarf_planets/pluto/charon.asset +++ b/data/assets/scene/solarsystem/dwarf_planets/pluto/charon.asset @@ -2,7 +2,7 @@ local assetHelper = asset.require('util/asset_helper') local transforms = asset.require('./transforms') asset.require("spice/base") asset.request('./trail') -local labelsPath = asset.require('./pluto_labels').LabelsPath +local labelsPath = asset.require('./pluto_globelabels').LabelsPath diff --git a/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto.asset b/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto.asset index 8d2b891b4b..ce98ef30f8 100644 --- a/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto.asset +++ b/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto.asset @@ -2,7 +2,7 @@ local assetHelper = asset.require('util/asset_helper') local transforms = asset.require('./transforms') asset.require("spice/base") asset.request('./trail') -local labelsPath = asset.require('./pluto_labels').LabelsPath +local labelsPath = asset.require('./pluto_globelabels').LabelsPath @@ -59,6 +59,25 @@ local Pluto = { } } +local PlutoLabel = { + Identifier = "PlutoLabel", + Parent = Pluto.Identifier, + Renderable = { + Enabled = false, + Type = "RenderableLabels", + LabelText = "Pluto", + FontSize = 100.0, + LabelSize = 8.9, + LabelMaxSize = 100.0, + LabelMinSize = 1.0, + BlendMode = "Additive", + LabelOrientationOption = "Camera View Direction" + }, + Tag = { "solarsystem_labels" }, + GUI = { + Name = "Pluto Label", + Path = "/Solar System/Dwarf Planets/Pluto" + } +} - -assetHelper.registerSceneGraphNodesAndExport(asset, { Pluto }) +assetHelper.registerSceneGraphNodesAndExport(asset, { Pluto, PlutoLabel }) diff --git a/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto_labels.asset b/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto_globelabels.asset similarity index 100% rename from data/assets/scene/solarsystem/dwarf_planets/pluto/pluto_labels.asset rename to data/assets/scene/solarsystem/dwarf_planets/pluto/pluto_globelabels.asset diff --git a/data/assets/scene/solarsystem/planets.asset b/data/assets/scene/solarsystem/planets.asset index 8603643031..a631b33339 100644 --- a/data/assets/scene/solarsystem/planets.asset +++ b/data/assets/scene/solarsystem/planets.asset @@ -1,6 +1,7 @@ asset.request('./planets/mercury/mercury') asset.request('./planets/venus/venus') +asset.request('./planets/venus/atmosphere') asset.request('./planets/earth/earth') asset.request('./planets/earth/atmosphere') diff --git a/data/assets/scene/solarsystem/planets/earth/earth.asset b/data/assets/scene/solarsystem/planets/earth/earth.asset index 3c90956e24..aab7c67f07 100644 --- a/data/assets/scene/solarsystem/planets/earth/earth.asset +++ b/data/assets/scene/solarsystem/planets/earth/earth.asset @@ -1,7 +1,7 @@ local transforms = asset.require('./transforms') local assetHelper = asset.require('util/asset_helper') local texturesPath = asset.require('./earth_textures').TexturesPath -local labelsPath = asset.require('./earth_labels').LabelsPath +local labelsPath = asset.require('./earth_globelabels').LabelsPath asset.request('./trail') @@ -287,6 +287,45 @@ local Earth = { } } +local EarthLabel = { + Identifier = "EarthLabel", + Parent = Earth.Identifier, + -- Transform = { + -- Translation = { + -- Type = "SpiceTranslation", + -- Target = "EARTH", + -- Observer = "EARTH BARYCENTER" + -- }, + -- -- Rotation = { + -- -- Type = "SpiceRotation", + -- -- SourceFrame = "IAU_MOON", + -- -- DestinationFrame = "GALACTIC" + -- -- } + -- }, + Renderable = { + Enabled = false, + Type = "RenderableLabels", + LabelText = "Earth", + FontSize = 100.0, + LabelSize = 8.6, + LabelMaxSize = 100.0, + LabelMinSize = 1.0, + LabelOrientationOption = "Camera View Direction", + BlendMode = "Additive", + EnableFading = true, + FadeStartUnit = "au", + FadeStartDistance = 1.5, + FadeStartSpeed = 1.0, + FadeEndUnit = "au", + FadeEndDistance = 15.0, + FadeEndSpeed = 25.0 + }, + Tag = { "solarsystem_labels" }, + GUI = { + Name = "Earth Label", + Path = "/Solar System/Planets/Earth" + } +} -assetHelper.registerSceneGraphNodesAndExport(asset, { Earth }) +assetHelper.registerSceneGraphNodesAndExport(asset, { Earth, EarthLabel }) diff --git a/data/assets/scene/solarsystem/planets/earth/earth_labels.asset b/data/assets/scene/solarsystem/planets/earth/earth_globelabels.asset similarity index 100% rename from data/assets/scene/solarsystem/planets/earth/earth_labels.asset rename to data/assets/scene/solarsystem/planets/earth/earth_globelabels.asset diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/satellites_shared.asset b/data/assets/scene/solarsystem/planets/earth/satellites/satellites_shared.asset index 58b3e35ec4..e5fde6d30c 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/satellites_shared.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/satellites_shared.asset @@ -56,7 +56,7 @@ local registerSatelliteGroupObjects = function(containingAsset, group, tleFolder Renderable = { Type = "RenderableSatellites", Path = file, - Segments = 160, + Segments = 120, Color = color, Fade = 0.5 }, diff --git a/data/assets/scene/solarsystem/planets/jupiter/callisto/callisto.asset b/data/assets/scene/solarsystem/planets/jupiter/callisto/callisto.asset index 1a31062cd1..d0b2496e52 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/callisto/callisto.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/callisto/callisto.asset @@ -3,7 +3,7 @@ local assetHelper = asset.require('util/asset_helper') asset.require("spice/base") asset.request('./trail') local kernel = asset.require('../kernels').jup310 -local labelsPath = asset.require('../jupiter_labels').LabelsPath +local labelsPath = asset.require('../jupiter_globelabels').LabelsPath diff --git a/data/assets/scene/solarsystem/planets/jupiter/europa/europa.asset b/data/assets/scene/solarsystem/planets/jupiter/europa/europa.asset index 9ee299ebf6..d5e455bb9f 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/europa/europa.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/europa/europa.asset @@ -3,7 +3,7 @@ local assetHelper = asset.require('util/asset_helper') asset.require("spice/base") asset.request('./trail') local kernel = asset.require('../kernels').jup310 -local labelsPath = asset.require('../jupiter_labels').LabelsPath +local labelsPath = asset.require('../jupiter_globelabels').LabelsPath local map_service_configs = asset.localResource("map_service_configs") diff --git a/data/assets/scene/solarsystem/planets/jupiter/ganymede/ganymede.asset b/data/assets/scene/solarsystem/planets/jupiter/ganymede/ganymede.asset index 510484cebf..513136ef98 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/ganymede/ganymede.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/ganymede/ganymede.asset @@ -3,7 +3,7 @@ local assetHelper = asset.require('util/asset_helper') asset.require("spice/base") asset.request('./trail') local kernel = asset.require('../kernels').jup310 -local labelsPath = asset.require('../jupiter_labels').LabelsPath +local labelsPath = asset.require('../jupiter_globelabels').LabelsPath diff --git a/data/assets/scene/solarsystem/planets/jupiter/io/io.asset b/data/assets/scene/solarsystem/planets/jupiter/io/io.asset index ca10670c06..fb10f0b3a8 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/io/io.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/io/io.asset @@ -3,7 +3,7 @@ local assetHelper = asset.require('util/asset_helper') asset.require("spice/base") asset.request('./trail') local kernel = asset.require('../kernels').jup310 -local labelsPath = asset.require('../jupiter_labels').LabelsPath +local labelsPath = asset.require('../jupiter_globelabels').LabelsPath diff --git a/data/assets/scene/solarsystem/planets/jupiter/jupiter.asset b/data/assets/scene/solarsystem/planets/jupiter/jupiter.asset index 9333c339c1..071a9cad9f 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/jupiter.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/jupiter.asset @@ -42,6 +42,25 @@ local Jupiter = { } } +local JupiterLabel = { + Identifier = "JupiterLabel", + Parent = Jupiter.Identifier, + Renderable = { + Enabled = false, + Type = "RenderableLabels", + LabelText = "Jupiter", + FontSize = 100.0, + LabelSize = 8.6, + LabelMaxSize = 100.0, + LabelMinSize = 1.0, + LabelOrientationOption = "Camera View Direction", + BlendMode = "Additive" + }, + Tag = { "solarsystem_labels" }, + GUI = { + Name = "Jupiter Label", + Path = "/Solar System/Planets/Jupiter" + } +} - -assetHelper.registerSceneGraphNodesAndExport(asset, { Jupiter }) +assetHelper.registerSceneGraphNodesAndExport(asset, { Jupiter, JupiterLabel }) diff --git a/data/assets/scene/solarsystem/planets/jupiter/jupiter_labels.asset b/data/assets/scene/solarsystem/planets/jupiter/jupiter_globelabels.asset similarity index 100% rename from data/assets/scene/solarsystem/planets/jupiter/jupiter_labels.asset rename to data/assets/scene/solarsystem/planets/jupiter/jupiter_globelabels.asset diff --git a/data/assets/scene/solarsystem/planets/mars/mars.asset b/data/assets/scene/solarsystem/planets/mars/mars.asset index 57ee23d861..ee4da17e7d 100644 --- a/data/assets/scene/solarsystem/planets/mars/mars.asset +++ b/data/assets/scene/solarsystem/planets/mars/mars.asset @@ -2,7 +2,7 @@ local transforms = asset.require('./transforms') local assetHelper = asset.require('util/asset_helper') asset.require("spice/base") asset.request('./trail') -local labelsPath = asset.require('./mars_labels').LabelsPath +local labelsPath = asset.require('./mars_globelabels').LabelsPath @@ -187,4 +187,31 @@ local Mars = { } } -assetHelper.registerSceneGraphNodesAndExport(asset, { Mars }) +local MarsLabel = { + Identifier = "MarsLabel", + Parent = Mars.Identifier, + Renderable = { + Enabled = false, + Type = "RenderableLabels", + LabelText = "Mars", + FontSize = 100.0, + LabelSize = 8.5, + LabelMaxSize = 100.0, + LabelMinSize = 1.0, + LabelOrientationOption = "Camera View Direction", + BlendMode = "Additive", + TransformationMatrix = { + 1.0, 0.0, 0.0, -8.0E6, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 1.0E7, + 0.0, 0.0, 0.0, 1.0 + }, + }, + Tag = { "solarsystem_labels" }, + GUI = { + Name = "Mars Label", + Path = "/Solar System/Planets/Mars" + } +} + +assetHelper.registerSceneGraphNodesAndExport(asset, { Mars, MarsLabel }) diff --git a/data/assets/scene/solarsystem/planets/mars/mars_labels.asset b/data/assets/scene/solarsystem/planets/mars/mars_globelabels.asset similarity index 100% rename from data/assets/scene/solarsystem/planets/mars/mars_labels.asset rename to data/assets/scene/solarsystem/planets/mars/mars_globelabels.asset diff --git a/data/assets/scene/solarsystem/planets/mercury/mercury.asset b/data/assets/scene/solarsystem/planets/mercury/mercury.asset index d2bcf7c591..8eda6c5eb9 100644 --- a/data/assets/scene/solarsystem/planets/mercury/mercury.asset +++ b/data/assets/scene/solarsystem/planets/mercury/mercury.asset @@ -1,6 +1,6 @@ local assetHelper = asset.require('util/asset_helper') local transforms = asset.require('./transforms') -local labelsPath = asset.require('./mercury_labels').LabelsPath +local labelsPath = asset.require('./mercury_globelabels').LabelsPath asset.require("spice/base") @@ -223,5 +223,25 @@ local Mercury = { } } +local MercuryLabel = { + Identifier = "MercuryLabel", + Parent = Mercury.Identifier, + Renderable = { + Enabled = false, + Type = "RenderableLabels", + LabelText = "Mercury", + FontSize = 100.0, + LabelSize = 8.3, + LabelMaxSize = 100.0, + LabelMinSize = 1.0, + LabelOrientationOption = "Camera View Direction", + BlendMode = "Additive" + }, + Tag = { "solarsystem_labels" }, + GUI = { + Name = "Mercury Label", + Path = "/Solar System/Planets/Mercury" + } +} -assetHelper.registerSceneGraphNodesAndExport(asset, { Mercury }) +assetHelper.registerSceneGraphNodesAndExport(asset, { Mercury, MercuryLabel }) diff --git a/data/assets/scene/solarsystem/planets/mercury/mercury_labels.asset b/data/assets/scene/solarsystem/planets/mercury/mercury_globelabels.asset similarity index 100% rename from data/assets/scene/solarsystem/planets/mercury/mercury_labels.asset rename to data/assets/scene/solarsystem/planets/mercury/mercury_globelabels.asset diff --git a/data/assets/scene/solarsystem/planets/neptune/neptune.asset b/data/assets/scene/solarsystem/planets/neptune/neptune.asset index 677395e8e5..326b2ef6c0 100644 --- a/data/assets/scene/solarsystem/planets/neptune/neptune.asset +++ b/data/assets/scene/solarsystem/planets/neptune/neptune.asset @@ -40,4 +40,25 @@ local Neptune = { } } -assetHelper.registerSceneGraphNodesAndExport(asset, { Neptune }) +local NeptuneLabel = { + Identifier = "NeptuneLabel", + Parent = Neptune.Identifier, + Renderable = { + Enabled = false, + Type = "RenderableLabels", + LabelText = "Neptune", + FontSize = 100.0, + LabelSize = 8.8, + LabelMaxSize = 100.0, + LabelMinSize = 1.0, + LabelOrientationOption = "Camera View Direction", + BlendMode = "Additive" + }, + Tag = { "solarsystem_labels" }, + GUI = { + Name = "Neptune Label", + Path = "/Solar System/Planets/Neptune" + } +} + +assetHelper.registerSceneGraphNodesAndExport(asset, { Neptune, NeptuneLabel }) diff --git a/data/assets/scene/solarsystem/planets/saturn/dione/dione.asset b/data/assets/scene/solarsystem/planets/saturn/dione/dione.asset index 7cdd49b5cd..ded4b6ae73 100644 --- a/data/assets/scene/solarsystem/planets/saturn/dione/dione.asset +++ b/data/assets/scene/solarsystem/planets/saturn/dione/dione.asset @@ -2,7 +2,7 @@ local transforms = asset.require('../transforms') local assetHelper = asset.require('util/asset_helper') local kernel = asset.require('../kernels').sat375 asset.request('./trail') -local labelsPath = asset.require('../saturn_labels').LabelsPath +local labelsPath = asset.require('../saturn_globelabels').LabelsPath diff --git a/data/assets/scene/solarsystem/planets/saturn/enceladus/enceladus.asset b/data/assets/scene/solarsystem/planets/saturn/enceladus/enceladus.asset index 5fa01501ba..8a66735198 100644 --- a/data/assets/scene/solarsystem/planets/saturn/enceladus/enceladus.asset +++ b/data/assets/scene/solarsystem/planets/saturn/enceladus/enceladus.asset @@ -2,7 +2,7 @@ local transforms = asset.require('../transforms') local assetHelper = asset.require('util/asset_helper') local kernel = asset.require('../kernels').sat375 asset.request('./trail') -local labelsPath = asset.require('../saturn_labels').LabelsPath +local labelsPath = asset.require('../saturn_globelabels').LabelsPath diff --git a/data/assets/scene/solarsystem/planets/saturn/iapetus/iapetus.asset b/data/assets/scene/solarsystem/planets/saturn/iapetus/iapetus.asset index bab9c45056..892cc2c13e 100644 --- a/data/assets/scene/solarsystem/planets/saturn/iapetus/iapetus.asset +++ b/data/assets/scene/solarsystem/planets/saturn/iapetus/iapetus.asset @@ -2,7 +2,7 @@ local transforms = asset.require('../transforms') local assetHelper = asset.require('util/asset_helper') local kernel = asset.require('../kernels').sat375 asset.request('./trail') -local labelsPath = asset.require('../saturn_labels').LabelsPath +local labelsPath = asset.require('../saturn_globelabels').LabelsPath diff --git a/data/assets/scene/solarsystem/planets/saturn/mimas/mimas.asset b/data/assets/scene/solarsystem/planets/saturn/mimas/mimas.asset index 4dbedaad48..53d9b7da21 100644 --- a/data/assets/scene/solarsystem/planets/saturn/mimas/mimas.asset +++ b/data/assets/scene/solarsystem/planets/saturn/mimas/mimas.asset @@ -2,7 +2,7 @@ local transforms = asset.require('../transforms') local assetHelper = asset.require('util/asset_helper') local kernel = asset.require('../kernels').sat375 asset.request('./trail') -local labelsPath = asset.require('../saturn_labels').LabelsPath +local labelsPath = asset.require('../saturn_globelabels').LabelsPath diff --git a/data/assets/scene/solarsystem/planets/saturn/rhea/rhea.asset b/data/assets/scene/solarsystem/planets/saturn/rhea/rhea.asset index 0ab5688544..008663ecf5 100644 --- a/data/assets/scene/solarsystem/planets/saturn/rhea/rhea.asset +++ b/data/assets/scene/solarsystem/planets/saturn/rhea/rhea.asset @@ -2,7 +2,7 @@ local transforms = asset.require('../transforms') local assetHelper = asset.require('util/asset_helper') local kernel = asset.require('../kernels').sat375 asset.request('./trail') -local labelsPath = asset.require('../saturn_labels').LabelsPath +local labelsPath = asset.require('../saturn_globelabels').LabelsPath diff --git a/data/assets/scene/solarsystem/planets/saturn/saturn.asset b/data/assets/scene/solarsystem/planets/saturn/saturn.asset index 77b45972f2..aabfe92b81 100644 --- a/data/assets/scene/solarsystem/planets/saturn/saturn.asset +++ b/data/assets/scene/solarsystem/planets/saturn/saturn.asset @@ -57,6 +57,26 @@ local SaturnRings = { } } +local SaturnLabel = { + Identifier = "SaturnLabel", + Parent = Saturn.Identifier, + Renderable = { + Enabled = false, + Type = "RenderableLabels", + LabelText = "Saturn", + FontSize = 100.0, + LabelSize = 8.7, + LabelMaxSize = 100.0, + LabelMinSize = 1.0, + BlendMode = "Additive", + LabelOrientationOption = "Camera View Direction" + }, + Tag = { "solarsystem_labels" }, + GUI = { + Name = "Saturn Label", + Path = "/Solar System/Planets/Saturn" + } +} -assetHelper.registerSceneGraphNodesAndExport(asset, { Saturn, SaturnRings }) +assetHelper.registerSceneGraphNodesAndExport(asset, { Saturn, SaturnRings, SaturnLabel }) diff --git a/data/assets/scene/solarsystem/planets/saturn/saturn_labels.asset b/data/assets/scene/solarsystem/planets/saturn/saturn_globelabels.asset similarity index 100% rename from data/assets/scene/solarsystem/planets/saturn/saturn_labels.asset rename to data/assets/scene/solarsystem/planets/saturn/saturn_globelabels.asset diff --git a/data/assets/scene/solarsystem/planets/saturn/tethys/tethys.asset b/data/assets/scene/solarsystem/planets/saturn/tethys/tethys.asset index 1979cf4d66..fea8618180 100644 --- a/data/assets/scene/solarsystem/planets/saturn/tethys/tethys.asset +++ b/data/assets/scene/solarsystem/planets/saturn/tethys/tethys.asset @@ -2,7 +2,7 @@ local transforms = asset.require('../transforms') local assetHelper = asset.require('util/asset_helper') local kernel = asset.require('../kernels').sat375 asset.request('./trail') -local labelsPath = asset.require('../saturn_labels').LabelsPath +local labelsPath = asset.require('../saturn_globelabels').LabelsPath diff --git a/data/assets/scene/solarsystem/planets/saturn/titan/titan.asset b/data/assets/scene/solarsystem/planets/saturn/titan/titan.asset index 0145308ed4..a086c9eecb 100644 --- a/data/assets/scene/solarsystem/planets/saturn/titan/titan.asset +++ b/data/assets/scene/solarsystem/planets/saturn/titan/titan.asset @@ -2,7 +2,7 @@ local transforms = asset.require('../transforms') local assetHelper = asset.require('util/asset_helper') local kernel = asset.require('../kernels').sat375 asset.request('./trail') -local labelsPath = asset.require('../saturn_labels').LabelsPath +local labelsPath = asset.require('../saturn_globelabels').LabelsPath local map_service_configs = asset.localResource("map_service_configs") diff --git a/data/assets/scene/solarsystem/planets/uranus/uranus.asset b/data/assets/scene/solarsystem/planets/uranus/uranus.asset index 1bb29fa184..db3fb11848 100644 --- a/data/assets/scene/solarsystem/planets/uranus/uranus.asset +++ b/data/assets/scene/solarsystem/planets/uranus/uranus.asset @@ -42,6 +42,25 @@ local Uranus = { } } +local UranusLabel = { + Identifier = "UranusLabel", + Parent = Uranus.Identifier, + Renderable = { + Enabled = false, + Type = "RenderableLabels", + LabelText = "Uranus", + FontSize = 100.0, + LabelSize = 8.7, + LabelMaxSize = 100.0, + LabelMinSize = 1.0, + LabelOrientationOption = "Camera View Direction", + BlendMode = "Additive" + }, + Tag = { "solarsystem_labels" }, + GUI = { + Name = "Neptune Label", + Path = "/Solar System/Planets/Uranus" + } +} - -assetHelper.registerSceneGraphNodesAndExport(asset, { Uranus }) +assetHelper.registerSceneGraphNodesAndExport(asset, { Uranus, UranusLabel }) diff --git a/data/assets/scene/solarsystem/planets/venus/atmosphere.asset b/data/assets/scene/solarsystem/planets/venus/atmosphere.asset new file mode 100644 index 0000000000..40a95cdc54 --- /dev/null +++ b/data/assets/scene/solarsystem/planets/venus/atmosphere.asset @@ -0,0 +1,66 @@ +local transforms = asset.require('./venus') +local assetHelper = asset.require('util/asset_helper') + + + +local Atmosphere = { + Identifier = "VenusAtmosphere", + Parent = transforms.Venus.Identifier, + Renderable = { + Type = "RenderableAtmosphere", + Atmosphere = { + -- Atmosphere radius in Km + AtmosphereRadius = 6121.9, + PlanetRadius = 6051.9, + PlanetAverageGroundReflectance = 0.018, + GroundRadianceEmittion = 0.8, + SunIntensity = 11.47, + --MieScatteringExtinctionPropCoefficient = 0.23862, + Rayleigh = { + Coefficients = { + -- Wavelengths are given in 10^-9m + Wavelengths = { 680, 550, 440 }, + -- Reflection coefficients are given in km^-1 + Scattering = { 19.518E-3, 13.83E-3, 3.65E-3 } + -- In Rayleigh scattering, the coefficients of + -- absorption and scattering are the same. + }, + -- Thichkness of atmosphere if its density were uniform, in Km + H_R = 6.7 + }, + -- Default + Mie = { + Coefficients = { + -- Reflection coefficients are given in km^-1 + Scattering = { 53.61771e-3, 53.61771e-3, 53.61771e-3 }, + -- Extinction coefficients are a fraction of the Scattering coefficients + Extinction = { 53.61771e-3/0.98979, 53.61771e-3/0.98979, 53.61771e-3/0.98979 } + }, + -- Mie Height scale (atmosphere thickness for constant density) in Km + H_M = 9.8, + -- Mie Phase Function Value (G e [-1.0, 1.0]. + -- If G = 1.0, Mie phase function = Rayleigh Phase Function) + G = 0.85 + }, + Image = { + ToneMapping = jToneMapping, + Exposure = 0.4, + Background = 1.8, + Gamma = 1.85 + }, + Debug = { + -- PreCalculatedTextureScale is a float from 1.0 to N, with N > 0.0 and N in Naturals (i.e., 1, 2, 3, 4, 5....) + PreCalculatedTextureScale = 1.0, + SaveCalculatedTextures = false + } + } + }, + GUI = { + Name = "Venus Atmosphere", + Path = "/Solar System/Planets/Venus" + } +} + + + +assetHelper.registerSceneGraphNodesAndExport(asset, { Atmosphere }) diff --git a/data/assets/scene/solarsystem/planets/venus/map_service_configs/Utah/MagellanDEM.wms b/data/assets/scene/solarsystem/planets/venus/map_service_configs/Utah/MagellanDEM.wms new file mode 100644 index 0000000000..c8072a6e30 --- /dev/null +++ b/data/assets/scene/solarsystem/planets/venus/map_service_configs/Utah/MagellanDEM.wms @@ -0,0 +1,21 @@ + + + http://openspace.sci.utah.edu/Venus/MagellanDEM/tile/${z}/${y}/${x} + + + -180.0 + 90.0 + 180.0 + -90.0 + 8192 + 4096 + 4 + top + + GEOGCS["GCS_Venus",DATUM["D_Venus",SPHEROID["Venus",6051000,0]],PRIMEM["Reference_Meridian",0],UNIT["Degree",0.0174532925199433]] + 256 + 256 + 1 + 10 + 5 + diff --git a/data/assets/scene/solarsystem/planets/venus/map_service_configs/Utah/MagellanMosaic.wms b/data/assets/scene/solarsystem/planets/venus/map_service_configs/Utah/MagellanMosaic.wms new file mode 100644 index 0000000000..084e231ea4 --- /dev/null +++ b/data/assets/scene/solarsystem/planets/venus/map_service_configs/Utah/MagellanMosaic.wms @@ -0,0 +1,21 @@ + + + http://openspace.sci.utah.edu/Venus/MagellanMosaic/tile/${z}/${y}/${x} + + + -180.0 + 84.0 + 180.0 + -80.0 + 506928 + 230948 + 9 + top + + GEOGCS["GCS_Venus",DATUM["D_Venus",SPHEROID["Venus_localRadius",6051000,0]],PRIMEM["Reference_Meridian",0],UNIT["Degree",0.0174532925199433]] + 512 + 512 + 1 + 10 + 5 + diff --git a/data/assets/scene/solarsystem/planets/venus/venus.asset b/data/assets/scene/solarsystem/planets/venus/venus.asset index 0b7617dad2..c6b3bc516d 100644 --- a/data/assets/scene/solarsystem/planets/venus/venus.asset +++ b/data/assets/scene/solarsystem/planets/venus/venus.asset @@ -2,9 +2,9 @@ local assetHelper = asset.require('util/asset_helper') local transforms = asset.require('./transforms') asset.require("spice/base") asset.request('./trail') -local labelsPath = asset.require('./venus_labels').LabelsPath - +local labelsPath = asset.require('./venus_globelabels').LabelsPath +local mapServiceConfigs = asset.localResource("map_service_configs") local textures = asset.syncedResource({ Name = "Venus Textures", @@ -13,6 +13,28 @@ local textures = asset.syncedResource({ Version = 1 }) +local color_layers = { + { + Identifier = "Texture", + FilePath = textures .. "/venus.jpg", + Enabled = true + }, + { + Identifier = "Magellan_Mosaic_Utah", + Name = "Magellan Mosaic [Utah]", + FilePath = mapServiceConfigs .. "/Utah/MagellanMosaic.wms" + } +} + +local height_layers = { + { + Identifier = "Magellan", + Name = "Magellan Elevation [Utah]", + FilePath = mapServiceConfigs .. "/Utah/MagellanDEM.wms", + TilePixelSize = 64 + } +} + local Venus = { Identifier = "Venus", Parent = transforms.VenusBarycenter.Identifier, @@ -30,16 +52,12 @@ local Venus = { }, Renderable = { Type = "RenderableGlobe", - Radii = { 6051900.0, 6051900.0, 6051800.0 }, + --Radii = { 6051900.0, 6051900.0, 6051800.0 }, + Radii = { 6051900.0, 6051900.0, 6051900.0 }, SegmentsPerPatch = 64, Layers = { - ColorLayers = { - { - Identifier = "Texture", - FilePath = textures .. "/venus.jpg", - Enabled = true - } - } + ColorLayers = color_layers, + HeightLayers = height_layers }, Labels = { Enable = false, @@ -64,6 +82,26 @@ local Venus = { } } +local VenusLabel = { + Identifier = "VenusLabel", + Parent = Venus.Identifier, + Renderable = { + Enabled = false, + Type = "RenderableLabels", + LabelText = "Venus", + FontSize = 100.0, + LabelSize = 8.4, + LabelMaxSize = 100.0, + LabelMinSize = 1.0, + LabelOrientationOption = "Camera View Direction", + BlendMode = "Additive" + }, + Tag = { "solarsystem_labels" }, + GUI = { + Name = "Venus Label", + Path = "/Solar System/Planets/Venus" + } +} -assetHelper.registerSceneGraphNodesAndExport(asset, { Venus }) +assetHelper.registerSceneGraphNodesAndExport(asset, { Venus, VenusLabel }) diff --git a/data/assets/scene/solarsystem/planets/venus/venus_labels.asset b/data/assets/scene/solarsystem/planets/venus/venus_globelabels.asset similarity index 100% rename from data/assets/scene/solarsystem/planets/venus/venus_labels.asset rename to data/assets/scene/solarsystem/planets/venus/venus_globelabels.asset diff --git a/data/assets/scene/solarsystem/sun/sun.asset b/data/assets/scene/solarsystem/sun/sun.asset index cc887dc4d2..10c0ff4aec 100644 --- a/data/assets/scene/solarsystem/sun/sun.asset +++ b/data/assets/scene/solarsystem/sun/sun.asset @@ -27,4 +27,32 @@ local Sun = { } } -assetHelper.registerSceneGraphNodesAndExport(asset, { Sun }) +local SunLabel = { + Identifier = "SunLabel", + Parent = Sun.Identifier, + Renderable = { + Enabled = false, + Type = "RenderableLabels", + LabelText = "Sun", + FontSize = 100.0, + LabelSize = 13.127, + LabelMaxSize = 100.0, + LabelMinSize = 1.0, + LabelOrientationOption = "Camera View Direction", + BlendMode = "Additive", + EnableFading = true, + FadeStartUnit = "Pm", + FadeStartDistance = 2.841, + FadeStartSpeed = 1.375, + FadeEndUnit = "pc", + FadeEndDistance = 1.326, + FadeEndSpeed = 1.0 + }, + Tag = { "solarsystem_labels" }, + GUI = { + Name = "Sun Label", + Path = "/Solar System/Sun" + } +} + +assetHelper.registerSceneGraphNodesAndExport(asset, { Sun, SunLabel }) diff --git a/include/openspace/properties/property.h b/include/openspace/properties/property.h index 6d7bbc3d3f..1b2f9fdbec 100644 --- a/include/openspace/properties/property.h +++ b/include/openspace/properties/property.h @@ -395,9 +395,7 @@ public: /** * Default view options that can be used in the Property::setViewOption method. The * values are: Property::ViewOptions::Color = \c color, - * Property::ViewOptions::LightPosition = \c lightPosition, - * Property::ViewOptions::PowerScaledScalar = \c powerScaledScalar, and - * Property::ViewOptions::PowerScaledCoordinate = \c powerScaledCoordinate. + * Property::ViewOptions::LightPosition = \c lightPosition */ struct ViewOptions { static const char* Color; diff --git a/include/openspace/rendering/framebufferrenderer.h b/include/openspace/rendering/framebufferrenderer.h index a49568fe17..7dd048052f 100644 --- a/include/openspace/rendering/framebufferrenderer.h +++ b/include/openspace/rendering/framebufferrenderer.h @@ -70,6 +70,7 @@ public: void updateDeferredcastData(); void updateHDRAndFiltering(); void updateFXAA(); + void updateDownscaledVolume(); void setResolution(glm::ivec2 res) override; void setHDRExposure(float hdrExposure) override; @@ -110,6 +111,9 @@ private: void resolveMSAA(float blackoutFactor); void applyTMO(float blackoutFactor); void applyFXAA(); + void updateDownscaleTextures(); + void updateExitVolumeTextures(); + void writeDownscaledVolume(); std::map _raycastData; RaycasterProgObjMap _exitPrograms; @@ -122,10 +126,13 @@ private: std::unique_ptr _hdrFilteringProgram; std::unique_ptr _tmoProgram; std::unique_ptr _fxaaProgram; + std::unique_ptr _downscaledVolumeProgram; UniformCache(hdrFeedingTexture, blackoutFactor, hdrExposure, gamma, Hue, Saturation, Value) _hdrUniformCache; UniformCache(renderedTexture, inverseScreenSize) _fxaaUniformCache; + UniformCache(downscaledRenderedVolume, downscaledRenderedVolumeDepth) + _writeDownscaledVolumeUniformCache; GLint _defaultFBO; GLuint _screenQuad; @@ -157,6 +164,13 @@ private: GLuint fxaaTexture; } _fxaaBuffers; + struct { + GLuint framebuffer; + GLuint colorTexture; + GLuint depthbuffer; + float currentDownscaleFactor = 1.f; + } _downscaleVolumeRendering; + unsigned int _pingPongIndex = 0u; bool _dirtyDeferredcastData; diff --git a/include/openspace/rendering/screenspacerenderable.h b/include/openspace/rendering/screenspacerenderable.h index d5dfabef94..abb4a498c9 100644 --- a/include/openspace/rendering/screenspacerenderable.h +++ b/include/openspace/rendering/screenspacerenderable.h @@ -75,6 +75,8 @@ public: protected: void createShaders(); + std::string makeUniqueIdentifier(std::string name); + glm::mat4 scaleMatrix(); glm::mat4 globalRotationMatrix(); glm::mat4 translationMatrix(); diff --git a/include/openspace/rendering/volumeraycaster.h b/include/openspace/rendering/volumeraycaster.h index f8ed000553..aa1133606e 100644 --- a/include/openspace/rendering/volumeraycaster.h +++ b/include/openspace/rendering/volumeraycaster.h @@ -128,6 +128,25 @@ public: * helper file) which should be a prefix to all symbols defined by the helper */ virtual std::string helperPath() const = 0; + + void setMaxSteps(int nsteps); + + int maxSteps() const; + + void setDownscaleRender(float value); + + float downscaleRender() const; + +private: + /** + * Maximum number of integration steps to be executed by the volume integrator. + */ + int _rayCastMaxSteps = 1000; + + /** + * Enable and set the downscale rendering of the volume. Used to improve performance. + */ + float _downscaleRenderConst = 1.0f; }; } // namespace openspace diff --git a/include/openspace/util/camera.h b/include/openspace/util/camera.h index 8131d04191..8335329b31 100644 --- a/include/openspace/util/camera.h +++ b/include/openspace/util/camera.h @@ -25,7 +25,6 @@ #ifndef __OPENSPACE_CORE___CAMERA___H__ #define __OPENSPACE_CORE___CAMERA___H__ -#include #include #include #include @@ -36,7 +35,6 @@ class SceneGraphNode; /** * This class still needs some more love. Suggested improvements: - * - Remove psc from the camera class interface. * - Accessors should return constant references to double precision class members. * - Remove the scaling variable (What is it used for?) * - Remove the maxFov and sinMaxfov variables. Redundant since the fov is embedded diff --git a/include/openspace/util/powerscaledcoordinate.h b/include/openspace/util/powerscaledcoordinate.h deleted file mode 100644 index 64f258940c..0000000000 --- a/include/openspace/util/powerscaledcoordinate.h +++ /dev/null @@ -1,114 +0,0 @@ -/***************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2019 * - * * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this * - * software and associated documentation files (the "Software"), to deal in the Software * - * without restriction, including without limitation the rights to use, copy, modify, * - * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * - * permit persons to whom the Software is furnished to do so, subject to the following * - * conditions: * - * * - * The above copyright notice and this permission notice shall be included in all copies * - * or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - ****************************************************************************************/ - -#ifndef __OPENSPACE_CORE___POWERSCALEDCOORDINATE___H__ -#define __OPENSPACE_CORE___POWERSCALEDCOORDINATE___H__ - -#include - -namespace openspace { - -class PowerScaledScalar; - -class PowerScaledCoordinate { -public: - // constructors - PowerScaledCoordinate() = default; - - PowerScaledCoordinate(PowerScaledCoordinate&& rhs); - PowerScaledCoordinate(const PowerScaledCoordinate& rhs); - - // Sets the power scaled coordinates directly - PowerScaledCoordinate(glm::vec4 v); - PowerScaledCoordinate(float f1, float f2, float f3, float f4); - // Sets the power scaled coordinates with w = 0 - PowerScaledCoordinate(glm::vec3 v); - - static PowerScaledCoordinate CreatePowerScaledCoordinate(double d1, double d2, - double d3); - - // get functions - // return the full, unmodified PSC - const glm::vec4& vec4() const; - - // returns the rescaled, "normal" coordinates - glm::vec3 vec3() const; - - // return the full psc as dvec4() - glm::dvec4 dvec4() const; - - // rescaled return as dvec3 - glm::dvec3 dvec3() const; - - // length of the vector as a pss - float length() const; - glm::vec3 direction() const; - - // operator overloading - PowerScaledCoordinate& operator=(const PowerScaledCoordinate& rhs); - PowerScaledCoordinate& operator=(PowerScaledCoordinate&& rhs); - PowerScaledCoordinate& operator+=(const PowerScaledCoordinate& rhs); - PowerScaledCoordinate operator+(const PowerScaledCoordinate& rhs) const; - PowerScaledCoordinate& operator-=(const PowerScaledCoordinate& rhs); - PowerScaledCoordinate operator-(const PowerScaledCoordinate& rhs) const; - float& operator[](unsigned int idx); - float operator[](unsigned int idx) const; - double dot(const PowerScaledCoordinate& rhs) const; - double angle(const PowerScaledCoordinate& rhs) const; - - // scalar operators - PowerScaledCoordinate operator*(const double& rhs) const; - PowerScaledCoordinate operator*(const float& rhs) const; - PowerScaledCoordinate operator*(const glm::mat4& matrix) const; - - - // comparison - bool operator==(const PowerScaledCoordinate& other) const; - bool operator!=(const PowerScaledCoordinate& other) const; - bool operator<(const PowerScaledCoordinate& other) const; - bool operator>(const PowerScaledCoordinate& other) const; - bool operator<=(const PowerScaledCoordinate& other) const; - bool operator>=(const PowerScaledCoordinate& other) const; - - // glm integration - PowerScaledCoordinate& operator=(const glm::dvec4& rhs); - PowerScaledCoordinate& operator=(const glm::vec4& rhs); - PowerScaledCoordinate& operator=(const glm::dvec3& rhs); - PowerScaledCoordinate& operator=(const glm::vec3& rhs); - - friend std::ostream& operator<<(std::ostream& os, const PowerScaledCoordinate& rhs); - - // allow the power scaled scalars to access private members - friend class PowerScaledScalar; - -private: - // internal glm vector - glm::vec4 _vec = glm::vec4(0.f); -}; - -typedef PowerScaledCoordinate psc; - -} // namespace openspace - -#endif // __OPENSPACE_CORE___POWERSCALEDCOORDINATE___H__ diff --git a/include/openspace/util/powerscaledsphere.h b/include/openspace/util/sphere.h similarity index 86% rename from include/openspace/util/powerscaledsphere.h rename to include/openspace/util/sphere.h index 8be00b6f0b..47ff24e061 100644 --- a/include/openspace/util/powerscaledsphere.h +++ b/include/openspace/util/sphere.h @@ -22,22 +22,20 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_CORE___POWERSCALEDSPHERE___H__ -#define __OPENSPACE_CORE___POWERSCALEDSPHERE___H__ +#ifndef __OPENSPACE_CORE___SPHERE___H__ +#define __OPENSPACE_CORE___SPHERE___H__ #include #include namespace openspace { -class PowerScaledSphere; - -class PowerScaledSphere { +class Sphere { public: - PowerScaledSphere(float radius, int segments = 8); - PowerScaledSphere(glm::vec3 radius, int segments); - PowerScaledSphere(const PowerScaledSphere& cpy); - ~PowerScaledSphere(); + Sphere(float radius, int segments = 8); + Sphere(glm::vec3 radius, int segments); + Sphere(const Sphere& cpy); + ~Sphere(); bool initialize(); @@ -62,4 +60,4 @@ public: } // namespace openspace -#endif // __OPENSPACE_CORE___POWERSCALEDSPHERE___H__ +#endif // __OPENSPACE_CORE___SPHERE___H__ diff --git a/include/openspace/util/spicemanager.h b/include/openspace/util/spicemanager.h index 8aab7b6094..634a836571 100644 --- a/include/openspace/util/spicemanager.h +++ b/include/openspace/util/spicemanager.h @@ -652,36 +652,6 @@ public: FieldOfViewMethod method, AberrationCorrection aberrationCorrection, double& ephemerisTime) const; - /** - * Determine whether a specific \p target is in the field-of-view of a specified - * \p instrument or an \p observer at a given time. The reference frame used is - * derived from the \p target by converting it into an \c IAU inertial reference - * frame. - * - * \param target The name or NAIF ID code string of the target - * \param observer The name or NAIF ID code string of the observer - * \param instrument The name or NAIF ID code string of the instrument - * \param method The type of shape model used for the target - * \param aberrationCorrection The aberration correction method - * \param ephemerisTime Time of the observation (seconds past J2000) - * \return \c true if the target is visible, \c false otherwise - * - * \throw SpiceException If the \p target or \p observer do not name valid - * NAIF objects, the \p target or \p observer name the same NAIF object, the - * \p instrument does not name a valid NAIF object, or insufficient kernel - * information has been loaded. - * \pre \p target must not be empty. - * \pre \p observer must not be empty. - * \pre \p target and \p observer must not be different strings - * \pre \p referenceFrame must not be empty. - * \pre \p instrument must not be empty. - * - * \sa http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/fovtrg_c.html - */ - bool isTargetInFieldOfView(const std::string& target, const std::string& observer, - const std::string& instrument, FieldOfViewMethod method, - AberrationCorrection aberrationCorrection, double& ephemerisTime) const; - /// Struct that is used as the return value from the #targetState method struct TargetStateResult { /// The target position @@ -902,26 +872,6 @@ public: AberrationCorrection aberrationCorrection, double ephemerisTime, int numberOfTerminatorPoints); - /** - * This function adds a frame to a body. - * - * \param body - the name of the body - * \param frame - the name of the frame - * \return false if the arguments are empty - * - * \todo I think this function should die ---abock - */ - bool addFrame(std::string body, std::string frame); - - /** - * This function returns the frame of a body if defined, otherwise it returns - * IAU_ + body (most frames are known by the International Astronomical Union) - * \param body - the name of the body - * \return the frame of the body - * \todo I think this function should die ---abock - */ - std::string frameFromBody(const std::string& body) const; - /** * Sets the SpiceManager's exception handling. If UseException::No is passed to this * function, all subsequent calls will not throw an error, but fail silently instead. @@ -1048,8 +998,6 @@ private: std::map>> _spkIntervals; std::map> _ckCoverageTimes; std::map> _spkCoverageTimes; - // Vector of pairs: Body, Frame - std::vector> _frameByBody; /// Stores whether the SpiceManager throws exceptions (Yes) or fails silently (No) UseException _useExceptions = UseException::Yes; diff --git a/include/openspace/util/updatestructures.h b/include/openspace/util/updatestructures.h index f6ecef64a4..406181eebc 100644 --- a/include/openspace/util/updatestructures.h +++ b/include/openspace/util/updatestructures.h @@ -26,7 +26,6 @@ #define __OPENSPACE_CORE___UPDATESTRUCTURES___H__ #include -#include #include namespace openspace { diff --git a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp index 3e5dec47ad..3cb7b040ff 100644 --- a/modules/atmosphere/rendering/atmospheredeferredcaster.cpp +++ b/modules/atmosphere/rendering/atmospheredeferredcaster.cpp @@ -60,7 +60,6 @@ #include #include -#include #include #include #include diff --git a/modules/base/CMakeLists.txt b/modules/base/CMakeLists.txt index 29379351a0..18a9c74159 100644 --- a/modules/base/CMakeLists.txt +++ b/modules/base/CMakeLists.txt @@ -41,6 +41,7 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/multimodelgeometry.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableboxgrid.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablecartesianaxes.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablelabels.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablemodel.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablenodeline.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableplane.h @@ -89,6 +90,7 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/multimodelgeometry.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableboxgrid.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablecartesianaxes.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablelabels.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablemodel.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablenodeline.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableplane.cpp diff --git a/modules/base/basemodule.cpp b/modules/base/basemodule.cpp index 3535e48522..1b6f3d8398 100644 --- a/modules/base/basemodule.cpp +++ b/modules/base/basemodule.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -123,6 +124,7 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) { fRenderable->registerClass("RenderableBoxGrid"); fRenderable->registerClass("RenderableCartesianAxes"); + fRenderable->registerClass("RenderableLabels"); fRenderable->registerClass("RenderableModel"); fRenderable->registerClass("RenderableNodeLine"); fRenderable->registerClass("RenderablePlaneImageLocal"); @@ -191,6 +193,7 @@ std::vector BaseModule::documentations() const { DashboardItemVelocity::Documentation(), RenderableBoxGrid::Documentation(), + RenderableLabels::Documentation(), RenderableModel::Documentation(), RenderableNodeLine::Documentation(), RenderablePlane::Documentation(), diff --git a/modules/base/rendering/renderablelabels.cpp b/modules/base/rendering/renderablelabels.cpp new file mode 100644 index 0000000000..d070d0f974 --- /dev/null +++ b/modules/base/rendering/renderablelabels.cpp @@ -0,0 +1,816 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2019 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + constexpr const char* _loggerCat = "base::RenderableLabels"; + + constexpr const char* MeterUnit = "m"; + constexpr const char* KilometerUnit = "Km"; + constexpr const char* MegameterUnit = "Mm"; + constexpr const char* GigameterUnit = "Gm"; + constexpr const char* AstronomicalUnit = "au"; + constexpr const char* TerameterUnit = "Tm"; + constexpr const char* PetameterUnit = "Pm"; + constexpr const char* ParsecUnit = "pc"; + constexpr const char* KiloparsecUnit = "Kpc"; + constexpr const char* MegaparsecUnit = "Mpc"; + constexpr const char* GigaparsecUnit = "Gpc"; + constexpr const char* GigalightyearUnit = "Gly"; + + enum BlendMode { + BlendModeNormal = 0, + BlendModeAdditive + }; + + constexpr const int ViewDirection = 0; + constexpr const int NormalDirection = 1; + + constexpr double PARSEC = 0.308567756E17; + + constexpr openspace::properties::Property::PropertyInfo BlendModeInfo = { + "BlendMode", + "Blending Mode", + "This determines the blending mode that is applied to this plane." + }; + + constexpr openspace::properties::Property::PropertyInfo LabelColorInfo = { + "LabelColor", + "Label Color", + "The label color for the astronomical object." + }; + + constexpr openspace::properties::Property::PropertyInfo FontSizeInfo = { + "FontSize", + "Font Size", + "The font size for the astronomical object labels." + }; + + constexpr openspace::properties::Property::PropertyInfo LabelSizeInfo = { + "LabelSize", + "Label Size", + "The label size for the astronomical object labels." + }; + + constexpr openspace::properties::Property::PropertyInfo LabelTextInfo = { + "LabelText", + "Label Text", + "The text that will be displayed on screen." + }; + + constexpr openspace::properties::Property::PropertyInfo LabelMinSizeInfo = { + "LabelMinSize", + "Label Min Size", + "The minimal size (in pixels) of the labels for the astronomical " + "objects being rendered." + }; + + constexpr openspace::properties::Property::PropertyInfo LabelMaxSizeInfo = { + "LabelMaxSize", + "Label Max Size", + "The maximum size (in pixels) of the labels for the astronomical " + "objects being rendered." + }; + + constexpr openspace::properties::Property::PropertyInfo TransformationMatrixInfo = { + "TransformationMatrix", + "Transformation Matrix", + "Transformation matrix to be applied to each astronomical object." + }; + + constexpr openspace::properties::Property::PropertyInfo LabelOrientationOptionInfo = { + "LabelOrientationOption", + "Label Orientation Option", + "Label orientation rendering mode." + }; + + constexpr openspace::properties::Property::PropertyInfo EnableFadingEffectInfo = { + "EnableFading", + "Enable/Disable Fade-in effect", + "Enable/Disable the Fade-in effect." + }; + + constexpr openspace::properties::Property::PropertyInfo PixelSizeControlInfo = { + "EnablePixelSizeControl", + "Enable pixel size control.", + "Enable pixel size control for rectangular projections." + }; + + constexpr openspace::properties::Property::PropertyInfo FadeStartUnitOptionInfo = { + "FadeStartUnit", + "Fade-In/-Out Start Unit.", + "Unit for fade-in/-out starting position calculation." + }; + + constexpr openspace::properties::Property::PropertyInfo FadeEndUnitOptionInfo = { + "FadeEndUnit", + "Fade-In/-Out End Unit.", + "Unit for fade-in/-out ending position calculation." + }; + + constexpr openspace::properties::Property::PropertyInfo FadeStartDistInfo = { + "FadeStartDistance", + "Fade-In/-Out starting distance.", + "Fade-In/-Out starting distance." + }; + + constexpr openspace::properties::Property::PropertyInfo FadeEndDistInfo = { + "FadeEndDistance", + "Fade-In/-Out ending distance.", + "Fade-In/-Out ending distance." + }; + + constexpr openspace::properties::Property::PropertyInfo FadeStartSpeedInfo = { + "FadeStartSpeed", + "Fade-In/-Out starting speed.", + "Fade-In/-Out starting speed." + }; + + constexpr openspace::properties::Property::PropertyInfo FadeEndSpeedInfo = { + "FadeEndSpeed", + "Fade-In/-Out ending speed.", + "Fade-In/-Out ending speed." + }; +} // namespace + +namespace openspace { + +documentation::Documentation RenderableLabels::Documentation() { + using namespace documentation; + return { + "Renderable Labels", + "base_renderable_labels", + { + { + BlendModeInfo.identifier, + new StringInListVerifier({ "Normal", "Additive" }), + Optional::Yes, + BlendModeInfo.description, // + " The default value is 'Normal'.", + }, + { + LabelOrientationOptionInfo.identifier, + new StringInListVerifier( + { "Camera View Direction", "Camera Position Normal" } + ), + Optional::Yes, + LabelOrientationOptionInfo.description, + }, + { + LabelColorInfo.identifier, + new DoubleVector4Verifier, + Optional::Yes, + LabelColorInfo.description, + }, + { + LabelColorInfo.identifier, + new DoubleVector4Verifier, + Optional::Yes, + LabelColorInfo.description, + }, + { + LabelTextInfo.identifier, + new StringVerifier, + Optional::No, + LabelTextInfo.description + }, + { + FontSizeInfo.identifier, + new DoubleVerifier, + Optional::Yes, + FontSizeInfo.description + }, + { + LabelSizeInfo.identifier, + new DoubleVerifier, + Optional::Yes, + LabelSizeInfo.description + }, + { + LabelMinSizeInfo.identifier, + new DoubleVerifier, + Optional::Yes, + LabelMinSizeInfo.description + }, + { + LabelMaxSizeInfo.identifier, + new DoubleVerifier, + Optional::Yes, + LabelMaxSizeInfo.description + }, + { + EnableFadingEffectInfo.identifier, + new BoolVerifier, + Optional::Yes, + EnableFadingEffectInfo.description + }, + { + PixelSizeControlInfo.identifier, + new BoolVerifier, + Optional::Yes, + PixelSizeControlInfo.description + }, + { + FadeStartUnitOptionInfo.identifier, + new StringInListVerifier( + { "m", "Km", "Mm", "Gm", "au", "Tm", "Pm", "pc", "Kpc", "Mpc", + "Gpc", "Gly"} + ), + Optional::Yes, + FadeStartUnitOptionInfo.description, + }, + { + FadeEndUnitOptionInfo.identifier, + new StringInListVerifier( + {"m", "Km", "Mm", "Gm", "au", "Tm", "Pm", "pc", "Kpc", "Mpc", + "Gpc", "Gly"} + ), + Optional::Yes, + FadeEndUnitOptionInfo.description, + }, + { + FadeStartDistInfo.identifier, + new DoubleVerifier, + Optional::Yes, + FadeStartDistInfo.description + }, + { + FadeEndDistInfo.identifier, + new DoubleVerifier, + Optional::Yes, + FadeEndDistInfo.description + }, + { + FadeStartSpeedInfo.identifier, + new DoubleVerifier, + Optional::Yes, + FadeStartSpeedInfo.description + }, + { + FadeEndSpeedInfo.identifier, + new DoubleVerifier, + Optional::Yes, + FadeEndSpeedInfo.description + }, + } + }; +} + +RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary) + : Renderable(dictionary) + , _blendMode(BlendModeInfo, properties::OptionProperty::DisplayType::Dropdown) + , _labelColor( + LabelColorInfo, + glm::vec4(1.f, 1.f, 1.f, 1.f), + glm::vec4(0.f), + glm::vec4(1.f) + ) + , _labelSize(LabelSizeInfo, 8.f, 0.5f, 30.f) + , _fontSize(FontSizeInfo, 50.f, 1.f, 100.f) + , _labelMinSize(LabelMinSizeInfo, 8.f, 0.5f, 24.f) + , _labelMaxSize(LabelMaxSizeInfo, 20.f, 0.5f, 100.f) + , _pixelSizeControl(PixelSizeControlInfo, false) + , _enableFadingEffect(EnableFadingEffectInfo, false) + , _labelText(LabelTextInfo) + , _fadeStartDistance(FadeStartDistInfo, 1.f, 0.f, 100.f) + , _fadeEndDistance(FadeEndDistInfo, 1.f, 0.f, 100.f) + , _fadeStartSpeed(FadeStartSpeedInfo, 1.f, 1.f, 100.f) + , _fadeEndSpeed(FadeEndSpeedInfo, 1.f, 1.f, 100.f) + , _labelOrientationOption( + LabelOrientationOptionInfo, + properties::OptionProperty::DisplayType::Dropdown + ) + , _fadeStartUnitOption( + FadeStartUnitOptionInfo, + properties::OptionProperty::DisplayType::Dropdown + ) + , _fadeEndUnitOption( + FadeEndUnitOptionInfo, + properties::OptionProperty::DisplayType::Dropdown + ) +{ + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "RenderableLabels" + ); + + registerUpdateRenderBinFromOpacity(); + + _blendMode.addOptions({ + { BlendModeNormal, "Normal" }, + { BlendModeAdditive, "Additive"} + }); + _blendMode.onChange([&]() { + switch (_blendMode) { + case BlendModeNormal: + setRenderBinFromOpacity(); + break; + case BlendModeAdditive: + setRenderBin(Renderable::RenderBin::Transparent); + break; + default: + throw ghoul::MissingCaseException(); + } + }); + + if (dictionary.hasKey(BlendModeInfo.identifier)) { + const std::string v = dictionary.value(BlendModeInfo.identifier); + if (v == "Normal") { + _blendMode = BlendModeNormal; + } + else if (v == "Additive") { + _blendMode = BlendModeAdditive; + } + } + + addProperty(_blendMode); + + _labelOrientationOption.addOption(ViewDirection, "Camera View Direction"); + _labelOrientationOption.addOption(NormalDirection, "Camera Position Normal"); + + _labelOrientationOption = NormalDirection; + if (dictionary.hasKeyAndValue(LabelOrientationOptionInfo.identifier)) { + const std::string o = dictionary.value( + LabelOrientationOptionInfo.identifier + ); + + if (o == "Camera View Direction") { + _labelOrientationOption = ViewDirection; + } + else if (o == "Camera Position Normal") { + _labelOrientationOption = NormalDirection; + } + } + + if (dictionary.hasKey(LabelTextInfo.identifier)) { + _labelText = dictionary.value(LabelTextInfo.identifier); + } + addProperty(_labelText); + + addProperty(_labelOrientationOption); + + _labelColor.setViewOption(properties::Property::ViewOptions::Color); + if (dictionary.hasKey(LabelColorInfo.identifier)) { + _labelColor = dictionary.value(LabelColorInfo.identifier); + } + addProperty(_labelColor); + + if (dictionary.hasKey(FontSizeInfo.identifier)) { + _fontSize = dictionary.value(FontSizeInfo.identifier); + } + _fontSize.onChange([&]() { + _font = global::fontManager.font( + "Mono", + _fontSize, + ghoul::fontrendering::FontManager::Outline::Yes, + ghoul::fontrendering::FontManager::LoadGlyphs::No + ); + }); + addProperty(_fontSize); + + if (dictionary.hasKey(LabelSizeInfo.identifier)) { + _labelSize = dictionary.value(LabelSizeInfo.identifier); + } + addProperty(_labelSize); + + if (dictionary.hasKey(LabelMinSizeInfo.identifier)) { + _labelMinSize = dictionary.value(LabelMinSizeInfo.identifier); + } + addProperty(_labelMinSize); + + if (dictionary.hasKey(LabelMaxSizeInfo.identifier)) { + _labelMaxSize = dictionary.value(LabelMaxSizeInfo.identifier); + } + addProperty(_labelMaxSize); + + if (dictionary.hasKey(TransformationMatrixInfo.identifier)) { + _transformationMatrix = dictionary.value( + TransformationMatrixInfo.identifier + ); + } + + if (dictionary.hasKey(PixelSizeControlInfo.identifier)) { + _pixelSizeControl = dictionary.value(PixelSizeControlInfo.identifier); + addProperty(_pixelSizeControl); + } + + if (dictionary.hasKey(EnableFadingEffectInfo.identifier)) { + _enableFadingEffect = dictionary.value(EnableFadingEffectInfo.identifier); + } + addProperty(_enableFadingEffect); + + if (dictionary.hasKey(FadeStartDistInfo.identifier)) { + _fadeStartDistance = dictionary.value(FadeStartDistInfo.identifier); + } + + addProperty(_fadeStartDistance); + + _fadeStartUnitOption.addOption(Meter, MeterUnit); + _fadeStartUnitOption.addOption(Kilometer, KilometerUnit); + _fadeStartUnitOption.addOption(Megameter, MegameterUnit); + _fadeStartUnitOption.addOption(Gigameter, GigameterUnit); + _fadeStartUnitOption.addOption(AU, AstronomicalUnit); + _fadeStartUnitOption.addOption(Terameter, TerameterUnit); + _fadeStartUnitOption.addOption(Petameter, PetameterUnit); + _fadeStartUnitOption.addOption(Parsec, ParsecUnit); + _fadeStartUnitOption.addOption(Kiloparsec, KiloparsecUnit); + _fadeStartUnitOption.addOption(Megaparsec, MegaparsecUnit); + _fadeStartUnitOption.addOption(Gigaparsec, GigaparsecUnit); + _fadeStartUnitOption.addOption(GigalightYears, GigalightyearUnit); + + _fadeStartUnitOption = AU; + + if (dictionary.hasKey(FadeStartUnitOptionInfo.identifier)) { + std::string unit = dictionary.value( + FadeStartUnitOptionInfo.identifier + ); + if (unit == MeterUnit) { + _fadeStartUnitOption = Meter; + } + else if (unit == KilometerUnit) { + _fadeStartUnitOption = Kilometer; + } + else if (unit == MegameterUnit) { + _fadeStartUnitOption = Megameter; + } + else if (unit == GigameterUnit) { + _fadeStartUnitOption = Gigameter; + } + else if (unit == AstronomicalUnit) { + _fadeStartUnitOption = AU; + } + else if (unit == TerameterUnit) { + _fadeStartUnitOption = Terameter; + } + else if (unit == PetameterUnit) { + _fadeStartUnitOption = Petameter; + } + else if (unit == ParsecUnit) { + _fadeStartUnitOption = Parsec; + } + else if (unit == KiloparsecUnit) { + _fadeStartUnitOption = Kiloparsec; + } + else if (unit == MegaparsecUnit) { + _fadeStartUnitOption = Megaparsec; + } + else if (unit == GigaparsecUnit) { + _fadeStartUnitOption = Gigaparsec; + } + else if (unit == GigalightyearUnit) { + _fadeStartUnitOption = GigalightYears; + } + else { + LWARNING( + "No unit given for RenderableLabels. Using kilometer as units." + ); + _fadeStartUnitOption = Kilometer; + } + } + + addProperty(_fadeStartUnitOption); + + if (dictionary.hasKey(FadeStartSpeedInfo.identifier)) { + _fadeStartSpeed = dictionary.value(FadeStartSpeedInfo.identifier); + } + + addProperty(_fadeStartSpeed); + + if (dictionary.hasKey(FadeEndDistInfo.identifier)) { + _fadeEndDistance = dictionary.value(FadeEndDistInfo.identifier); + } + + addProperty(_fadeEndDistance); + + _fadeEndUnitOption.addOption(Meter, MeterUnit); + _fadeEndUnitOption.addOption(Kilometer, KilometerUnit); + _fadeEndUnitOption.addOption(Megameter, MegameterUnit); + _fadeEndUnitOption.addOption(Gigameter, GigameterUnit); + _fadeEndUnitOption.addOption(AU, AstronomicalUnit); + _fadeEndUnitOption.addOption(Terameter, TerameterUnit); + _fadeEndUnitOption.addOption(Petameter, PetameterUnit); + _fadeEndUnitOption.addOption(Parsec, ParsecUnit); + _fadeEndUnitOption.addOption(Kiloparsec, KiloparsecUnit); + _fadeEndUnitOption.addOption(Megaparsec, MegaparsecUnit); + _fadeEndUnitOption.addOption(Gigaparsec, GigaparsecUnit); + _fadeEndUnitOption.addOption(GigalightYears, GigalightyearUnit); + + _fadeEndUnitOption = AU; + + if (dictionary.hasKey(FadeEndUnitOptionInfo.identifier)) { + std::string unit = dictionary.value( + FadeEndUnitOptionInfo.identifier + ); + if (unit == MeterUnit) { + _fadeEndUnitOption = Meter; + } + else if (unit == KilometerUnit) { + _fadeEndUnitOption = Kilometer; + } + else if (unit == MegameterUnit) { + _fadeEndUnitOption = Megameter; + } + else if (unit == GigameterUnit) { + _fadeEndUnitOption = Gigameter; + } + else if (unit == AstronomicalUnit) { + _fadeEndUnitOption = AU; + } + else if (unit == TerameterUnit) { + _fadeEndUnitOption = Terameter; + } + else if (unit == PetameterUnit) { + _fadeEndUnitOption = Petameter; + } + else if (unit == ParsecUnit) { + _fadeEndUnitOption = Parsec; + } + else if (unit == KiloparsecUnit) { + _fadeEndUnitOption = Kiloparsec; + } + else if (unit == MegaparsecUnit) { + _fadeEndUnitOption = Megaparsec; + } + else if (unit == GigaparsecUnit) { + _fadeEndUnitOption = Gigaparsec; + } + else if (unit == GigalightyearUnit) { + _fadeEndUnitOption = GigalightYears; + } + else { + LWARNING( + "No unit given for RenderableLabels. Using kilometer as units." + ); + _fadeEndUnitOption = Kilometer; + } + } + + addProperty(_fadeEndUnitOption); + + if (dictionary.hasKey(FadeEndSpeedInfo.identifier)) { + _fadeEndSpeed = dictionary.value(FadeEndSpeedInfo.identifier); + } + + addProperty(_fadeEndSpeed); +} + +bool RenderableLabels::isReady() const { + return true; +} + +void RenderableLabels::initialize() { + bool success = true;// loadData(); + if (!success) { + throw ghoul::RuntimeError("Error loading objects labels data."); + } + + setRenderBin(Renderable::RenderBin::Transparent); +} + +void RenderableLabels::initializeGL() { + if (_font == nullptr) { + //size_t _fontSize = 50; + _font = global::fontManager.font( + "Mono", + _fontSize, + ghoul::fontrendering::FontManager::Outline::Yes, + ghoul::fontrendering::FontManager::LoadGlyphs::No + ); + } +} + +void RenderableLabels::deinitializeGL() {} + +void RenderableLabels::render(const RenderData& data, RendererTasks&) { + + //bool additiveBlending = (_blendMode == BlendModeAdditive); + //if (additiveBlending) { + glDepthMask(false); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + //} + + float fadeInVariable = 1.f; + + if (_enableFadingEffect) { + float distanceNodeToCamera = glm::distance( + data.camera.positionVec3(), + data.modelTransform.translation + ); + float sUnit = getUnit(_fadeStartUnitOption); + float eUnit = getUnit(_fadeEndUnitOption); + float startX = _fadeStartDistance * sUnit; + float endX = _fadeEndDistance * eUnit; + //fadeInVariable = changedPerlinSmoothStepFunc(distanceNodeToCamera, startX, endX); + fadeInVariable = linearSmoothStepFunc( + distanceNodeToCamera, + startX, + endX, + sUnit, + eUnit + ); + } + + glm::dmat4 modelMatrix(1.0); + glm::dmat4 modelViewMatrix = data.camera.combinedViewMatrix() * modelMatrix; + glm::dmat4 projectionMatrix = glm::dmat4(data.camera.projectionMatrix()); + + glm::dmat4 modelViewProjectionMatrix = projectionMatrix * modelViewMatrix; + + glm::dvec3 cameraViewDirectionWorld = -data.camera.viewDirectionWorldSpace(); + glm::dvec3 cameraUpDirectionWorld = data.camera.lookUpVectorWorldSpace(); + glm::dvec3 orthoRight = glm::normalize( + glm::cross(cameraUpDirectionWorld, cameraViewDirectionWorld) + ); + if (orthoRight == glm::dvec3(0.0)) { + glm::dvec3 otherVector( + cameraUpDirectionWorld.y, + cameraUpDirectionWorld.x, + cameraUpDirectionWorld.z + ); + orthoRight = glm::normalize(glm::cross(otherVector, cameraViewDirectionWorld)); + } + glm::dvec3 orthoUp = glm::normalize(glm::cross(cameraViewDirectionWorld, orthoRight)); + + renderLabels(data, modelViewProjectionMatrix, orthoRight, orthoUp, fadeInVariable); + + //if (additiveBlending) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(true); + //} +} + +void RenderableLabels::update(const UpdateData&) { +} + +void RenderableLabels::setLabelText(const std::string & newText) { + _labelText = newText; +} + +void RenderableLabels::renderLabels(const RenderData& data, + const glm::dmat4& modelViewProjectionMatrix, + const glm::dvec3& orthoRight, + const glm::dvec3& orthoUp, float fadeInVariable) +{ + glm::vec4 textColor = _labelColor; + + textColor.a *= fadeInVariable; + textColor.a *= _opacity; + + ghoul::fontrendering::FontRenderer::ProjectedLabelsInformation labelInfo; + + labelInfo.orthoRight = orthoRight; + labelInfo.orthoUp = orthoUp; + labelInfo.minSize = static_cast(_labelMinSize); + labelInfo.maxSize = static_cast(_labelMaxSize); + labelInfo.cameraPos = data.camera.positionVec3(); + labelInfo.cameraLookUp = data.camera.lookUpVectorWorldSpace(); + labelInfo.renderType = _labelOrientationOption; + labelInfo.mvpMatrix = modelViewProjectionMatrix; + labelInfo.scale = powf(10.f, _labelSize); + labelInfo.enableDepth = true; + labelInfo.enableFalseDepth = false; + + // We don't use spice rotation and scale + glm::vec3 transformedPos( + _transformationMatrix * glm::dvec4(data.modelTransform.translation, 1.0) + ); + + ghoul::fontrendering::FontRenderer::defaultProjectionRenderer().render( + *_font, + transformedPos, + _labelText, + textColor, + labelInfo + ); +} + +float RenderableLabels::changedPerlinSmoothStepFunc(float x, float startX, + float endX) const +{ + float f1 = 6.f * powf((x - startX), 5.f) - 15.f * powf((x - startX), 4.f) + + 10.f * powf((x - startX), 3.f); + float f2 = -6.f * powf((x - endX), 5.f) + 15.f * powf((x - endX), 4.f) - + 10.f * powf((x - endX), 3.f) + 1.f; + float f3 = 1.f; + + if (x <= startX) { + return std::clamp(f1, 0.f, 1.f); + } + else if (x > startX && x < endX) { + return f3; + } + else if (x >= endX) { + return std::clamp(f2, 0.f, 1.f); + } +} + +float RenderableLabels::linearSmoothStepFunc(float x, float startX, float endX, + float sUnit, float eUnit) const +{ + float sdiv = 1.f / (sUnit * _fadeStartSpeed); + float ediv = -1.f / (eUnit * _fadeEndSpeed); + float f1 = sdiv * (x - startX) + 1.f; + float f2 = ediv * (x - endX) + 1.f; + float f3 = 1.f; + + if (x <= startX) { + return std::clamp(f1, 0.f, 1.f); + } + else if (x > startX && x < endX) { + return f3; + } + else if (x >= endX) { + return std::clamp(f2, 0.f, 1.f); + } +} + +float RenderableLabels::getUnit(int unit) const { + + float scale = 0.f; + switch (static_cast(unit)) { + case Meter: + scale = 1.f; + break; + case Kilometer: + scale = 1e3; + break; + case Megameter: + scale = 1e6; + break; + case Gigameter: + scale = 1e9; + break; + case AU: + scale = 149597870700.f; + break; + case Terameter: + scale = 1e12; + break; + case Petameter: + scale = 1e15; + break; + case Parsec: + scale = static_cast(PARSEC); + break; + case Kiloparsec: + scale = static_cast(1e3 * PARSEC); + break; + case Megaparsec: + scale = static_cast(1e6 * PARSEC); + break; + case Gigaparsec: + scale = static_cast(1e9 * PARSEC); + break; + case GigalightYears: + scale = static_cast(306391534.73091 * PARSEC); + break; + } + + return scale; +} + +} // namespace openspace diff --git a/modules/base/rendering/renderablelabels.h b/modules/base/rendering/renderablelabels.h new file mode 100644 index 0000000000..0f5bbf6f99 --- /dev/null +++ b/modules/base/rendering/renderablelabels.h @@ -0,0 +1,134 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2019 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_BASE___RENDERABLELABELS___H__ +#define __OPENSPACE_MODULE_BASE___RENDERABLELABELS___H__ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace ghoul::filesystem { class File; } +namespace ghoul::fontrendering { class Font; } +namespace ghoul::opengl { + class ProgramObject; + class Texture; +} // namespace ghoul::opengl + +namespace openspace { + +struct RenderData; +struct UpdateData; + +namespace documentation { struct Documentation; } + +struct LinePoint; + +class RenderableLabels : public Renderable { +public: + RenderableLabels(const ghoul::Dictionary& dictionary); + + void initialize() override; + void initializeGL() override; + void deinitializeGL() override; + + bool isReady() const override; + + void render(const RenderData& data, RendererTasks& rendererTask) override; + void update(const UpdateData& data) override; + + static documentation::Documentation Documentation(); + + void setLabelText(const std::string & newText); + +protected: + properties::OptionProperty _blendMode; + +private: + enum Unit { + Meter = 0, + Kilometer, + Megameter, + Gigameter, + AU, + Terameter, + Petameter, + Parsec, + Kiloparsec, + Megaparsec, + Gigaparsec, + GigalightYears + }; + + void renderLabels(const RenderData& data, const glm::dmat4& modelViewProjectionMatrix, + const glm::dvec3& orthoRight, const glm::dvec3& orthoUp, float fadeInVariable); + + float changedPerlinSmoothStepFunc(float x, float startX, float endX) const; + + float linearSmoothStepFunc(float x, float startX, float endX, float sUnit, + float eUnit) const; + + float getUnit(int unit) const; + + properties::Vec4Property _labelColor; + properties::FloatProperty _labelSize; + properties::FloatProperty _fontSize; + properties::FloatProperty _labelMinSize; + properties::FloatProperty _labelMaxSize; + properties::BoolProperty _pixelSizeControl; + properties::BoolProperty _enableFadingEffect; + properties::StringProperty _labelText; + properties::FloatProperty _fadeStartDistance; + properties::FloatProperty _fadeEndDistance; + properties::FloatProperty _fadeStartSpeed; + properties::FloatProperty _fadeEndSpeed; + + properties::OptionProperty _labelOrientationOption; + properties::OptionProperty _fadeStartUnitOption; + properties::OptionProperty _fadeEndUnitOption; + + std::shared_ptr _font; + + std::string _speckFile; + std::string _colorMapFile; + std::string _labelFile; + std::string _colorOptionString; + std::string _datavarSizeOptionString; + + // Data may require some type of transformation prior the spice transformation being + // applied. + glm::dmat4 _transformationMatrix = glm::dmat4(1.0); +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_BASE___RENDERABLELABELS___H__ diff --git a/modules/base/rendering/renderablesphere.cpp b/modules/base/rendering/renderablesphere.cpp index 1d653791fd..c3ffa2dc70 100644 --- a/modules/base/rendering/renderablesphere.cpp +++ b/modules/base/rendering/renderablesphere.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include @@ -304,7 +304,7 @@ bool RenderableSphere::isReady() const { } void RenderableSphere::initializeGL() { - _sphere = std::make_unique(_size, _segments); + _sphere = std::make_unique(_size, _segments); _sphere->initialize(); _shader = BaseModule::ProgramObjectManager.request( @@ -467,7 +467,7 @@ void RenderableSphere::update(const UpdateData&) { } if (_sphereIsDirty) { - _sphere = std::make_unique(_size, _segments); + _sphere = std::make_unique(_size, _segments); _sphere->initialize(); _sphereIsDirty = false; } diff --git a/modules/base/rendering/renderablesphere.h b/modules/base/rendering/renderablesphere.h index b7ff144fbd..e8e195eb71 100644 --- a/modules/base/rendering/renderablesphere.h +++ b/modules/base/rendering/renderablesphere.h @@ -40,7 +40,7 @@ namespace ghoul::opengl { namespace openspace { -class PowerScaledSphere; +class Sphere; struct RenderData; struct UpdateData; @@ -80,7 +80,7 @@ private: ghoul::opengl::ProgramObject* _shader = nullptr; std::unique_ptr _texture; - std::unique_ptr _sphere; + std::unique_ptr _sphere; UniformCache(opacity, modelViewProjection, modelViewRotation, colorTexture, _mirrorTexture) _uniformCache; diff --git a/modules/base/rendering/screenspacedashboard.cpp b/modules/base/rendering/screenspacedashboard.cpp index d86376d06f..c0530f8491 100644 --- a/modules/base/rendering/screenspacedashboard.cpp +++ b/modules/base/rendering/screenspacedashboard.cpp @@ -151,24 +151,15 @@ ScreenSpaceDashboard::ScreenSpaceDashboard(const ghoul::Dictionary& dictionary) "ScreenSpaceDashboard" ); - int iIdentifier = 0; - if (_identifier.empty()) { - static int id = 0; - iIdentifier = id; - - if (iIdentifier == 0) { - setIdentifier("ScreenSpaceDashboard"); - } - else { - setIdentifier("ScreenSpaceDashboard" + std::to_string(iIdentifier)); - } - ++id; + std::string identifier; + if (dictionary.hasKeyAndValue(KeyIdentifier)) { + identifier = dictionary.value(KeyIdentifier); } - - if (_guiName.empty()) { - // Adding an extra space to the user-facing name as it looks nicer - setGuiName("ScreenSpaceDashboard " + std::to_string(iIdentifier)); + else { + identifier = "ScreenSpaceDashboard"; } + identifier = makeUniqueIdentifier(identifier); + setIdentifier(std::move(identifier)); if (dictionary.hasKey(UseMainInfo.identifier)) { _useMainDashboard = dictionary.value(UseMainInfo.identifier); diff --git a/modules/base/rendering/screenspaceimagelocal.cpp b/modules/base/rendering/screenspaceimagelocal.cpp index 392a8952d0..6e0896ab21 100644 --- a/modules/base/rendering/screenspaceimagelocal.cpp +++ b/modules/base/rendering/screenspaceimagelocal.cpp @@ -78,24 +78,15 @@ ScreenSpaceImageLocal::ScreenSpaceImageLocal(const ghoul::Dictionary& dictionary "ScreenSpaceImageLocal" ); - int iIdentifier = 0; - if (_identifier.empty()) { - static int id = 0; - iIdentifier = id; - - if (iIdentifier == 0) { - setIdentifier("ScreenSpaceImageLocal"); - } - else { - setIdentifier("ScreenSpaceImageLocal" + std::to_string(iIdentifier)); - } - ++id; + std::string identifier; + if (dictionary.hasKeyAndValue(KeyIdentifier)) { + identifier = dictionary.value(KeyIdentifier); } - - if (_guiName.empty()) { - // Adding an extra space to the user-facing name as it looks nicer - setGuiName("ScreenSpaceImageLocal " + std::to_string(iIdentifier)); + else { + identifier = "ScreenSpaceImageLocal"; } + identifier = makeUniqueIdentifier(identifier); + setIdentifier(identifier); _texturePath.onChange([this]() { if (!FileSys.fileExists(FileSys.absolutePath(_texturePath))) { diff --git a/modules/base/rendering/screenspaceimageonline.cpp b/modules/base/rendering/screenspaceimageonline.cpp index 83026445cc..b3df9654b4 100644 --- a/modules/base/rendering/screenspaceimageonline.cpp +++ b/modules/base/rendering/screenspaceimageonline.cpp @@ -80,24 +80,15 @@ ScreenSpaceImageOnline::ScreenSpaceImageOnline(const ghoul::Dictionary& dictiona "ScreenSpaceImageOnline" ); - int iIdentifier = 0; - if (_identifier.empty()) { - static int id = 0; - iIdentifier = id; - - if (iIdentifier == 0) { - setIdentifier("ScreenSpaceImageOnline"); - } - else { - setIdentifier("ScreenSpaceImageOnline" + std::to_string(iIdentifier)); - } - ++id; + std::string identifier; + if (dictionary.hasKeyAndValue(KeyIdentifier)) { + identifier = dictionary.value(KeyIdentifier); } - - if (_guiName.empty()) { - // Adding an extra space to the user-facing name as it looks nicer - setGuiName("ScreenSpaceImageOnline " + std::to_string(iIdentifier)); + else { + identifier = "ScreenSpaceImageOnline"; } + identifier = makeUniqueIdentifier(identifier); + setIdentifier(std::move(identifier)); _texturePath.onChange([this]() { _textureIsDirty = true; }); addProperty(_texturePath); diff --git a/modules/base/shaders/imageplane_vs.glsl b/modules/base/shaders/imageplane_vs.glsl index 0962157b38..995c35950c 100644 --- a/modules/base/shaders/imageplane_vs.glsl +++ b/modules/base/shaders/imageplane_vs.glsl @@ -22,6 +22,8 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ +// @TODO (abock, 2019-12-27) Move this file to the spacecraftinstruments module + #version __CONTEXT__ #include "PowerScaling/powerScaling_vs.hglsl" @@ -36,7 +38,7 @@ uniform mat4 modelViewProjectionTransform; void main() { - vec4 position = vec4(in_position.xyz * pow(10, in_position.w), 1); + vec4 position = vec4(in_position.xyz, 1); vec4 positionClipSpace = modelViewProjectionTransform * position; vec4 positionScreenSpace = z_normalization(positionClipSpace); diff --git a/modules/cefwebgui/cefwebguimodule.cpp b/modules/cefwebgui/cefwebguimodule.cpp index 44c3ffa24b..e0a1de88e7 100644 --- a/modules/cefwebgui/cefwebguimodule.cpp +++ b/modules/cefwebgui/cefwebguimodule.cpp @@ -103,7 +103,9 @@ void CefWebGuiModule::startOrStopGui() { new GUIKeyboardHandler ); _instance->initialize(); - _instance->loadUrl(_url); + if (!_url.value().empty()) { + _instance->loadUrl(_url); + } } if (_visible) { webBrowserModule->attachEventHandler(_instance.get()); diff --git a/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp b/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp index da42b36210..c5a6032e25 100644 --- a/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp +++ b/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include @@ -814,21 +813,23 @@ void RenderableBillboardsCloud::renderBillboards(const RenderData& data, _program->setUniform(_uniformCache.cameraPos, data.camera.positionVec3()); _program->setUniform( _uniformCache.cameraLookup, - data.camera.lookUpVectorWorldSpace() + glm::vec3(data.camera.lookUpVectorWorldSpace()) ); _program->setUniform(_uniformCache.renderOption, _renderOption.value()); _program->setUniform(_uniformCache.modelMatrix, modelMatrix); _program->setUniform( _uniformCache.cameraViewProjectionMatrix, - glm::dmat4(data.camera.projectionMatrix()) * data.camera.combinedViewMatrix() + glm::mat4( + glm::dmat4(data.camera.projectionMatrix()) * data.camera.combinedViewMatrix() + ) ); _program->setUniform(_uniformCache.minBillboardSize, _billboardMinSize); // in pixels _program->setUniform(_uniformCache.maxBillboardSize, _billboardMaxSize); // in pixels _program->setUniform(_uniformCache.color, _pointColor); _program->setUniform(_uniformCache.alphaValue, _opacity); _program->setUniform(_uniformCache.scaleFactor, _scaleFactor); - _program->setUniform(_uniformCache.up, orthoUp); - _program->setUniform(_uniformCache.right, orthoRight); + _program->setUniform(_uniformCache.up, glm::vec3(orthoUp)); + _program->setUniform(_uniformCache.right, glm::vec3(orthoRight)); _program->setUniform(_uniformCache.fadeInValue, fadeInVariable); _program->setUniform( diff --git a/modules/digitaluniverse/shaders/billboard_fs.glsl b/modules/digitaluniverse/shaders/billboard_fs.glsl index ea696b2ee6..cccfbeb58e 100644 --- a/modules/digitaluniverse/shaders/billboard_fs.glsl +++ b/modules/digitaluniverse/shaders/billboard_fs.glsl @@ -25,7 +25,7 @@ #include "fragment.glsl" flat in vec4 gs_colorMap; -in float vs_screenSpaceDepth; +flat in float vs_screenSpaceDepth; in vec2 texCoord; in float ta; @@ -35,18 +35,23 @@ uniform sampler2D spriteTexture; uniform bool hasColorMap; uniform float fadeInValue; -Fragment getFragment() { - +Fragment getFragment() { vec4 textureColor = texture(spriteTexture, texCoord); + if (textureColor.a == 0.f || gs_colorMap.a == 0.f || ta == 0.f || fadeInValue == 0.f) + { + discard; + } + vec4 fullColor = vec4(1.0); if (hasColorMap) { fullColor = vec4( - gs_colorMap.rgb * textureColor.rgb, + gs_colorMap.rgb * textureColor.rgb, gs_colorMap.a * textureColor.a * alphaValue - ); - } else { + ); + } + else { fullColor = vec4(color.rgb * textureColor.rgb, textureColor.a * alphaValue); } @@ -58,13 +63,13 @@ Fragment getFragment() { } Fragment frag; - frag.color = fullColor; - frag.depth = vs_screenSpaceDepth; + frag.color = fullColor; + frag.depth = vs_screenSpaceDepth; // Setting the position of the billboards to not interact // with the ATM. - frag.gPosition = vec4(-1e32, -1e32, -1e32, 1.0); - frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0); + frag.gPosition = vec4(-1e32, -1e32, -1e32, 1.0); + frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0); //frag.disableLDR2HDR = true; return frag; -} \ No newline at end of file +} diff --git a/modules/digitaluniverse/shaders/billboard_gs.glsl b/modules/digitaluniverse/shaders/billboard_gs.glsl index cb955fbc33..644be37dd3 100644 --- a/modules/digitaluniverse/shaders/billboard_gs.glsl +++ b/modules/digitaluniverse/shaders/billboard_gs.glsl @@ -30,16 +30,16 @@ layout(points) in; layout(triangle_strip, max_vertices = 4) out; uniform float scaleFactor; -uniform dvec3 up; -uniform dvec3 right; +uniform vec3 up; +uniform vec3 right; uniform dvec3 cameraPosition; // in world space (no SGCT View was considered) -uniform dvec3 cameraLookUp; // in world space (no SGCT View was considered) +uniform vec3 cameraLookUp; // in world space (no SGCT View was considered) uniform int renderOption; uniform vec2 screenSize; uniform float maxBillboardSize; uniform float minBillboardSize; -uniform dmat4 cameraViewProjectionMatrix; +uniform mat4 cameraViewProjectionMatrix; uniform dmat4 modelMatrix; uniform float correctionSizeFactor; @@ -55,7 +55,7 @@ flat in float dvarScaling[]; flat out vec4 gs_colorMap; out vec2 texCoord; -out float vs_screenSpaceDepth; +flat out float vs_screenSpaceDepth; out float ta; const double PARSEC = 0.308567756e17LF; @@ -94,11 +94,11 @@ void main() { dvec4 dpos = dvec4(dvec3(pos.xyz) * unit, 1.0); dpos = modelMatrix * dpos; - double scaleMultiply = exp(scaleFactor * 0.10); + float scaleMultiply = exp(scaleFactor * 0.10f); scaleMultiply = hasDvarScaling ? dvarScaling[0] * scaleMultiply : scaleMultiply; - dvec3 scaledRight = dvec3(0.0); - dvec3 scaledUp = dvec3(0.0); + vec3 scaledRight = vec3(0.f); + vec3 scaledUp = vec3(0.f); vec4 initialPosition, secondPosition, thirdPosition, crossCorner; @@ -106,15 +106,15 @@ void main() { scaledRight = scaleMultiply * right * 0.5f; scaledUp = scaleMultiply * up * 0.5f; } else if (renderOption == 1) { - dvec3 normal = normalize(cameraPosition - dpos.xyz); - dvec3 newRight = normalize(cross(cameraLookUp, normal)); - dvec3 newUp = cross(normal, newRight); + vec3 normal = vec3(normalize(cameraPosition - dpos.xyz)); + vec3 newRight = normalize(cross(cameraLookUp, normal)); + vec3 newUp = cross(normal, newRight); if (!enabledRectSizeControl) { double distCamera = length(cameraPosition - dpos.xyz); float expVar = float(-distCamera) / pow(10.f, correctionSizeEndDistance); - double factorVar = double(pow(10, correctionSizeFactor)); - scaleMultiply *= 1.0 / (1.0 + factorVar * double(exp(expVar))); + float factorVar = pow(10.f, correctionSizeFactor); + scaleMultiply *= 1.f / (1.f + factorVar * exp(expVar)); } scaledRight = scaleMultiply * newRight * 0.5f; @@ -122,11 +122,13 @@ void main() { } if (enabledRectSizeControl) { - initialPosition = z_normalization(vec4(cameraViewProjectionMatrix * - dvec4(dpos.xyz - scaledRight - scaledUp, dpos.w))); + initialPosition = z_normalization(cameraViewProjectionMatrix * + vec4(vec3(dpos.xyz) - scaledRight - scaledUp, dpos.w)); + vs_screenSpaceDepth = initialPosition.w; - crossCorner = z_normalization(vec4(cameraViewProjectionMatrix * - dvec4(dpos.xyz + scaledUp + scaledRight, dpos.w))); + + crossCorner = z_normalization(cameraViewProjectionMatrix * + vec4(vec3(dpos.xyz) + scaledUp + scaledRight, dpos.w)); // Testing size for rectangular viewport: vec2 halfViewSize = vec2(screenSize.x, screenSize.y) * 0.5f; @@ -158,30 +160,35 @@ void main() { } } } - - initialPosition = z_normalization(vec4(cameraViewProjectionMatrix * - dvec4(dpos.xyz - scaledRight - scaledUp, dpos.w))); - vs_screenSpaceDepth = initialPosition.w; - secondPosition = z_normalization(vec4(cameraViewProjectionMatrix * - dvec4(dpos.xyz + scaledRight - scaledUp, dpos.w))); - crossCorner = z_normalization(vec4(cameraViewProjectionMatrix * - dvec4(dpos.xyz + scaledUp + scaledRight, dpos.w))); - thirdPosition = z_normalization(vec4(cameraViewProjectionMatrix * - dvec4(dpos.xyz + scaledUp - scaledRight, dpos.w))); + // Saving one matrix multiplication: + vec4 dposClip = cameraViewProjectionMatrix * vec4(dpos); + vec4 scaledRightClip = cameraViewProjectionMatrix * vec4(scaledRight, 0.0); + vec4 scaledUpClip = cameraViewProjectionMatrix * vec4(scaledUp, 0.0); + + initialPosition = z_normalization(dposClip - scaledRightClip - scaledUpClip); + vs_screenSpaceDepth = initialPosition.w; + secondPosition = z_normalization(dposClip + scaledRightClip - scaledUpClip); + crossCorner = z_normalization(dposClip + scaledUpClip + scaledRightClip); + thirdPosition = z_normalization(dposClip + scaledUpClip - scaledRightClip); // Build primitive - texCoord = corners[3]; - gl_Position = thirdPosition; - EmitVertex(); + texCoord = corners[0]; gl_Position = initialPosition; EmitVertex(); - texCoord = corners[2]; - gl_Position = crossCorner; - EmitVertex(); + texCoord = corners[1]; gl_Position = secondPosition; EmitVertex(); + + texCoord = corners[3]; + gl_Position = thirdPosition; + EmitVertex(); + + texCoord = corners[2]; + gl_Position = crossCorner; + EmitVertex(); + EndPrimitive(); } \ No newline at end of file diff --git a/modules/galaxy/rendering/renderablegalaxy.cpp b/modules/galaxy/rendering/renderablegalaxy.cpp index 1d88c2da23..ecdd0c276f 100644 --- a/modules/galaxy/rendering/renderablegalaxy.cpp +++ b/modules/galaxy/rendering/renderablegalaxy.cpp @@ -34,7 +34,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -46,18 +48,21 @@ #include namespace { + constexpr int8_t CurrentCacheVersion = 1; + constexpr const char* GlslRaycastPath = - "${MODULES}/galaxy/shaders/galaxyraycast.glsl"; + "${MODULE_GALAXY}/shaders/galaxyraycast.glsl"; constexpr const char* GlslBoundsVsPath = - "${MODULES}/galaxy/shaders/raycasterbounds_vs.glsl"; + "${MODULE_GALAXY}/shaders/raycasterbounds_vs.glsl"; constexpr const char* GlslBoundsFsPath = - "${MODULES}/galaxy/shaders/raycasterbounds_fs.glsl"; - constexpr const char* _loggerCat = "Renderable Galaxy"; + "${MODULE_GALAXY}/shaders/raycasterbounds_fs.glsl"; + constexpr const char* _loggerCat = "Renderable Galaxy"; constexpr const std::array UniformNamesPoints = { "modelMatrix", "cameraViewProjectionMatrix", "eyePosition", "opacityCoefficient" }; + constexpr const std::array UniformNamesBillboards = { "modelMatrix", "cameraViewProjectionMatrix", "cameraUp", "eyePosition", "psfTexture" @@ -117,11 +122,55 @@ namespace { "Enabled points", "" // @TODO Missing documentation }; + + constexpr openspace::properties::Property::PropertyInfo DownscaleVolumeRenderingInfo = + { + "Downscale", + "Downscale Factor Volume Rendering", + "This value set the downscaling factor" + " when rendering the current volume." + }; + + constexpr openspace::properties::Property::PropertyInfo NumberOfRayCastingStepsInfo = + { + "Steps", + "Number of RayCasting Steps", + "This value set the number of integration steps during the raycasting procedure." + }; + + void saveCachedFile(const std::string& file, const std::vector& positions, + const std::vector& colors, int64_t nPoints, + float pointsRatio) + { + std::ofstream fileStream(file, std::ofstream::binary); + + if (!fileStream.good()) { + LERROR(fmt::format("Error opening file '{}' for save cache file", file)); + return; + } + + fileStream.write(reinterpret_cast(&CurrentCacheVersion), sizeof(int8_t)); + fileStream.write(reinterpret_cast(&nPoints), sizeof(int64_t)); + fileStream.write(reinterpret_cast(&pointsRatio), sizeof(float)); + uint64_t nPositions = static_cast(positions.size()); + fileStream.write(reinterpret_cast(&nPositions), sizeof(uint64_t)); + fileStream.write( + reinterpret_cast(positions.data()), + positions.size() * sizeof(glm::vec3) + ); + uint64_t nColors = static_cast(colors.size()); + fileStream.write(reinterpret_cast(&nColors), sizeof(uint64_t)); + fileStream.write( + reinterpret_cast(colors.data()), + colors.size() * sizeof(glm::vec3) + ); + } + } // namespace namespace openspace { - RenderableGalaxy::RenderableGalaxy(const ghoul::Dictionary& dictionary) +RenderableGalaxy::RenderableGalaxy(const ghoul::Dictionary& dictionary) : Renderable(dictionary) , _volumeRenderingEnabled(VolumeRenderingEnabledInfo, true) , _starRenderingEnabled(StarRenderingEnabledInfo, true) @@ -135,6 +184,8 @@ namespace openspace { , _enabledPointsRatio(EnabledPointsRatioInfo, 0.5f, 0.01f, 1.0f) , _translation(TranslationInfo, glm::vec3(0.f), glm::vec3(0.f), glm::vec3(1.f)) , _rotation(RotationInfo, glm::vec3(0.f), glm::vec3(0.f), glm::vec3(6.28f)) + , _downScaleVolumeRendering(DownscaleVolumeRenderingInfo, 1.f, 0.1f, 1.f) + , _numberOfRayCastingSteps(NumberOfRayCastingStepsInfo, 1000.f, 1.f, 1000.f) { dictionary.getValue("VolumeRenderingEnabled", _volumeRenderingEnabled); dictionary.getValue("StarRenderingEnabled", _starRenderingEnabled); @@ -149,7 +200,7 @@ namespace openspace { if (dictionary.hasKeyAndValue(VolumeRenderingEnabledInfo.identifier)) { _volumeRenderingEnabled = dictionary.value( VolumeRenderingEnabledInfo.identifier - ); + ); } if (dictionary.hasKeyAndValue(StarRenderingEnabledInfo.identifier)) { @@ -224,6 +275,21 @@ namespace openspace { LERROR("No volume dimensions specified."); } + if (volumeDictionary.hasKey(NumberOfRayCastingStepsInfo.identifier)) { + _numberOfRayCastingSteps = static_cast( + volumeDictionary.value(NumberOfRayCastingStepsInfo.identifier) + ); + } + else { + LINFO("Number of raycasting steps not specified. Using default value."); + } + + _downScaleVolumeRendering.setVisibility(properties::Property::Visibility::Developer); + if (volumeDictionary.hasKey(DownscaleVolumeRenderingInfo.identifier)) { + _downScaleVolumeRendering = + volumeDictionary.value(DownscaleVolumeRenderingInfo.identifier); + } + if (!dictionary.hasKeyAndValue("Points")) { LERROR("No points dictionary specified."); } @@ -240,7 +306,7 @@ namespace openspace { if (pointsDictionary.hasKeyAndValue(EnabledPointsRatioInfo.identifier)) { _enabledPointsRatio = static_cast( pointsDictionary.value(EnabledPointsRatioInfo.identifier) - ); + ); } std::string pointSpreadFunctionTexturePath; @@ -260,6 +326,7 @@ void RenderableGalaxy::initializeGL() { _aspect = static_cast(_volumeDimensions); _aspect /= std::max(std::max(_aspect.x, _aspect.y), _aspect.z); + // The volume volume::RawVolumeReader> reader( _volumeFilename, _volumeDimensions @@ -272,10 +339,11 @@ void RenderableGalaxy::initializeGL() { GL_RGBA, GL_UNSIGNED_BYTE, ghoul::opengl::Texture::FilterMode::Linear, - ghoul::opengl::Texture::WrappingMode::ClampToEdge); + ghoul::opengl::Texture::WrappingMode::ClampToEdge + ); - _texture->setPixelData(reinterpret_cast( - _volume->data()), + _texture->setPixelData( + reinterpret_cast(_volume->data()), ghoul::opengl::Texture::TakeOwnership::No ); @@ -307,133 +375,141 @@ void RenderableGalaxy::initializeGL() { addProperty(_enabledPointsRatio); addProperty(_translation); addProperty(_rotation); + addProperty(_downScaleVolumeRendering); + addProperty(_numberOfRayCastingSteps); // initialize points. - if (!_pointsFilename.empty()) { - _pointsProgram = global::renderEngine.buildRenderProgram( - "Galaxy points", - absPath("${MODULE_GALAXY}/shaders/points_vs.glsl"), - absPath("${MODULE_GALAXY}/shaders/points_fs.glsl") - ); - _billboardsProgram = global::renderEngine.buildRenderProgram( - "Galaxy billboard", - absPath("${MODULE_GALAXY}/shaders/billboard_vs.glsl"), - absPath("${MODULE_GALAXY}/shaders/billboard_fs.glsl"), - absPath("${MODULE_GALAXY}/shaders/billboard_ge.glsl") - ); - - if (!_pointSpreadFunctionTexturePath.empty()) { - _pointSpreadFunctionTexture = ghoul::io::TextureReader::ref().loadTexture( - absPath(_pointSpreadFunctionTexturePath) - ); - - if (_pointSpreadFunctionTexture) { - LDEBUG(fmt::format( - "Loaded texture from '{}'", - absPath(_pointSpreadFunctionTexturePath) - )); - _pointSpreadFunctionTexture->uploadTexture(); - } - _pointSpreadFunctionTexture->setFilter( - ghoul::opengl::Texture::FilterMode::AnisotropicMipMap - ); - - _pointSpreadFunctionFile = std::make_unique( - _pointSpreadFunctionTexturePath - ); - } - - ghoul::opengl::updateUniformLocations( - *_pointsProgram, - _uniformCachePoints, - UniformNamesPoints - ); - ghoul::opengl::updateUniformLocations( - *_billboardsProgram, - _uniformCacheBillboards, - UniformNamesBillboards - ); - - _pointsProgram->setIgnoreUniformLocationError( - ghoul::opengl::ProgramObject::IgnoreError::Yes - ); - - GLint positionAttrib = _pointsProgram->attributeLocation("in_position"); - GLint colorAttrib = _pointsProgram->attributeLocation("in_color"); - - std::ifstream pointFile(_pointsFilename, std::ios::in); - - std::vector pointPositions; - std::vector pointColors; - int64_t nPoints; - - // Read header for OFF (Object File Format) - std::string line; - std::getline(pointFile, line); - - // Read point count - std::getline(pointFile, line); - std::istringstream iss(line); - iss >> nPoints; - - // Prepare point reading - _nPoints = static_cast(nPoints); - float maxdist = 0; - - // Read points - float x, y, z, r, g, b, a; - for (size_t i = 0; - i < static_cast(_nPoints * _enabledPointsRatio.maxValue()) + 1; - ++i) - { - std::getline(pointFile, line); - std::istringstream issp(line); - issp >> x >> y >> z >> r >> g >> b >> a; - - //Convert klioparsec to meters - glm::vec3 position = glm::vec3(x, y, z); - position *= (openspace::distanceconstants::Parsec * 100); - - maxdist = std::max(maxdist, glm::length(position)); - - pointPositions.emplace_back(position); - pointColors.emplace_back(r, g, b); - } - - pointFile.close(); - - std::cout << maxdist << std::endl; - - glGenVertexArrays(1, &_pointsVao); - glGenBuffers(1, &_positionVbo); - glGenBuffers(1, &_colorVbo); - - glBindVertexArray(_pointsVao); - glBindBuffer(GL_ARRAY_BUFFER, _positionVbo); - glBufferData(GL_ARRAY_BUFFER, - pointPositions.size() * sizeof(glm::vec3), - pointPositions.data(), - GL_STATIC_DRAW - ); - - glBindBuffer(GL_ARRAY_BUFFER, _colorVbo); - glBufferData(GL_ARRAY_BUFFER, - pointColors.size() * sizeof(glm::vec3), - pointColors.data(), - GL_STATIC_DRAW - ); - - glBindBuffer(GL_ARRAY_BUFFER, _positionVbo); - glEnableVertexAttribArray(positionAttrib); - glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, GL_FALSE, 0, nullptr); - - glBindBuffer(GL_ARRAY_BUFFER, _colorVbo); - glEnableVertexAttribArray(colorAttrib); - glVertexAttribPointer(colorAttrib, 3, GL_FLOAT, GL_FALSE, 0, nullptr); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); + if (_pointsFilename.empty()) { + return; } + + _pointsProgram = global::renderEngine.buildRenderProgram( + "Galaxy points", + absPath("${MODULE_GALAXY}/shaders/points_vs.glsl"), + absPath("${MODULE_GALAXY}/shaders/points_fs.glsl") + ); + _billboardsProgram = global::renderEngine.buildRenderProgram( + "Galaxy billboard", + absPath("${MODULE_GALAXY}/shaders/billboard_vs.glsl"), + absPath("${MODULE_GALAXY}/shaders/billboard_fs.glsl"), + absPath("${MODULE_GALAXY}/shaders/billboard_ge.glsl") + ); + + if (!_pointSpreadFunctionTexturePath.empty()) { + _pointSpreadFunctionTexture = ghoul::io::TextureReader::ref().loadTexture( + absPath(_pointSpreadFunctionTexturePath) + ); + + if (_pointSpreadFunctionTexture) { + LDEBUG(fmt::format( + "Loaded texture from '{}'", + absPath(_pointSpreadFunctionTexturePath) + )); + _pointSpreadFunctionTexture->uploadTexture(); + } + _pointSpreadFunctionTexture->setFilter( + ghoul::opengl::Texture::FilterMode::AnisotropicMipMap + ); + + _pointSpreadFunctionFile = std::make_unique( + _pointSpreadFunctionTexturePath + ); + } + + ghoul::opengl::updateUniformLocations( + *_pointsProgram, + _uniformCachePoints, + UniformNamesPoints + ); + ghoul::opengl::updateUniformLocations( + *_billboardsProgram, + _uniformCacheBillboards, + UniformNamesBillboards + ); + + _pointsProgram->setIgnoreUniformLocationError( + ghoul::opengl::ProgramObject::IgnoreError::Yes + ); + + GLint positionAttrib = _pointsProgram->attributeLocation("in_position"); + GLint colorAttrib = _pointsProgram->attributeLocation("in_color"); + + + std::vector pointPositions; + std::vector pointColors; + + std::string cachedPointsFile = FileSys.cacheManager()->cachedFilename( + _pointsFilename, + ghoul::filesystem::CacheManager::Persistent::Yes + ); + const bool hasCachedFile = FileSys.fileExists(cachedPointsFile); + if (hasCachedFile) { + LINFO(fmt::format("Cached file '{}' used for galaxy point file '{}'", + cachedPointsFile, _pointsFilename + )); + + Result res = loadCachedFile(cachedPointsFile); + if (res.success) { + pointPositions = std::move(res.positions); + pointColors = std::move(res.color); + } + else { + FileSys.cacheManager()->removeCacheFile(_pointsFilename); + Result res = loadPointFile(_pointsFilename); + pointPositions = std::move(res.positions); + pointColors = std::move(res.color); + saveCachedFile( + cachedPointsFile, + pointPositions, + pointColors, + _nPoints, + _enabledPointsRatio + ); + } + } + else { + Result res = loadPointFile(_pointsFilename); + ghoul_assert(res.success, "Point file loading failed"); + pointPositions = std::move(res.positions); + pointColors = std::move(res.color); + saveCachedFile( + cachedPointsFile, + pointPositions, + pointColors, + _nPoints, + _enabledPointsRatio + ); + } + + glGenVertexArrays(1, &_pointsVao); + glGenBuffers(1, &_positionVbo); + glGenBuffers(1, &_colorVbo); + + glBindVertexArray(_pointsVao); + glBindBuffer(GL_ARRAY_BUFFER, _positionVbo); + glBufferData(GL_ARRAY_BUFFER, + pointPositions.size() * sizeof(glm::vec3), + pointPositions.data(), + GL_STATIC_DRAW + ); + + glBindBuffer(GL_ARRAY_BUFFER, _colorVbo); + glBufferData(GL_ARRAY_BUFFER, + pointColors.size() * sizeof(glm::vec3), + pointColors.data(), + GL_STATIC_DRAW + ); + + glBindBuffer(GL_ARRAY_BUFFER, _positionVbo); + glEnableVertexAttribArray(positionAttrib); + glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + + glBindBuffer(GL_ARRAY_BUFFER, _colorVbo); + glEnableVertexAttribArray(colorAttrib); + glVertexAttribPointer(colorAttrib, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); } void RenderableGalaxy::deinitializeGL() { @@ -441,6 +517,10 @@ void RenderableGalaxy::deinitializeGL() { global::raycasterManager.detachRaycaster(*_raycaster); _raycaster = nullptr; } + + glDeleteVertexArrays(1, &_pointsVao); + glDeleteBuffers(1, &_positionVbo); + glDeleteBuffers(1, &_colorVbo); } bool RenderableGalaxy::isReady() const { @@ -448,41 +528,44 @@ bool RenderableGalaxy::isReady() const { } void RenderableGalaxy::update(const UpdateData& data) { - if (_raycaster) { - //glm::mat4 transform = glm::translate(, static_cast(_translation)); - const glm::vec3 eulerRotation = static_cast(_rotation); - glm::mat4 transform = glm::rotate( - glm::mat4(1.0), - eulerRotation.x, - glm::vec3(1, 0, 0) - ); - transform = glm::rotate(transform, eulerRotation.y, glm::vec3(0, 1, 0)); - transform = glm::rotate(transform, eulerRotation.z, glm::vec3(0, 0, 1)); - - glm::mat4 volumeTransform = glm::scale(transform, _volumeSize); - _pointTransform = transform; - //_pointTransform = glm::scale(transform, _pointScaling); - - const glm::vec4 translation = glm::vec4(_translation.value()*_volumeSize, 0.0); - - // Todo: handle floating point overflow, to actually support translation. - - volumeTransform[3] += translation; - _pointTransform[3] += translation; - - _raycaster->setStepSize(_stepSize); - _raycaster->setAspect(_aspect); - _raycaster->setModelTransform(volumeTransform); - _raycaster->setAbsorptionMultiplier(_absorptionMultiply); - _raycaster->setEmissionMultiplier(_emissionMultiply); - _raycaster->setTime(data.time.j2000Seconds()); + if (!_raycaster) { + return; } + //glm::mat4 transform = glm::translate(, static_cast(_translation)); + const glm::vec3 eulerRotation = static_cast(_rotation); + glm::mat4 transform = glm::rotate( + glm::mat4(1.0), + eulerRotation.x, + glm::vec3(1, 0, 0) + ); + transform = glm::rotate(transform, eulerRotation.y, glm::vec3(0, 1, 0)); + transform = glm::rotate(transform, eulerRotation.z, glm::vec3(0, 0, 1)); + + glm::mat4 volumeTransform = glm::scale(transform, _volumeSize); + _pointTransform = transform; + //_pointTransform = glm::scale(transform, _pointScaling); + + const glm::vec4 translation = glm::vec4(_translation.value()*_volumeSize, 0.0); + + // Todo: handle floating point overflow, to actually support translation. + + volumeTransform[3] += translation; + _pointTransform[3] += translation; + + _raycaster->setDownscaleRender(_downScaleVolumeRendering); + _raycaster->setMaxSteps(_numberOfRayCastingSteps); + _raycaster->setStepSize(_stepSize); + _raycaster->setAspect(_aspect); + _raycaster->setModelTransform(volumeTransform); + _raycaster->setAbsorptionMultiplier(_absorptionMultiply); + _raycaster->setEmissionMultiplier(_emissionMultiply); + _raycaster->setTime(data.time.j2000Seconds()); } void RenderableGalaxy::render(const RenderData& data, RendererTasks& tasks) { // Render the volume if (_raycaster && _volumeRenderingEnabled) { - RaycasterTask task{ _raycaster.get(), data }; + RaycasterTask task { _raycaster.get(), data }; const glm::vec3 position = data.camera.positionVec3(); const float length = safeLength(position); @@ -499,15 +582,19 @@ void RenderableGalaxy::render(const RenderData& data, RendererTasks& tasks) { float opacityCoefficient = 1.f; if (length < lowerRampStart) { opacityCoefficient = 0.f; // camera really close - } else if (length < lowerRampEnd) { + } + else if (length < lowerRampEnd) { opacityCoefficient = (length - lowerRampStart) / (lowerRampEnd - lowerRampStart); - } else if (length < upperRampStart) { + } + else if (length < upperRampStart) { opacityCoefficient = 1.f; // sweet spot (max) - } else if (length < upperRampEnd) { + } + else if (length < upperRampEnd) { opacityCoefficient = 1.f - (length - upperRampStart) / (upperRampEnd - upperRampStart); //fade out - } else { + } + else { opacityCoefficient = 0; } @@ -534,163 +621,166 @@ void RenderableGalaxy::render(const RenderData& data, RendererTasks& tasks) { } void RenderableGalaxy::renderPoints(const RenderData& data) { - if (_pointsProgram) { - // Saving current OpenGL state - GLenum blendEquationRGB; - GLenum blendEquationAlpha; - GLenum blendDestAlpha; - GLenum blendDestRGB; - GLenum blendSrcAlpha; - GLenum blendSrcRGB; - GLboolean depthMask; - - glGetIntegerv(GL_BLEND_EQUATION_RGB, &blendEquationRGB); - glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blendEquationAlpha); - glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDestAlpha); - glGetIntegerv(GL_BLEND_DST_RGB, &blendDestRGB); - glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha); - glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcRGB); - - glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask); - - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - glDepthMask(false); - glDisable(GL_DEPTH_TEST); - - _pointsProgram->activate(); - - glm::dmat4 rotMatrix = glm::rotate( - glm::dmat4(1.0), - glm::pi(), - glm::dvec3(1.0, 0.0, 0.0)) * - glm::rotate(glm::dmat4(1.0), 3.1248, glm::dvec3(0.0, 1.0, 0.0)) * - glm::rotate(glm::dmat4(1.0), 4.45741, glm::dvec3(0.0, 0.0, 1.0) - ); - - glm::dmat4 modelMatrix = - glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * - glm::dmat4(data.modelTransform.rotation) * rotMatrix * - glm::dmat4(glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale))); - - glm::dmat4 projectionMatrix = glm::dmat4(data.camera.projectionMatrix()); - - glm::dmat4 cameraViewProjectionMatrix = projectionMatrix * - data.camera.combinedViewMatrix(); - - _pointsProgram->setUniform(_uniformCachePoints.modelMatrix, modelMatrix); - _pointsProgram->setUniform( - _uniformCachePoints.cameraViewProjectionMatrix, - cameraViewProjectionMatrix - ); - - glm::dvec3 eyePosition = glm::dvec3( - glm::inverse(data.camera.combinedViewMatrix()) * - glm::dvec4(0.0, 0.0, 0.0, 1.0) - ); - _pointsProgram->setUniform(_uniformCachePoints.eyePosition, eyePosition); - _pointsProgram->setUniform( - _uniformCachePoints.opacityCoefficient, - _opacityCoefficient - ); - - glBindVertexArray(_pointsVao); - glDrawArrays(GL_POINTS, 0, static_cast(_nPoints * _enabledPointsRatio)); - - glBindVertexArray(0); - - _pointsProgram->deactivate(); - - glEnable(GL_DEPTH_TEST); - glDepthMask(true); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - // Restores OpenGL blending state - glBlendEquationSeparate(blendEquationRGB, blendEquationAlpha); - glBlendFuncSeparate(blendSrcRGB, blendDestRGB, blendSrcAlpha, blendDestAlpha); - glDepthMask(depthMask); + if (!_pointsProgram) { + return; } + // Saving current OpenGL state + GLenum blendEquationRGB; + GLenum blendEquationAlpha; + GLenum blendDestAlpha; + GLenum blendDestRGB; + GLenum blendSrcAlpha; + GLenum blendSrcRGB; + GLboolean depthMask; + + glGetIntegerv(GL_BLEND_EQUATION_RGB, &blendEquationRGB); + glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blendEquationAlpha); + glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDestAlpha); + glGetIntegerv(GL_BLEND_DST_RGB, &blendDestRGB); + glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha); + glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcRGB); + + glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glDepthMask(false); + glDisable(GL_DEPTH_TEST); + + _pointsProgram->activate(); + + glm::dmat4 rotMatrix = glm::rotate( + glm::dmat4(1.0), + glm::pi(), + glm::dvec3(1.0, 0.0, 0.0)) * + glm::rotate(glm::dmat4(1.0), 3.1248, glm::dvec3(0.0, 1.0, 0.0)) * + glm::rotate(glm::dmat4(1.0), 4.45741, glm::dvec3(0.0, 0.0, 1.0) + ); + + glm::dmat4 modelMatrix = + glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * + glm::dmat4(data.modelTransform.rotation) * rotMatrix * + glm::dmat4(glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale))); + + glm::dmat4 projectionMatrix = glm::dmat4(data.camera.projectionMatrix()); + + glm::dmat4 cameraViewProjectionMatrix = projectionMatrix * + data.camera.combinedViewMatrix(); + + _pointsProgram->setUniform(_uniformCachePoints.modelMatrix, modelMatrix); + _pointsProgram->setUniform( + _uniformCachePoints.cameraViewProjectionMatrix, + cameraViewProjectionMatrix + ); + + glm::dvec3 eyePosition = glm::dvec3( + glm::inverse(data.camera.combinedViewMatrix()) * + glm::dvec4(0.0, 0.0, 0.0, 1.0) + ); + _pointsProgram->setUniform(_uniformCachePoints.eyePosition, eyePosition); + _pointsProgram->setUniform( + _uniformCachePoints.opacityCoefficient, + _opacityCoefficient + ); + + glBindVertexArray(_pointsVao); + glDrawArrays(GL_POINTS, 0, static_cast(_nPoints * _enabledPointsRatio)); + + glBindVertexArray(0); + + _pointsProgram->deactivate(); + + glEnable(GL_DEPTH_TEST); + glDepthMask(true); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // Restores OpenGL blending state + glBlendEquationSeparate(blendEquationRGB, blendEquationAlpha); + glBlendFuncSeparate(blendSrcRGB, blendDestRGB, blendSrcAlpha, blendDestAlpha); + glDepthMask(depthMask); } void RenderableGalaxy::renderBillboards(const RenderData& data) { - if (_billboardsProgram) { - // Saving current OpenGL state - GLenum blendEquationRGB; - GLenum blendEquationAlpha; - GLenum blendDestAlpha; - GLenum blendDestRGB; - GLenum blendSrcAlpha; - GLenum blendSrcRGB; - GLboolean depthMask; - - glGetIntegerv(GL_BLEND_EQUATION_RGB, &blendEquationRGB); - glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blendEquationAlpha); - glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDestAlpha); - glGetIntegerv(GL_BLEND_DST_RGB, &blendDestRGB); - glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha); - glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcRGB); - - glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask); - - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - glDepthMask(false); - glDisable(GL_DEPTH_TEST); - - _billboardsProgram->activate(); - - glm::dmat4 rotMatrix = glm::rotate( - glm::dmat4(1.0), - glm::pi(), - glm::dvec3(1.0, 0.0, 0.0)) * - glm::rotate(glm::dmat4(1.0), 3.1248, glm::dvec3(0.0, 1.0, 0.0)) * - glm::rotate(glm::dmat4(1.0), 4.45741, glm::dvec3(0.0, 0.0, 1.0) - ); - - glm::dmat4 modelMatrix = - glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * - glm::dmat4(data.modelTransform.rotation) * rotMatrix * - glm::dmat4(glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale))); - - glm::dmat4 projectionMatrix = glm::dmat4(data.camera.projectionMatrix()); - - glm::dmat4 cameraViewProjectionMatrix = projectionMatrix * - data.camera.combinedViewMatrix(); - - _billboardsProgram->setUniform(_uniformCacheBillboards.modelMatrix, modelMatrix); - _billboardsProgram->setUniform( - _uniformCacheBillboards.cameraViewProjectionMatrix, - cameraViewProjectionMatrix - ); - - glm::dvec3 eyePosition = glm::dvec3( - glm::inverse(data.camera.combinedViewMatrix()) * - glm::dvec4(0.0, 0.0, 0.0, 1.0) - ); - _billboardsProgram->setUniform(_uniformCacheBillboards.eyePosition, eyePosition); - - glm::dvec3 cameraUp = data.camera.lookUpVectorWorldSpace(); - _billboardsProgram->setUniform(_uniformCacheBillboards.cameraUp, cameraUp); - - ghoul::opengl::TextureUnit psfUnit; - psfUnit.activate(); - _pointSpreadFunctionTexture->bind(); - _billboardsProgram->setUniform(_uniformCacheBillboards.psfTexture, psfUnit); - - glBindVertexArray(_pointsVao); - glDrawArrays(GL_POINTS, 0, static_cast(_nPoints * _enabledPointsRatio)); - - glBindVertexArray(0); - - _billboardsProgram->deactivate(); - - glEnable(GL_DEPTH_TEST); - glDepthMask(true); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - // Restores OpenGL blending state - glBlendEquationSeparate(blendEquationRGB, blendEquationAlpha); - glBlendFuncSeparate(blendSrcRGB, blendDestRGB, blendSrcAlpha, blendDestAlpha); - glDepthMask(depthMask); + if (!_billboardsProgram) { + return; } + + // Saving current OpenGL state + GLenum blendEquationRGB; + GLenum blendEquationAlpha; + GLenum blendDestAlpha; + GLenum blendDestRGB; + GLenum blendSrcAlpha; + GLenum blendSrcRGB; + GLboolean depthMask; + + glGetIntegerv(GL_BLEND_EQUATION_RGB, &blendEquationRGB); + glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blendEquationAlpha); + glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDestAlpha); + glGetIntegerv(GL_BLEND_DST_RGB, &blendDestRGB); + glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha); + glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcRGB); + + glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glDepthMask(false); + glDisable(GL_DEPTH_TEST); + + _billboardsProgram->activate(); + + glm::dmat4 rotMatrix = glm::rotate( + glm::dmat4(1.0), + glm::pi(), + glm::dvec3(1.0, 0.0, 0.0)) * + glm::rotate(glm::dmat4(1.0), 3.1248, glm::dvec3(0.0, 1.0, 0.0)) * + glm::rotate(glm::dmat4(1.0), 4.45741, glm::dvec3(0.0, 0.0, 1.0) + ); + + glm::dmat4 modelMatrix = + glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * + glm::dmat4(data.modelTransform.rotation) * rotMatrix * + glm::dmat4(glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale))); + + glm::dmat4 projectionMatrix = glm::dmat4(data.camera.projectionMatrix()); + + glm::dmat4 cameraViewProjectionMatrix = projectionMatrix * + data.camera.combinedViewMatrix(); + + _billboardsProgram->setUniform(_uniformCacheBillboards.modelMatrix, modelMatrix); + _billboardsProgram->setUniform( + _uniformCacheBillboards.cameraViewProjectionMatrix, + cameraViewProjectionMatrix + ); + + glm::dvec3 eyePosition = glm::dvec3( + glm::inverse(data.camera.combinedViewMatrix()) * + glm::dvec4(0.0, 0.0, 0.0, 1.0) + ); + _billboardsProgram->setUniform(_uniformCacheBillboards.eyePosition, eyePosition); + + glm::dvec3 cameraUp = data.camera.lookUpVectorWorldSpace(); + _billboardsProgram->setUniform(_uniformCacheBillboards.cameraUp, cameraUp); + + ghoul::opengl::TextureUnit psfUnit; + psfUnit.activate(); + _pointSpreadFunctionTexture->bind(); + _billboardsProgram->setUniform(_uniformCacheBillboards.psfTexture, psfUnit); + + glBindVertexArray(_pointsVao); + glDrawArrays(GL_POINTS, 0, static_cast(_nPoints * _enabledPointsRatio)); + + glBindVertexArray(0); + + _billboardsProgram->deactivate(); + + glEnable(GL_DEPTH_TEST); + glDepthMask(true); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // Restores OpenGL blending state + glBlendEquationSeparate(blendEquationRGB, blendEquationAlpha); + glBlendFuncSeparate(blendSrcRGB, blendDestRGB, blendSrcAlpha, blendDestAlpha); + glDepthMask(depthMask); } float RenderableGalaxy::safeLength(const glm::vec3& vector) const { @@ -700,4 +790,95 @@ float RenderableGalaxy::safeLength(const glm::vec3& vector) const { return glm::length(vector / maxComponent) * maxComponent; } +RenderableGalaxy::Result RenderableGalaxy::loadPointFile(const std::string& file) { + std::vector pointPositions; + std::vector pointColors; + int64_t nPoints; + + std::ifstream pointFile(_pointsFilename, std::ios::in); + + // Read header for OFF (Object File Format) + std::string line; + std::getline(pointFile, line); + + // Read point count + std::getline(pointFile, line); + std::istringstream iss(line); + iss >> nPoints; + + // Prepare point reading + _nPoints = static_cast(nPoints); + + // Read points + float x, y, z, r, g, b, a; + for (size_t i = 0; + i < static_cast(_nPoints * _enabledPointsRatio.maxValue()) + 1; + ++i) + { + std::getline(pointFile, line); + std::istringstream issp(line); + issp >> x >> y >> z >> r >> g >> b >> a; + + // Convert kiloparsec to meters + glm::vec3 position = glm::vec3(x, y, z); + position *= (distanceconstants::Parsec * 100); + + pointPositions.emplace_back(position); + pointColors.emplace_back(r, g, b); + } + + Result res; + res.success = true; + res.positions = std::move(pointPositions); + res.color = std::move(pointColors); + return res; +} + +RenderableGalaxy::Result RenderableGalaxy::loadCachedFile(const std::string& file) { + std::ifstream fileStream(file, std::ifstream::binary); + if (!fileStream.good()) { + LERROR(fmt::format("Error opening file '{}' for loading cache file", file)); + return { false, {}, {} }; + } + + int8_t cacheVersion; + fileStream.read(reinterpret_cast(&cacheVersion), sizeof(int8_t)); + if (cacheVersion != CurrentCacheVersion) { + LINFO(fmt::format("Removing cache file '{}' as the version changed")); + return { false, {}, {} }; + } + + int64_t nPoints; + fileStream.read(reinterpret_cast(&nPoints), sizeof(int64_t)); + _nPoints = static_cast(nPoints); + + float enabledPointsRatio; + fileStream.read(reinterpret_cast(&enabledPointsRatio), sizeof(float)); + _enabledPointsRatio = enabledPointsRatio; + + uint64_t nPositions; + fileStream.read(reinterpret_cast(&nPositions), sizeof(uint64_t)); + std::vector positions; + positions.resize(nPositions); + fileStream.read( + reinterpret_cast(positions.data()), + nPositions * sizeof(glm::vec3) + ); + + uint64_t nColors; + fileStream.read(reinterpret_cast(&nColors), sizeof(uint64_t)); + std::vector colors; + colors.resize(nColors); + fileStream.read( + reinterpret_cast(colors.data()), + nColors * sizeof(glm::vec3) + ); + + Result result; + result.success = true; + result.positions = std::move(positions); + result.color = std::move(colors); + return result; +} + } // namespace openspace diff --git a/modules/galaxy/rendering/renderablegalaxy.h b/modules/galaxy/rendering/renderablegalaxy.h index 0b49d848c4..2f8c4ff570 100644 --- a/modules/galaxy/rendering/renderablegalaxy.h +++ b/modules/galaxy/rendering/renderablegalaxy.h @@ -33,9 +33,7 @@ #include #include -namespace ghoul::opengl { - class ProgramObject; -} // namespace ghoul::opengl +namespace ghoul::opengl { class ProgramObject; } namespace openspace { @@ -60,6 +58,14 @@ private: void renderBillboards(const RenderData& data); float safeLength(const glm::vec3& vector) const; + struct Result { + bool success; + std::vector positions; + std::vector color; + }; + Result loadPointFile(const std::string& file); + Result loadCachedFile(const std::string& file); + glm::vec3 _volumeSize; glm::vec3 _pointScaling; properties::BoolProperty _volumeRenderingEnabled; @@ -71,6 +77,8 @@ private: properties::FloatProperty _enabledPointsRatio; properties::Vec3Property _translation; properties::Vec3Property _rotation; + properties::FloatProperty _downScaleVolumeRendering; + properties::FloatProperty _numberOfRayCastingSteps; std::unique_ptr _pointSpreadFunctionTexture; std::unique_ptr _pointSpreadFunctionFile; diff --git a/modules/galaxy/shaders/galaxyraycast.glsl b/modules/galaxy/shaders/galaxyraycast.glsl index a16188aa5d..dab687e3ca 100644 --- a/modules/galaxy/shaders/galaxyraycast.glsl +++ b/modules/galaxy/shaders/galaxyraycast.glsl @@ -29,17 +29,18 @@ uniform float absorptionMultiply#{id} = 50.0; uniform float emissionMultiply#{id} = 1500.0; uniform sampler3D galaxyTexture#{id}; -void sample#{id}(vec3 samplePos, +void sample#{id}( + vec3 samplePos, vec3 dir, inout vec3 accumulatedColor, inout vec3 accumulatedAlpha, - inout float stepSize) - { + inout float stepSize + ) { vec3 aspect = aspect#{id}; stepSize = maxStepSize#{id} / length(dir / aspect); //Early ray termination on black parts of the data - vec3 normalizedPos = samplePos*2.0 - 1.0; + vec3 normalizedPos = samplePos * 2.f - 1.f; if (normalizedPos.x * normalizedPos.x + normalizedPos.y * normalizedPos.y > 0.7) { return; } @@ -51,12 +52,12 @@ void sample#{id}(vec3 samplePos, sampledColor = sampledColor*sampledColor; // Fudge for the dust "spreading" - sampledColor.a = clamp(sampledColor.a, 0.0, 1.0); - sampledColor.a = pow(sampledColor.a, 0.7); + sampledColor.a = clamp(sampledColor.a, 0.f, 1.f); + sampledColor.a = pow(sampledColor.a, 0.7f); // Absorption probability float scaledDensity = sampledColor.a * stepSize * absorptionMultiply#{id}; - vec3 alphaTint = vec3(0.3, 0.54, 0.85); + vec3 alphaTint = vec3(0.3f, 0.54f, 0.85f); vec3 absorption = alphaTint * scaledDensity; // Extinction @@ -67,10 +68,10 @@ void sample#{id}(vec3 samplePos, accumulatedColor.rgb += sampledColor.rgb * stepSize * emissionMultiply#{id} * opacityCoefficient#{id}; - vec3 oneMinusFrontAlpha = vec3(1.0) - accumulatedAlpha; + vec3 oneMinusFrontAlpha = vec3(1.f) - accumulatedAlpha; accumulatedAlpha += oneMinusFrontAlpha * sampledColor.rgb * opacityCoefficient#{id}; } float stepSize#{id}(vec3 samplePos, vec3 dir) { - return maxStepSize#{id} * length(dir * 1.0 / aspect#{id}); + return maxStepSize#{id} * length(dir * 1.f / aspect#{id}); } diff --git a/modules/iswa/rendering/datasphere.cpp b/modules/iswa/rendering/datasphere.cpp index 10cdc263a2..cb68d437c7 100644 --- a/modules/iswa/rendering/datasphere.cpp +++ b/modules/iswa/rendering/datasphere.cpp @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include #include @@ -88,7 +88,7 @@ void DataSphere::initializeGL() { bool DataSphere::createGeometry() { const float radius = 6.371f * _radius * glm::pow(10.f, 6.f); int segments = 100; - _sphere = std::make_unique(radius, segments); + _sphere = std::make_unique(radius, segments); _sphere->initialize(); return true; } diff --git a/modules/iswa/rendering/datasphere.h b/modules/iswa/rendering/datasphere.h index 2ec89762ea..66b5948a93 100644 --- a/modules/iswa/rendering/datasphere.h +++ b/modules/iswa/rendering/datasphere.h @@ -29,7 +29,7 @@ namespace openspace { -class PowerScaledSphere; +class Sphere; /** * DataSphere is a concrete IswaCygnet with data files as its input source. The class @@ -53,7 +53,7 @@ protected: void setUniforms() override; std::vector textureData() override; - std::unique_ptr _sphere; + std::unique_ptr _sphere; float _radius; }; diff --git a/modules/iswa/rendering/iswacygnet.cpp b/modules/iswa/rendering/iswacygnet.cpp index 663ba6dca4..967613f9bf 100644 --- a/modules/iswa/rendering/iswacygnet.cpp +++ b/modules/iswa/rendering/iswacygnet.cpp @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -157,12 +156,13 @@ void IswaCygnet::render(const RenderData& data, RendererTasks&) { } transform = transform * _rotation; - psc position = + glm::vec4 pposition = static_cast(glm::dvec4(data.modelTransform.translation, 0.0)) + transform * glm::vec4( _data.spatialScale.x * _data.offset, _data.spatialScale.w ); + glm::vec3 position = glm::vec3(pposition) * pow(10.f, pposition.w); // Activate shader _shader->activate(); @@ -173,7 +173,7 @@ void IswaCygnet::render(const RenderData& data, RendererTasks&) { _shader->setUniform("ModelTransform", transform); _shader->setUniform("campos", glm::vec4(data.camera.positionVec3(), 1.f)); - _shader->setUniform("objpos", glm::vec4(position.vec3(), 0.f)); + _shader->setUniform("objpos", glm::vec4(position, 0.f)); _shader->setUniform("camrot", glm::mat4(data.camera.viewRotationMatrix())); _shader->setUniform("scaling", glm::vec2(1.f, 0.f)); diff --git a/modules/kameleon/ext/kameleon b/modules/kameleon/ext/kameleon index 1b4549edc7..338d482c86 160000 --- a/modules/kameleon/ext/kameleon +++ b/modules/kameleon/ext/kameleon @@ -1 +1 @@ -Subproject commit 1b4549edc74ef371730ef9d39c1ffa0efe90a985 +Subproject commit 338d482c8617bfacda0a5af8f3f6bb23163d436f diff --git a/modules/space/rendering/renderablesatellites.cpp b/modules/space/rendering/renderablesatellites.cpp index 7453ff44f5..9998db6b2c 100644 --- a/modules/space/rendering/renderablesatellites.cpp +++ b/modules/space/rendering/renderablesatellites.cpp @@ -66,13 +66,6 @@ namespace { "method includes lines. If the rendering mode is set to Points, this value is " "ignored." }; - constexpr openspace::properties::Property::PropertyInfo FadeInfo = { - "Fade", - "Line fade", - "The fading factor that is applied to the trail if the 'EnableFade' value is " - "'true'. If it is 'false', this setting has no effect. The higher the number, " - "the less fading is applied." - }; constexpr openspace::properties::Property::PropertyInfo LineColorInfo = { "Color", "Color", @@ -301,12 +294,6 @@ documentation::Documentation RenderableSatellites::Documentation() { Optional::Yes, LineWidthInfo.description }, - { - FadeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - FadeInfo.description - }, { LineColorInfo.identifier, new DoubleVector3Verifier, @@ -320,9 +307,7 @@ documentation::Documentation RenderableSatellites::Documentation() { RenderableSatellites::RenderableSatellites(const ghoul::Dictionary& dictionary) : Renderable(dictionary) , _path(PathInfo) - , _nSegments(SegmentsInfo) - , _lineFade(FadeInfo) - + , _nSegments(SegmentsInfo, 120, 4, 1024) { documentation::testSpecificationAndThrow( Documentation(), @@ -332,16 +317,32 @@ RenderableSatellites::RenderableSatellites(const ghoul::Dictionary& dictionary) _path = dictionary.value(PathInfo.identifier); _nSegments = static_cast(dictionary.value(SegmentsInfo.identifier)); - _lineFade = static_cast(dictionary.value(FadeInfo.identifier)); if (dictionary.hasKeyAndValue(LineColorInfo.identifier)) { _appearance.lineColor = dictionary.value(LineColorInfo.identifier); } + if (dictionary.hasKeyAndValue("FadeInfo")) { + _appearance.lineFade = static_cast( + dictionary.value("FadeInfo") + ); + } + else { + _appearance.lineFade = 20; + } + + auto reinitializeTrailBuffers = [this]() { + initializeGL(); + }; + + _path.onChange(reinitializeTrailBuffers); + _nSegments.onChange(reinitializeTrailBuffers); addPropertySubOwner(_appearance); addProperty(_path); addProperty(_nSegments); - addProperty(_lineFade); + addProperty(_opacity); + + setRenderBin(Renderable::RenderBin::Overlay); } @@ -484,7 +485,6 @@ void RenderableSatellites::initializeGL() { _uniformCache.opacity = _programObject->uniformLocation("opacity"); updateBuffers(); - setRenderBin(Renderable::RenderBin::Overlay); } void RenderableSatellites::deinitializeGL() { @@ -523,9 +523,12 @@ void RenderableSatellites::render(const RenderData& data, RendererTasks&) { data.camera.combinedViewMatrix() * modelTransform ); + // Because we want the property to work similar to the planet trails + float fade = static_cast(pow(_appearance.lineFade.maxValue() - _appearance.lineFade, 2.0)); + _programObject->setUniform(_uniformCache.projection, data.camera.projectionMatrix()); _programObject->setUniform(_uniformCache.color, _appearance.lineColor); - _programObject->setUniform(_uniformCache.lineFade, _appearance.lineFade); + _programObject->setUniform(_uniformCache.lineFade, fade); glLineWidth(_appearance.lineWidth); @@ -604,10 +607,10 @@ void RenderableSatellites::updateBuffers() { ); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(TrailVBOLayout), (GLvoid*)0); // stride : 4*sizeof(GL_FLOAT) + 2*sizeof(GL_DOUBLE) + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(TrailVBOLayout), nullptr); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_DOUBLE, GL_FALSE, sizeof(TrailVBOLayout), (GLvoid*)(4*sizeof(GL_FLOAT)) ); + glVertexAttribPointer(1, 2, GL_DOUBLE, GL_FALSE, sizeof(TrailVBOLayout), (GLvoid*)(4 * sizeof(GL_FLOAT))); glBindVertexArray(0); diff --git a/modules/space/rendering/renderablesatellites.h b/modules/space/rendering/renderablesatellites.h index e052683cfc..8f58d936d8 100644 --- a/modules/space/rendering/renderablesatellites.h +++ b/modules/space/rendering/renderablesatellites.h @@ -94,10 +94,6 @@ private: /// trail. std::vector _vertexBufferData; - /// The index array that is potentially used in the draw call. If this is empty, no - /// element draw call is used. - std::vector _indexBufferData; - GLuint _vertexArray; GLuint _vertexBuffer; GLuint _indexBuffer; @@ -113,8 +109,6 @@ private: properties::StringProperty _path; properties::UIntProperty _nSegments; - properties::DoubleProperty _lineFade; - RenderableTrail::Appearance _appearance; glm::vec3 _position; diff --git a/modules/space/rendering/simplespheregeometry.cpp b/modules/space/rendering/simplespheregeometry.cpp index 347752cc3c..4b8fcdd514 100644 --- a/modules/space/rendering/simplespheregeometry.cpp +++ b/modules/space/rendering/simplespheregeometry.cpp @@ -25,9 +25,9 @@ #include #include -#include #include -#include +#include +#include namespace { constexpr openspace::properties::Property::PropertyInfo RadiusInfo = { @@ -124,7 +124,7 @@ void SimpleSphereGeometry::createSphere() { const glm::vec3 radius = _radius.value(); delete _sphere; - _sphere = new PowerScaledSphere(radius, _segments); + _sphere = new Sphere(radius, _segments); _sphere->initialize(); } diff --git a/modules/space/rendering/simplespheregeometry.h b/modules/space/rendering/simplespheregeometry.h index 8148ec052e..abed585ab9 100644 --- a/modules/space/rendering/simplespheregeometry.h +++ b/modules/space/rendering/simplespheregeometry.h @@ -32,7 +32,7 @@ namespace openspace { class Renderable; - class PowerScaledSphere; + class Sphere; } // namespace openspace namespace openspace::documentation { struct Documentation; } @@ -57,7 +57,7 @@ private: properties::Vec3Property _radius; properties::IntProperty _segments; - PowerScaledSphere* _sphere; + Sphere* _sphere; }; } // namespace openspace::planetgeometry diff --git a/modules/space/shaders/debrisViz_fs.glsl b/modules/space/shaders/debrisViz_fs.glsl index ada17beb95..e54886d99a 100644 --- a/modules/space/shaders/debrisViz_fs.glsl +++ b/modules/space/shaders/debrisViz_fs.glsl @@ -63,15 +63,25 @@ Fragment getFragment() { vertexDistance_f += 1.0; } - float invert = 1.0 - vertexDistance_f; - float fade = clamp(invert * lineFade, 0.0, 1.0); + float invert = pow((1.0 - vertexDistance_f), lineFade); + float fade = clamp(invert, 0.0, 1.0); + // Currently even fully transparent lines can occlude other lines, thus we discard + // these fragments since debris and satellites are rendered so close to each other + if (fade < 0.05) { + discard; + } Fragment frag; + + // Use additive blending for some values to make the discarding less abrupt + if (fade < 0.15) { + frag.blend = BLEND_MODE_ADDITIVE; + } + frag.color = vec4(color, fade * opacity); frag.depth = vs_position_w; frag.gPosition = viewSpacePosition; frag.gNormal = vec4(1, 1, 1, 0); - // frag.blend = BLEND_MODE_ADDITIVE; // to debug using colors use this if-statment. diff --git a/modules/space/shaders/star_ge.glsl b/modules/space/shaders/star_ge.glsl index dcb36a5711..80ba2dd4f1 100644 --- a/modules/space/shaders/star_ge.glsl +++ b/modules/space/shaders/star_ge.glsl @@ -82,14 +82,6 @@ void main() { vs_position = gl_in[0].gl_Position; // in object space dvec4 dpos = modelMatrix * dvec4(vs_position); - dvec4 clipTestPos = cameraViewProjectionMatrix * dpos; - clipTestPos /= clipTestPos.w; - if ((clipTestPos.x < -1.0 || clipTestPos.x > 1.0) || - (clipTestPos.y < -1.0 || clipTestPos.y > 1.0)) - { - return; - } - ge_bvLumAbsMagAppMag = vs_bvLumAbsMagAppMag[0]; ge_velocity = vs_velocity[0]; ge_speed = vs_speed[0]; @@ -156,96 +148,43 @@ void main() { dvec3 scaledUp = dvec3(0.0); vec4 bottomLeftVertex, bottomRightVertex, topLeftVertex, topRightVertex; - // if (distanceToStarInParsecs > 1800.0) { - // scaledRight = scaleMultiply * invariantRight * 0.5f; - // scaledUp = scaleMultiply * invariantUp * 0.5f; - // } else { - dvec3 normal = normalize(eyePosition - dpos.xyz); - dvec3 newRight = normalize(cross(cameraUp, normal)); - dvec3 newUp = cross(normal, newRight); - scaledRight = scaleMultiply * newRight; - scaledUp = scaleMultiply * newUp; - //} - + dvec3 normal = normalize(eyePosition - dpos.xyz); + dvec3 newRight = normalize(cross(cameraUp, normal)); + dvec3 newUp = cross(normal, newRight); + scaledRight = scaleMultiply * newRight; + scaledUp = scaleMultiply * newUp; + bottomLeftVertex = z_normalization(vec4(cameraViewProjectionMatrix * dvec4(dpos.xyz - scaledRight - scaledUp, dpos.w))); gs_screenSpaceDepth = bottomLeftVertex.w; - topRightVertex = z_normalization(vec4(cameraViewProjectionMatrix * - dvec4(dpos.xyz + scaledUp + scaledRight, dpos.w))); + topRightVertex = z_normalization(vec4(cameraViewProjectionMatrix * + dvec4(dpos.xyz + scaledUp + scaledRight, dpos.w))); - // Testing size: - // vec3 tmpPos = vec3(eyePositionDelta); - // vec4 falseBottomLeftVertex = z_normalization(vec4(cameraViewProjectionMatrix * - // dvec4(tmpPos - scaledRight - scaledUp, dpos.w))); + bottomRightVertex = z_normalization(vec4(cameraViewProjectionMatrix * + dvec4(dpos.xyz + scaledRight - scaledUp, dpos.w))); - // vec4 falseTopRightVertex = z_normalization(vec4(cameraViewProjectionMatrix * - // dvec4(tmpPos + scaledUp + scaledRight, dpos.w))); - // vec2 halfViewSize = vec2(screenSize.x, screenSize.y) * 0.5f; - // vec2 topRight = falseTopRightVertex.xy/falseTopRightVertex.w; - // vec2 bottomLeft = falseBottomLeftVertex.xy/falseBottomLeftVertex.w; - - // Complete algebra - // topRight = ((topRight + vec2(1.0)) * halfViewSize) - vec2(0.5); - // bottomLeft = ((bottomLeft + vec2(1.0)) * halfViewSize) - vec2(0.5); - //vec2 sizes = abs(topRight - bottomLeft); - - // Optimized version - // vec2 sizes = abs(halfViewSize * (topRight - bottomLeft)); - - // float height = sizes.y; - // float width = sizes.x; - - // if ((height > billboardSize) || - // (width > billboardSize)) { - // float correctionScale = height > billboardSize ? billboardSize / height : - // billboardSize / width; - - // scaledRight *= correctionScale; - // scaledUp *= correctionScale; - // bottomLeftVertex = z_normalization(vec4(cameraViewProjectionMatrix * - // dvec4(dpos.xyz - scaledRight - scaledUp, dpos.w))); - // gs_screenSpaceDepth = bottomLeftVertex.w; - // topRightVertex = z_normalization(vec4(cameraViewProjectionMatrix * - // dvec4(dpos.xyz + scaledUp + scaledRight, dpos.w))); - - - // bottomRightVertex = z_normalization(vec4(cameraViewProjectionMatrix * - // dvec4(dpos.xyz + scaledRight - scaledUp, dpos.w))); - - // topLeftVertex = z_normalization(vec4(cameraViewProjectionMatrix * - // dvec4(dpos.xyz + scaledUp - scaledRight, dpos.w))); - - // } else { - // if (width < 2.0f) { - // float maxVar = 2.0f; - // float minVar = 1.0f; - // float var = (height + width); - // float ta = ( (var - minVar)/(maxVar - minVar) ); - // if (ta == 0.0f) - // return; - // } - // float minSize = 30.f; - // if ((width < minSize) || (height < minSize)) - // return; - bottomRightVertex = z_normalization(vec4(cameraViewProjectionMatrix * - dvec4(dpos.xyz + scaledRight - scaledUp, dpos.w))); - topLeftVertex = z_normalization(vec4(cameraViewProjectionMatrix * + topLeftVertex = z_normalization(vec4(cameraViewProjectionMatrix * dvec4(dpos.xyz + scaledUp - scaledRight, dpos.w))); - // } - + // Build primitive - gl_Position = topLeftVertex; - psfCoords = vec2(-1.0, 1.0); - EmitVertex(); + gl_Position = bottomLeftVertex; psfCoords = vec2(-1.0, -1.0); EmitVertex(); - gl_Position = topRightVertex; - psfCoords = vec2(1.0, 1.0); - EmitVertex(); + gl_Position = bottomRightVertex; psfCoords = vec2(1.0, -1.0); EmitVertex(); + + gl_Position = topLeftVertex; + psfCoords = vec2(-1.0, 1.0); + EmitVertex(); + + gl_Position = topRightVertex; + psfCoords = vec2(1.0, 1.0); + EmitVertex(); + EndPrimitive(); + } diff --git a/modules/spacecraftinstruments/rendering/renderablefov.cpp b/modules/spacecraftinstruments/rendering/renderablefov.cpp index ab4e0696e9..d4396b270e 100644 --- a/modules/spacecraftinstruments/rendering/renderablefov.cpp +++ b/modules/spacecraftinstruments/rendering/renderablefov.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -151,7 +152,6 @@ namespace { return 0.5 * bisect(p1, half, testFunction, half); } } - } // namespace namespace openspace { @@ -294,7 +294,10 @@ RenderableFov::RenderableFov(const ghoul::Dictionary& dictionary) if (dictionary.hasKey(KeyFrameConversions)) { ghoul::Dictionary fc = dictionary.value(KeyFrameConversions); for (const std::string& key : fc.keys()) { - openspace::SpiceManager::ref().addFrame(key, fc.value(key)); + global::moduleEngine.module()->addFrame( + key, + fc.value(key) + ); } } @@ -524,7 +527,12 @@ void RenderableFov::computeIntercepts(const UpdateData& data, const std::string& { const bool convert = (ref.find("IAU_") == std::string::npos); if (convert) { - return { SpiceManager::ref().frameFromBody(target), true }; + return { + global::moduleEngine.module()->frameFromBody( + target + ), + true + }; } else { return { ref, false }; @@ -917,6 +925,7 @@ std::pair RenderableFov::determineTarget(double time) { bool inFOV = SpiceManager::ref().isTargetInFieldOfView( pt, _instrument.spacecraft, + global::moduleEngine.module()->frameFromBody(pt), _instrument.name, SpiceManager::FieldOfViewMethod::Ellipsoid, _instrument.aberrationCorrection, diff --git a/modules/spacecraftinstruments/rendering/renderablemodelprojection.cpp b/modules/spacecraftinstruments/rendering/renderablemodelprojection.cpp index 8dba28ee8d..556c946e1f 100644 --- a/modules/spacecraftinstruments/rendering/renderablemodelprojection.cpp +++ b/modules/spacecraftinstruments/rendering/renderablemodelprojection.cpp @@ -461,11 +461,7 @@ void RenderableModelProjection::attitudeParameters(double time) { lightTime ); - // @TODO: Remove this and replace with cpos = p * 1000 ? - psc position = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z); - - position[3] += 4; - const glm::vec3 cpos = position.vec3(); + const glm::vec3 cpos = p * 10000.0; const float distance = glm::length(cpos); const float radius = boundingSphere(); diff --git a/modules/spacecraftinstruments/rendering/renderableplaneprojection.cpp b/modules/spacecraftinstruments/rendering/renderableplaneprojection.cpp index 48508ce2f8..64b7864e70 100644 --- a/modules/spacecraftinstruments/rendering/renderableplaneprojection.cpp +++ b/modules/spacecraftinstruments/rendering/renderableplaneprojection.cpp @@ -24,8 +24,10 @@ #include +#include #include #include +#include #include #include #include @@ -227,8 +229,7 @@ void RenderablePlaneProjection::updatePlane(const Image& img, double currentTime ); // The apparent position, CN+S, makes image align best with target - // @TODO: Remove these powerscaled coordinates - psc projection[4]; + glm::dvec3 projection[4]; for (size_t j = 0; j < bounds.size(); ++j) { bounds[j] = SpiceManager::ref().frameTransformationMatrix( frame, @@ -246,12 +247,8 @@ void RenderablePlaneProjection::updatePlane(const Image& img, double currentTime currentTime ) * cornerPosition; - projection[j] = PowerScaledCoordinate::CreatePowerScaledCoordinate( - cornerPosition[0], - cornerPosition[1], - cornerPosition[2] - ); - projection[j][3] += 3; + // km -> m + projection[j] = cornerPosition * 1000.0; } if (!_moving) { @@ -264,21 +261,28 @@ void RenderablePlaneProjection::updatePlane(const Image& img, double currentTime } } + glm::vec3 p[4] = { + glm::vec3(projection[0]), + glm::vec3(projection[1]), + glm::vec3(projection[2]), + glm::vec3(projection[3]) + + }; const GLfloat vertex_data[] = { // square of two triangles drawn within fov in target coordinates // x y z w s t // Lower left 1 - projection[1][0], projection[1][1], projection[1][2], projection[1][3], 0, 0, + p[1].x, p[1].y, p[1].z, 0.f, 0.f, 0.f, // Upper right 2 - projection[3][0], projection[3][1], projection[3][2], projection[3][3], 1, 1, + p[3].x, p[3].y, p[3].z, 0.f, 1.f, 1.f, // Upper left 3 - projection[2][0], projection[2][1], projection[2][2], projection[2][3], 0, 1, + p[2].x, p[2].y, p[2].z, 0.f, 0.f, 1.f, // Lower left 4 = 1 - projection[1][0], projection[1][1], projection[1][2], projection[1][3], 0, 0, + p[1].x, p[1].y, p[1].z, 0.f, 0.f, 0.f, // Lower right 5 - projection[0][0], projection[0][1], projection[0][2], projection[0][3], 1, 0, + p[0].x, p[0].y, p[0].z, 0.f, 1.f, 0.f, // Upper left 6 = 2 - projection[3][0], projection[3][1], projection[3][2], projection[3][3], 1, 1, + p[3].x, p[3].y, p[3].z, 0.f, 1.f, 1.f, }; glBindVertexArray(_quad); @@ -307,7 +311,8 @@ void RenderablePlaneProjection::setTarget(std::string body) { return; } - _target.frame = SpiceManager::ref().frameFromBody(body); + _target.frame = + global::moduleEngine.module()->frameFromBody(body); _target.body = std::move(body); } diff --git a/modules/spacecraftinstruments/spacecraftinstrumentsmodule.cpp b/modules/spacecraftinstruments/spacecraftinstrumentsmodule.cpp index 3e2bf6847a..460418b055 100644 --- a/modules/spacecraftinstruments/spacecraftinstrumentsmodule.cpp +++ b/modules/spacecraftinstruments/spacecraftinstrumentsmodule.cpp @@ -94,4 +94,31 @@ SpacecraftInstrumentsModule::documentations() const }; } +bool SpacecraftInstrumentsModule::addFrame(std::string body, std::string frame) { + if (body.empty() || frame.empty()) { + return false; + } + else { + _frameByBody.emplace_back(body, frame); + return true; + } +} + +std::string SpacecraftInstrumentsModule::frameFromBody(const std::string& body) { + for (const std::pair& pair : _frameByBody) { + if (pair.first == body) { + return pair.second; + } + } + + constexpr const char* unionPrefix = "IAU_"; + + if (body.find(unionPrefix) == std::string::npos) { + return unionPrefix + body; + } + else { + return body; + } +} + } // namespace openspace diff --git a/modules/spacecraftinstruments/spacecraftinstrumentsmodule.h b/modules/spacecraftinstruments/spacecraftinstrumentsmodule.h index d05fefe8c5..fc37bd53bb 100644 --- a/modules/spacecraftinstruments/spacecraftinstrumentsmodule.h +++ b/modules/spacecraftinstruments/spacecraftinstrumentsmodule.h @@ -41,10 +41,16 @@ public: static ghoul::opengl::ProgramObjectManager ProgramObjectManager; + bool addFrame(std::string body, std::string frame); + std::string frameFromBody(const std::string& body); + protected: void internalInitialize(const ghoul::Dictionary&) override; void internalDeinitialize() override; void internalDeinitializeGL() override; + +private: + std::vector> _frameByBody; }; } // namespace openspace diff --git a/modules/spout/renderableplanespout.cpp b/modules/spout/renderableplanespout.cpp index f3c2eb2dac..c398898adc 100644 --- a/modules/spout/renderableplanespout.cpp +++ b/modules/spout/renderableplanespout.cpp @@ -101,17 +101,17 @@ RenderablePlaneSpout::RenderablePlaneSpout(const ghoul::Dictionary& dictionary) iIdentifier = id; if (iIdentifier == 0) { - setIdentifier("ScreenSpaceSpout"); + setIdentifier("RenderablePlaneSpout"); } else { - setIdentifier("ScreenSpaceSpout" + std::to_string(iIdentifier)); + setIdentifier("RenderablePlaneSpout" + std::to_string(iIdentifier)); } ++id; } if (_guiName.empty()) { // Adding an extra space to the user-facing name as it looks nicer - setGuiName("ScreenSpaceSpout " + std::to_string(iIdentifier)); + setGuiName("RenderablePlaneSpout " + std::to_string(iIdentifier)); } if (dictionary.hasKey(NameInfo.identifier)) { diff --git a/modules/spout/screenspacespout.cpp b/modules/spout/screenspacespout.cpp index 5d8f23f430..b3204f0135 100644 --- a/modules/spout/screenspacespout.cpp +++ b/modules/spout/screenspacespout.cpp @@ -93,24 +93,15 @@ ScreenSpaceSpout::ScreenSpaceSpout(const ghoul::Dictionary& dictionary) "ScreenSpaceSpout" ); - int iIdentifier = 0; - if (_identifier.empty()) { - static int id = 0; - iIdentifier = id; - - if (iIdentifier == 0) { - setIdentifier("ScreenSpaceSpout"); - } - else { - setIdentifier("ScreenSpaceSpout" + std::to_string(iIdentifier)); - } - ++id; + std::string identifier; + if (dictionary.hasKeyAndValue(KeyIdentifier)) { + identifier = dictionary.value(KeyIdentifier); } - - if (_guiName.empty()) { - // Adding an extra space to the user-facing name as it looks nicer - setGuiName("ScreenSpaceSpout " + std::to_string(iIdentifier)); + else { + identifier = "ScreenSpaceSpout"; } + identifier = makeUniqueIdentifier(identifier); + setIdentifier(std::move(identifier)); if (dictionary.hasKey(NameInfo.identifier)) { _spoutName = dictionary.value(NameInfo.identifier); diff --git a/modules/touch/CMakeLists.txt b/modules/touch/CMakeLists.txt index 07190880d5..d0b7ec5289 100644 --- a/modules/touch/CMakeLists.txt +++ b/modules/touch/CMakeLists.txt @@ -26,6 +26,7 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/ext/levmarq.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/directinputsolver.h ${CMAKE_CURRENT_SOURCE_DIR}/include/tuioear.h ${CMAKE_CURRENT_SOURCE_DIR}/include/touchinteraction.h ${CMAKE_CURRENT_SOURCE_DIR}/include/touchmarker.h @@ -35,6 +36,7 @@ source_group("Header Files" FILES ${HEADER_FILES}) set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/ext/levmarq.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/directinputsolver.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/tuioear.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/touchinteraction.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/touchmarker.cpp diff --git a/modules/touch/include/directinputsolver.h b/modules/touch/include/directinputsolver.h new file mode 100644 index 0000000000..50f5cbeceb --- /dev/null +++ b/modules/touch/include/directinputsolver.h @@ -0,0 +1,65 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2019 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_TOUCH___DIRECTINPUT_SOLVER___H__ +#define __OPENSPACE_MODULE_TOUCH___DIRECTINPUT_SOLVER___H__ + +#include +#include +#include + + +namespace openspace { + +class Camera; +class SceneGraphNode; + +class DirectInputSolver { +public: + // Stores the selected node, the cursor ID as well as the surface coordinates the + // cursor touched + struct SelectedBody { + long id; + SceneGraphNode* node; + glm::dvec3 coordinates; + }; + + DirectInputSolver(); + bool solve(const std::vector& list, + const std::vector& selectedBodies, + std::vector* calculatedValues, const Camera& camera); + int getNDof() const; + + const LMstat& getLevMarqStat(); + void setLevMarqVerbosity(bool verbose); + +private: + int _nDof = 0; + LMstat _lmstat; +}; + +} // openspace namespace + +#endif // __OPENSPACE_MODULE_TOUCH___DIRECTINPUT_SOLVER___H__ + diff --git a/modules/touch/include/touchinteraction.h b/modules/touch/include/touchinteraction.h index f8de436b4b..7158973b70 100644 --- a/modules/touch/include/touchinteraction.h +++ b/modules/touch/include/touchinteraction.h @@ -27,7 +27,7 @@ #include -#include +#include #include #include @@ -38,6 +38,8 @@ #include #include +#include + //#define TOUCH_DEBUG_PROPERTIES //#define TOUCH_DEBUG_NODE_PICK_MESSAGES @@ -79,27 +81,6 @@ public: glm::dvec2 pan; }; - // Stores the selected node, the cursor ID as well as the surface coordinates the - // cursor touched - struct SelectedBody { - long id; - SceneGraphNode* node; - glm::dvec3 coordinates; - }; - - // Used in the LM algorithm - struct FunctionData { - std::vector selectedPoints; - std::vector screenPoints; - int nDOF; - glm::dvec2(*castToNDC)(const glm::dvec3&, Camera&, SceneGraphNode*); - double(*distToMinimize)(double* par, int x, void* fdata, LMstat* lmstat); - Camera* camera; - SceneGraphNode* node; - LMstat stats; - double objectScreenRadius; - }; - /* Main function call * 1 Checks if doubleTap occured * 2 Goes through the guiMode() function @@ -256,9 +237,10 @@ private: bool _zoomOutTap; bool _lmSuccess; bool _guiON; - std::vector _selected; + std::vector _selected; SceneGraphNode* _pickingSelected = nullptr; - LMstat _lmstat; + DirectInputSolver _solver; + glm::dquat _toSlerp; glm::dvec3 _centroid; diff --git a/modules/touch/src/directinputsolver.cpp b/modules/touch/src/directinputsolver.cpp new file mode 100644 index 0000000000..6ceed7dac4 --- /dev/null +++ b/modules/touch/src/directinputsolver.cpp @@ -0,0 +1,281 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2019 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include + +namespace { + // Used in the LM algorithm + struct FunctionData { + std::vector selectedPoints; + std::vector screenPoints; + int nDOF; + const openspace::Camera* camera; + openspace::SceneGraphNode* node; + LMstat stats; + }; +} + +namespace openspace { + +DirectInputSolver::DirectInputSolver() { + levmarq_init(&_lmstat); +} + +// project back a 3D point in model view to clip space [-1,1] coordinates on the view plane +glm::dvec2 castToNDC(const glm::dvec3& vec, Camera& camera, SceneGraphNode* node) { + glm::dvec3 posInCamSpace = glm::inverse(camera.rotationQuaternion()) * + (node->worldRotationMatrix() * vec + + (node->worldPosition() - camera.positionVec3())); + + glm::dvec4 clipspace = camera.projectionMatrix() * glm::dvec4(posInCamSpace, 1.0); + return (glm::dvec2(clipspace) / clipspace.w); +} + +// Returns the screen point s(xi,par) dependent the transform M(par) and object point xi +double distToMinimize(double* par, int x, void* fdata, LMstat* lmstat) { + FunctionData* ptr = reinterpret_cast(fdata); + + // Apply transform to camera and find the new screen point of the updated camera state + + // { vec2 globalRot, zoom, roll, vec2 localRot } + double q[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + for (int i = 0; i < ptr->nDOF; ++i) { + q[i] = par[i]; + } + + using namespace glm; + // Create variables from current state + dvec3 camPos = ptr->camera->positionVec3(); + dvec3 centerPos = ptr->node->worldPosition(); + + dvec3 directionToCenter = normalize(centerPos - camPos); + dvec3 lookUp = ptr->camera->lookUpVectorWorldSpace(); + dvec3 camDirection = ptr->camera->viewDirectionWorldSpace(); + + // Make a representation of the rotation quaternion with local and global + // rotations + dmat4 lookAtMat = lookAt( + dvec3(0, 0, 0), + directionToCenter, + // To avoid problem with lookup in up direction + normalize(camDirection + lookUp)); + dquat globalCamRot = normalize(quat_cast(inverse(lookAtMat))); + dquat localCamRot = inverse(globalCamRot) * ptr->camera->rotationQuaternion(); + + { // Roll + dquat rollRot = angleAxis(q[3], dvec3(0.0, 0.0, 1.0)); + localCamRot = localCamRot * rollRot; + } + { // Panning (local rotation) + dvec3 eulerAngles(q[5], q[4], 0); + dquat panRot = dquat(eulerAngles); + localCamRot = localCamRot * panRot; + } + { // Orbit (global rotation) + dvec3 eulerAngles(q[1], q[0], 0); + dquat rotationDiffCamSpace = dquat(eulerAngles); + + dvec3 centerToCamera = camPos - centerPos; + + dquat rotationDiffWorldSpace = + globalCamRot * rotationDiffCamSpace * inverse(globalCamRot); + dvec3 rotationDiffVec3 = centerToCamera * rotationDiffWorldSpace - centerToCamera; + camPos += rotationDiffVec3; + + centerToCamera = camPos - centerPos; + directionToCenter = normalize(-centerToCamera); + dvec3 lookUpWhenFacingCenter = + globalCamRot * dvec3(ptr->camera->lookUpVectorCameraSpace()); + lookAtMat = lookAt( + dvec3(0, 0, 0), + directionToCenter, + lookUpWhenFacingCenter + ); + globalCamRot = normalize(quat_cast(inverse(lookAtMat))); + } + { // Zooming + camPos += directionToCenter * q[2]; + } + // Update the camera state + Camera cam = *(ptr->camera); + cam.setPositionVec3(camPos); + cam.setRotation(globalCamRot * localCamRot); + + // we now have a new position and orientation of camera, project surfacePoint to + // the new screen to get distance to minimize + glm::dvec2 newScreenPoint = castToNDC( + ptr->selectedPoints.at(x), + cam, + ptr->node + ); + lmstat->pos.push_back(newScreenPoint); + return glm::length(ptr->screenPoints.at(x) - newScreenPoint); +} + +// Gradient of distToMinimize w.r.t par (using forward difference) +void gradient(double* g, double* par, int x, void* fdata, LMstat* lmstat) { + FunctionData* ptr = reinterpret_cast(fdata); + double f0 = distToMinimize(par, x, fdata, lmstat); + // scale value to find minimum step size h, dependant on planet size + double scale = log10(ptr->node->boundingSphere()); + std::vector dPar(ptr->nDOF, 0.0); + dPar.assign(par, par + ptr->nDOF); + + for (int i = 0; i < ptr->nDOF; ++i) { + // Initial values + double h = 1e-8; + double lastG = 1; + dPar.at(i) += h; + double f1 = distToMinimize(dPar.data(), x, fdata, lmstat); + dPar.at(i) = par[i]; + // Iterative process to find the minimum step h that gives a good gradient + for (int j = 0; j < 100; ++j) { + if ((f1 - f0) != 0 && lastG == 0) { // found minimum step size h + // scale up to get a good initial guess value + h *= scale * scale * scale; + + // clamp min step size to a fraction of the incoming parameter + if (i == 2) { + double epsilon = 1e-3; + // make sure incoming parameter is larger than 0 + h = std::max(std::max(std::abs(dPar.at(i)), epsilon) * 0.001, h); + } + else if (ptr->nDOF == 2) { + h = std::max(std::abs(dPar.at(i)) * 0.001, h); + } + + // calculate f1 with good h for finite difference + dPar.at(i) += h; + f1 = distToMinimize(dPar.data(), x, fdata, lmstat); + dPar.at(i) = par[i]; + break; + } + else if ((f1 - f0) != 0 && lastG != 0) { // h too big + h /= scale; + } + else if ((f1 - f0) == 0) { // h too small + h *= scale; + } + lastG = f1 - f0; + dPar.at(i) += h; + f1 = distToMinimize(dPar.data(), x, fdata, lmstat); + dPar.at(i) = par[i]; + } + g[i] = (f1 - f0) / h; + } + if (ptr->nDOF == 2) { + // normalize on 1 finger case to allow for horizontal/vertical movement + for (int i = 0; i < 2; ++i) { + g[i] = g[i] / std::abs(g[i]); + } + } + else if (ptr->nDOF == 6) { + for (int i = 0; i < ptr->nDOF; ++i) { + // lock to only pan and zoom on 3 finger case, no roll/orbit + g[i] = (i == 2) ? g[i] : g[i] / std::abs(g[i]); + } + } +} + +bool DirectInputSolver::solve(const std::vector& list, + const std::vector& selectedBodies, + std::vector* parameters, const Camera& camera) +{ + int nFingers = std::min(static_cast(list.size()), 3); + _nDof = std::min(nFingers * 2, 6); + + // Parse input data to be used in the LM algorithm + std::vector selectedPoints; + std::vector screenPoints; + + for (int i = 0; i < nFingers; ++i) { + const SelectedBody& sb = selectedBodies.at(i); + selectedPoints.push_back(sb.coordinates); + screenPoints.emplace_back( + 2 * (list[i].getX() - 0.5), + -2 * (list[i].getY() - 0.5) + ); + + // This might be needed when we're directing the touchtable from another screen? + // std::vector::const_iterator c = std::find_if( + // list.begin(), + // list.end(), + // [&sb](const TuioCursor& c) { return c.getSessionID() == sb.id; } + // ); + // if (c != list.end()) { + // // normalized -1 to 1 coordinates on screen + // screenPoints.emplace_back(2 * (c->getX() - 0.5), -2 * (c->getY() - 0.5)); + // } + // else { + // global::moduleEngine.module()->touchInput = { + // true, + // glm::dvec2(0.0, 0.0), + // 1 + // }; + // resetAfterInput(); + // return; + // } + } + + FunctionData fData = { + selectedPoints, + screenPoints, + _nDof, + &camera, + selectedBodies.at(0).node, + _lmstat + }; + void* dataPtr = reinterpret_cast(&fData); + + bool result = levmarq( + _nDof, + parameters->data(), + static_cast(screenPoints.size()), + nullptr, + distToMinimize, + gradient, + dataPtr, + &_lmstat + ); + + return result; +} + +int DirectInputSolver::getNDof() const { + return _nDof; +} + +const LMstat& DirectInputSolver::getLevMarqStat() { + return _lmstat; +} + +void DirectInputSolver::setLevMarqVerbosity(bool verbose) { + _lmstat.verbose = verbose; +} + +} // openspace namespace + diff --git a/modules/touch/src/touchinteraction.cpp b/modules/touch/src/touchinteraction.cpp index 1653b13248..eab3fa0185 100644 --- a/modules/touch/src/touchinteraction.cpp +++ b/modules/touch/src/touchinteraction.cpp @@ -23,7 +23,9 @@ ****************************************************************************************/ #include + #include +#include #include #include @@ -369,11 +371,8 @@ TouchInteraction::TouchInteraction() } }); - levmarq_init(&_lmstat); - _time.initSession(); } - // Called each frame if there is any input void TouchInteraction::updateStateFromInput(const std::vector& list, std::vector& lastProcessed) @@ -513,231 +512,21 @@ void TouchInteraction::directControl(const std::vector& list) { #ifdef TOUCH_DEBUG_PROPERTIES LINFO("DirectControl"); #endif - // Returns the screen point s(xi,par) dependent the transform M(par) and object - // point xi - auto distToMinimize = [](double* par, int x, void* fdata, LMstat* lmstat) { - FunctionData* ptr = reinterpret_cast(fdata); - - // Apply transform to camera and find the new screen point of the updated camera - // state - - // { vec2 globalRot, zoom, roll, vec2 localRot } - double q[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; - for (int i = 0; i < ptr->nDOF; ++i) { - q[i] = par[i]; - } - - using namespace glm; - // Create variables from current state - dvec3 camPos = ptr->camera->positionVec3(); - dvec3 centerPos = ptr->node->worldPosition(); - - dvec3 directionToCenter = normalize(centerPos - camPos); - dvec3 lookUp = ptr->camera->lookUpVectorWorldSpace(); - dvec3 camDirection = ptr->camera->viewDirectionWorldSpace(); - - // Make a representation of the rotation quaternion with local and global - // rotations - dmat4 lookAtMat = lookAt( - dvec3(0, 0, 0), - directionToCenter, - // To avoid problem with lookup in up direction - normalize(camDirection + lookUp)); - dquat globalCamRot = normalize(quat_cast(inverse(lookAtMat))); - dquat localCamRot = inverse(globalCamRot) * ptr->camera->rotationQuaternion(); - - { // Roll - dquat rollRot = angleAxis(q[3], dvec3(0.0, 0.0, 1.0)); - localCamRot = localCamRot * rollRot; - } - { // Panning (local rotation) - dvec3 eulerAngles(q[5], q[4], 0); - dquat panRot = dquat(eulerAngles); - localCamRot = localCamRot * panRot; - } - { // Orbit (global rotation) - dvec3 eulerAngles(q[1], q[0], 0); - dquat rotationDiffCamSpace = dquat(eulerAngles); - - dvec3 centerToCamera = camPos - centerPos; - - dquat rotationDiffWorldSpace = - globalCamRot * rotationDiffCamSpace * inverse(globalCamRot); - dvec3 rotationDiffVec3 = - centerToCamera * rotationDiffWorldSpace - centerToCamera; - camPos += rotationDiffVec3; - - centerToCamera = camPos - centerPos; - directionToCenter = normalize(-centerToCamera); - dvec3 lookUpWhenFacingCenter = - globalCamRot * dvec3(ptr->camera->lookUpVectorCameraSpace()); - lookAtMat = lookAt( - dvec3(0, 0, 0), - directionToCenter, - lookUpWhenFacingCenter); - globalCamRot = normalize(quat_cast(inverse(lookAtMat))); - } - { // Zooming - camPos += directionToCenter * q[2]; - } - // Update the camera state - Camera cam = *(ptr->camera); - cam.setPositionVec3(camPos); - cam.setRotation(globalCamRot * localCamRot); - - // we now have a new position and orientation of camera, project surfacePoint to - // the new screen to get distance to minimize - glm::dvec2 newScreenPoint = ptr->castToNDC( - ptr->selectedPoints.at(x), - cam, - ptr->node - ); - lmstat->pos.push_back(newScreenPoint); - return glm::length(ptr->screenPoints.at(x) - newScreenPoint); - }; - // Gradient of distToMinimize w.r.t par (using forward difference) - auto gradient = [](double* g, double* par, int x, void* fdata, LMstat* lmstat) { - FunctionData* ptr = reinterpret_cast(fdata); - double h, lastG, f1, f0 = ptr->distToMinimize(par, x, fdata, lmstat); - // scale value to find minimum step size h, dependant on planet size - double scale = log10(ptr->node->boundingSphere()); - std::vector dPar(ptr->nDOF, 0.0); - dPar.assign(par, par + ptr->nDOF); - - for (int i = 0; i < ptr->nDOF; ++i) { - // Initial values - h = 1e-8; - lastG = 1; - dPar.at(i) += h; - f1 = ptr->distToMinimize(dPar.data(), x, fdata, lmstat); - dPar.at(i) = par[i]; - // Iterative process to find the minimum step h that gives a good gradient - for (int j = 0; j < 100; ++j) { - if ((f1 - f0) != 0 && lastG == 0) { // found minimum step size h - // scale up to get a good initial guess value - h *= scale * scale * scale; - - // clamp min step size to a fraction of the incoming parameter - if (i == 2) { - double epsilon = 1e-3; - // make sure incoming parameter is larger than 0 - h = std::max(std::max(std::abs(dPar.at(i)), epsilon) * 0.001, h); - } - else if (ptr->nDOF == 2) { - h = std::max(std::abs(dPar.at(i)) * 0.001, h); - } - - // calculate f1 with good h for finite difference - dPar.at(i) += h; - f1 = ptr->distToMinimize(dPar.data(), x, fdata, lmstat); - dPar.at(i) = par[i]; - break; - } - else if ((f1 - f0) != 0 && lastG != 0) { // h too big - h /= scale; - } - else if ((f1 - f0) == 0) { // h too small - h *= scale; - } - lastG = f1 - f0; - dPar.at(i) += h; - f1 = ptr->distToMinimize(dPar.data(), x, fdata, lmstat); - dPar.at(i) = par[i]; - } - g[i] = (f1 - f0) / h; - } - if (ptr->nDOF == 2) { - // normalize on 1 finger case to allow for horizontal/vertical movement - for (int i = 0; i < 2; ++i) { - g[i] = g[i]/std::abs(g[i]); - } - } - else if (ptr->nDOF == 6) { - for (int i = 0; i < ptr->nDOF; ++i) { - // lock to only pan and zoom on 3 finger case, no roll/orbit - g[i] = (i == 2) ? g[i] : g[i] / std::abs(g[i]); - } - } - }; - - // project back a 3D point in model view to clip space [-1,1] coordinates on the view - // plane - auto castToNDC = [](const glm::dvec3& vec, Camera& camera, SceneGraphNode* node) { - glm::dvec3 posInCamSpace = glm::inverse(camera.rotationQuaternion()) * - (node->rotationMatrix() * vec + - (node->worldPosition() - camera.positionVec3())); - - glm::dvec4 clipspace = camera.projectionMatrix() * glm::dvec4(posInCamSpace, 1.0); - return (glm::dvec2(clipspace) / clipspace.w); - }; - - // only send in first three fingers (to make it easier for LMA to converge on 3+ - // finger case with only zoom/pan) - int nFingers = std::min(static_cast(list.size()), 3); - int nDOF = std::min(nFingers * 2, 6); - std::vector par(nDOF, 0.0); - par.at(0) = _lastVel.orbit.x; // use _lastVel for orbit - par.at(1) = _lastVel.orbit.y; - - // Parse input data to be used in the LM algorithm - std::vector selectedPoints; - std::vector screenPoints; - for (int i = 0; i < nFingers; ++i) { - const SelectedBody& sb = _selected.at(i); - selectedPoints.push_back(sb.coordinates); - - std::vector::const_iterator c = std::find_if( - list.begin(), - list.end(), - [&sb](const TuioCursor& c) { return c.getSessionID() == sb.id; } - ); - if (c != list.end()) { - // normalized -1 to 1 coordinates on screen - screenPoints.emplace_back(2 * (c->getX() - 0.5), -2 * (c->getY() - 0.5)); - } - else { - global::moduleEngine.module()->touchInput = { - true, - glm::dvec2(0.0, 0.0), - 1 - }; - resetAfterInput(); - return; - } - } - - FunctionData fData = { - selectedPoints, - screenPoints, - nDOF, - castToNDC, - distToMinimize, - _camera, - _selected.at(0).node, - _lmstat, - _currentRadius - }; - void* dataPtr = reinterpret_cast(&fData); // finds best transform values for the new camera state and stores them in par - _lmSuccess = levmarq( - nDOF, - par.data(), - static_cast(screenPoints.size()), - nullptr, - distToMinimize, - gradient, - dataPtr, - &_lmstat - ); + std::vector par(6, 0.0); + par.at(0) = _lastVel.orbit.x; // use _lastVel for orbit + par.at(1) = _lastVel.orbit.y; + _lmSuccess = _solver.solve(list, _selected, &par, *_camera); + int nDof = _solver.getNDof(); if (_lmSuccess && !_unitTest) { // if good values were found set new camera state _vel.orbit = glm::dvec2(par.at(0), par.at(1)); - if (nDOF > 2) { + if (nDof > 2) { _vel.zoom = par.at(2); _vel.roll = par.at(3); - if (_panEnabled && nDOF > 4) { + if (_panEnabled && nDof > 4) { _vel.roll = 0.0; _vel.pan = glm::dvec2(par.at(4), par.at(5)); } @@ -784,20 +573,18 @@ void TouchInteraction::findSelectedNode(const std::vector& list) { glm::dquat camToWorldSpace = _camera->rotationQuaternion(); glm::dvec3 camPos = _camera->positionVec3(); - std::vector newSelected; - - struct PickingInfo { - SceneGraphNode* node; - double pickingDistanceNDC; - double pickingDistanceWorld; + std::vector newSelected; + + //node & distance + std::tuple currentlyPicked = { + nullptr, + std::numeric_limits::max() }; - std::vector pickingInfo; - + for (const TuioCursor& c : list) { double xCo = 2 * (c.getX() - 0.5); double yCo = -2 * (c.getY() - 0.5); // normalized -1 to 1 coordinates on screen - // vec3(projectionmatrix * clipspace), divide with w? glm::dvec3 cursorInWorldSpace = camToWorldSpace * glm::dvec3(glm::inverse(_camera->projectionMatrix()) * glm::dvec4(xCo, yCo, -1.0, 1.0)); @@ -806,28 +593,27 @@ void TouchInteraction::findSelectedNode(const std::vector& list) { long id = c.getSessionID(); for (SceneGraphNode* node : selectableNodes) { - double boundingSphere = node->boundingSphere(); + double boundingSphereSquared = static_cast(node->boundingSphere()) * + static_cast(node->boundingSphere()); glm::dvec3 camToSelectable = node->worldPosition() - camPos; - double dist = length(glm::cross(cursorInWorldSpace, camToSelectable)) / - glm::length(cursorInWorldSpace) - boundingSphere; - if (dist <= 0.0) { - // finds intersection closest point between boundingsphere and line in - // world coordinates, assumes line direction is normalized - double d = glm::dot(raytrace, camToSelectable); - double root = boundingSphere * boundingSphere - - glm::dot(camToSelectable, camToSelectable) + d * d; - if (root > 0) { // two intersection points (take the closest one) - d -= sqrt(root); - } - glm::dvec3 intersectionPoint = camPos + d * raytrace; - glm::dvec3 pointInModelView = glm::inverse(node->rotationMatrix()) * - (intersectionPoint - node->worldPosition()); + double intersectionDist = 0.0; + bool intersected = glm::intersectRaySphere( + camPos, + raytrace, + node->worldPosition(), + boundingSphereSquared, + intersectionDist + ); + if (intersected) { + glm::dvec3 intersectionPos = camPos + raytrace * intersectionDist; + glm::dvec3 pointInModelView = glm::inverse(node->worldRotationMatrix()) * + (intersectionPos - node->worldPosition()); // Add id, node and surface coordinates to the selected list - std::vector::iterator oldNode = std::find_if( + auto oldNode = std::find_if( newSelected.begin(), newSelected.end(), - [id](SelectedBody s) { return s.id == id; } + [id](const DirectInputSolver::SelectedBody& s) { return s.id == id; } ); if (oldNode != newSelected.end()) { double oldNodeDist = glm::length( @@ -859,56 +645,44 @@ void TouchInteraction::findSelectedNode(const std::vector& list) { // We either want to select the object if it's bounding sphere as been // touched (checked by the first part of this loop above) or if the touch // point is within a minimum distance of the center - if (dist <= 0.0 || (ndcDist <= _pickingRadiusMinimum)) { - // If the user touched the planet directly, this is definitely the one - // they are interested in => minimum distance - if (dist <= 0.0) { + // If the user touched the planet directly, this is definitely the one + // they are interested in => minimum distance + if (intersected) { #ifdef TOUCH_DEBUG_NODE_PICK_MESSAGES - LINFOC( - node->identifier(), - "Picking candidate based on direct touch" - ); + LINFOC( + node->identifier(), + "Picking candidate based on direct touch" + ); #endif //#ifdef TOUCH_DEBUG_NODE_PICK_MESSAGES - pickingInfo.push_back({ - node, - -std::numeric_limits::max(), - -std::numeric_limits::max() - }); - } - else { - // The node was considered due to minimum picking distance radius + currentlyPicked = { + node, + -std::numeric_limits::max() + }; + } + else if (ndcDist <= _pickingRadiusMinimum) { + // The node was considered due to minimum picking distance radius #ifdef TOUCH_DEBUG_NODE_PICK_MESSAGES - LINFOC( - node->identifier(), - "Picking candidate based on proximity" - ); + LINFOC( + node->identifier(), + "Picking candidate based on proximity" + ); #endif //#ifdef TOUCH_DEBUG_NODE_PICK_MESSAGES - pickingInfo.push_back({ + double dist = length(camToSelectable); + if (dist < std::get<1>(currentlyPicked)) { + currentlyPicked = { node, - ndcDist, dist - }); + }; } } } } } - - // After we are done with all of the nodes, we can sort the picking list and pick the - // one that fits best (= is closest or was touched directly) - std::sort( - pickingInfo.begin(), - pickingInfo.end(), - [](const PickingInfo& lhs, const PickingInfo& rhs) { - return lhs.pickingDistanceWorld < rhs.pickingDistanceWorld; - } - ); - // If an item has been picked, it's in the first position of the vector now - if (!pickingInfo.empty()) { - _pickingSelected = pickingInfo.begin()->node; + if (SceneGraphNode* node = std::get<0>(currentlyPicked)) { + _pickingSelected = node; #ifdef TOUCH_DEBUG_NODE_PICK_MESSAGES LINFOC("Picking", "Picked node: " + _pickingSelected->identifier()); #endif //#ifdef TOUCH_DEBUG_NODE_PICK_MESSAGES @@ -1360,8 +1134,11 @@ void TouchInteraction::step(double dt) { else if (_zoomInLimit.value() < zoomInBounds) { // If zoom in limit is less than the estimated node radius we need to // make sure we do not get too close to possible height maps - SurfacePositionHandle posHandle = anchor->calculateSurfacePositionHandle(camPos); - glm::dvec3 centerToActualSurfaceModelSpace = posHandle.centerToReferenceSurface + + SurfacePositionHandle posHandle = anchor->calculateSurfacePositionHandle( + camPos + ); + glm::dvec3 centerToActualSurfaceModelSpace = + posHandle.centerToReferenceSurface + posHandle.referenceSurfaceOutDirection * posHandle.heightToSurface; glm::dvec3 centerToActualSurface = glm::dmat3(anchor->modelTransform()) * centerToActualSurfaceModelSpace; @@ -1370,9 +1147,8 @@ void TouchInteraction::step(double dt) { // Because of heightmaps we should make sure we do not go through the surface if (_zoomInLimit.value() < nodeRadius) { #ifdef TOUCH_DEBUG_PROPERTIES - LINFO(fmt::format( - "{}: Zoom In Limit should be larger than anchor center to surface, setting it to {}", - _loggerCat, zoomInBounds)); + LINFO(fmt::format("{}: Zoom In limit should be larger than anchor " + "center to surface, setting it to {}", _loggerCat, zoomInBounds)); #endif _zoomInLimit.setValue(zoomInBounds); } @@ -1392,9 +1168,12 @@ void TouchInteraction::step(double dt) { double currentPosDistance = length(centerToCamera); // Possible with other navigations performed outside touch interaction - bool currentPosViolatingZoomOutLimit = (currentPosDistance >= _zoomOutLimit.value()); - bool willNewPositionViolateZoomOutLimit = (newPosDistance >= _zoomOutLimit.value()); - bool willNewPositionViolateZoomInLimit = (newPosDistance < _zoomInLimit.value()); + bool currentPosViolatingZoomOutLimit = + (currentPosDistance >= _zoomOutLimit.value()); + bool willNewPositionViolateZoomOutLimit = + (newPosDistance >= _zoomOutLimit.value()); + bool willNewPositionViolateZoomInLimit = + (newPosDistance < _zoomInLimit.value()); if (!willNewPositionViolateZoomInLimit && !willNewPositionViolateZoomOutLimit){ camPos += zoomDistanceIncrement; @@ -1447,7 +1226,7 @@ void TouchInteraction::step(double dt) { void TouchInteraction::unitTest() { if (_unitTest) { - _lmstat.verbose = true; + _solver.setLevMarqVerbosity(true); // set _selected pos and new pos (on screen) std::vector lastFrame = { @@ -1468,7 +1247,7 @@ void TouchInteraction::unitTest() { snprintf(buffer, sizeof(char) * 32, "lmdata%i.csv", _numOfTests); _numOfTests++; std::ofstream file(buffer); - file << _lmstat.data; + file << _solver.getLevMarqStat().data; // clear everything _selected.clear(); @@ -1480,6 +1259,7 @@ void TouchInteraction::unitTest() { _lastVel = _vel; _unitTest = false; + _solver.setLevMarqVerbosity(false); // could be the camera copy in func } } diff --git a/modules/touch/src/win32_touch.cpp b/modules/touch/src/win32_touch.cpp index 8d248d3a63..03ded0a114 100644 --- a/modules/touch/src/win32_touch.cpp +++ b/modules/touch/src/win32_touch.cpp @@ -28,11 +28,8 @@ #include #include - #include - #include - #include #include @@ -42,7 +39,7 @@ namespace { bool gStarted{ false }; TUIO::TuioServer* gTuioServer{ nullptr }; std::unordered_map gCursorMap; -} +} // namespace namespace openspace { @@ -69,22 +66,32 @@ LRESULT CALLBACK HookCallback(int nCode, WPARAM wParam, LPARAM lParam) { // native touch to screen conversion ScreenToClient(pStruct->hwnd, reinterpret_cast(&p)); - float xPos = (float)p.x / (float)(rect.right - rect.left); - float yPos = (float)p.y / (float)(rect.bottom - rect.top); + float xPos = static_cast(p.x) / + static_cast(rect.right - rect.left); + float yPos = static_cast(p.y) / + static_cast(rect.bottom - rect.top); if (pointerInfo.pointerFlags & POINTER_FLAG_DOWN) { // Handle new touchpoint gTuioServer->initFrame(TUIO::TuioTime::getSessionTime()); - gCursorMap[pointerInfo.pointerId] = gTuioServer->addTuioCursor(xPos, yPos); + gCursorMap[pointerInfo.pointerId] = gTuioServer->addTuioCursor( + xPos, + yPos + ); gTuioServer->commitFrame(); } else if (pointerInfo.pointerFlags & POINTER_FLAG_UPDATE) { // Handle update of touchpoint TUIO::TuioTime frameTime = TUIO::TuioTime::getSessionTime(); - if (gCursorMap[pointerInfo.pointerId]->getTuioTime() == frameTime) { + if (gCursorMap[pointerInfo.pointerId]->getTuioTime() == frameTime) + { break; } gTuioServer->initFrame(frameTime); - gTuioServer->updateTuioCursor(gCursorMap[pointerInfo.pointerId], xPos, yPos); + gTuioServer->updateTuioCursor( + gCursorMap[pointerInfo.pointerId], + xPos, + yPos + ); gTuioServer->commitFrame(); } else if (pointerInfo.pointerFlags & POINTER_FLAG_UP) { @@ -139,14 +146,23 @@ Win32TouchHook::Win32TouchHook(void* nativeWindow) const DWORD dwHwndTabletProperty = TABLET_DISABLE_PRESSANDHOLD; ATOM atom = ::GlobalAddAtom(MICROSOFT_TABLETPENSERVICE_PROPERTY); - ::SetProp(hWnd, MICROSOFT_TABLETPENSERVICE_PROPERTY, reinterpret_cast(dwHwndTabletProperty)); + ::SetProp( + hWnd, + MICROSOFT_TABLETPENSERVICE_PROPERTY, + reinterpret_cast(dwHwndTabletProperty) + ); ::GlobalDeleteAtom(atom); if (!gStarted) { gStarted = true; gTuioServer = new TUIO::TuioServer("localhost", 3333); TUIO::TuioTime::initSession(); - gTouchHook = SetWindowsHookExW(WH_GETMESSAGE, HookCallback, GetModuleHandleW(NULL), GetCurrentThreadId()); + gTouchHook = SetWindowsHookExW( + WH_GETMESSAGE, + HookCallback, + GetModuleHandleW(NULL), + GetCurrentThreadId() + ); if (!gTouchHook) { LINFO(fmt::format("Failed to setup WindowsHook for touch input redirection")); delete gTuioServer; diff --git a/modules/touch/touchmodule.cpp b/modules/touch/touchmodule.cpp index a47e2fe4d2..f968095a44 100644 --- a/modules/touch/touchmodule.cpp +++ b/modules/touch/touchmodule.cpp @@ -164,7 +164,7 @@ TouchModule::TouchModule() if (nativeWindowHandle) { _win32TouchHook.reset(new Win32TouchHook(nativeWindowHandle)); } -#endif //WIN32 +#endif }); global::callback::deinitializeGL.push_back([&]() { diff --git a/modules/toyvolume/rendering/renderabletoyvolume.cpp b/modules/toyvolume/rendering/renderabletoyvolume.cpp index ccb5018780..a5c37bf4e2 100644 --- a/modules/toyvolume/rendering/renderabletoyvolume.cpp +++ b/modules/toyvolume/rendering/renderabletoyvolume.cpp @@ -29,8 +29,10 @@ #include #include #include +#include namespace { + constexpr const char* _loggerCat = "Renderable ToyVolume"; constexpr openspace::properties::Property::PropertyInfo SizeInfo = { "Size", "Size", @@ -66,6 +68,13 @@ namespace { "Color", "" // @TODO Missing documentation }; + + constexpr openspace::properties::Property::PropertyInfo DownscaleVolumeRenderingInfo = { + "Downscale", + "Downscale Factor Volume Rendering", + "This value set the downscaling factor" + " when rendering the current volume." + }; } // namespace namespace openspace { @@ -78,6 +87,7 @@ RenderableToyVolume::RenderableToyVolume(const ghoul::Dictionary& dictionary) , _translation(TranslationInfo, glm::vec3(0.f), glm::vec3(0.f), glm::vec3(10.f)) , _rotation(RotationInfo, glm::vec3(0.f, 0.f, 0.f), glm::vec3(0), glm::vec3(6.28f)) , _color(ColorInfo, glm::vec4(1.f, 0.f, 0.f, 0.1f), glm::vec4(0.f), glm::vec4(1.f)) + , _downScaleVolumeRendering(DownscaleVolumeRenderingInfo, 1.f, 0.1f, 1.f) { if (dictionary.hasKeyAndValue(ScalingExponentInfo.identifier)) { _scalingExponent = static_cast( @@ -104,6 +114,22 @@ RenderableToyVolume::RenderableToyVolume(const ghoul::Dictionary& dictionary) if (dictionary.hasKeyAndValue(StepSizeInfo.identifier)) { _stepSize = static_cast(dictionary.value(StepSizeInfo.identifier)); } + + _downScaleVolumeRendering.setVisibility( + openspace::properties::Property::Visibility::Developer + ); + if (dictionary.hasKey("Downscale")) { + _downScaleVolumeRendering = dictionary.value("Downscale"); + } + + if (dictionary.hasKey("Steps")) { + _rayCastSteps = static_cast(dictionary.value("Steps")); + } + else { + LINFO("Number of raycasting steps not specified for ToyVolume." + " Using default value."); + } + } RenderableToyVolume::~RenderableToyVolume() {} @@ -131,6 +157,7 @@ void RenderableToyVolume::initializeGL() { addProperty(_translation); addProperty(_rotation); addProperty(_color); + addProperty(_downScaleVolumeRendering); } void RenderableToyVolume::deinitializeGL() { @@ -167,6 +194,8 @@ void RenderableToyVolume::update(const UpdateData& data) { _raycaster->setStepSize(_stepSize); _raycaster->setModelTransform(transform); _raycaster->setTime(data.time.j2000Seconds()); + _raycaster->setDownscaleRender(_downScaleVolumeRendering); + _raycaster->setMaxSteps(_rayCastSteps); } } diff --git a/modules/toyvolume/rendering/renderabletoyvolume.h b/modules/toyvolume/rendering/renderabletoyvolume.h index 8c1b0a36e0..d946bd21f9 100644 --- a/modules/toyvolume/rendering/renderabletoyvolume.h +++ b/modules/toyvolume/rendering/renderabletoyvolume.h @@ -55,8 +55,11 @@ private: properties::Vec3Property _translation; properties::Vec3Property _rotation; properties::Vec4Property _color; + properties::FloatProperty _downScaleVolumeRendering; std::unique_ptr _raycaster; + + int _rayCastSteps = 1000; }; } // namespace openspace diff --git a/modules/toyvolume/rendering/toyvolumeraycaster.cpp b/modules/toyvolume/rendering/toyvolumeraycaster.cpp index 2f5f82f0ac..97d71c05bf 100644 --- a/modules/toyvolume/rendering/toyvolumeraycaster.cpp +++ b/modules/toyvolume/rendering/toyvolumeraycaster.cpp @@ -24,7 +24,6 @@ #include -#include #include #include #include diff --git a/modules/volume/rendering/basicvolumeraycaster.cpp b/modules/volume/rendering/basicvolumeraycaster.cpp index f81912cfeb..b404d97bb3 100644 --- a/modules/volume/rendering/basicvolumeraycaster.cpp +++ b/modules/volume/rendering/basicvolumeraycaster.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/modules/webbrowser/src/screenspacebrowser.cpp b/modules/webbrowser/src/screenspacebrowser.cpp index 1c69bb0b4c..72621a96cc 100644 --- a/modules/webbrowser/src/screenspacebrowser.cpp +++ b/modules/webbrowser/src/screenspacebrowser.cpp @@ -72,13 +72,16 @@ ScreenSpaceBrowser::ScreenSpaceBrowser(const ghoul::Dictionary &dictionary) , _dimensions(DimensionsInfo, glm::vec2(0.f), glm::vec2(0.f), glm::vec2(3000.f)) , _reload(ReloadInfo) { - if (dictionary.hasKey(KeyIdentifier)) { - setIdentifier(dictionary.value(KeyIdentifier)); - } else { - static int id = 0; - setIdentifier("ScreenSpaceBrowser " + std::to_string(id)); - ++id; + + std::string identifier; + if (dictionary.hasKeyAndValue(KeyIdentifier)) { + identifier = dictionary.value(KeyIdentifier); } + else { + identifier = "ScreenSpaceBrowser"; + } + identifier = makeUniqueIdentifier(identifier); + setIdentifier(identifier); if (dictionary.hasKeyAndValue(UrlInfo.identifier)) { _url = dictionary.value(UrlInfo.identifier); diff --git a/shaders/framebuffer/hdrAndFiltering.frag b/shaders/framebuffer/hdrAndFiltering.frag index b22ebd9bc4..0e2b3b2090 100644 --- a/shaders/framebuffer/hdrAndFiltering.frag +++ b/shaders/framebuffer/hdrAndFiltering.frag @@ -38,7 +38,6 @@ uniform float Hue; uniform float Saturation; uniform float Value; uniform float Lightness; -uniform int nAaSamples; uniform sampler2D hdrFeedingTexture; diff --git a/tests/test_powerscalecoordinates.inl b/shaders/framebuffer/mergeDownscaledVolume.frag similarity index 75% rename from tests/test_powerscalecoordinates.inl rename to shaders/framebuffer/mergeDownscaledVolume.frag index 23b22a70a9..14a6405735 100644 --- a/tests/test_powerscalecoordinates.inl +++ b/shaders/framebuffer/mergeDownscaledVolume.frag @@ -22,42 +22,16 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#include +#version __CONTEXT__ -#include +layout (location = 0) out vec4 finalColor; -class PowerscaleCoordinatesTest : public testing::Test { -protected: - PowerscaleCoordinatesTest() { - } +uniform sampler2D downscaledRenderedVolume; +uniform sampler2D downscaledRenderedVolumeDepth; - ~PowerscaleCoordinatesTest() { - } +in vec2 texCoord; - void reset() { - } - - openspace::Scene* scenegraph; -}; - - -TEST_F(PowerscaleCoordinatesTest, psc) { - - openspace::psc reference(2.f, 1.f, 1.1f, 1.f); - - openspace::psc first(1.f, 0.f, 1.f, 0.f); - openspace::psc second(1.9f, 1.f, 1.f, 1.f); - - EXPECT_EQ(reference, first + second); - EXPECT_TRUE(reference == (first + second)); - - openspace::psc third = first; - first[0] = 0.0; - - EXPECT_TRUE(third != first); - - +void main() { + finalColor = texture(downscaledRenderedVolume, texCoord); + gl_FragDepth = texture(downscaledRenderedVolumeDepth, texCoord).r; } - - - diff --git a/shaders/framebuffer/mergeDownscaledVolume.vert b/shaders/framebuffer/mergeDownscaledVolume.vert new file mode 100644 index 0000000000..f737e51882 --- /dev/null +++ b/shaders/framebuffer/mergeDownscaledVolume.vert @@ -0,0 +1,33 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2019 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#version __CONTEXT__ + +layout(location = 0) in vec4 position; +out vec2 texCoord; + +void main() { + texCoord = 0.5 + position.xy * 0.5; + gl_Position = position; +} diff --git a/shaders/framebuffer/raycastframebuffer.frag b/shaders/framebuffer/raycastframebuffer.frag index 6a949b4cc9..bff04b1dbe 100644 --- a/shaders/framebuffer/raycastframebuffer.frag +++ b/shaders/framebuffer/raycastframebuffer.frag @@ -28,10 +28,11 @@ uniform sampler2D exitColorTexture; uniform sampler2D exitDepthTexture; uniform sampler2D mainDepthTexture; -uniform bool insideRaycaster; uniform vec3 cameraPosInRaycaster; uniform vec2 windowSize; +uniform int rayCastSteps; + #include "blending.glsl" #include "rand.glsl" #include "floatoperations.glsl" @@ -45,17 +46,17 @@ uniform vec2 windowSize; out vec4 finalColor; #define ALPHA_LIMIT 0.99 -#define RAYCAST_MAX_STEPS 1000 #include <#{getEntryPath}> void main() { vec2 texCoord = vec2(gl_FragCoord.xy / windowSize); + // Boundary position in view space vec4 exitColorTexture = texture(exitColorTexture, texCoord); // If we don't have an exit, discard the ray - if (exitColorTexture.a < 1.0 || exitColorTexture.rgb == vec3(0.0)) { + if (exitColorTexture.a < 1.f || exitColorTexture.rgb == vec3(0.f)) { discard; } @@ -63,13 +64,13 @@ void main() { vec3 exitPos = exitColorTexture.rgb; float exitDepth = denormalizeFloat(texture(exitDepthTexture, texCoord).x); - float jitterFactor = 0.5 + 0.5 * rand(gl_FragCoord.xy); // should be between 0.5 and 1.0 + float jitterFactor = 0.5f + 0.5f * rand(gl_FragCoord.xy); // should be between 0.5 and 1.0 vec3 entryPos; float entryDepth; getEntry(entryPos, entryDepth); // If we don't have an entry, discard the ray - if (entryPos == vec3(0.0)) { + if (entryPos == vec3(0.f)) { discard; } @@ -79,30 +80,30 @@ void main() { vec3 direction = normalize(diff); float raycastDepth = length(diff); - float geoDepth = denormalizeFloat(texelFetch(mainDepthTexture, ivec2(gl_FragCoord), 0).x); - float geoRatio = clamp((geoDepth - entryDepth) / (exitDepth - entryDepth), 0.0, 1.0); + float geoDepth = denormalizeFloat((texture(mainDepthTexture, texCoord).x)); + float geoRatio = clamp((geoDepth - entryDepth) / (exitDepth - entryDepth), 0.f, 1.f); raycastDepth = geoRatio * raycastDepth; - float currentDepth = 0.0; + float currentDepth = 0.f; float nextStepSize = stepSize#{id}(position, direction); float currentStepSize; - float previousJitterDistance = 0.0; + float previousJitterDistance = 0.f; int nSteps = 0; int sampleIndex = 0; - float opacityDecay = 1.0; + float opacityDecay = 1.f; - vec3 accumulatedColor = vec3(0.0); - vec3 accumulatedAlpha = vec3(0.0); + vec3 accumulatedColor = vec3(0.f); + vec3 accumulatedAlpha = vec3(0.f); for (nSteps = 0; (accumulatedAlpha.r < ALPHA_LIMIT || accumulatedAlpha.g < ALPHA_LIMIT || - accumulatedAlpha.b < ALPHA_LIMIT) && nSteps < RAYCAST_MAX_STEPS; + accumulatedAlpha.b < ALPHA_LIMIT) && nSteps < rayCastSteps; ++nSteps) { - if (nextStepSize < raycastDepth / 10000000000.0) { + if (nextStepSize < raycastDepth / 10000000000.f) { break; } @@ -110,7 +111,7 @@ void main() { currentDepth += currentStepSize; float jitteredStepSize = currentStepSize * jitterFactor; - vec3 jitteredPosition = position + direction*jitteredStepSize; + vec3 jitteredPosition = position + direction * jitteredStepSize; position += direction * currentStepSize; sample#{id}(jitteredPosition, direction, accumulatedColor, accumulatedAlpha, nextStepSize); @@ -122,8 +123,9 @@ void main() { nextStepSize = min(nextStepSize, maxStepSize); } - finalColor = vec4(accumulatedColor, (accumulatedAlpha.r + accumulatedAlpha.g + accumulatedAlpha.b) / 3); + finalColor = vec4(accumulatedColor, (accumulatedAlpha.r + accumulatedAlpha.g + accumulatedAlpha.b) / 3.f); finalColor.rgb /= finalColor.a ; + gl_FragDepth = normalizeFloat(entryDepth); } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d6bae69e26..bba42b68da 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -177,11 +177,10 @@ set(OPENSPACE_SOURCE ${OPENSPACE_BASE_DIR}/src/util/httprequest.cpp ${OPENSPACE_BASE_DIR}/src/util/keys.cpp ${OPENSPACE_BASE_DIR}/src/util/openspacemodule.cpp - ${OPENSPACE_BASE_DIR}/src/util/powerscaledcoordinate.cpp - ${OPENSPACE_BASE_DIR}/src/util/powerscaledsphere.cpp ${OPENSPACE_BASE_DIR}/src/util/progressbar.cpp ${OPENSPACE_BASE_DIR}/src/util/resourcesynchronization.cpp ${OPENSPACE_BASE_DIR}/src/util/screenlog.cpp + ${OPENSPACE_BASE_DIR}/src/util/sphere.cpp ${OPENSPACE_BASE_DIR}/src/util/spicemanager.cpp ${OPENSPACE_BASE_DIR}/src/util/spicemanager_lua.inl ${OPENSPACE_BASE_DIR}/src/util/syncbuffer.cpp @@ -371,11 +370,10 @@ set(OPENSPACE_HEADER ${OPENSPACE_BASE_DIR}/include/openspace/util/keys.h ${OPENSPACE_BASE_DIR}/include/openspace/util/mouse.h ${OPENSPACE_BASE_DIR}/include/openspace/util/openspacemodule.h - ${OPENSPACE_BASE_DIR}/include/openspace/util/powerscaledcoordinate.h - ${OPENSPACE_BASE_DIR}/include/openspace/util/powerscaledsphere.h ${OPENSPACE_BASE_DIR}/include/openspace/util/progressbar.h ${OPENSPACE_BASE_DIR}/include/openspace/util/resourcesynchronization.h ${OPENSPACE_BASE_DIR}/include/openspace/util/screenlog.h + ${OPENSPACE_BASE_DIR}/include/openspace/util/sphere.h ${OPENSPACE_BASE_DIR}/include/openspace/util/spicemanager.h ${OPENSPACE_BASE_DIR}/include/openspace/util/syncable.h ${OPENSPACE_BASE_DIR}/include/openspace/util/syncbuffer.h diff --git a/src/rendering/dashboarditem.cpp b/src/rendering/dashboarditem.cpp index d7ee5306cd..42fef0b961 100644 --- a/src/rendering/dashboarditem.cpp +++ b/src/rendering/dashboarditem.cpp @@ -111,8 +111,10 @@ DashboardItem::DashboardItem(const ghoul::Dictionary& dictionary) std::string identifier = dictionary.value(IdentifierInfo.identifier); setIdentifier(std::move(identifier)); - std::string guiName = dictionary.value(GuiNameInfo.identifier); - setGuiName(std::move(guiName)); + if (dictionary.hasKeyAndValue(GuiNameInfo.identifier)) { + std::string guiName = dictionary.value(GuiNameInfo.identifier); + setGuiName(std::move(guiName)); + } addProperty(_isEnabled); } diff --git a/src/rendering/framebufferrenderer.cpp b/src/rendering/framebufferrenderer.cpp index 284d2920c3..a6b327149b 100644 --- a/src/rendering/framebufferrenderer.cpp +++ b/src/rendering/framebufferrenderer.cpp @@ -59,6 +59,10 @@ namespace { "renderedTexture", "inverseScreenSize" }; + constexpr const std::array DownscaledVolumeUniformNames = { + "downscaledRenderedVolume", "downscaledRenderedVolumeDepth" + }; + constexpr const char* ExitFragmentShaderPath = "${SHADERS}/framebuffer/exitframebuffer.frag"; constexpr const char* RaycastFragmentShaderPath = @@ -184,6 +188,11 @@ void FramebufferRenderer::initialize() { glGenFramebuffers(1, &_fxaaBuffers.fxaaFramebuffer); glGenTextures(1, &_fxaaBuffers.fxaaTexture); + // DownscaleVolumeRendering + glGenFramebuffers(1, &_downscaleVolumeRendering.framebuffer); + glGenTextures(1, &_downscaleVolumeRendering.colorTexture); + glGenTextures(1, &_downscaleVolumeRendering.depthbuffer); + // Allocate Textures/Buffers Memory updateResolution(); @@ -307,11 +316,35 @@ void FramebufferRenderer::initialize() { LERROR("FXAA framebuffer is not complete"); } + //================================================// + //===== Downscale Volume Rendering Buffers =====// + //================================================// + glBindFramebuffer(GL_FRAMEBUFFER, _downscaleVolumeRendering.framebuffer); + glFramebufferTexture( + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + _downscaleVolumeRendering.colorTexture, + 0 + ); + glFramebufferTexture( + GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + _downscaleVolumeRendering.depthbuffer, + 0 + ); + + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + LERROR("Downscale Volume Rendering framebuffer is not complete"); + } + + // JCC: Moved to here to avoid NVidia: "Program/shader state performance warning" // Building programs updateHDRAndFiltering(); updateFXAA(); updateDeferredcastData(); + updateDownscaledVolume(); // Sets back to default FBO glBindFramebuffer(GL_FRAMEBUFFER, _defaultFBO); @@ -326,6 +359,11 @@ void FramebufferRenderer::initialize() { _fxaaUniformCache, FXAAUniformNames ); + ghoul::opengl::updateUniformLocations( + *_downscaledVolumeProgram, + _writeDownscaledVolumeUniformCache, + DownscaledVolumeUniformNames + ); global::raycasterManager.addListener(*this); global::deferredcasterManager.addListener(*this); @@ -342,6 +380,7 @@ void FramebufferRenderer::deinitialize() { glDeleteFramebuffers(1, &_hdrBuffers.hdrFilteringFramebuffer); glDeleteFramebuffers(1, &_fxaaBuffers.fxaaFramebuffer); glDeleteFramebuffers(1, &_pingPongBuffers.framebuffer); + glDeleteFramebuffers(1, &_downscaleVolumeRendering.framebuffer); glDeleteTextures(1, &_gBuffers.colorTexture); glDeleteTextures(1, &_gBuffers.depthTexture); @@ -350,7 +389,9 @@ void FramebufferRenderer::deinitialize() { glDeleteTextures(1, &_fxaaBuffers.fxaaTexture); glDeleteTextures(1, &_gBuffers.positionTexture); glDeleteTextures(1, &_gBuffers.normalTexture); - + glDeleteTextures(1, &_downscaleVolumeRendering.colorTexture); + glDeleteTextures(1, &_downscaleVolumeRendering.depthbuffer); + glDeleteTextures(1, &_pingPongBuffers.colorTexture[1]); glDeleteTextures(1, &_exitColorTexture); @@ -459,6 +500,124 @@ void FramebufferRenderer::applyFXAA() { _fxaaProgram->deactivate(); } +void FramebufferRenderer::updateDownscaleTextures() { + glBindTexture(GL_TEXTURE_2D, _downscaleVolumeRendering.colorTexture); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGBA32F, + _resolution.x * _downscaleVolumeRendering.currentDownscaleFactor, + _resolution.y * _downscaleVolumeRendering.currentDownscaleFactor, + 0, + GL_RGBA, + GL_FLOAT, + nullptr + ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + float volumeBorderColor[] = { 0.0f, 0.0f, 0.0f, 1.0f }; + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, volumeBorderColor); + + glBindTexture(GL_TEXTURE_2D, _downscaleVolumeRendering.depthbuffer); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_DEPTH_COMPONENT32F, + _resolution.x * _downscaleVolumeRendering.currentDownscaleFactor, + _resolution.y * _downscaleVolumeRendering.currentDownscaleFactor, + 0, + GL_DEPTH_COMPONENT, + GL_FLOAT, + nullptr + ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +} + +void FramebufferRenderer::writeDownscaledVolume() { + const bool doPerformanceMeasurements = global::performanceManager.isEnabled(); + std::unique_ptr perfInternal; + + if (doPerformanceMeasurements) { + perfInternal = std::make_unique( + "FramebufferRenderer::render::writeDownscaledVolume" + ); + } + + // Saving current OpenGL state + GLboolean blendEnabled = glIsEnabledi(GL_BLEND, 0); + + GLenum blendEquationRGB; + glGetIntegerv(GL_BLEND_EQUATION_RGB, &blendEquationRGB); + + GLenum blendEquationAlpha; + glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blendEquationAlpha); + + GLenum blendDestAlpha; + glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDestAlpha); + + GLenum blendDestRGB; + glGetIntegerv(GL_BLEND_DST_RGB, &blendDestRGB); + + GLenum blendSrcAlpha; + glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha); + + GLenum blendSrcRGB; + glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcRGB); + + glEnablei(GL_BLEND, 0); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + + _downscaledVolumeProgram->activate(); + + ghoul::opengl::TextureUnit downscaledTextureUnit; + downscaledTextureUnit.activate(); + glBindTexture( + GL_TEXTURE_2D, + _downscaleVolumeRendering.colorTexture + ); + + _downscaledVolumeProgram->setUniform( + _writeDownscaledVolumeUniformCache.downscaledRenderedVolume, + downscaledTextureUnit + ); + + ghoul::opengl::TextureUnit downscaledDepthUnit; + downscaledDepthUnit.activate(); + glBindTexture( + GL_TEXTURE_2D, + _downscaleVolumeRendering.depthbuffer + ); + + _downscaledVolumeProgram->setUniform( + _writeDownscaledVolumeUniformCache.downscaledRenderedVolumeDepth, + downscaledDepthUnit + ); + + + glEnablei(GL_BLEND, 0); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + + glDisable(GL_DEPTH_TEST); + + glBindVertexArray(_screenQuad); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); + + glEnable(GL_DEPTH_TEST); + + _downscaledVolumeProgram->deactivate(); + + // Restores blending state + glBlendEquationSeparate(blendEquationRGB, blendEquationAlpha); + glBlendFuncSeparate(blendSrcRGB, blendDestRGB, blendSrcAlpha, blendDestAlpha); + + if (!blendEnabled) { + glDisablei(GL_BLEND, 0); + } + +} + void FramebufferRenderer::update() { if (_dirtyResolution) { updateResolution(); @@ -492,6 +651,16 @@ void FramebufferRenderer::update() { ); } + if (_downscaledVolumeProgram->isDirty()) { + _downscaledVolumeProgram->rebuildFromFile(); + + ghoul::opengl::updateUniformLocations( + *_downscaledVolumeProgram, + _writeDownscaledVolumeUniformCache, + DownscaledVolumeUniformNames + ); + } + using K = VolumeRaycaster*; using V = std::unique_ptr; for (const std::pair& program : _exitPrograms) { @@ -651,6 +820,39 @@ void FramebufferRenderer::updateResolution() { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + // Downscale Volume Rendering + glBindTexture(GL_TEXTURE_2D, _downscaleVolumeRendering.colorTexture); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RGBA32F, + _resolution.x * _downscaleVolumeRendering.currentDownscaleFactor, + _resolution.y * _downscaleVolumeRendering.currentDownscaleFactor, + 0, + GL_RGBA, + GL_FLOAT, + nullptr + ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + float volumeBorderColor[] = { 0.0f, 0.0f, 0.0f, 1.0f }; + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, volumeBorderColor); + + glBindTexture(GL_TEXTURE_2D, _downscaleVolumeRendering.depthbuffer); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_DEPTH_COMPONENT32F, + _resolution.x * _downscaleVolumeRendering.currentDownscaleFactor, + _resolution.y * _downscaleVolumeRendering.currentDownscaleFactor, + 0, + GL_DEPTH_COMPONENT, + GL_FLOAT, + nullptr + ); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + // Volume Rendering Textures glBindTexture(GL_TEXTURE_2D, _exitColorTexture); glTexImage2D( @@ -834,6 +1036,17 @@ void FramebufferRenderer::updateFXAA() { //_fxaaProgram->setIgnoreUniformLocationError(IgnoreError::Yes); } +void FramebufferRenderer::updateDownscaledVolume() { + _downscaledVolumeProgram = ghoul::opengl::ProgramObject::Build( + "Write Downscaled Volume Program", + absPath("${SHADERS}/framebuffer/mergeDownscaledVolume.vert"), + absPath("${SHADERS}/framebuffer/mergeDownscaledVolume.frag") + ); + using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError; + //_downscaledVolumeProgram->setIgnoreSubroutineUniformLocationError(IgnoreError::Yes); + //_downscaledVolumeProgram->setIgnoreUniformLocationError(IgnoreError::Yes); +} + void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFactor) { // Set OpenGL default rendering state glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_defaultFBO); @@ -959,7 +1172,20 @@ void FramebufferRenderer::performRaycasterTasks(const std::vector exitProgram->deactivate(); } - glBindFramebuffer(GL_FRAMEBUFFER, _gBuffers.framebuffer); + if (raycaster->downscaleRender() < 1.f) { + float scaleDown = raycaster->downscaleRender(); + glBindFramebuffer(GL_FRAMEBUFFER, _downscaleVolumeRendering.framebuffer); + glViewport(0, 0, _resolution.x * scaleDown, _resolution.y * scaleDown); + if (_downscaleVolumeRendering.currentDownscaleFactor != scaleDown) { + _downscaleVolumeRendering.currentDownscaleFactor = scaleDown; + updateDownscaleTextures(); + } + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + else { + glBindFramebuffer(GL_FRAMEBUFFER, _gBuffers.framebuffer); + } + glm::vec3 cameraPosition; bool isCameraInside = raycaster->isCameraInside( raycasterTask.renderData, @@ -991,6 +1217,8 @@ void FramebufferRenderer::performRaycasterTasks(const std::vector } if (raycastProgram) { + raycastProgram->setUniform("rayCastSteps", raycaster->maxSteps()); + raycaster->preRaycast(_raycastData[raycaster], *raycastProgram); ghoul::opengl::TextureUnit exitColorTextureUnit; @@ -1008,7 +1236,16 @@ void FramebufferRenderer::performRaycasterTasks(const std::vector glBindTexture(GL_TEXTURE_2D, _gBuffers.depthTexture); raycastProgram->setUniform("mainDepthTexture", mainDepthTextureUnit); - raycastProgram->setUniform("windowSize", static_cast(_resolution)); + if (raycaster->downscaleRender() < 1.f) { + float scaleDown = raycaster->downscaleRender(); + raycastProgram->setUniform( + "windowSize", + glm::vec2(_resolution.x * scaleDown, _resolution.y * scaleDown) + ); + } + else { + raycastProgram->setUniform("windowSize", static_cast(_resolution)); + } glDisable(GL_DEPTH_TEST); glDepthMask(false); @@ -1029,12 +1266,17 @@ void FramebufferRenderer::performRaycasterTasks(const std::vector else { LWARNING("Raycaster is not attached when trying to perform raycaster task"); } + + if (raycaster->downscaleRender() < 1.f) { + glViewport(0, 0, _resolution.x, _resolution.y); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _gBuffers.framebuffer); + writeDownscaledVolume(); + } } } void FramebufferRenderer::performDeferredTasks( - const std::vector& tasks - ) + const std::vector& tasks) { for (const DeferredcasterTask& deferredcasterTask : tasks) { Deferredcaster* deferredcaster = deferredcasterTask.deferredcaster; diff --git a/src/rendering/screenspacerenderable.cpp b/src/rendering/screenspacerenderable.cpp index 9a3b01f0dc..6fe7813bc8 100644 --- a/src/rendering/screenspacerenderable.cpp +++ b/src/rendering/screenspacerenderable.cpp @@ -206,8 +206,6 @@ namespace { wrap(elevation, -glm::pi(), glm::pi()) ); } - - } // namespace namespace openspace { @@ -314,6 +312,27 @@ std::unique_ptr ScreenSpaceRenderable::createFromDictiona ); } +std::string ScreenSpaceRenderable::makeUniqueIdentifier(std::string name) { + std::vector r = global::renderEngine.screenSpaceRenderables(); + + auto nameTaken = [&r](const std::string& name) { + bool nameTaken = std::any_of( + r.begin(), + r.end(), + [&name](ScreenSpaceRenderable* r) { return r->identifier() == name; } + ); + return nameTaken; + }; + + std::string baseName = name; + int i = 1; + while (nameTaken(name)) { + name = baseName + std::to_string(i); + i++; + } + return name; +} + ScreenSpaceRenderable::ScreenSpaceRenderable(const ghoul::Dictionary& dictionary) : properties::PropertyOwner({ "" }) , _enabled(EnabledInfo, true) diff --git a/src/rendering/volumeraycaster.cpp b/src/rendering/volumeraycaster.cpp index 17d13627c0..954bda7ac7 100644 --- a/src/rendering/volumeraycaster.cpp +++ b/src/rendering/volumeraycaster.cpp @@ -33,4 +33,20 @@ bool VolumeRaycaster::isCameraInside(const RenderData&, glm::vec3&) { return false; } +void VolumeRaycaster::setMaxSteps(int nsteps) { + _rayCastMaxSteps = nsteps; +} + +int VolumeRaycaster::maxSteps() const { + return _rayCastMaxSteps; +} + +void VolumeRaycaster::setDownscaleRender(float value) { + _downscaleRenderConst = value; +} + +float VolumeRaycaster::downscaleRender() const { + return _downscaleRenderConst; +} + } // namespace openspace diff --git a/src/util/powerscaledcoordinate.cpp b/src/util/powerscaledcoordinate.cpp deleted file mode 100644 index e5d1f5df75..0000000000 --- a/src/util/powerscaledcoordinate.cpp +++ /dev/null @@ -1,322 +0,0 @@ -/***************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2019 * - * * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this * - * software and associated documentation files (the "Software"), to deal in the Software * - * without restriction, including without limitation the rights to use, copy, modify, * - * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * - * permit persons to whom the Software is furnished to do so, subject to the following * - * conditions: * - * * - * The above copyright notice and this permission notice shall be included in all copies * - * or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - ****************************************************************************************/ - -#include - -#include -#include - -namespace { - constexpr const double k = 10.0; -} // namespace - -namespace openspace { - -PowerScaledCoordinate::PowerScaledCoordinate(PowerScaledCoordinate&& rhs) { - _vec = std::move(rhs._vec); -} - -PowerScaledCoordinate::PowerScaledCoordinate(glm::vec4 v) { - _vec = std::move(v); -} - -PowerScaledCoordinate::PowerScaledCoordinate(glm::vec3 v) { - _vec = glm::vec4(v, 0.f); -} - -PowerScaledCoordinate::PowerScaledCoordinate(float f1, float f2, float f3, float f4) { - _vec = glm::vec4(f1, f2, f3, f4); -} - -PowerScaledCoordinate::PowerScaledCoordinate(const PowerScaledCoordinate& rhs) { - _vec = rhs._vec; -} - -PowerScaledCoordinate -PowerScaledCoordinate::CreatePowerScaledCoordinate(double d1, double d2, double d3) -{ - char buff[600]; - - // find the number with maximum number of digits - double ad1 = std::abs(d1); - double ad2 = std::abs(d2); - double ad3 = std::abs(d3); - double max = (ad2 > ad1) ? ad2 : (ad3 > ad1) ? ad3 : ad1; - - // find out how many digits - // TODO: profile the next two lines and replace with something more efficient (ab) -#ifdef _MSC_VER - sprintf_s(buff, 600, "%.0f", max); - //sprintf(buff, "%.0f", max); -#else - sprintf(buff, "%.0f", max); -#endif - size_t digits = strlen(buff); - - //digits += 3; - - // rescale and return - double tp = 1.0 / pow(k, digits); - return PowerScaledCoordinate( - static_cast(d1 * tp), - static_cast(d2 * tp), - static_cast(d3 * tp), - static_cast(digits)); -} - -const glm::vec4& PowerScaledCoordinate::vec4() const -{ - return _vec; -} - -glm::vec3 PowerScaledCoordinate::vec3() const -{ - return glm::vec3(_vec[0] * pow(k, _vec[3]), _vec[1] * pow(k, _vec[3]), - _vec[2] * pow(k, _vec[3])); -} - -glm::dvec4 PowerScaledCoordinate::dvec4() const -{ - //return _vec; - return glm::dvec4(_vec); -} - -glm::dvec3 PowerScaledCoordinate::dvec3() const -{ - double p = pow(static_cast(k), static_cast(_vec[3])); - return glm::dvec3( static_cast(_vec[0]) * p, static_cast(_vec[1]) * p, - static_cast(_vec[2]) * p); -} - -float PowerScaledCoordinate::length() const -{ - return glm::length(glm::vec3(_vec[0], _vec[1], _vec[2])) * std::pow(10, _vec[3]); -} - -glm::vec3 PowerScaledCoordinate::direction() const -{ - glm::vec3 tmp(_vec[0], _vec[1], _vec[2]); - return glm::normalize(glm::vec3(_vec[0], _vec[1], _vec[2])); -} - -PowerScaledCoordinate& PowerScaledCoordinate::operator=(const PowerScaledCoordinate& rhs) -{ - if (this != &rhs) { - _vec = rhs._vec; - } - return *this; // Return a reference to myself. -} - -PowerScaledCoordinate& PowerScaledCoordinate::operator=(const glm::vec4& rhs) { - _vec = rhs; - return *this; // Return a reference to myself. -} - -PowerScaledCoordinate& PowerScaledCoordinate::operator=(const glm::vec3& rhs) { - _vec = glm::vec4(rhs[0], rhs[1], rhs[2], 0.0); - return *this; // Return a reference to myself. -} - -PowerScaledCoordinate& PowerScaledCoordinate::operator=(const glm::dvec4& rhs) { - _vec = glm::vec4(rhs); - return *this; // Return a reference to myself. -} - -PowerScaledCoordinate& PowerScaledCoordinate::operator=(const glm::dvec3& rhs) { - _vec = glm::vec4(rhs[0], rhs[1], rhs[2], 0.0); - return *this; // Return a reference to myself. -} - -PowerScaledCoordinate& PowerScaledCoordinate::operator=(PowerScaledCoordinate&& rhs) { - _vec = std::move(rhs._vec); - return *this; -} - -PowerScaledCoordinate& PowerScaledCoordinate::operator+=(const PowerScaledCoordinate& rhs) -{ - double ds = _vec[3] - rhs._vec[3]; - if (ds >= 0.0) { - double p = pow(k, -ds); - *this = PowerScaledCoordinate(static_cast(rhs._vec[0] * p + _vec[0]), - static_cast(rhs._vec[1] * p + _vec[1]), - static_cast(rhs._vec[2] * p + _vec[2]), - _vec[3]); - } else { - double p = pow(k, ds); - *this = PowerScaledCoordinate(static_cast(rhs._vec[0] + _vec[0] * p), - static_cast(rhs._vec[1] + _vec[1] * p), - static_cast(rhs._vec[2] + _vec[2] * p), - rhs._vec[3]); - } - - return *this; -} - -PowerScaledCoordinate PowerScaledCoordinate:: - operator+(const PowerScaledCoordinate& rhs) const -{ - return PowerScaledCoordinate(*this) += rhs; -} - -PowerScaledCoordinate& PowerScaledCoordinate::operator-=(const PowerScaledCoordinate& rhs) -{ - double ds = this->_vec[3] - rhs._vec[3]; - if (ds >= 0.0) { - double p = pow(k, -ds); - *this = PowerScaledCoordinate(static_cast(-rhs._vec[0] * p + _vec[0]), - static_cast(-rhs._vec[1] * p + _vec[1]), - static_cast(-rhs._vec[2] * p + _vec[2]), - _vec[3]); - } else { - double p = pow(k, ds); - *this = PowerScaledCoordinate(static_cast(-rhs._vec[0] + _vec[0] * p), - static_cast(-rhs._vec[1] + _vec[1] * p), - static_cast(-rhs._vec[2] + _vec[2] * p), - rhs._vec[3]); - } - - return *this; -} - -PowerScaledCoordinate PowerScaledCoordinate::operator*(const double& rhs) const -{ - return PowerScaledCoordinate(static_cast(_vec[0] * rhs), - static_cast(_vec[1] * rhs), - static_cast(_vec[2] * rhs), _vec[3]); -} - -PowerScaledCoordinate PowerScaledCoordinate::operator*(const float& rhs) const -{ - return PowerScaledCoordinate(_vec[0] * rhs, _vec[1] * rhs, _vec[2] * rhs, _vec[3]); -} - -PowerScaledCoordinate PowerScaledCoordinate::operator*(const glm::mat4& matrix) const -{ - return matrix * _vec; -} - -PowerScaledCoordinate PowerScaledCoordinate:: - operator-(const PowerScaledCoordinate& rhs) const -{ - return PowerScaledCoordinate(*this) -= rhs; -} - -float& PowerScaledCoordinate::operator[](unsigned int idx) -{ - return _vec[idx]; -} - -float PowerScaledCoordinate::operator[](unsigned int idx) const -{ - return _vec[idx]; -} - -double PowerScaledCoordinate::dot(const PowerScaledCoordinate& rhs) const -{ - double ds = _vec[3] - rhs._vec[3]; - if (ds >= 0.0) { - double p = pow(k, -ds); - glm::dvec3 uPowerScaledCoordinatealed(rhs._vec[0] * p, rhs._vec[1] * p, - rhs._vec[2] * p); - glm::dvec3 shortened(_vec[0], _vec[1], _vec[2]); - return glm::dot(uPowerScaledCoordinatealed, shortened); - } else { - double p = pow(k, ds); - glm::dvec3 uPowerScaledCoordinatealed(_vec[0] * p, _vec[1] * p, _vec[2] * p); - glm::dvec3 shortened(rhs._vec[0], rhs._vec[1], rhs._vec[2]); - return glm::dot(uPowerScaledCoordinatealed, shortened); - } -} - -double PowerScaledCoordinate::angle(const PowerScaledCoordinate& rhs) const -{ - glm::dvec3 uPowerScaledCoordinatealed(rhs._vec[0], rhs._vec[1], rhs._vec[2]); - glm::dvec3 shortened(_vec[0], _vec[1], _vec[2]); - uPowerScaledCoordinatealed = glm::normalize(uPowerScaledCoordinatealed); - shortened = glm::normalize(shortened); - - return acos(glm::dot(uPowerScaledCoordinatealed, shortened)); -} - -bool PowerScaledCoordinate::operator==(const PowerScaledCoordinate& other) const -{ - return _vec == other._vec; -} - -bool PowerScaledCoordinate::operator!=(const PowerScaledCoordinate& other) const -{ - return _vec != other._vec; -} - -bool PowerScaledCoordinate::operator<(const PowerScaledCoordinate& other) const -{ - double ds = _vec[3] - other._vec[3]; - if (ds >= 0) { - double p = pow(k, -ds); - glm::dvec3 upscaled(other._vec[0] * p, other._vec[1] * p, - other._vec[2] * p); - glm::dvec3 shortened(_vec[0], _vec[1], _vec[2]); - return glm::length(shortened) < glm::length(upscaled); - } else { - double p = pow(k, ds); - glm::dvec3 upscaled(_vec[0] * p, _vec[1] * p, _vec[2] * p); - glm::dvec3 shortened(other._vec[0], other._vec[1], other._vec[2]); - return glm::length(shortened) < glm::length(upscaled); - } -} - -bool PowerScaledCoordinate::operator>(const PowerScaledCoordinate& other) const -{ - double ds = this->_vec[3] - other._vec[3]; - if (ds >= 0) { - double p = pow(k, -ds); - glm::dvec3 upscaled(other._vec[0] * p, other._vec[1] * p, - other._vec[2] * p); - glm::dvec3 shortened(_vec[0], _vec[1], _vec[2]); - return glm::length(shortened) > glm::length(upscaled); - } else { - double p = pow(k, ds); - glm::dvec3 upscaled(_vec[0] * p, _vec[1] * p, _vec[2] * p); - glm::dvec3 shortened(other._vec[0], other._vec[1], other._vec[2]); - return glm::length(shortened) > glm::length(upscaled); - } -} - -bool PowerScaledCoordinate::operator<=(const PowerScaledCoordinate& other) const -{ - return *this < other || *this == other; -} - -bool PowerScaledCoordinate::operator>=(const PowerScaledCoordinate& other) const -{ - return *this > other || *this == other; -} - -std::ostream& operator<<(::std::ostream& os, const PowerScaledCoordinate& rhs) -{ - os << "(" << rhs[0] << ", " << rhs[1] << ", " << rhs[2] << "; " << rhs[3] << ")"; - return os; -} - -} // namespace openspace diff --git a/src/util/powerscaledsphere.cpp b/src/util/sphere.cpp similarity index 93% rename from src/util/powerscaledsphere.cpp rename to src/util/sphere.cpp index 25319ddba1..cbd3cfc4dc 100644 --- a/src/util/powerscaledsphere.cpp +++ b/src/util/sphere.cpp @@ -22,9 +22,8 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#include +#include -#include #include #include @@ -34,12 +33,12 @@ namespace { namespace openspace { -PowerScaledSphere::PowerScaledSphere(float radius, int segments) - : PowerScaledSphere(glm::vec3(radius), segments) +Sphere::Sphere(float radius, int segments) + : Sphere(glm::vec3(radius), segments) {} // Alternative Constructor for using accurate triaxial ellipsoid -PowerScaledSphere::PowerScaledSphere(glm::vec3 radius, int segments) +Sphere::Sphere(glm::vec3 radius, int segments) : _isize(6 * segments * segments) , _vsize((segments + 1) * (segments + 1)) , _varray(new Vertex[_vsize]) @@ -110,7 +109,7 @@ PowerScaledSphere::PowerScaledSphere(glm::vec3 radius, int segments) } } -PowerScaledSphere::PowerScaledSphere(const PowerScaledSphere& cpy) +Sphere::Sphere(const Sphere& cpy) : _vaoID(cpy._vaoID) , _vBufferID(cpy._vBufferID) , _iBufferID(cpy._iBufferID) @@ -125,7 +124,7 @@ PowerScaledSphere::PowerScaledSphere(const PowerScaledSphere& cpy) std::memcpy(_iarray, cpy._iarray, _isize * sizeof(int)); } -PowerScaledSphere::~PowerScaledSphere() { +Sphere::~Sphere() { delete[] _varray; delete[] _iarray; @@ -137,7 +136,7 @@ PowerScaledSphere::~PowerScaledSphere() { glDeleteVertexArrays(1, &_vaoID); } -bool PowerScaledSphere::initialize() { +bool Sphere::initialize() { // Initialize and upload to graphics card if (_vaoID == 0) { glGenVertexArrays(1, &_vaoID); @@ -197,7 +196,7 @@ bool PowerScaledSphere::initialize() { return true; } -void PowerScaledSphere::render() { +void Sphere::render() { glBindVertexArray(_vaoID); // select first VAO glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID); glDrawElements(GL_TRIANGLES, _isize, GL_UNSIGNED_INT, nullptr); diff --git a/src/util/spicemanager.cpp b/src/util/spicemanager.cpp index 9aa2e51803..bd65b59db5 100644 --- a/src/util/spicemanager.cpp +++ b/src/util/spicemanager.cpp @@ -687,24 +687,6 @@ bool SpiceManager::isTargetInFieldOfView(const std::string& target, return visible == SPICETRUE; } -bool SpiceManager::isTargetInFieldOfView(const std::string& target, - const std::string& observer, - const std::string& instrument, - FieldOfViewMethod method, - AberrationCorrection aberrationCorrection, - double& ephemerisTime) const -{ - return isTargetInFieldOfView( - target, - observer, - frameFromBody(target), - instrument, - method, - aberrationCorrection, - ephemerisTime - ); -} - SpiceManager::TargetStateResult SpiceManager::targetState(const std::string& target, const std::string& observer, const std::string& referenceFrame, @@ -913,33 +895,6 @@ SpiceManager::TerminatorEllipseResult SpiceManager::terminatorEllipse( return res; } -bool SpiceManager::addFrame(std::string body, std::string frame) { - if (body.empty() || frame.empty()) { - return false; - } - else { - _frameByBody.emplace_back(body, frame); - return true; - } -} - -std::string SpiceManager::frameFromBody(const std::string& body) const { - for (const std::pair& pair : _frameByBody) { - if (pair.first == body) { - return pair.second; - } - } - - constexpr const char* unionPrefix = "IAU_"; - - if (body.find(unionPrefix) == std::string::npos) { - return unionPrefix + body; - } - else { - return body; - } -} - void SpiceManager::findCkCoverage(const std::string& path) { ghoul_assert(!path.empty(), "Empty file path"); ghoul_assert(FileSys.fileExists(path), fmt::format("File '{}' does not exist", path)); diff --git a/tests/main.cpp b/tests/main.cpp index b5c3cd717f..8fa9ef3765 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -66,7 +66,6 @@ #include #include #include -#include #include #include #include