Merge branch 'master' into project/infravis-2025-visA

This commit is contained in:
Andreas Engberg
2025-11-25 10:18:10 +01:00
138 changed files with 2325 additions and 789 deletions
+12
View File
@@ -38,6 +38,18 @@ set(OPENSPACE_VERSION_MAJOR)
set(OPENSPACE_VERSION_MINOR)
set(OPENSPACE_VERSION_PATCH)
# Optionally disable vcpkg to prevent dependency conflicts
set(DISABLE_VCPKG OFF CACHE BOOL "Disable the use of vcpkg libs for Windows builds")
if (WIN32 AND DISABLE_VCPKG)
# This works for all subprojects due to MSBuild's hierarchical search
configure_file(
"${CMAKE_SOURCE_DIR}/support/cmake/Directory.Build.Props.template"
"${CMAKE_BINARY_DIR}/Directory.Build.props"
COPYONLY
)
message(STATUS "Vcpkg disabled through CMake option DISABLE_VCPKG")
endif ()
include(${PROJECT_SOURCE_DIR}/support/cmake/module_common.cmake)
include(${PROJECT_SOURCE_DIR}/ext/ghoul/support/cmake/message_macros.cmake)
@@ -85,7 +85,8 @@ namespace {
const int levelChange = elem.level - level;
if (levelChange == 0) {
parent->insertChildren(++nChildInsert, 1, 3);
nChildInsert++;
parent->insertChildren(nChildInsert, 1, 3);
parent->child(nChildInsert)->setData(
0,
QString::fromStdString(elem.line)
+1 -1
View File
@@ -1336,7 +1336,7 @@ int main(int argc, char* argv[]) {
LINFO(std::format("Configuration Path '{}'", configurationFilePath));
// Register the base path as the directory where the configuration file lives
std::filesystem::path base = configurationFilePath.parent_path();
std::filesystem::path base = findConfiguration().parent_path();
FileSys.registerPathToken("${BASE}", std::move(base));
// The previous incarnation of this was initializing GLFW to get the primary
@@ -15,13 +15,12 @@ local AddSunTrail = {
date = openspace.time.UTC()
end
local datePlus = openspace.time.advancedTime(date, '1d')
date = string.sub(date, 1, string.find(date, "T") - 1)
datePlus = string.sub(datePlus, 1, string.find(datePlus, "T") - 1)
dateSub = string.sub(date, 1, string.find(date, "T") - 1)
date = dateSub .. "T00:00:00Z"
local datePlus = dateSub .. "T23:59:59Z"
local SunTrailEarth = {
Identifier = "SunTrailEarth" .. date,
Identifier = "SunTrailEarth" .. dateSub,
Parent = "Earth",
Renderable = {
Type = "RenderableTrailTrajectory",
@@ -40,12 +39,16 @@ local AddSunTrail = {
},
Tag = { "sun_trail" },
GUI = {
Name = "Sun Trail " .. date,
Name = "Sun Trail " .. dateSub,
Path = "/Night Sky/Sun Trails",
}
}
openspace.addSceneGraphNode(SunTrailEarth)
if not openspace.hasSceneGraphNode(SunTrailEarth.Identifier) then
openspace.addSceneGraphNode(SunTrailEarth)
else
openspace.printWarning("Sun trail for date " .. dateSub .. " already exists.")
end
]],
Documentation = [[
Adds a trail for the sun, if an argument is provided, that date will be used instead of now
@@ -1,6 +1,6 @@
-- No Decorations
-- This example adds a new DashboardItem that shows the current in-game simulation date
-- without any additional text surrounding the current date
-- without any additional text surrounding the current date.
local Item = {
Identifier = "DashboardItemDate_Example_NoDecoration",
@@ -1,88 +0,0 @@
local sun = asset.require("scene/solarsystem/sun/transforms")
local earth = asset.require("scene/solarsystem/planets/earth/earth")
local models = asset.resource({
Name = "New Horizons Model",
Type = "HttpSynchronization",
Identifier = "newhorizons_model",
Version = 2
})
local ExampleFixedHeight = {
Identifier = "ExampleFixedHeight",
Parent = earth.Earth.Identifier,
Transform = {
Translation = {
Type = "GlobeTranslation",
Globe = earth.Earth.Identifier,
Latitude = 40.7128,
Longitude = -74.006,
Altitude = 100000.0
}
},
Renderable = {
Type = "RenderableModel",
GeometryFile = models .. "NewHorizonsCleanModel.obj",
LightSources = {
sun.LightSource
}
},
GUI = {
Name = "GlobeTranslation - Fixed Height",
Path = "/Examples"
}
}
local ExampleAdaptiveHeight = {
Identifier = "ExampleAdaptiveHeight",
Parent = earth.Earth.Identifier,
Transform = {
Translation = {
Type = "GlobeTranslation",
Globe = earth.Earth.Identifier,
Latitude = 40.7128,
Longitude = -74.006,
UseHeightmap = true
}
},
Renderable = {
Type = "RenderableModel",
GeometryFile = models .. "NewHorizonsCleanModel.obj",
LightSources = {
sun.LightSource
}
},
GUI = {
Name = "GlobeTranslation - Adaptive Height",
Path = "/Examples"
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(ExampleFixedHeight)
openspace.addSceneGraphNode(ExampleAdaptiveHeight)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(ExampleAdaptiveHeight)
openspace.removeSceneGraphNode(ExampleFixedHeight)
end)
asset.export(ExampleFixedHeight)
asset.export(ExampleAdaptiveHeight)
asset.meta = {
Name = "GlobeTranslation Example",
Description = [[An example that demonstrates how to place an object on a planet surface
using the "GlobeTranslation" transform. For the altitude, a fixed height can be used,
or the height can be queried from the height map]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}
-70
View File
@@ -1,70 +0,0 @@
local AU = 149597870700 -- 1 AU
local Circle = {
Identifier = "ExampleCircle",
Transform = {
Scale = {
Type = "StaticScale",
Scale = AU
}
},
Renderable = {
Type = "RenderableRadialGrid",
Color = { 0.6, 0.6, 0.8 },
LineWidth = 3.0,
GridSegments = { 1, 1 },
CircleSegments = 64,
Radii = { 0.0, 1.0 }
},
GUI = {
Name = "Example Circle",
Path = "/Examples/Primitives"
}
}
local Ellipse = {
Identifier = "ExampleEllipse",
Transform = {
Scale = {
Type = "NonUniformStaticScale",
Scale = { 1.5, 1.0, 1.0 }
}
},
Renderable = {
Type = "RenderableRadialGrid",
Color = { 0.6, 0.8, 0.6 },
LineWidth = 3.0,
GridSegments = { 1, 1 },
CircleSegments = 64,
Radii = { 0.0, AU }
},
GUI = {
Name = "Example Ellipse",
Path = "/Examples/Primitives"
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(Circle)
openspace.addSceneGraphNode(Ellipse)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(Ellipse)
openspace.removeSceneGraphNode(Circle)
end)
asset.export(Circle)
asset.export(Ellipse)
asset.meta = {
Name = "Primitives Example",
Description = [[Examples of different simple rendered primitives, such as circles
and ellipses.]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}
@@ -1,6 +1,6 @@
local transforms = asset.require("scene/solarsystem/sun/transforms")
-- With Custom Shader
-- This example creates a rendering of the volumetric milky way galaxy, but using a custom
-- shader to highlight the arms of the galaxy.
local data = asset.resource({
Name = "Milkyway Volume Data",
@@ -12,15 +12,13 @@ local data = asset.resource({
local KiloParsec = 3.086E19
local MilkyWayVolume = {
Identifier = "MilkyWayVolume_CustomShader",
Parent = transforms.SolarSystemBarycenter.Identifier,
local Node = {
Identifier = "RenderableGalaxy_Example_CustomShader",
Transform = {
Translation = {
Type = "StaticTranslation",
-- 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.
-- The x-axis of galactic coordinates points from the Sun towards the galaxy center
Position = { 8 * KiloParsec, 0, 0 }
}
},
@@ -46,30 +44,15 @@ local MilkyWayVolume = {
}
},
GUI = {
Path = "/Milky Way",
Name = "Milky Way Volume (Custom Shader)",
Description = "Volumetric rendering of Milky Way galaxy based on simulation from NAOJ"
Name = "RenderableGalaxy - Custom Shader",
Path = "/Examples"
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(MilkyWayVolume)
openspace.addSceneGraphNode(Node)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(MilkyWayVolume)
openspace.removeSceneGraphNode(Node)
end)
asset.export(MilkyWayVolume)
asset.meta = {
Name = "Milky Way Volume",
Description = [[Volumetric rendering of Milky Way galaxy based on simulations from "
"NAOJ with a custom shader]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT License"
}
@@ -4,8 +4,6 @@
-- the plane does not become larger or smaller than a given max height and min height, in
-- meters.
local earth = asset.require("scene/solarsystem/planets/earth/earth")
local Node = {
Identifier = "RenderablePlaneImageLocal_Example_ScaleByDistance",
Renderable = {
@@ -1,16 +1,16 @@
-- Ring
-- The `RenderableRadialGrid` can also be used to create a simple ring. This is done by
-- Circle
-- The `RenderableRadialGrid` can also be used to create a simple circle. This is done by
-- setting the number of segments in each direction to 1 and make sure the inner radius
-- is zero (which is the default).
local Node = {
Identifier = "RenderableRadialGrid_Example_Ring",
Identifier = "RenderableRadialGrid_Example_Circle",
Renderable = {
Type = "RenderableRadialGrid",
GridSegments = { 1, 1 }
},
GUI = {
Name = "RenderableRadialGrid - Ring",
Name = "RenderableRadialGrid - Circle",
Path = "/Examples"
}
}
@@ -0,0 +1,32 @@
-- Ellipse
-- The `RenderableRadialGrid` can also be used to create a simple ellipse. This is done by
-- setting the number of segments in each direction to 1 and make sure the inner radius
-- is zero (which is the default). By then applying a
-- [NonUniformStaticScale](#base_transform_scale_nonuniformstatic) to the scene graph node
-- this circle can be deformed into an ellipse.
local Node = {
Identifier = "RenderableRadialGrid_Example_Ellipse",
Transform = {
Scale = {
Type = "NonUniformStaticScale",
Scale = { 1.5, 1.0, 1.0 }
}
},
Renderable = {
Type = "RenderableRadialGrid",
GridSegments = { 1, 1 }
},
GUI = {
Name = "RenderableRadialGrid - Ellipse",
Path = "/Examples"
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(Node)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(Node)
end)
@@ -0,0 +1,25 @@
-- Basic
-- A simple example of a toy volume rendered using direct volume rendering.
local Node = {
Identifier = "RenderableToyVolume_Example",
Renderable = {
Type = "RenderableToyVolume",
Size = { 5, 5, 5 },
ScalingExponent = 11,
StepSize = 0.01,
Color = { 1.0, 0.0, 0.0 }
},
GUI = {
Name = "RenderableToyVolume - Basic",
Path = "/Examples"
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(Node)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(Node)
end)
@@ -1,7 +1,7 @@
-- Basic
-- This asset creates a rotation that places a coordinate axes on the surface of a
-- planetary body. The rotation causes the coordinate axes to remain fixed to the surface
-- of the globe.
-- This asset creates a rotation that places coordinate axes on the surface of a planetary
-- body. The rotation causes the coordinate axes to remain fixed to the surface of the
-- globe.
--
-- In order for this feature to work properly, the coordinate axes need to be located at
-- the same place as well, so this example also needs a `GlobeTranslation` applied.
@@ -1,8 +1,8 @@
-- Angle
-- This asset creates a rotation that places a coordinate axes on the surface of a
-- planetary body. The rotation causes the coordinate axes to remain fixed to the surface
-- of the globe. Additionally, the coordinate axes are rotated around the up-axis by a
-- fixed amount.
-- This asset creates a rotation that places coordinate axes on the surface of a planetary
-- body. The rotation causes the coordinate axes to remain fixed to the surface of the
-- globe. Additionally, the coordinate axes are rotated around the up-axis by a fixed
-- amount.
--
-- In order for this feature to work properly, the coordinate axes need to be located at
-- the same place as well, so this example also needs a `GlobeTranslation` applied.
@@ -1,9 +1,9 @@
-- UseCamera
-- This asset creates a rotation that places a coordinate axes on the surface of a
-- planetary body. The rotation causes the coordinate axes to remain fixed to the surface
-- of the globe. In this example, the rotation of the object will be updated based on the
-- location of the camera. When loading this example, make sure to focus the camera on
-- the Globe object for the follow-function to work.
-- This asset creates a rotation that places coordinate axes on the surface of a planetary
-- body. The rotation causes the coordinate axes to remain fixed to the surface of the
-- globe. In this example, the rotation of the object will be updated based on the
-- location of the camera. When loading this example, make sure to focus the camera on the
-- Globe object for the follow-function to work.
--
-- In order for this feature to work properly, the coordinate axes need to be located at
-- the same place as well, so this example also needs a `GlobeTranslation` applied, which
@@ -1,7 +1,7 @@
-- Basic
-- This example shows how to load and show a webpage in the rendering, in screen space.
local Object = {
local Item = {
Type = "ScreenSpaceBrowser",
Identifier = "ScreenSpaceBrowser_Example",
Url = "https://www.openspaceproject.com/",
@@ -9,9 +9,9 @@ local Object = {
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -2,7 +2,7 @@
-- This example shows how to display dashboard items in a screen space. In this specific
-- example it is show the date in the simulation, but any #DashboardItem is supported.
local Object = {
local Item = {
Type = "ScreenSpaceDashboard",
Identifier = "ScreenSpaceDashboard_Example",
Name = "ScreenSpaceDashboard Example - Basic",
@@ -15,9 +15,9 @@ local Object = {
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -0,0 +1,16 @@
-- Basic
-- This example creates a screen space renderable that shows the current simulation time.
local Item = {
Type = "ScreenSpaceDate",
Identifier = "ScreenSpaceDate_Example",
Name = "ScreenSpace Date Example - Basic"
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -0,0 +1,18 @@
-- Day of Year
-- This example creates a screen space renderable that shows the current simulation time
-- with the current year and the number of days that have passed in the year.
local Item = {
Type = "ScreenSpaceDate",
Identifier = "ScreenSpaceDate_Example_DayOfYear",
Name = "ScreenSpace Date Example - Day of Year",
TimeFormat = "YYYY DOY"
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -0,0 +1,19 @@
-- Font
-- This example creates a screen space renderable that shows the current simulation time
-- with a non-standard font. This is using one of the fonts that is loaded by default in the
-- openspace.cfg file.
local Item = {
Type = "ScreenSpaceDate",
Identifier = "ScreenSpaceDate_Example_Font",
Name = "ScreenSpace Date Example - Font",
FontName = "Light"
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -0,0 +1,21 @@
-- Font Size
-- This example creates a screen space renderable that shows the current simulation time
-- with a larger font. The FontSize parameter is increased to improve the fidelity of the
-- text being rendered. The Scale parameter will make the text show up larger on the
-- screen.
local Item = {
Type = "ScreenSpaceDate",
Identifier = "ScreenSpaceDate_Example_FontSize",
Name = "ScreenSpace Date Example - Font Size",
Scale = 0.5,
FontSize = 72
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -0,0 +1,18 @@
-- No Decorations
-- This example creates a screen space renderable that shows the current simulation time
-- without any additional text surrounding the current date.
local Item = {
Type = "ScreenSpaceDate",
Identifier = "ScreenSpaceDate_Example_NoDecoration",
Name = "ScreenSpace Date Example - No Decoration",
FormatString = "{}"
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -0,0 +1,18 @@
-- Timezone
-- This example creates a screen space renderable that shows the current simulation time
-- with a timezone of UTC-7 (=PDT)
local Item = {
Type = "ScreenSpaceDate",
Identifier = "ScreenSpaceDate_Example_Timezone",
Name = "ScreenSpace Date Example - Timezone",
TimeFormat = "YYYY MON DD HR:MN:SC.### PDT ::UTC-7"
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -0,0 +1,18 @@
-- Year Month Day
-- This example creates a screen space renderable that shows the current simulation time
-- with a resolution of days.
local Item = {
Type = "ScreenSpaceDate",
Identifier = "ScreenSpaceDate_Example_YearMonthDay",
Name = "ScreenSpace Date Example - Year/Month/Day",
TimeFormat = "YYYY MON DD"
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -4,7 +4,7 @@
--
-- The texture that is displayed can be changed during runtime. Here it is just set to 1.
local Object = {
local Item = {
Identifier = "ScreenSpaceDebugPlane_Example",
Type = "ScreenSpaceDebugPlane",
Texture = 1,
@@ -12,9 +12,9 @@ local Object = {
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -2,7 +2,7 @@
-- Create a screenspace image plane that shows the content of a local image file on disk.
-- In this case we use a test image from the OpenSpace/data folder.
local Object = {
local Item = {
Type = "ScreenSpaceImageLocal",
Identifier = "ScreenSpaceImageLocal_Example",
TexturePath = openspace.absPath("${DATA}/test3.jpg"),
@@ -10,9 +10,9 @@ local Object = {
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -1,7 +1,7 @@
-- Basic
-- Create a screenspace image plane that shows the content of an image from a web URL.
local Object = {
local Item = {
Type = "ScreenSpaceImageOnline",
Identifier = "ScreenSpaceImageOnline_Example",
URL = "https://data.openspaceproject.com/moon_mars/apollo8/earthrise.jpg",
@@ -9,9 +9,9 @@ local Object = {
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -2,12 +2,12 @@
-- Creates a screenspace image plane with controls to for a blackout shape. Can be used
-- when using a secondary projector to project content on a dome surface.
local inset = {
local Item = {
Identifier = "ScreenSpaceInsetBlackout_Example",
Type = "ScreenSpaceInsetBlackout",
Name = "ScreenSpaceInsetBlackout Example - Basic",
Blackoutshape = {
-- Must always contain four corners in the following order:
-- Must always contain four corners in the following order:
-- top-left, top-right, bottom-right, bottom-left
Corners = { {0.0, 1.0}, {1.0, 1.0}, {1.0, 0.0}, {0.0, 0.0} }
},
@@ -15,9 +15,9 @@ local inset = {
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(inset)
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(inset)
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -9,7 +9,7 @@ local texturePath = asset.resource({
Version = 1
})
local inset = {
local Item = {
Identifier = "ScreenSpaceInsetBlackout_Example_Calibration_Pattern",
Type = "ScreenSpaceInsetBlackout",
Name = "ScreenSpaceInsetBlackout Example - Calibration Pattern",
@@ -24,9 +24,9 @@ local inset = {
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(inset)
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(inset)
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -2,7 +2,7 @@
-- Creates a screenspace image plane with controls to for a blackout shape. Can be used
-- when using a secondary projector to project content on a dome surface.
local inset = {
local Item = {
Identifier = "ScreenSpaceInsetBlackout_Example_Points",
Type = "ScreenSpaceInsetBlackout",
Name = "ScreenSpaceInsetBlackout Example - Points",
@@ -27,9 +27,9 @@ local inset = {
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(inset)
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(inset)
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -2,7 +2,7 @@
-- Creates a screenspace image that shows a spherical grid as an example for any
-- [Renderable](#renderable) that can be displayed.
local Object = {
local Item = {
Type = "ScreenSpaceRenderableRenderable",
Identifier = "ScreenSpaceRenderableRenderable_Example",
Renderable = {
@@ -14,9 +14,9 @@ local Object = {
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -4,7 +4,7 @@
-- onto the axes and increases the field of view of the camera to a wider degree. We also
-- set the background color to be fully opaque to make it easier to see the axes.
local Object = {
local Item = {
Type = "ScreenSpaceRenderableRenderable",
Identifier = "ScreenSpaceRenderableRenderable_Example_Axes",
Renderable = {
@@ -16,9 +16,9 @@ local Object = {
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -12,7 +12,7 @@ local modelFolder = asset.resource({
Version = 1
})
local Object = {
local Item = {
Type = "ScreenSpaceRenderableRenderable",
Identifier = "ScreenSpaceRenderableRenderable_Example_ModelDistance",
Renderable = {
@@ -33,9 +33,9 @@ local Object = {
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -12,7 +12,7 @@ local modelFolder = asset.resource({
Version = 1
})
local Object = {
local Item = {
Type = "ScreenSpaceRenderableRenderable",
Identifier = "ScreenSpaceRenderableRenderable_Example_Model",
Transform = {
@@ -39,9 +39,9 @@ local Object = {
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -0,0 +1,16 @@
-- Basic
-- This example creates a screen space renderable that displays a static text.
local Item = {
Type = "ScreenSpaceText",
Identifier = "ScreenSpaceText_Example",
Text = "Example Text"
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -0,0 +1,19 @@
-- Changing Font
-- This example creates a screen space renderable that displays a static text with a
-- non-standard font. This is using one of the fonts that is loaded by default in the
-- openspace.cfg file.
local Item = {
Type = "ScreenSpaceText",
Identifier = "ScreenSpaceText_Example_Font",
Text = "Example Text - Font",
FontName = "Light"
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -0,0 +1,20 @@
-- Font Size
-- This example creates a screen space renderable that displays a static text with a
-- larger font. The FontSize parameter is increased to improve the fidelity of the text
-- being rendered. The Scale parameter will make the text show up larger on the screen.
local Item = {
Type = "ScreenSpaceText",
Identifier = "ScreenSpaceText_Example_FontSize",
Text = "Example Text - Font Size",
Scale = 0.5,
FontSize = 72
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Item)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Item)
end)
@@ -0,0 +1,47 @@
-- Basic
-- This asset creates a translation that places coordinate axes on the surface of a
-- planetary body. Note that this examples only the position of the coordinate axes, but
-- leaves the orientation unchanged, causing their rotation to be inherited from the
-- parent node.
-- The example needs a `RenderableGlobe` as a parent to function
local Globe = {
Identifier = "GlobeTranslation_Example_Globe",
Renderable = {
Type = "RenderableGlobe"
},
GUI = {
Name = "GlobeTranslation - Basic (Globe)",
Path = "/Examples"
}
}
local Node = {
Identifier = "GlobeTranslation_Example",
Parent = "GlobeTranslation_Example_Globe",
Transform = {
Translation = {
Type = "GlobeTranslation",
Globe = "GlobeTranslation_Example_Globe",
Latitude = 20.0,
Longitude = -45.0
}
},
Renderable = {
Type = "RenderableCartesianAxes"
},
GUI = {
Name = "GlobeTranslation - Basic",
Path = "/Examples"
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(Globe)
openspace.addSceneGraphNode(Node)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(Node)
openspace.removeSceneGraphNode(Globe)
end)
@@ -0,0 +1,58 @@
-- Adaptive Height
-- This asset creates a translation that places coordinate axes on the surface of a
-- planetary body while adjusting to the existing height map on the globe. Note that this
-- examples only the position of the coordinate axes, but leaves the orientation
-- unchanged, causing their rotation to be inherited from the parent node.
-- The example needs a `RenderableGlobe` with a height map as a parent to function
local layer = asset.require("scene/solarsystem/planets/earth/layers/heightlayers/blue_marble_height")
local Globe = {
Identifier = "GlobeTranslation_Example_AdaptiveHeight_Globe",
Renderable = {
Type = "RenderableGlobe",
Layers = {
HeightLayers = { layer.layer }
}
},
GUI = {
Name = "GlobeTranslation - Adaptive Height (Globe)",
Path = "/Examples"
}
}
local Node = {
Identifier = "GlobeTranslation_Example_AdaptiveHeight",
Parent = "GlobeTranslation_Example_AdaptiveHeight_Globe",
Transform = {
Translation = {
Type = "GlobeTranslation",
Globe = "GlobeTranslation_Example_AdaptiveHeight_Globe",
Latitude = 20.0,
Longitude = -45.0,
UseHeightmap = true
}
},
Renderable = {
Type = "RenderableCartesianAxes"
},
GUI = {
Name = "GlobeTranslation - Adaptive Height",
Path = "/Examples"
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(Globe)
-- The layer is designed for a globe with Earth scale. So we need to scale it down for
-- it to make sense for this example
openspace.setPropertyValueSingle("Scene.GlobeTranslation_Example_AdaptiveHeight_Globe.Renderable.Layers.HeightLayers.Earth_Bluemarble_Height.Enabled", true)
enspace.setPropertyValueSingle("Scene.GlobeTranslation_Example_AdaptiveHeight_Globe.Renderable.Layers.HeightLayers.Earth_Bluemarble_Height.Settings.Multiplier", 1.9)
openspace.setPropertyValueSingle("Scene.GlobeTranslation_Example_AdaptiveHeight_Globe.Renderable.Layers.HeightLayers.Earth_Bluemarble_Height.Settings.Gamma", 0.16)
openspace.addSceneGraphNode(Node)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(Node)
openspace.removeSceneGraphNode(Globe)
end)
@@ -0,0 +1,48 @@
-- Fixed Height
-- This asset creates a translation that places coordinate axes on the surface of a
-- planetary body with a fixed height to the reference surface of the globe. Note that
-- this examples only the position of the coordinate axes, but leaves the orientation
-- unchanged, causing their rotation to be inherited from the parent node.
-- The example needs a `RenderableGlobe` with a height map as a parent to function
local Globe = {
Identifier = "GlobeTranslation_Example_FixedHeight_Globe",
Renderable = {
Type = "RenderableGlobe"
},
GUI = {
Name = "GlobeTranslation - Fixed Height (Globe)",
Path = "/Examples"
}
}
local Node = {
Identifier = "GlobeTranslation_Example_FixedHeight",
Parent = "GlobeTranslation_Example_FixedHeight_Globe",
Transform = {
Translation = {
Type = "GlobeTranslation",
Globe = "GlobeTranslation_Example_FixedHeight_Globe",
Latitude = 20.0,
Longitude = -45.0,
Altitude = 2.0
}
},
Renderable = {
Type = "RenderableCartesianAxes"
},
GUI = {
Name = "GlobeTranslation - Fixed Height",
Path = "/Examples"
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(Globe)
openspace.addSceneGraphNode(Node)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(Node)
openspace.removeSceneGraphNode(Globe)
end)
@@ -1,29 +0,0 @@
local transforms = asset.require("scene/solarsystem/sun/transforms")
local ToyVolume = {
Identifier = "RenderableToyVolume",
Parent = transforms.SolarSystemBarycenter.Identifier,
Renderable = {
Type = "RenderableToyVolume",
Size = { 5, 5, 5 },
ScalingExponent = 11,
StepSize = 0.01,
Color = { 1.0, 0.0, 0.0 }
},
GUI = {
Path = "/Examples"
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(ToyVolume)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(ToyVolume)
end)
asset.export(ToyVolume)
@@ -1,5 +0,0 @@
width 1024
lower 0.0
upper 1.0
mappingkey 0.0 250 250 250 0
mappingkey 1.0 200 200 200 255
+4 -1
View File
@@ -58,7 +58,10 @@ local AltAzGrid = {
Opacity = 0.8,
Color = { 0.2, 0.4, 0.2 },
LineWidth = 2.0,
RenderBinMode = "PostDeferredTransparent"
RenderBinMode = "PostDeferredTransparent",
LatSegments = 19,
LongSegments = 36
},
Tag = { "nightsky_marking" },
GUI = {
+19 -12
View File
@@ -46,10 +46,11 @@ local Mercury = {
Tag = { "nightsky_billboard" },
GUI = {
Name = "Night Sky Mercury",
Description = [[A night sky version of the planet Mercury, making it visible as
a bright object on the sky (textured representation).]],
Path = "/Night Sky/Planets",
OrderingNumber = 1
Focusable = false,
OrderingNumber = 1,
Description = [[A night sky version of the planet Mercury, making it visible as
a bright object on the sky (textured representation).]]
}
}
@@ -78,10 +79,11 @@ local Venus = {
Tag = { "nightsky_billboard" },
GUI = {
Name = "Night Sky Venus",
Description = [[A night sky version of the planet Venus, making it visible as
a bright object on the sky (textured representation).]],
Path = "/Night Sky/Planets",
OrderingNumber = 2
Focusable = false,
OrderingNumber = 2,
Description = [[A night sky version of the planet Venus, making it visible as
a bright object on the sky (textured representation).]]
}
}
@@ -111,6 +113,7 @@ local Mars = {
GUI = {
Name = "Night Sky Mars",
Path = "/Night Sky/Planets",
Focusable = false,
OrderingNumber = 4
}
}
@@ -140,10 +143,11 @@ local Jupiter = {
Tag = { "nightsky_billboard" },
GUI = {
Name = "Night Sky Jupiter",
Description = [[A night sky version of the planet Jupiter, making it visible as
a bright object on the sky (textured representation).]],
Path = "/Night Sky/Planets",
OrderingNumber = 5
Focusable = false,
OrderingNumber = 5,
Description = [[A night sky version of the planet Jupiter, making it visible as
a bright object on the sky (textured representation).]]
}
}
@@ -160,6 +164,8 @@ local Saturn = {
File = textures .. "glare.png"
},
SizeSettings = {
ScaleFactor = 10,
ScaleExponent = 15,
MaxSize = 0.332,
EnableMaxSizeControl = true
},
@@ -170,10 +176,11 @@ local Saturn = {
Tag = { "nightsky_billboard" },
GUI = {
Name = "Night Sky Saturn",
Description = [[A night sky version of the planet Saturn, making it visible as
a bright object on the sky (textured representation).]],
Path = "/Night Sky/Planets",
OrderingNumber = 6
Focusable = false,
OrderingNumber = 6,
Description = [[A night sky version of the planet Saturn, making it visible as
a bright object on the sky (textured representation).]]
}
}
@@ -37,6 +37,7 @@ local COBE = {
GUI = {
Name = "COBE",
Path = "/Universe/Cosmic Microwave Background",
Focusable = false,
Description = [[In 1990, COBE, the Cosmic Background Explorer, took the first
detailed map of the cosmic microwave background light. The red areas are
relatively hotter areas of the CMB, while the blue areas are cooler than the
@@ -71,6 +72,7 @@ local WMAP = {
GUI = {
Name = "WMAP",
Path = "/Universe/Cosmic Microwave Background",
Focusable = false,
Description = [[WMAP, the Wilkinson Microwave Anisotropy Probe, released this all-sky
image of the cosmic microwave background light in 2003. The blue colors are slightly
cooler than average and red is slightly warmer, with fluctuations of about a
@@ -104,6 +106,7 @@ local Planck = {
GUI = {
Name = "Planck",
Path = "/Universe/Cosmic Microwave Background",
Focusable = false,
Description = [[The Planck mission's 2013 image of the cosmic microwave background
light release is the most detailed view of the CMB we have to date. The orange
areas represent the slightly hotter areas, and the blue areas show the areas that
@@ -33,7 +33,8 @@ local PlanckMultiverse1 = {
},
GUI = {
Name = "Planck Multiverse 1",
Path = "/Universe/Cosmic Microwave Background"
Path = "/Universe/Cosmic Microwave Background",
Focusable = false
}
}
@@ -64,7 +65,8 @@ local PlanckMultiverse2 = {
},
GUI = {
Name = "Planck Multiverse 2",
Path = "/Universe/Cosmic Microwave Background"
Path = "/Universe/Cosmic Microwave Background",
Focusable = false
}
}
@@ -95,7 +97,8 @@ local PlanckMultiverse3 = {
},
GUI = {
Name = "Planck Multiverse 3",
Path = "/Universe/Cosmic Microwave Background"
Path = "/Universe/Cosmic Microwave Background",
Focusable = false
}
}
@@ -126,7 +129,8 @@ local PlanckMultiverse4 = {
},
GUI = {
Name = "Planck Multiverse 4",
Path = "/Universe/Cosmic Microwave Background"
Path = "/Universe/Cosmic Microwave Background",
Focusable = false
}
}
@@ -104,7 +104,7 @@ local EquatorialSphere = {
Opacity = 1.0,
Color = { 0.3, 0.3, 0.15 },
LineWidth = 2.0,
LatSegments = 36,
LatSegments = 19,
LongSegments = 24,
},
Tag = { "du_grid" },
@@ -164,7 +164,9 @@ local EclipticSphere = {
Enabled = false,
Opacity = 1.0,
Color = { 0.3, 0.15, 0.15 },
LineWidth = 2.0
LineWidth = 2.0,
LatSegments = 19,
LongSegments = 24
},
Tag = { "du_grid" },
GUI = {
@@ -36,6 +36,7 @@ local OrionClusterStars = {
GUI = {
Name = "Orion Nebula Star Cluster",
Path = "/Milky Way/Orion",
Focusable = false,
Description = [[In order to have an accurate depiction of the Orion nebula, we need to
include the star cluster that was birthed from it. We turned to a study of the
cluster's stellar population by Lynne Hillenbrand, who was working at the University
@@ -80,6 +80,7 @@ local OrionNebulaModel = {
GUI = {
Name = "Orion Nebula Model",
Path = "/Milky Way/Orion",
Focusable = false,
Description = "Orion Nebula 3D model. See Orion Nebula for description"
}
}
@@ -114,6 +115,7 @@ local OrionNebulaShocksModel = {
GUI = {
Name = "Orion Nebula Shocks",
Path = "/Milky Way/Orion",
Focusable = false,
Description = "Orion Nebula Shocks 3D model. See Orion Nebula for description"
}
}
@@ -148,6 +150,7 @@ local OrionNebulaProplydsModel = {
GUI = {
Name = "Orion Nebula Proplyds",
Path = "/Milky Way/Orion",
Focusable = false,
Description = "Orion Nebula Proplyds 3D model. See Orion Nebula for description"
}
}
@@ -1,4 +1,5 @@
asset.require("./trail")
asset.require("./trail_barycentric")
asset.require("./pluto")
asset.require("./charon/charon")
asset.require("./charon/charon_trail")
@@ -0,0 +1,48 @@
local transforms = asset.require("./transforms")
local coreKernels = asset.require("spice/core")
local PlutoTrailBarycentric = {
Identifier = "PlutoBarycentricTrail",
Parent = transforms.PlutoBarycenter.Identifier,
Renderable = {
Type = "RenderableTrailOrbit",
Translation = {
Type = "SpiceTranslation",
Target = coreKernels.ID.Pluto,
Observer = coreKernels.ID.PlutoBarycenter
},
Color = { 0.00, 0.62, 1.00 },
Period = 6.38723,
Resolution = 1000
},
Tag = { "planetTrail_dwarf" },
GUI = {
Name = "Pluto Barycentric Trail",
Path = "/Solar System/Dwarf Planets/Pluto",
Focusable = false,
Description = "Orbit of Pluto around its Barycenter"
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(PlutoTrailBarycentric)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(PlutoTrailBarycentric)
end)
asset.export(PlutoTrailBarycentric)
asset.meta = {
Name = "Pluto Barycentric Trail",
Description = "Trail of Pluto as observed by its Barycenter",
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}
@@ -34,8 +34,9 @@ local EquatorialCutplane = {
Opacity = 0.7
},
GUI = {
Name = "Cutplane Equitorial",
Name = "Cutplane Equatorial",
Path = "/Solar System/Heliosphere/Bastille Day 2000",
Focusable = false,
Description = [[Equatorial cutplane sequence for the bastille day CME event. This
asset contains data from 2000-07-14 08:38 to 2000-07-14 12:00]]
}
@@ -65,6 +66,7 @@ local MeridialCutplane = {
GUI = {
Name = "Cutplane Meridial",
Path = "/Solar System/Heliosphere/Bastille Day 2000",
Focusable = false,
Description = [[Meridial cutplane sequence for the bastille day CME event. This asset
contains data from 2000-07-14 08:38 to 2000-07-14 12:00]]
}
@@ -26,8 +26,9 @@ local TravelSpeedIndicator = {
FadeLength = 10
},
GUI = {
Name = "Speed Indicator",
Path = "/Solar System/Heliosphere",
Name = "Speed indicator",
Focusable = false,
Description = "Speed of light indicator from sun to earth"
}
}
@@ -33,7 +33,7 @@ local CarringtonPrimeMeridian = {
Color = { 1.0, 0.0, 0.0 },
LineWidth = 2.0,
LongSegments = 2,
LatSegments = 64
LatSegments = 19
},
GUI = {
Name = "Carrington Prime Meridian",
@@ -63,7 +63,7 @@ local WSA_GridSlice = {
Color = { 0.8, 0.8, 0.8 },
LineWidth = 2.0,
LongSegments = 2,
LatSegments = 64
LatSegments = 19
},
GUI = {
Name = "Solar Longitude Facing the Earth",
@@ -86,8 +86,7 @@ local WSA_Grid10Degrees = {
Type = "RenderableSphericalGrid",
Size = gridSizeRadius,
Color = { 0.035, 0.675, 0.255 },
LineWidth = 1.0,
Segments = 36
LineWidth = 1.0
},
GUI = {
Name = "Grid on Sun",
@@ -26,7 +26,8 @@ local Station2Boulder1Holder = {
},
GUI = {
Name = "Station 2 Boulder 1",
Path = "/Solar System/Missions/Apollo/17/Station 2"
Path = "/Solar System/Missions/Apollo/17/Station 2",
Focusable = false
}
}
@@ -75,7 +76,8 @@ local Station2Boulder2Holder = {
},
GUI = {
Name = "Station 2 Boulder 2",
Path = "/Solar System/Missions/Apollo/17/Station 2"
Path = "/Solar System/Missions/Apollo/17/Station 2",
Focusable = false
}
}
@@ -124,7 +126,8 @@ local Station2Boulder3Holder = {
},
GUI = {
Name = "Station 2 Boulder 3",
Path = "/Solar System/Missions/Apollo/17/Station 2"
Path = "/Solar System/Missions/Apollo/17/Station 2",
Focusable = false
}
}
@@ -26,7 +26,8 @@ local Station6Frag1Holder = {
},
GUI = {
Name = "Station 6 Fragment 1",
Path = "/Solar System/Missions/Apollo/17/Station 6"
Path = "/Solar System/Missions/Apollo/17/Station 6",
Focusable = false
}
}
@@ -73,7 +74,8 @@ local Station6Frag23Holder = {
Parent = moon.Moon.Identifier,
GUI = {
Name = "Station 6 Fragments 2 & 3 Holder",
Path = "/Solar System/Missions/Apollo/17/Station 6"
Path = "/Solar System/Missions/Apollo/17/Station 6",
Focusable = false
}
}
@@ -26,7 +26,8 @@ local Station7BoulderHolder = {
},
GUI = {
Name = "Station 7 Boulder",
Path = "/Solar System/Missions/Apollo/17/Station 7"
Path = "/Solar System/Missions/Apollo/17/Station 7",
Focusable = false
}
}
@@ -78,7 +78,8 @@ local PolyCam = {
},
GUI = {
Name = "OCAMS POLYCAM",
Path = "/Solar System/Missions/OSIRIS REx/Instruments"
Path = "/Solar System/Missions/OSIRIS REx/Instruments",
Focusable = false
}
}
@@ -110,7 +111,8 @@ local Rexis = {
},
GUI = {
Name = "REXIS",
Path = "/Solar System/Missions/OSIRIS REx/Instruments"
Path = "/Solar System/Missions/OSIRIS REx/Instruments",
Focusable = false
}
}
@@ -24,7 +24,8 @@ local EarthMarker = {
},
GUI = {
Name = "Earth Marker",
Path = "/Solar System/Planets/Earth"
Path = "/Solar System/Planets/Earth",
Focusable = false
}
}
@@ -127,7 +127,7 @@ for i,v in ipairs(layers_names) do
local layer = {
Identifier = Identifier .. "-" .. v,
Name = Name .. " " .. v,
Enabled = asset.enabled,
Enabled = false,
ZIndex = 100,
FilePath = imagesDestination .. "/" .. v .. ".jpg",
Description = Description
@@ -52,6 +52,7 @@ local NeptuneLabel = {
GUI = {
Name = "Neptune Label",
Path = "/Solar System/Planets/Neptune",
Focusable = false,
Description = "Main planet label for Neptune"
}
}
@@ -53,7 +53,8 @@ local MirandaTrail = {
},
GUI = {
Name = "Miranda Trail",
Path = "/Solar System/Planets/Uranus/Major Moons/Miranda"
Path = "/Solar System/Planets/Uranus/Major Moons/Miranda",
Focusable = false
}
}
@@ -77,7 +78,8 @@ local MirandaLabel = {
Tag = { "solarsystem_labels", "moon_labels", "major_moon_labels" },
GUI = {
Name = "Miranda Label",
Path = "/Solar System/Planets/Uranus/Major Moons/Miranda"
Path = "/Solar System/Planets/Uranus/Major Moons/Miranda",
Focusable = false
}
}
@@ -130,7 +132,8 @@ local ArielTrail = {
},
GUI = {
Name = "Ariel Trail",
Path = "/Solar System/Planets/Uranus/Major Moons/Ariel"
Path = "/Solar System/Planets/Uranus/Major Moons/Ariel",
Focusable = false
}
}
@@ -154,7 +157,8 @@ local ArielLabel = {
Tag = { "solarsystem_labels", "moon_labels", "major_moon_labels" },
GUI = {
Name = "Ariel Label",
Path = "/Solar System/Planets/Uranus/Major Moons/Ariel"
Path = "/Solar System/Planets/Uranus/Major Moons/Ariel",
Focusable = false
}
}
@@ -207,7 +211,8 @@ local UmbrielTrail = {
},
GUI = {
Name = "Umbriel Trail",
Path = "/Solar System/Planets/Uranus/Major Moons/Umbriel"
Path = "/Solar System/Planets/Uranus/Major Moons/Umbriel",
Focusable = false
}
}
@@ -231,7 +236,8 @@ local UmbrielLabel = {
Tag = { "solarsystem_labels", "moon_labels", "major_moon_labels" },
GUI = {
Name = "Umbriel Label",
Path = "/Solar System/Planets/Uranus/Major Moons/Umbriel"
Path = "/Solar System/Planets/Uranus/Major Moons/Umbriel",
Focusable = false
}
}
@@ -284,7 +290,8 @@ local TitaniaTrail = {
},
GUI = {
Name = "Titania Trail",
Path = "/Solar System/Planets/Uranus/Major Moons/Titania"
Path = "/Solar System/Planets/Uranus/Major Moons/Titania",
Focusable = false
}
}
@@ -308,7 +315,8 @@ local TitaniaLabel = {
Tag = { "solarsystem_labels", "moon_labels", "major_moon_labels" },
GUI = {
Name = "Titania Label",
Path = "/Solar System/Planets/Uranus/Major Moons/Titania"
Path = "/Solar System/Planets/Uranus/Major Moons/Titania",
Focusable = false
}
}
@@ -361,7 +369,8 @@ local OberonTrail = {
},
GUI = {
Name = "Oberon Trail",
Path = "/Solar System/Planets/Uranus/Major Moons/Oberon"
Path = "/Solar System/Planets/Uranus/Major Moons/Oberon",
Focusable = false
}
}
@@ -385,7 +394,8 @@ local OberonLabel = {
Tag = { "solarsystem_labels", "moon_labels", "major_moon_labels" },
GUI = {
Name = "Oberon Label",
Path = "/Solar System/Planets/Uranus/Major Moons/Oberon"
Path = "/Solar System/Planets/Uranus/Major Moons/Oberon",
Focusable = false
}
}
@@ -66,6 +66,7 @@ local HUDFJWSTLine = {
GUI = {
Name = "JWST to HUDF Line",
Path = "/Solar System/Telescopes/JWST/HUDF",
Focusable = false,
Description = [[
Line from the James Webb Space Telescope to the Hubble Ultra Deep Field
]]
@@ -22,8 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_BASE___SCREENSPACEFRAMEBUFFER___H__
#define __OPENSPACE_MODULE_BASE___SCREENSPACEFRAMEBUFFER___H__
#ifndef __OPENSPACE_CORE___SCREENSPACEFRAMEBUFFER___H__
#define __OPENSPACE_CORE___SCREENSPACEFRAMEBUFFER___H__
#include <openspace/rendering/screenspacerenderable.h>
@@ -44,19 +44,18 @@ namespace documentation { struct Documentation; }
* an attached texture. The texture is then used on a screen space plane that works both
* in fisheye and flat screens.
*/
class ScreenSpaceFramebuffer : public ScreenSpaceRenderable {
class ScreenSpaceRenderableFramebuffer : public ScreenSpaceRenderable {
public:
using RenderFunction = std::function<void()>;
explicit ScreenSpaceFramebuffer(const ghoul::Dictionary& dictionary);
virtual ~ScreenSpaceFramebuffer() override;
explicit ScreenSpaceRenderableFramebuffer(const ghoul::Dictionary& dictionary);
virtual ~ScreenSpaceRenderableFramebuffer() override;
void initializeGL() override;
void deinitializeGL() override;
void render(const RenderData& renderData) override;
bool isReady() const override;
void setSize(glm::vec2 size);
void addRenderFunction(RenderFunction renderFunction);
void removeAllRenderFunctions();
@@ -79,4 +78,4 @@ private:
} //namespace openspace
#endif // __OPENSPACE_MODULE_BASE___SCREENSPACEFRAMEBUFFER___H__
#endif // __OPENSPACE_CORE___SCREENSPACEFRAMEBUFFER___H__
@@ -0,0 +1,77 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* 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___SCREENSPACERENDERABLETEXT___H__
#define __OPENSPACE_CORE___SCREENSPACERENDERABLETEXT___H__
#include <openspace/rendering/screenspacerenderable.h>
#include <openspace/properties/misc/stringproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <ghoul/font/fontrenderer.h>
namespace ghoul { class Dictionary; }
namespace ghoul::opengl {
class FramebufferObject;
class Texture;
} // namespace ghoul::opengl
namespace ghoul::fontrendering { class Font; }
namespace openspace {
namespace documentation { struct Documentation; }
class ScreenSpaceRenderableText : public ScreenSpaceRenderable {
public:
explicit ScreenSpaceRenderableText(const ghoul::Dictionary& dictionary);
void initializeGL() override;
void deinitializeGL() override;
bool isReady() const override;
void update() override;
void render(const RenderData& renderData) override;
static documentation::Documentation Documentation();
protected:
std::string _buffer;
private:
void updateFramebuffer();
void bindTexture() override;
properties::StringProperty _fontName;
properties::FloatProperty _fontSize;
std::shared_ptr<ghoul::fontrendering::Font> _font;
std::unique_ptr<ghoul::fontrendering::FontRenderer> _fontRenderer;
std::unique_ptr<ghoul::opengl::FramebufferObject> _framebuffer;
std::unique_ptr<ghoul::opengl::Texture> _texture;
};
} //namespace openspace
#endif // __OPENSPACE_CORE___SCREENSPACERENDERABLETEXT___H__
+4 -2
View File
@@ -32,7 +32,8 @@ Keyframe<T>::Keyframe(size_t i, double t, T d)
template <typename T>
void Timeline<T>::addKeyframe(double timestamp, T&& data) {
Keyframe<T> keyframe(++_nextKeyframeId, timestamp, std::move(data));
_nextKeyframeId++;
Keyframe<T> keyframe(_nextKeyframeId, timestamp, std::move(data));
const auto iter = std::upper_bound(
_keyframes.cbegin(),
_keyframes.cend(),
@@ -44,7 +45,8 @@ void Timeline<T>::addKeyframe(double timestamp, T&& data) {
template <typename T>
void Timeline<T>::addKeyframe(double timestamp, const T& data) {
Keyframe<T> keyframe(++_nextKeyframeId, timestamp, data);
_nextKeyframeId++;
Keyframe<T> keyframe(_nextKeyframeId, timestamp, data);
const auto iter = std::upper_bound(
_keyframes.cbegin(),
_keyframes.cend(),
+4 -2
View File
@@ -71,11 +71,12 @@ set(HEADER_FILES
rendering/renderabletrailorbit.h
rendering/renderabletrailtrajectory.h
rendering/screenspacedashboard.h
rendering/screenspaceframebuffer.h
rendering/screenspacedate.h
rendering/screenspaceimagelocal.h
rendering/screenspaceimageonline.h
rendering/screenspaceinsetblackout.h
rendering/screenspacerenderablerenderable.h
rendering/screenspacetext.h
rendering/screenspacetimevaryingimageonline.h
rotation/timelinerotation.h
rotation/constantrotation.h
@@ -149,11 +150,12 @@ set(SOURCE_FILES
rendering/renderabletrailtrajectory.cpp
rendering/screenspacedashboard.cpp
rendering/screenspacedashboard_lua.inl
rendering/screenspaceframebuffer.cpp
rendering/screenspacedate.cpp
rendering/screenspaceimagelocal.cpp
rendering/screenspaceimageonline.cpp
rendering/screenspaceinsetblackout.cpp
rendering/screenspacerenderablerenderable.cpp
rendering/screenspacetext.cpp
rendering/screenspacetimevaryingimageonline.cpp
rotation/timelinerotation.cpp
rotation/constantrotation.cpp
+6 -3
View File
@@ -67,11 +67,12 @@
#include <modules/base/rendering/renderableprism.h>
#include <modules/base/rendering/renderabletimevaryingsphere.h>
#include <modules/base/rendering/screenspacedashboard.h>
#include <modules/base/rendering/screenspaceframebuffer.h>
#include <modules/base/rendering/screenspaceimagelocal.h>
#include <modules/base/rendering/screenspaceimageonline.h>
#include <modules/base/rendering/screenspaceinsetblackout.h>
#include <modules/base/rendering/screenspacerenderablerenderable.h>
#include <modules/base/rendering/screenspacedate.h>
#include <modules/base/rendering/screenspacetext.h>
#include <modules/base/rendering/screenspacetimevaryingimageonline.h>
#include <modules/base/rotation/constantrotation.h>
#include <modules/base/rotation/fixedrotation.h>
@@ -115,7 +116,6 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) {
ghoul_assert(fSsRenderable, "ScreenSpaceRenderable factory was not created");
fSsRenderable->registerClass<ScreenSpaceDashboard>("ScreenSpaceDashboard");
fSsRenderable->registerClass<ScreenSpaceFramebuffer>("ScreenSpaceFramebuffer");
fSsRenderable->registerClass<ScreenSpaceImageLocal>("ScreenSpaceImageLocal");
fSsRenderable->registerClass<ScreenSpaceImageOnline>("ScreenSpaceImageOnline");
fSsRenderable->registerClass<ScreenSpaceInsetBlackout>("ScreenSpaceInsetBlackout");
@@ -125,6 +125,8 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) {
fSsRenderable->registerClass<ScreenSpaceTimeVaryingImageOnline>(
"ScreenSpaceTimeVaryingImageOnline"
);
fSsRenderable->registerClass<ScreenSpaceDate>("ScreenSpaceDate");
fSsRenderable->registerClass<ScreenSpaceText>("ScreenSpaceText");
ghoul::TemplateFactory<DashboardItem>* fDashboard =
@@ -308,11 +310,12 @@ std::vector<documentation::Documentation> BaseModule::documentations() const {
SizeMappingComponent::Documentation(),
ScreenSpaceDashboard::Documentation(),
ScreenSpaceFramebuffer::Documentation(),
ScreenSpaceDate::Documentation(),
ScreenSpaceImageLocal::Documentation(),
ScreenSpaceImageOnline::Documentation(),
ScreenSpaceInsetBlackout::Documentation(),
ScreenSpaceRenderableRenderable::Documentation(),
ScreenSpaceText::Documentation(),
ScreenSpaceTimeVaryingImageOnline::Documentation(),
ConstantRotation::Documentation(),
@@ -124,7 +124,7 @@ RenderableSphericalGrid::RenderableSphericalGrid(const ghoul::Dictionary& dictio
, _gridProgram(nullptr)
, _color(ColorInfo, glm::vec3(0.5f), glm::vec3(0.f), glm::vec3(1.f))
, _longSegments(LongSegmentsInfo, 36, 4, 200)
, _latSegments(LatSegmentsInfo, 36, 4, 200)
, _latSegments(LatSegmentsInfo, 19, 4, 200)
, _lineWidth(LineWidthInfo, 0.5f, 1.f, 20.f)
{
const Parameters p = codegen::bake<Parameters>(dictionary);
@@ -136,9 +136,8 @@ RenderableSphericalGrid::RenderableSphericalGrid(const ghoul::Dictionary& dictio
addProperty(_color);
auto gridDirty = [this]() {
if (_longSegments.value() % 2 == 1) {
_longSegments = _longSegments - 1;
}
_longSegments = std::max<int>(_longSegments, 3);
_latSegments = std::max<int>(_latSegments, 3);
_gridIsDirty = true;
};
_longSegments = p.segments.value_or(p.longSegments.value_or(_longSegments));
@@ -188,11 +187,9 @@ void RenderableSphericalGrid::initializeGL() {
glGenVertexArrays(1, &_vaoID);
glGenBuffers(1, &_vBufferID);
glGenBuffers(1, &_iBufferID);
glBindVertexArray(_vaoID);
glBindBuffer(GL_ARRAY_BUFFER, _vBufferID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
}
@@ -204,9 +201,6 @@ void RenderableSphericalGrid::deinitializeGL() {
glDeleteBuffers(1, &_vBufferID);
_vBufferID = 0;
glDeleteBuffers(1, &_iBufferID);
_iBufferID = 0;
BaseModule::ProgramObjectManager.release(
"GridProgram",
[](ghoul::opengl::ProgramObject* p) {
@@ -239,8 +233,23 @@ void RenderableSphericalGrid::render(const RenderData& data, RendererTasks&) {
glEnable(GL_LINE_SMOOTH);
glBindVertexArray(_vaoID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID);
glDrawElements(GL_LINES, 6 * _longSegments * _latSegments, GL_UNSIGNED_INT, nullptr);
// Render latitude rings
glMultiDrawArrays(
GL_LINE_LOOP,
_latitudeRenderInfo.first.data(),
_latitudeRenderInfo.count.data(),
_latSegments
);
// Render longitude segments
glMultiDrawArrays(
GL_LINE_STRIP,
_longitudeRenderInfo.first.data(),
_longitudeRenderInfo.count.data(),
_longSegments
);
glBindVertexArray(0);
_gridProgram->deactivate();
@@ -286,71 +295,72 @@ void RenderableSphericalGrid::update(const UpdateData&) {
return;
}
unsigned int vertSize = (_longSegments + 1) * (_latSegments + 1);
std::vector<Vertex> vert = std::vector<Vertex>(vertSize, { 0.f, 0.f, 0.f });
unsigned int idxSize = 6 * _longSegments * _latSegments;
std::vector<int> idx = std::vector<int>(idxSize, 0);
// Instead of using an element buffer which didn't save that much memory and just
// caused some indirections, we are creating two sets of vertices in the same vertex
// buffer in this function. First all of the vertices for the longitudinal rings, one
// ring after another. After that it is all the vertices for the latitudinal arcs, one
// arc after another
int nr = 0;
for (int lat = 0; lat <= _latSegments; lat++) {
// define an extra vertex around the y-axis due to texture mapping
for (int lng = 0; lng <= _longSegments; lng++) {
// * 2 since we store all vertices twice
const unsigned int vertSize = _longSegments * _latSegments * 2;
std::vector<Vertex> vert;
vert.reserve(vertSize);
for (int lat = 0; lat < _latSegments; lat++) {
for (int lng = 0; lng < _longSegments; lng++) {
// inclination angle (north to south)
const float theta = lat * glm::pi<float>() / _latSegments * 2.f; // 0 -> PI
const float theta =
static_cast<float>(lat) / static_cast<float>(_latSegments - 1) *
glm::pi<float>(); // 0 -> PI
// azimuth angle (east to west)
const float phi = lng * 2.f * glm::pi<float>() / _longSegments; // 0 -> 2*PI
// Dividing by one segment more as the points for 0 and 2*pi are identical
const float phi =
static_cast<float>(lng) / static_cast<float>(_longSegments) *
2.f * glm::pi<float>(); // 0 -> 2*PI
const float x = std::sin(phi) * std::sin(theta); //
const float y = std::cos(theta); // up
const float z = std::cos(phi) * std::sin(theta); //
glm::vec3 normal = glm::vec3(x, y, z);
if (x != 0.f || y != 0.f || z != 0.f) {
normal = glm::normalize(normal);
}
glm::vec4 tmp = glm::vec4(x, y, z, 1.f);
const glm::mat4 rot = glm::rotate(
glm::mat4(1.f),
glm::half_pi<float>(),
glm::vec3(1.f, 0.f, 0.f)
);
tmp = glm::vec4(glm::dmat4(rot) * glm::dvec4(tmp));
for (int i = 0; i < 3; i++) {
vert[nr].location[i] = tmp[i];
}
++nr;
const float y = std::cos(phi) * std::sin(theta); //
const float z = std::cos(theta); // up
vert.push_back({ x, y, z });
}
}
nr = 0;
// define indices for all triangles
for (int i = 1; i <= _latSegments; i++) {
for (int j = 0; j < _longSegments; j++) {
const int t = _longSegments + 1;
idx[nr] = t * (i - 1) + j + 0; ++nr;
idx[nr] = t * (i + 0) + j + 0; ++nr;
idx[nr] = t * (i + 0) + j + 1; ++nr;
idx[nr] = t * (i - 1) + j + 1; ++nr;
idx[nr] = t * (i - 1) + j + 0; ++nr;
// Create the render info struct to be able to render the longitude rings using
// glMultiDrawArrays in the render function
_latitudeRenderInfo.first.clear();
_latitudeRenderInfo.count.clear();
for (int i = 0; i < _latSegments; i++) {
_latitudeRenderInfo.first.push_back(i * _longSegments);
_latitudeRenderInfo.count.push_back(_longSegments);
}
// Create the duplicate vertex entries to efficiently render the latitude arcs. We
// take every vertex in a longitude segment and connect it to the same index along all
// latitude arcs
for (int lng = 0; lng < _longSegments; lng++) {
for (int lat = 0; lat < _latSegments; lat++) {
Vertex v = vert[lat * _longSegments + lng];
vert.push_back(v);
}
}
// Create the render info struct to be able to render the latitude arcs using
// glMultiDrawArrays in the render function. The `base` is the offset to make this
// render call use the vertices that are in the second "block" of the VBO
_longitudeRenderInfo.first.clear();
_longitudeRenderInfo.count.clear();
const int base = _longSegments * _latSegments;
for (int i = 0; i < _longSegments; i++) {
_longitudeRenderInfo.first.push_back(i * _latSegments + base);
_longitudeRenderInfo.count.push_back(_latSegments);
}
glBindVertexArray(_vaoID);
glBindBuffer(GL_ARRAY_BUFFER, _vBufferID);
glBufferData(GL_ARRAY_BUFFER, vertSize * sizeof(Vertex), vert.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID);
glBufferData(
GL_ELEMENT_ARRAY_BUFFER,
idxSize * sizeof(int),
idx.data(), GL_STATIC_DRAW
);
_gridIsDirty = false;
}
@@ -69,7 +69,14 @@ protected:
GLuint _vaoID = 0;
GLuint _vBufferID = 0;
GLuint _iBufferID = 0;
struct {
std::vector<GLint> first;
std::vector<GLsizei> count;
} _latitudeRenderInfo;
struct {
std::vector<GLint> first;
std::vector<GLsizei> count;
} _longitudeRenderInfo;
bool _gridIsDirty = true;
+1 -1
View File
@@ -769,7 +769,7 @@ void RenderableModel::render(const RenderData& data, RendererTasks&) {
_lightDirectionsViewSpaceBuffer[nLightSources] =
lightSource->directionViewSpace(data);
++nLightSources;
nLightSources++;
}
if (_uniformCache.performShading != -1) {
@@ -408,7 +408,7 @@ RenderableTrailOrbit::UpdateReport RenderableTrailOrbit::updateTrails(
else {
// Move the current pointer fowards one step to be used as the new
// floating
++_primaryRenderInformation.first;
_primaryRenderInformation.first++;
}
}
@@ -69,7 +69,7 @@ documentation::Documentation ScreenSpaceDashboard::Documentation() {
}
ScreenSpaceDashboard::ScreenSpaceDashboard(const ghoul::Dictionary& dictionary)
: ScreenSpaceFramebuffer(dictionary)
: ScreenSpaceRenderableFramebuffer(dictionary)
, _useMainDashboard(UseMainInfo, false)
{
const Parameters p = codegen::bake<Parameters>(dictionary);
@@ -98,7 +98,7 @@ ScreenSpaceDashboard::ScreenSpaceDashboard(const ghoul::Dictionary& dictionary)
}
void ScreenSpaceDashboard::initializeGL() {
ScreenSpaceFramebuffer::initializeGL();
ScreenSpaceRenderableFramebuffer::initializeGL();
addRenderFunction([this]() {
glm::vec2 penPosition = glm::vec2(0.f, _size.value().x);
@@ -25,7 +25,7 @@
#ifndef __OPENSPACE_MODULE_BASE___SCREENSPACEDASHBOARD___H__
#define __OPENSPACE_MODULE_BASE___SCREENSPACEDASHBOARD___H__
#include <modules/base/rendering/screenspaceframebuffer.h>
#include <openspace/rendering/screenspacerenderableframebuffer.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/rendering/dashboard.h>
@@ -40,7 +40,7 @@ namespace openspace {
namespace documentation { struct Documentation; }
namespace scripting { struct LuaLibrary; }
class ScreenSpaceDashboard : public ScreenSpaceFramebuffer {
class ScreenSpaceDashboard : public ScreenSpaceRenderableFramebuffer {
public:
explicit ScreenSpaceDashboard(const ghoul::Dictionary& dictionary);
virtual ~ScreenSpaceDashboard() override = default;
+108
View File
@@ -0,0 +1,108 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/base/rendering/screenspacedate.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/time.h>
#include <openspace/util/timemanager.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/opengl/framebufferobject.h>
#include <ghoul/opengl/texture.h>
namespace {
constexpr openspace::properties::Property::PropertyInfo FormatStringInfo = {
"FormatString",
"Format string",
"The format text describing how this dashboard item renders its text. This text "
"must contain exactly one {} which is a placeholder that will contain the date "
"in the format as specified by `TimeFormat`.",
openspace::properties::Property::Visibility::AdvancedUser
};
constexpr openspace::properties::Property::PropertyInfo TimeFormatInfo = {
"TimeFormat",
"Time format",
"The format string used for formatting the date/time before being passed to the "
"string in FormatString. See "
"https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/timout_c.html for full "
"information about how to structure this format.",
openspace::properties::Property::Visibility::User
};
// This `ScreenSpaceRenderable` shows the current in-game simulation time. The
// `FormatString` and the `TimeFormat` options provide the ability to customize the
// output that is printed. See these two parameters for more information on how to
// structure the inputs.
struct [[codegen::Dictionary(ScreenSpaceTextDate)]] Parameters {
// [[codegen::verbatim(FormatStringInfo.description)]]
std::optional<std::string> formatString;
// [[codegen::verbatim(TimeFormatInfo.description)]]
std::optional<std::string> timeFormat;
};
#include "screenspacedate_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation ScreenSpaceDate::Documentation() {
return codegen::doc<Parameters>(
"base_screenspace_date",
ScreenSpaceRenderableText::Documentation()
);
}
ScreenSpaceDate::ScreenSpaceDate(const ghoul::Dictionary& dictionary)
: ScreenSpaceRenderableText(dictionary)
, _formatString(FormatStringInfo, "Date: {}")
, _timeFormat(TimeFormatInfo, "YYYY MON DD HR:MN:SC.### UTC ::RND")
{
const Parameters p = codegen::bake<Parameters>(dictionary);
_formatString = p.formatString.value_or(_formatString);
addProperty(_formatString);
_timeFormat = p.timeFormat.value_or(_timeFormat);
addProperty(_timeFormat);
}
void ScreenSpaceDate::update() {
std::string time = SpiceManager::ref().dateFromEphemerisTime(
global::timeManager->time().j2000Seconds(),
_timeFormat.value().c_str()
);
try {
// @CPP26(abock): This can be replaced with std::runtime_format
_buffer = std::vformat(_formatString.value(), std::make_format_args(time));
}
catch (const std::format_error&) {
LERRORC("ScreenSpaceDate", "Illegal format string");
}
ScreenSpaceRenderableText::update();
}
} // namespace openspace
+49
View File
@@ -0,0 +1,49 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* 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___SCREENSPACEDATE___H__
#define __OPENSPACE_MODULE_BASE___SCREENSPACEDATE___H__
#include <openspace/rendering/screenspacerenderabletext.h>
#include <openspace/properties/misc/stringproperty.h>
namespace openspace {
class ScreenSpaceDate : public ScreenSpaceRenderableText {
public:
explicit ScreenSpaceDate(const ghoul::Dictionary& dictionary);
void update() override;
static documentation::Documentation Documentation();
private:
properties::StringProperty _formatString;
properties::StringProperty _timeFormat;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_BASE___SCREENSPACEDATE___H__
@@ -143,13 +143,13 @@ namespace openspace {
documentation::Documentation ScreenSpaceRenderableRenderable::Documentation() {
return codegen::doc<Parameters>(
"base_screenspace_renderable",
ScreenSpaceFramebuffer::Documentation()
ScreenSpaceRenderableFramebuffer::Documentation()
);
}
ScreenSpaceRenderableRenderable::ScreenSpaceRenderableRenderable(
const ghoul::Dictionary& dictionary)
: ScreenSpaceFramebuffer(dictionary)
: ScreenSpaceRenderableFramebuffer(dictionary)
, _time(
TimeInfo,
0.0,
@@ -232,7 +232,7 @@ ScreenSpaceRenderableRenderable::ScreenSpaceRenderableRenderable(
ScreenSpaceRenderableRenderable::~ScreenSpaceRenderableRenderable() {}
void ScreenSpaceRenderableRenderable::initialize() {
ScreenSpaceFramebuffer::initialize();
ScreenSpaceRenderableFramebuffer::initialize();
_transform.translation->initialize();
_transform.rotation->initialize();
_transform.scale->initialize();
@@ -240,7 +240,7 @@ void ScreenSpaceRenderableRenderable::initialize() {
}
void ScreenSpaceRenderableRenderable::initializeGL() {
ScreenSpaceFramebuffer::initializeGL();
ScreenSpaceRenderableFramebuffer::initializeGL();
_renderable->initializeGL();
@@ -288,7 +288,7 @@ void ScreenSpaceRenderableRenderable::deinitializeGL() {
_renderable->deinitializeGL();
_renderable->deinitialize();
ScreenSpaceFramebuffer::deinitializeGL();
ScreenSpaceRenderableFramebuffer::deinitializeGL();
}
void ScreenSpaceRenderableRenderable::update() {
@@ -25,7 +25,7 @@
#ifndef __OPENSPACE_MODULE_BASE___SCREENSPACERENDERABLERENDERABLE___H__
#define __OPENSPACE_MODULE_BASE___SCREENSPACERENDERABLERENDERABLE___H__
#include <modules/base//rendering/screenspaceframebuffer.h>
#include <openspace/rendering/screenspacerenderableframebuffer.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/doubleproperty.h>
@@ -43,7 +43,7 @@ class Translation;
namespace documentation { struct Documentation; }
class ScreenSpaceRenderableRenderable : public ScreenSpaceFramebuffer {
class ScreenSpaceRenderableRenderable : public ScreenSpaceRenderableFramebuffer {
public:
using RenderFunction = std::function<void()>;
@@ -0,0 +1,71 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/base/rendering/screenspacetext.h>
#include <ghoul/opengl/framebufferobject.h>
#include <ghoul/opengl/texture.h>
namespace {
constexpr openspace::properties::Property::PropertyInfo TextInfo = {
"Text",
"Text",
"The text to be displayed.",
openspace::properties::Property::Visibility::User
};
// This `ScreenSpaceRenderable` shows a static text that can be changed via a
// property.
struct [[codegen::Dictionary(DashboardItemText)]] Parameters {
// [[codegen::verbatim(TextInfo.description)]]
std::optional<std::string> text;
};
#include "screenspacetext_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation ScreenSpaceText::Documentation() {
return codegen::doc<Parameters>(
"base_screenspace_text",
ScreenSpaceRenderableText::Documentation()
);
}
ScreenSpaceText::ScreenSpaceText(const ghoul::Dictionary& dictionary)
: ScreenSpaceRenderableText(dictionary)
, _text(TextInfo, "")
{
const Parameters p = codegen::bake<Parameters>(dictionary);
_text = p.text.value_or(_text);
addProperty(_text);
}
void ScreenSpaceText::update() {
_buffer = _text.value();
ScreenSpaceRenderableText::update();
}
} // namespace openspace
+48
View File
@@ -0,0 +1,48 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* 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___SCREENSPACETEXT___H__
#define __OPENSPACE_MODULE_BASE___SCREENSPACETEXT___H__
#include <openspace/rendering/screenspacerenderabletext.h>
#include <openspace/properties/misc/stringproperty.h>
namespace openspace {
class ScreenSpaceText : public ScreenSpaceRenderableText {
public:
explicit ScreenSpaceText(const ghoul::Dictionary& dictionary);
void update() override;
static documentation::Documentation Documentation();
private:
properties::StringProperty _text;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_BASE___SCREENSPACETEXT___H__
+2 -2
View File
@@ -21,14 +21,14 @@ openspace.debugging.documentation = {
current focus node is used instead.
\\param scale An optional parameter that specifies the size of the coordinate axes,
in meters. If not specified, the size is set to 2.5 times the
interaction sphere of the selected node.
bounding sphere of the selected node.
]]
}
}
openspace.debugging.createCoordinateAxes = function (nodeIdentifier, scale)
local node = nodeIdentifier or openspace.navigation.getNavigationState().Anchor
local sphere = openspace.propertyValue("Scene." .. node .. ".EvaluatedInteractionSphere")
local sphere = openspace.propertyValue("Scene." .. node .. ".EvaluatedBoundingSphere")
if sphere == -1 then
sphere = 1
end
+1 -1
View File
@@ -130,7 +130,7 @@ std::vector<std::string> hostStarsWithSufficientData() {
// Read number of lines
int nExoplanets = 0;
while (ghoul::getline(lookupTableFile, line)) {
++nExoplanets;
nExoplanets++;
}
lookupTableFile.clear();
lookupTableFile.seekg(0);
@@ -148,7 +148,7 @@ void ExoplanetsDataPreparationTask::perform(
int total = 0;
std::string row;
while (ghoul::getline(inputDataFile, row)) {
++total;
total++;
}
inputDataFile.clear();
inputDataFile.seekg(0);
@@ -161,7 +161,7 @@ void ExoplanetsDataPreparationTask::perform(
int exoplanetCount = 0;
while (ghoul::getline(inputDataFile, row)) {
++exoplanetCount;
exoplanetCount++;
progressCallback(static_cast<float>(exoplanetCount) / static_cast<float>(total));
PlanetData planetData = parseDataRow(
@@ -193,7 +193,7 @@ void KameleonVolumeToFieldlinesTask::perform(
throw ghoul::MissingCaseException();
}
}
++fileNumber;
fileNumber++;
}
// Ideally, we would want to signal about progress earlier as well, but
@@ -371,7 +371,7 @@ void FieldlinesState::saveStateToJson(const std::string& absPath) {
size_t pointIndex = 0;
for (size_t lineIndex = 0; lineIndex < nLines; lineIndex++) {
json jData = json::array();
for (GLsizei i = 0; i < _lineCount[lineIndex]; i++, ++pointIndex) {
for (GLsizei i = 0; i < _lineCount[lineIndex]; i++, pointIndex++) {
const glm::vec3 pos = _vertexPositions[pointIndex];
json jDataElement = { pos.x, pos.y, pos.z };
@@ -176,7 +176,7 @@ extractSeedPointsFromFiles(std::filesystem::path path, size_t nth)
outVec.push_back(std::move(point));
}
}
++linenumber;
linenumber++;
}
if (outVec.empty()) {
+1 -1
View File
@@ -1022,7 +1022,7 @@ bool OctreeManager::insertInNode(OctreeNode& node, const std::vector<float>& sta
storeStarData(node, starValues);
}
return insertInNode(*node.children[index], starValues, ++depth);
return insertInNode(*node.children[index], starValues, depth + 1);
}
void OctreeManager::sliceNodeLodCache(OctreeNode& node) {
+10 -30
View File
@@ -118,27 +118,6 @@ GDALDataType toGDALDataType(GLenum glType) {
}
}
/**
* Use as a helper function when determining the maximum tile level. This function
* returns the negated number of overviews requred to downscale the highest overview
* dataset so that it fits within minimumPixelSize pixels in the x-dimension.
*/
int calculateTileLevelDifference(GDALDataset* dataset, int minimumPixelSize) {
GDALRasterBand* firstBand = dataset->GetRasterBand(1);
GDALRasterBand* maxOverview = nullptr;
const int numOverviews = firstBand->GetOverviewCount();
if (numOverviews <= 0) { // No overviews. Use first band.
maxOverview = firstBand;
}
else { // Pick the highest overview.
maxOverview = firstBand->GetOverview(numOverviews - 1);
}
const int sizeLevel0 = maxOverview->GetXSize();
const double diff = log2(minimumPixelSize) - log2(sizeLevel0);
const double intdiff = diff >= 0 ? ceil(diff) : floor(diff);
return static_cast<int>(intdiff);
}
bool isInside(const PixelRegion& lhs, const PixelRegion& rhs) {
const glm::ivec2 e = lhs.start + lhs.numPixels;
const glm::ivec2 re = rhs.start + rhs.numPixels;
@@ -434,17 +413,18 @@ void RawTileDataReader::initialize() {
_padfTransform = geoTransform(_rasterXSize, _rasterYSize);
}
const double tileLevelDifference = calculateTileLevelDifference(
_dataset,
_initData.dimensions.x
);
const int numOverviews = _dataset->GetRasterBand(1)->GetOverviewCount();
_maxChunkLevel = static_cast<int>(-tileLevelDifference);
if (numOverviews > 0) {
_maxChunkLevel += numOverviews;
const int nOverviews = _dataset->GetRasterBand(1)->GetOverviewCount();
if (nOverviews > 0) {
_maxChunkLevel = nOverviews;
}
else {
const int sizeLevel0 = _dataset->GetRasterBand(1)->GetXSize();
const double diff = log2(sizeLevel0) - log2(_initData.dimensions.x);
const double intdiff = diff >= 0 ? ceil(diff) : floor(diff);
_maxChunkLevel = intdiff;
}
_maxChunkLevel = std::max(_maxChunkLevel, 2);
}
void RawTileDataReader::reset() {
+2 -2
View File
@@ -837,7 +837,7 @@ KameleonWrapper::TraceLine KameleonWrapper::traceCartesianFieldline(
pos = pos + (step / 6.f) * (k1 + 2.f * k2 + 2.f * k3 + k4);
++numSteps;
numSteps++;
if (numSteps > MaxSteps) {
LDEBUG(std::format("Max number of steps taken ({})", MaxSteps));
break;
@@ -951,7 +951,7 @@ KameleonWrapper::TraceLine KameleonWrapper::traceLorentzTrajectory(
v0 = v0 + step / 6.f * (k1 + 2.f * k2 + 2.f * k3 + k4);
++numSteps;
numSteps++;
if (numSteps > MaxSteps) {
LDEBUG(std::format("Max number of steps taken ({})", MaxSteps));
break;
@@ -73,7 +73,8 @@ bool ErrorHistogramManager::buildHistograms(int numBins) {
if (!success) {
return false;
}
pb.print(++processedLeaves);
processedLeaves++;
pb.print(processedLeaves);
}
}
+1 -1
View File
@@ -848,7 +848,7 @@ std::vector<Parameters> readMpcFile(const std::filesystem::path& file) {
argPeriapsis,
meanAnomaly,
epochFromYMDdSubstring(epochDate),
std::chrono::seconds(std::chrono::hours(24)).count() / meanMotion
(360.0 / meanMotion) * std::chrono::seconds(std::chrono::hours(24)).count()
);
}
@@ -340,7 +340,7 @@ bool RenderableConstellationBounds::loadVertexFile() {
static_cast<float>(rectangularValues[1]),
static_cast<float>(rectangularValues[2])
});
++currentLineNumber;
currentLineNumber++;
}
// Due to the way we read the file, the first (empty) constellation bounds will not
@@ -624,7 +624,7 @@ void RenderableFluxNodes::populateStartTimes() {
std::string columnName;
// loops through the names/columns in first line/header
while (s >> columnName) {
++nColumns;
nColumns++;
}
while (ghoul::getline(tfs, line)) { // for each line of data
std::istringstream iss(line);
@@ -40,18 +40,24 @@
#include <ghoul/logging/logmanager.h>
#include <chrono>
#include <cmath>
#include <execution>
#include <fstream>
#include <random>
#include <vector>
namespace {
// The possible values for the _renderingModes property
enum RenderingMode {
enum class RenderMode {
RenderingModeTrail = 0,
RenderingModePoint,
RenderingModePointTrail
};
enum class PointRenderingMode {
ViewDirection = 0,
PositionNormal
};
constexpr openspace::properties::Property::PropertyInfo PathInfo = {
"Path",
"Path",
@@ -59,6 +65,17 @@ namespace {
openspace::properties::Property::Visibility::AdvancedUser
};
constexpr openspace::properties::Property::PropertyInfo PointRenderingModeInfo = {
"PointRenderingMode",
"Point Rendering Mode",
"Controls how the points will be oriented. \"Camera View Direction\" rotates the "
"points so that they are orthogonal to the viewing direction of the camera "
"(useful for planar displays), and \"Camera Position Normal\" rotates the points "
"towards the position of the camera (useful for spherical displays, like dome "
"theaters).",
openspace::properties::Property::Visibility::AdvancedUser
};
constexpr openspace::properties::Property::PropertyInfo SegmentQualityInfo = {
"SegmentQuality",
"Segment quality",
@@ -193,6 +210,13 @@ namespace {
// The file format that is contained in the file.
Format format;
enum class [[codegen::map(PointRenderingMode)]] PointRenderingMode {
ViewDirection [[codegen::key("Camera View Direction")]],
PositionNormal [[codegen::key("Camera Position Normal")]]
};
// [[codegen::verbatim(PointRenderingModeInfo.description)]]
std::optional<PointRenderingMode> pointRenderingMode;
// [[codegen::verbatim(SegmentQualityInfo.description)]]
int segmentQuality;
@@ -261,22 +285,24 @@ RenderableOrbitalKepler::Appearance::Appearance()
, enableMaxSize(EnableMaxSizeInfo, true)
, maxSize(MaxSizeInfo, 5.f, 0.f, 45.f)
, renderingModes(RenderingModeInfo)
, pointRenderOption(PointRenderingModeInfo)
, trailFade(TrailFadeInfo, 20.f, 0.f, 30.f)
, enableOutline(EnableOutlineInfo, true)
, outlineColor(OutlineColorInfo, glm::vec3(0.f), glm::vec3(0.f), glm::vec3(1.f))
, outlineWidth(OutlineWidthInfo, 0.2f, 0.f, 1.f)
{
renderingModes.addOptions({
{ RenderingModeTrail, "Trails" },
{ RenderingModePoint, "Points" },
{ RenderingModePointTrail , "Points and Trails" }
{ static_cast<int>(RenderMode::RenderingModeTrail), "Trails" },
{ static_cast<int>(RenderMode::RenderingModePoint), "Points"},
{ static_cast<int>(RenderMode::RenderingModePointTrail) , "Points and Trails" }
});
renderingModes.onChange([this]() { isRenderTypeDirty = true; });
addProperty(renderingModes);
color.setViewOption(properties::Property::ViewOptions::Color);
addProperty(color);
addProperty(trailWidth);
addProperty(trailFade);
addProperty(pointRenderOption);
addProperty(pointSizeExponent);
addProperty(enableMaxSize);
addProperty(maxSize);
@@ -288,6 +314,7 @@ RenderableOrbitalKepler::Appearance::Appearance()
RenderableOrbitalKepler::RenderableOrbitalKepler(const ghoul::Dictionary& dict)
: Renderable(dict)
, _nThreads(std::max(1u, std::thread::hardware_concurrency() / 2u))
, _segmentQuality(SegmentQualityInfo, 2, 1, 10)
, _startRenderIdx(StartRenderIdxInfo, 0, 0, 1)
, _sizeRender(RenderSizeInfo, 1, 1, 2)
@@ -299,11 +326,12 @@ RenderableOrbitalKepler::RenderableOrbitalKepler(const ghoul::Dictionary& dict)
addProperty(Fadeable::_opacity);
_segmentQuality = static_cast<unsigned int>(p.segmentQuality);
_segmentQuality.onChange([this]() { updateBuffers(); });
_segmentQuality.onChange([this]() { _updateDataBuffersAtNextRender = true; });
addProperty(_segmentQuality);
_appearance.color = p.color;
_appearance.trailFade = p.trailFade.value_or(_appearance.trailFade);
_appearance.trailFade.onChange([this]() { _forceUpdate = true; });
_appearance.trailWidth = p.trailWidth.value_or(_appearance.trailWidth);
_appearance.enableMaxSize = p.enableMaxSize.value_or(_appearance.enableMaxSize);
_appearance.maxSize = p.maxSize.value_or(_appearance.maxSize);
@@ -313,21 +341,49 @@ RenderableOrbitalKepler::RenderableOrbitalKepler(const ghoul::Dictionary& dict)
_appearance.pointSizeExponent =
p.pointSizeExponent.value_or(_appearance.pointSizeExponent);
if (p.renderingMode.has_value()) {
switch (*p.renderingMode) {
case Parameters::RenderingMode::Trail:
_appearance.renderingModes = RenderingModeTrail;
_appearance.pointRenderOption.addOption(
static_cast<int>(PointRenderingMode::ViewDirection),
"Camera View Direction"
);
_appearance.pointRenderOption.addOption(
static_cast<int>(PointRenderingMode::PositionNormal),
"Camera Position Normal"
);
if (p.pointRenderingMode.has_value()) {
switch (*p.pointRenderingMode) {
case Parameters::PointRenderingMode::ViewDirection:
_appearance.pointRenderOption =
static_cast<int>(PointRenderingMode::ViewDirection);
break;
case Parameters::RenderingMode::Point:
_appearance.renderingModes = RenderingModePoint;
break;
case Parameters::RenderingMode::PointsTrails:
_appearance.renderingModes = RenderingModePointTrail;
case Parameters::PointRenderingMode::PositionNormal:
_appearance.pointRenderOption =
static_cast<int>(PointRenderingMode::PositionNormal);
break;
}
}
else {
_appearance.renderingModes = RenderingModeTrail;
_appearance.pointRenderOption =
static_cast<int>(PointRenderingMode::ViewDirection);
}
if (p.renderingMode.has_value()) {
switch (*p.renderingMode) {
case Parameters::RenderingMode::Trail:
_appearance.renderingModes =
static_cast<int>(RenderMode::RenderingModeTrail);
break;
case Parameters::RenderingMode::Point:
_appearance.renderingModes =
static_cast<int>(RenderMode::RenderingModePoint);
break;
case Parameters::RenderingMode::PointsTrails:
_appearance.renderingModes =
static_cast<int>(RenderMode::RenderingModePointTrail);
break;
}
}
else {
_appearance.renderingModes = static_cast<int>(RenderMode::RenderingModeTrail);
}
addPropertySubOwner(_appearance);
@@ -336,8 +392,8 @@ RenderableOrbitalKepler::RenderableOrbitalKepler(const ghoul::Dictionary& dict)
_startRenderIdx = p.startRenderIdx.value_or(0);
_startRenderIdx.onChange([this]() {
if (_contiguousMode) {
if ((_numObjects - _startRenderIdx) < _sizeRender) {
_sizeRender = static_cast<unsigned int>(_numObjects - _startRenderIdx);
if ((_nOrbits - _startRenderIdx) < _sizeRender) {
_sizeRender = static_cast<unsigned int>(_nOrbits - _startRenderIdx);
}
_updateDataBuffersAtNextRender = true;
}
@@ -347,8 +403,8 @@ RenderableOrbitalKepler::RenderableOrbitalKepler(const ghoul::Dictionary& dict)
_sizeRender = p.renderSize.value_or(0u);
_sizeRender.onChange([this]() {
if (_contiguousMode) {
if (_sizeRender > (_numObjects - _startRenderIdx)) {
_startRenderIdx = static_cast<unsigned int>(_numObjects - _sizeRender);
if (_sizeRender > (_nOrbits - _startRenderIdx)) {
_startRenderIdx = static_cast<unsigned int>(_nOrbits - _sizeRender);
}
}
_updateDataBuffersAtNextRender = true;
@@ -360,7 +416,7 @@ RenderableOrbitalKepler::RenderableOrbitalKepler(const ghoul::Dictionary& dict)
addProperty(_contiguousMode);
_path = p.path.string();
_path.onChange([this]() { updateBuffers(); });
_path.onChange([this]() { _updateDataBuffersAtNextRender = true; });
addProperty(_path);
}
@@ -398,7 +454,7 @@ void RenderableOrbitalKepler::initializeGL() {
ghoul::opengl::updateUniformLocations(*_trailProgram, _uniformTrailCache);
ghoul::opengl::updateUniformLocations(*_pointProgram, _uniformPointCache);
updateBuffers();
_updateDataBuffersAtNextRender = true;
}
void RenderableOrbitalKepler::deinitializeGL() {
@@ -427,11 +483,32 @@ bool RenderableOrbitalKepler::isReady() const {
return _pointProgram != nullptr && _trailProgram != nullptr;
}
void RenderableOrbitalKepler::update(const UpdateData&) {
void RenderableOrbitalKepler::update(const UpdateData& data) {
if (_updateDataBuffersAtNextRender) {
_updateDataBuffersAtNextRender = false;
updateBuffers();
_forceUpdate = true;
}
if (_appearance.isRenderTypeDirty) {
_forceUpdate = true;
}
bool isPaused = data.time.j2000Seconds() == data.previousFrameTime.j2000Seconds();
if (!isPaused || _forceUpdate) {
std::for_each(
std::execution::par_unseq,
_threadIds.begin(),
_threadIds.end(),
[&](int threadId) {
threadedSegmentCalculations(threadId, data);
}
);
}
_lineDrawCount = static_cast<GLsizei>(_segmentsPerOrbit.size() * 2);
_updateDataBuffersAtNextRender = false;
_appearance.isRenderTypeDirty = false;
_forceUpdate = false;
}
void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) {
@@ -439,18 +516,21 @@ void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) {
return;
}
const int selection = _appearance.renderingModes;
const bool renderPoints = (
selection == RenderingModePoint ||
selection == RenderingModePointTrail
);
const bool renderTrails = (
selection == RenderingModeTrail ||
selection == RenderingModePointTrail
);
if (renderPoints) {
calculateSegmentsForPoints(data);
if (_renderPoints) {
glm::vec3 cameraViewDirectionWorld = -data.camera.viewDirectionWorldSpace();
glm::vec3 cameraUpDirectionWorld = data.camera.lookUpVectorWorldSpace();
glm::vec3 orthoRight = glm::normalize(
glm::cross(cameraUpDirectionWorld, cameraViewDirectionWorld)
);
if (orthoRight == glm::vec3(0.f)) {
glm::vec3 otherVector = glm::vec3(
cameraUpDirectionWorld.y,
cameraUpDirectionWorld.x,
cameraUpDirectionWorld.z
);
orthoRight = glm::normalize(glm::cross(otherVector, cameraViewDirectionWorld));
}
glm::vec3 orthoUp = glm::normalize(glm::cross(cameraViewDirectionWorld, orthoRight));
_pointProgram->activate();
_pointProgram->setUniform(
@@ -465,6 +545,18 @@ void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) {
_uniformPointCache.projectionTransform,
data.camera.projectionMatrix()
);
_pointProgram->setUniform(
_uniformPointCache.renderOption,
_appearance.pointRenderOption
);
_pointProgram->setUniform(
_uniformPointCache.cameraViewDirectionUp,
orthoUp
);
_pointProgram->setUniform(
_uniformPointCache.cameraViewDirectionRight,
orthoRight
);
_pointProgram->setUniform(
_uniformPointCache.cameraPositionWorld,
data.camera.positionVec3()
@@ -513,9 +605,7 @@ void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) {
_pointProgram->deactivate();
}
if (renderTrails) {
calculateSegmentsForTrails(data);
if (_renderTrails) {
_trailProgram->activate();
_trailProgram->setUniform(_uniformTrailCache.opacity, opacity());
_trailProgram->setUniform(_uniformTrailCache.color, _appearance.color);
@@ -562,32 +652,31 @@ void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) {
void RenderableOrbitalKepler::updateBuffers() {
_parameters = kepler::readFile(_path.value(), _format);
_nOrbits = static_cast<unsigned int>(_parameters.size());
_numObjects = _parameters.size();
if (_startRenderIdx >= _numObjects) {
if (_startRenderIdx >= _nOrbits) {
throw ghoul::RuntimeError(std::format(
"Start index {} out of range [0, {}]", _startRenderIdx.value(), _numObjects
"Start index {} out of range [0, {}]", _startRenderIdx.value(), _nOrbits
));
}
long long endElement = _startRenderIdx + _sizeRender - 1;
endElement = (endElement >= _numObjects) ? _numObjects - 1 : endElement;
if (endElement < 0 || endElement >= _numObjects) {
endElement = (endElement >= _nOrbits) ? _nOrbits - 1 : endElement;
if (endElement < 0 || endElement >= _nOrbits) {
throw ghoul::RuntimeError(std::format(
"End index {} out of range [0, {}]", endElement, _numObjects
"End index {} out of range [0, {}]", endElement, _nOrbits
));
}
_startRenderIdx.setMaxValue(static_cast<unsigned int>(_numObjects - 1));
_sizeRender.setMaxValue(static_cast<unsigned int>(_numObjects));
_startRenderIdx.setMaxValue(static_cast<unsigned int>(_nOrbits - 1));
_sizeRender.setMaxValue(static_cast<unsigned int>(_nOrbits));
if (_sizeRender == 0u) {
_sizeRender = static_cast<unsigned int>(_numObjects);
_sizeRender = static_cast<unsigned int>(_nOrbits);
}
if (_contiguousMode) {
if (_startRenderIdx >= _parameters.size() ||
(_startRenderIdx + _sizeRender) >= _parameters.size())
(_startRenderIdx + _sizeRender) > _parameters.size())
{
throw ghoul::RuntimeError(std::format(
"Tried to load {} objects but only {} are available",
@@ -613,64 +702,112 @@ void RenderableOrbitalKepler::updateBuffers() {
);
}
_threadIds.clear();
_orbitsPerThread.clear();
_updateHelper.clear();
_startIndexPoints.clear();
_segmentSizePoints.clear();
_vertexBufferOffset.clear();
_startIndexTrails.clear();
_segmentSizeTrails.clear();
_segmentSizeRaw.clear();
size_t nVerticesTotal = 0;
const int numOrbits = static_cast<int>(_parameters.size());
for (int i = 0; i < numOrbits; i++) {
_segmentsPerOrbit.clear();
_updateHelper.resize(_sizeRender);
_startIndexPoints.resize(_sizeRender);
_segmentSizePoints.resize(_sizeRender);
_vertexBufferOffset.resize(_sizeRender);
_segmentsPerOrbit.resize(_sizeRender);
// Trail vectors needs double length as it may use two trails per orbit
_startIndexTrails.resize(_sizeRender * 2);
_segmentSizeTrails.resize(_sizeRender * 2);
double maxSemiMajorAxis = 0.0;
size_t nVerticesTotal = 0;
for (unsigned int i = 0; i < _sizeRender; i++) {
// For points rendering as they are always two vertices long
_segmentSizePoints.push_back(2);
_segmentSizePoints[i] = 2;
const double scale = static_cast<double>(_segmentQuality) * 10.0;
const kepler::Parameters& p = _parameters[i];
_segmentSizeRaw.push_back(
static_cast<int>(scale + (scale / std::pow(1.0 - p.eccentricity, 1.2)))
_segmentsPerOrbit[i] = static_cast<int>(
scale + (scale / std::pow(1.0 - p.eccentricity, 1.2))
);
nVerticesTotal += _segmentSizeRaw[i];
_vertexBufferOffset[i] = static_cast<int>(nVerticesTotal);
nVerticesTotal += _segmentsPerOrbit[i];
// Find largest value for bounding sphere
if (p.semiMajorAxis > maxSemiMajorAxis) {
maxSemiMajorAxis = p.semiMajorAxis;
}
}
_startIndexPoints.resize(numOrbits);
_startIndexTrails.resize(numOrbits*2);
_segmentSizeTrails.resize(numOrbits*2);
setBoundingSphere(maxSemiMajorAxis * 1000);
_vertexBufferData.resize(nVerticesTotal);
size_t vertexBufIdx = 0;
for (int orbitIdx = 0; orbitIdx < numOrbits; orbitIdx++) {
const kepler::Parameters& orbit = _parameters[orbitIdx];
std::vector<int> orbitIdHolder;
orbitIdHolder.resize(_sizeRender);
std::iota(orbitIdHolder.begin(), orbitIdHolder.end(), 0);
ghoul::Dictionary d;
d.setValue("Type", std::string("KeplerTranslation"));
d.setValue("Eccentricity", orbit.eccentricity);
d.setValue("SemiMajorAxis", orbit.semiMajorAxis);
d.setValue("Inclination", orbit.inclination);
d.setValue("AscendingNode", orbit.ascendingNode);
d.setValue("ArgumentOfPeriapsis", orbit.argumentOfPeriapsis);
d.setValue("MeanAnomaly", orbit.meanAnomaly);
d.setValue("Period", orbit.period);
d.setValue("Epoch", orbit.epoch);
KeplerTranslation keplerTranslator = KeplerTranslation(d);
std::for_each(
std::execution::par_unseq,
orbitIdHolder.begin(),
orbitIdHolder.end(),
[&](int index) {
ZoneScoped;
const int nSegments = _segmentSizeRaw[orbitIdx];
for (GLint j = 0 ; j < nSegments; j++) {
const double timeOffset = orbit.period *
static_cast<double>(j) / static_cast<double>(nSegments - 1);
const kepler::Parameters& orbit = _parameters[index];
const glm::dvec3 position = keplerTranslator.position({
{},
Time(timeOffset + orbit.epoch),
Time(0.0)
});
const KeplerCalculator calc = KeplerCalculator(
orbit.eccentricity,
orbit.semiMajorAxis,
orbit.inclination,
orbit.ascendingNode,
orbit.argumentOfPeriapsis,
orbit.meanAnomaly,
orbit.period,
orbit.epoch
);
_vertexBufferData[vertexBufIdx + j].x = static_cast<float>(position.x);
_vertexBufferData[vertexBufIdx + j].y = static_cast<float>(position.y);
_vertexBufferData[vertexBufIdx + j].z = static_cast<float>(position.z);
_vertexBufferData[vertexBufIdx + j].time = static_cast<float>(timeOffset);
_vertexBufferData[vertexBufIdx + j].epoch = orbit.epoch;
_vertexBufferData[vertexBufIdx + j].period = orbit.period;
const int nVerts = _segmentsPerOrbit[index];
const int offset = _vertexBufferOffset[index];
const int nSegments = nVerts - 1;
for (GLint j = 0; j < nVerts; j++) {
const double timeOffset = orbit.period *
static_cast<double>(j) / static_cast<double>(nSegments);
const glm::dvec3 position = calc.position(timeOffset + orbit.epoch);
_vertexBufferData[offset + j].x = static_cast<float>(position.x);
_vertexBufferData[offset + j].y = static_cast<float>(position.y);
_vertexBufferData[offset + j].z = static_cast<float>(position.z);
_vertexBufferData[offset + j].time = timeOffset;
_vertexBufferData[offset + j].epoch = orbit.epoch;
_vertexBufferData[offset + j].period = orbit.period;
}
_updateHelper[index].timePerStep = orbit.period / nSegments;
}
vertexBufIdx += nSegments;
);
// Calculate how many orbits we calculate per thread
// 1000 per thread (arbitrary) to not create threads that do little to no work
unsigned int orbitsPerThread = std::max(
1000,
static_cast<int>(std::ceil(static_cast<double>(_sizeRender) / _nThreads))
);
// Vector that maps thread index to number of orbits to render
int threadId = 0;
unsigned int remainingOrbits = _sizeRender;
while (remainingOrbits >= orbitsPerThread) {
_threadIds.push_back(threadId);
_orbitsPerThread.push_back(orbitsPerThread);
remainingOrbits -= orbitsPerThread;
threadId++;
}
if (remainingOrbits > 0) {
_threadIds.push_back(threadId);
_orbitsPerThread.push_back(remainingOrbits);
}
glBindVertexArray(_vertexArray);
@@ -684,120 +821,145 @@ void RenderableOrbitalKepler::updateBuffers() {
);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(TrailVBOLayout), nullptr);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(TrailVBOLayout), nullptr);
glEnableVertexAttribArray(1);
glVertexAttribLPointer(
1,
2,
3,
GL_DOUBLE,
sizeof(TrailVBOLayout),
reinterpret_cast<GLvoid*>(4 * sizeof(GL_FLOAT))
reinterpret_cast<GLvoid*>(offsetof(TrailVBOLayout, time))
);
glBindVertexArray(0);
double maxSemiMajorAxis = 0.0;
for (const kepler::Parameters& kp : _parameters) {
if (kp.semiMajorAxis > maxSemiMajorAxis) {
maxSemiMajorAxis = kp.semiMajorAxis;
}
}
setBoundingSphere(maxSemiMajorAxis * 1000);
}
void RenderableOrbitalKepler::calculateSegmentsForPoints(const RenderData& data) {
int startVertexIndex = 0;
for (size_t i = 0; i < _segmentSizeRaw.size(); i++) {
// Check how far along the trail we are
const kepler::Parameters& orbit = _parameters[i];
const double nRevs = (data.time.j2000Seconds() - orbit.epoch) / orbit.period;
float frac = static_cast<float>(nRevs - std::trunc(nRevs));
frac += (frac < 0.f) ? 1.f: 0.f;
void RenderableOrbitalKepler::threadedSegmentCalculations(int threadId,
const UpdateData& data)
{
ZoneScoped;
// Get the closest vertex before that point
const int nSegments = _segmentSizeRaw[i] - 1;
const int offset = static_cast<int>(std::floor(frac * nSegments));
const int selection = _appearance.renderingModes;
_renderPoints = (
selection == static_cast<int>(RenderMode::RenderingModePoint) ||
selection == static_cast<int>(RenderMode::RenderingModePointTrail)
);
_renderTrails = (
selection == static_cast<int>(RenderMode::RenderingModeTrail) ||
selection == static_cast<int>(RenderMode::RenderingModePointTrail)
);
// Set start vertex ID in buffer
_startIndexPoints[i] = startVertexIndex + offset;
startVertexIndex += _segmentSizeRaw[i];
}
}
void RenderableOrbitalKepler::calculateSegmentsForTrails(const RenderData& data) {
const float fade = std::pow(
_appearance.trailFade.maxValue() - _appearance.trailFade,
2.f
);
const float threshold = 1.f - std::pow(0.05f, 1.f / fade);
int nTotalTrailParts = 0;
int startVertexIndex = 0;
for (size_t i = 0; i < _segmentSizeRaw.size(); i++) {
// Check how far along the trail we are
const kepler::Parameters& orbit = _parameters[i];
const double nRevs = (data.time.j2000Seconds() - orbit.epoch) / orbit.period;
float frac = static_cast<float>(nRevs - std::trunc(nRevs));
frac += (frac < 0.f) ? 1.f : 0.f;
int offset = std::accumulate(
_orbitsPerThread.begin(),
_orbitsPerThread.begin() + threadId,
0
);
const int cutoff = offset + _orbitsPerThread[threadId];
int p0Start = 0;
int p0Length = 0;
int p1Start = 0;
int p1Length = 0;
const double now = data.time.j2000Seconds();
int startVertexIndex = _vertexBufferOffset[offset];
for (int i = offset; i < cutoff; i++) {
UpdateInfo* helper = &_updateHelper[i];
double upper = helper->timestamp + (helper->timePerStep);
double lower = helper->timestamp - (helper->timePerStep);
const bool shouldUpdate = (now >= upper || now <= lower);
const int nVerts = _segmentSizeRaw[i];
const int nSegments = nVerts - 1;
const int trailLength = static_cast<int>(std::ceil(threshold * nSegments));
if (trailLength == nSegments) {
// Whole trail should be visible
p0Start = startVertexIndex;
p0Length = nVerts;
}
else {
const int headOffset = static_cast<int>(std::ceil(frac * nSegments));
const int headVertexIndex = startVertexIndex + headOffset;
const int correctTrailLength = trailLength + 2;
const int nVerts = _segmentsPerOrbit[i];
if (shouldUpdate || _forceUpdate) {
// Check how far along the trail we are
const kepler::Parameters& orbit = _parameters[i];
const double nRevs = (data.time.j2000Seconds() - orbit.epoch) / orbit.period;
double frac = static_cast<double>(nRevs - std::trunc(nRevs));
frac += (frac < 0.0) ? 1.0 : 0.0;
int correctVertexIndex = headVertexIndex - correctTrailLength + 1;
const int nSegments = nVerts - 1;
const int pointHead = static_cast<int>(std::floor(frac * nSegments));
// If the start of the trail should be at the end of the orbit
if (correctVertexIndex < startVertexIndex) {
correctVertexIndex += nVerts;
// We can always do this since it has no cost
_startIndexPoints[i] = startVertexIndex + pointHead;
// There is a lot of what seems to be "magic numbers" in this section.
// They will most likely disappear when we change our method of determining
// the trail fade amount is changed.
if (_renderTrails) {
// When rendering a trail we don't know if the trail will pass over
// the starting point of the orbit or not. If the trail passes over the
// starting point of the orbit, then we can't draw the entire trail as
// line strip. Instead we need to divide the line strip into two parts,
// where p0 and p1 denotes the respctive line strips (parts).
int p0Start = -1;
int p0Length = -1;
int p1Start = -1;
int p1Length = -1;
const int trailLength =
static_cast<int>(std::ceil(threshold * nSegments));
if (trailLength == nSegments) {
// Whole trail should be visible
p0Start = startVertexIndex;
p0Length = nVerts;
p1Start = 0;
p1Length = 0;
}
else {
const int trailHead = static_cast<int>(std::ceil(frac * nSegments));
const int headVertexIndex = startVertexIndex + trailHead + 1;
const int correctTrailLength = trailLength + 3;
// Need to do this due to order of vertex data in the vertex buffer
int correctVertexIndex = headVertexIndex - correctTrailLength;
// If the start of the trail should be at the end of the orbit
if (correctVertexIndex < startVertexIndex) {
correctVertexIndex += nVerts;
}
// If the trail is length passes over the last point of the orbit
const int lastVertexIndex = startVertexIndex + nVerts;
if (correctVertexIndex + correctTrailLength > lastVertexIndex) {
p0Start = startVertexIndex;
p1Start = correctVertexIndex;
// Special check to make sure we don't end up with segment
// sections 1 vertex length. A segment must contain at least 2
// vertices or more.
if (lastVertexIndex - correctVertexIndex == 1) {
p1Length = 0;
p0Length = correctTrailLength - 1;
}
else {
p1Length = lastVertexIndex - correctVertexIndex;
p0Length = correctTrailLength - p1Length;
}
}
else {
// If the entire trail is within the bounds of the orbit
p0Start = correctVertexIndex;
p0Length = correctTrailLength;
p1Start = 0;
p1Length = 0;
}
}
_startIndexTrails[i * 2] = p0Start;
_segmentSizeTrails[i * 2] = p0Length;
_startIndexTrails[i * 2 + 1] = p1Start;
_segmentSizeTrails[i * 2 + 1] = p1Length;
}
// If the trail is length passes over the last point of the orbit
const int lastVertexIndex = startVertexIndex + nVerts;
if (correctVertexIndex + correctTrailLength > lastVertexIndex) {
p1Start = correctVertexIndex - 1;
p1Length = lastVertexIndex - correctVertexIndex + 1;
p0Start = startVertexIndex;
p0Length = correctTrailLength - p1Length + 1;
}
else {
// If the entire trail is within the bounds of the orbit
p0Start = correctVertexIndex;
p0Length = correctTrailLength;
}
}
int newTrailParts = 0;
if (p0Length > 1) {
_startIndexTrails[nTotalTrailParts] = p0Start;
_segmentSizeTrails[nTotalTrailParts] = p0Length;
newTrailParts += 1;
}
if (p1Length > 1) {
_startIndexTrails[nTotalTrailParts + newTrailParts] = p1Start;
_segmentSizeTrails[nTotalTrailParts + newTrailParts] = p1Length;
newTrailParts += 1;
_updateHelper[i].timestamp = orbit.epoch +
(std::floor(frac * nSegments) * _updateHelper[i].timePerStep) +
(std::floor(nRevs) * orbit.period);
}
startVertexIndex += nVerts;
nTotalTrailParts += newTrailParts;
}
_lineDrawCount = static_cast<GLsizei>(nTotalTrailParts);
}
} // namespace openspace
@@ -68,6 +68,8 @@ private:
properties::FloatProperty maxSize;
/// Max angular size between vector cameraToPoint and edge of the point
properties::OptionProperty renderingModes;
/// Specifies rendering orientation when rendering points
properties::OptionProperty pointRenderOption;
/// Specifies a multiplicative factor that fades out the trail line
properties::FloatProperty trailFade;
/// Specifies if the point outline should be enabled
@@ -76,59 +78,73 @@ private:
properties::Vec3Property outlineColor;
/// Specifies how much if the point should be covered by the outline
properties::FloatProperty outlineWidth;
bool isRenderTypeDirty = false;
};
void updateBuffers();
void calculateSegmentsForPoints(const RenderData& data);
void calculateSegmentsForTrails(const RenderData& data);
void threadedSegmentCalculations(int threadId, const UpdateData& data);
const int _nThreads = 0;
std::vector<int> _threadIds;
std::vector<int> _orbitsPerThread;
std::vector<int> _vertexBufferOffset;
bool _renderTrails = false;
bool _renderPoints = false;
bool _forceUpdate = false;
bool _updateDataBuffersAtNextRender = false;
long long _numObjects = 0;
unsigned int _nOrbits = 0;
GLsizei _lineDrawCount = 0;
properties::UIntProperty _segmentQuality;
properties::UIntProperty _startRenderIdx;
properties::UIntProperty _sizeRender;
std::vector<GLint> _segmentSizeRaw;
std::vector<GLint> _segmentsPerOrbit;
std::vector<GLint> _startIndexPoints;
std::vector<GLint> _segmentSizePoints;
std::vector<GLint> _startIndexTrails;
std::vector<GLint> _segmentSizeTrails;
std::vector<kepler::Parameters> _parameters;
/// Extra data for more efficient updating of vectors
struct UpdateInfo {
double timestamp = std::numeric_limits<double>::min();
double timePerStep = 0.0;
};
std::vector<UpdateInfo> _updateHelper;
/// The layout of the VBOs
struct TrailVBOLayout {
float x = 0.f;
float y = 0.f;
float z = 0.f;
float time = 0.f;
double time = 0.0;
double epoch = 0.0;
double period = 0.0;
};
/// The backend storage for the vertex buffer object containing all points
std::vector<TrailVBOLayout> _vertexBufferData;
GLuint _vertexArray = 0;
GLuint _vertexBuffer = 0;
ghoul::opengl::ProgramObject* _trailProgram = nullptr;
ghoul::opengl::ProgramObject* _pointProgram = nullptr;
properties::UIntProperty _segmentQuality;
properties::UIntProperty _startRenderIdx;
properties::UIntProperty _sizeRender;
properties::StringProperty _path;
properties::BoolProperty _contiguousMode;
kepler::Format _format;
RenderableOrbitalKepler::Appearance _appearance;
GLuint _vertexArray = 0;
GLuint _vertexBuffer = 0;
// Line cache
UniformCache(modelViewTransform, projectionTransform, trailFadeExponent,
colorFadeCutoffValue, inGameTime, color, opacity)
_uniformTrailCache;
colorFadeCutoffValue, inGameTime, color, opacity) _uniformTrailCache;
// Point cache
UniformCache(modelTransform, viewTransform, projectionTransform,
cameraPositionWorld, cameraUpWorld, inGameTime, color,
pointSizeExponent, enableMaxSize, maxSize, enableOutline,
outlineColor, outlineWeight, opacity)
_uniformPointCache;
UniformCache(modelTransform, viewTransform, projectionTransform, renderOption,
cameraViewDirectionUp, cameraViewDirectionRight, cameraPositionWorld,
cameraUpWorld, inGameTime, color, pointSizeExponent, enableMaxSize, maxSize,
enableOutline, outlineColor, outlineWeight, opacity) _uniformPointCache;
};
} // namespace openspace
+26 -7
View File
@@ -33,17 +33,27 @@ flat in float vertexRevolutionFraction[];
uniform dmat4 modelTransform;
uniform dmat4 viewTransform;
uniform mat4 projectionTransform;
uniform dvec3 cameraPositionWorld;
uniform vec3 cameraUpWorld;
uniform float pointSizeExponent;
uniform bool enableMaxSize;
uniform float maxSize;
uniform int renderOption;
// Camera View Direction
uniform vec3 cameraViewDirectionUp;
uniform vec3 cameraViewDirectionRight;
// Camera Normal
uniform dvec3 cameraPositionWorld;
uniform vec3 cameraUpWorld;
layout(triangle_strip, max_vertices = 4) out;
out float projectionViewDepth;
out vec4 viewSpace;
out vec2 texCoord;
const int RenderOptionCameraViewDirection = 0;
const int RenderOptionCameraPositionNormal = 1;
void main() {
// cFrac is how far along the trail orbit the head of the trail is.
// v0Frac and v1Frac are how far the two vertices that creates the current line strip
@@ -65,12 +75,21 @@ void main() {
// Calculate current vertex position to world space
dvec4 vertPosWorldSpace = modelTransform * pos;
// Calculate new axis for plane
vec3 camPosToVertPos = vec3(cameraPositionWorld - vertPosWorldSpace.xyz);
vec3 normal = normalize(camPosToVertPos);
vec3 right = normalize(cross(cameraUpWorld, normal));
vec3 up = normalize(cross(normal, right));
vec3 up;
vec3 right;
// Calculate new axis for plane
if (renderOption == RenderOptionCameraViewDirection) {
up = cameraViewDirectionUp;
right = cameraViewDirectionRight;
}
else {
// Camera Position Normal
vec3 normal = normalize(camPosToVertPos);
right = normalize(cross(cameraUpWorld, normal));
up = normalize(cross(normal, right));
}
// Calculate size of points
float initialSize = pow(10.0, pointSizeExponent);
+6 -5
View File
@@ -24,8 +24,8 @@
#version __CONTEXT__
layout (location = 0) in vec4 vertexData; // 1: x, 2: y, 3: z, 4: timeOffset,
layout (location = 1) in dvec2 orbitData; // 1: epoch, 2: period
layout (location = 0) in vec3 vertexData; // 1: x, 2: y, 3: z
layout (location = 1) in dvec3 orbitData; // 1: timeOffset, 2: epoch, 3: period
uniform double inGameTime;
@@ -33,8 +33,9 @@ flat out float currentRevolutionFraction;
flat out float vertexRevolutionFraction;
void main() {
double epoch = orbitData.x;
double period = orbitData.y;
double timeOffset = orbitData.x;
double epoch = orbitData.y;
double period = orbitData.z;
// calculate nr of periods, get fractional part to know where the vertex closest to the
// debris part is right now
@@ -45,7 +46,7 @@ void main() {
}
// Same procedure for the current vertex
vertexRevolutionFraction = float(vertexData.w / period);
vertexRevolutionFraction = float(timeOffset / period);
gl_Position = vec4(vertexData.xyz, 1.0);
}

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