From 9be88fdea8af74f5568ca2c5f393aadd465bcc4d Mon Sep 17 00:00:00 2001 From: Micah Acinapura Date: Sat, 15 Apr 2023 17:26:38 -0400 Subject: [PATCH] added more scale objects and helper file (#2605) * added more scale objects and helper file * Update file identifiers * reworked scale models with node support script * using url sync for models that need to be updated --------- Co-authored-by: Alexander Bock --- .../educational/scale/arc_de_triomphe.asset | 79 +++++++++++++ data/assets/educational/scale/big_ben.asset | 81 +++++++++++++ .../educational/scale/burj_khalifa.asset | 82 +++++++++++++ .../educational/scale/eiffeltower.asset | 57 ++++----- .../scale/empire_state_building.asset | 84 +++++++++++++ .../educational/scale/gateway_arch.asset | 86 ++++++++++++++ .../scale/golden_gate_bridge.asset | 87 ++++++++++++++ .../scale/kuala_lumpur_tower.asset | 79 +++++++++++++ data/assets/educational/scale/rose_bowl.asset | 80 +++++++++++++ .../assets/educational/scale/school_bus.asset | 80 +++++++++++++ data/assets/educational/scale/scientist.asset | 80 +++++++++++++ .../educational/scale/statue_of_liberty.asset | 80 +++++++++++++ data/assets/util/scale_model_helper.asset | 111 ++++++++++++++++++ modules/globebrowsing/globebrowsingmodule.cpp | 5 +- .../globebrowsing/scripts/node_support.lua | 53 +++++++++ 15 files changed, 1085 insertions(+), 39 deletions(-) create mode 100644 data/assets/educational/scale/arc_de_triomphe.asset create mode 100644 data/assets/educational/scale/big_ben.asset create mode 100644 data/assets/educational/scale/burj_khalifa.asset create mode 100644 data/assets/educational/scale/empire_state_building.asset create mode 100644 data/assets/educational/scale/gateway_arch.asset create mode 100644 data/assets/educational/scale/golden_gate_bridge.asset create mode 100644 data/assets/educational/scale/kuala_lumpur_tower.asset create mode 100644 data/assets/educational/scale/rose_bowl.asset create mode 100644 data/assets/educational/scale/school_bus.asset create mode 100644 data/assets/educational/scale/scientist.asset create mode 100644 data/assets/educational/scale/statue_of_liberty.asset create mode 100644 data/assets/util/scale_model_helper.asset create mode 100644 modules/globebrowsing/scripts/node_support.lua diff --git a/data/assets/educational/scale/arc_de_triomphe.asset b/data/assets/educational/scale/arc_de_triomphe.asset new file mode 100644 index 0000000000..40a92d01f0 --- /dev/null +++ b/data/assets/educational/scale/arc_de_triomphe.asset @@ -0,0 +1,79 @@ +local earthAsset = asset.require('scene/solarsystem/planets/earth/earth') +local sunAsset = asset.require('scene/solarsystem/sun/sun') + +local modelFolder = asset.syncedResource({ + Name = "Scale Model Arc de Triomphe", + Type = "HttpSynchronization", + Identifier = "scale_model_arc_de_triomphe", + Version = 1 +}) + +local scaleModel = { + Identifier = "Scale_ArcDeTriomphe", + Parent = earthAsset.Earth.Identifier, + --Note: Lat/Lon/Scale values comes from alignment with Esri World Imagery 2D layer + Transform = { + Translation = { + Type = "GlobeTranslation", + Globe = earthAsset.Earth.Identifier, + Latitude = 48.87389, + Longitude = 2.29492, + Altitude = 0.0, + UseHeightmap = true + }, + Rotation = { + Type = "GlobeRotation", + Globe = earthAsset.Earth.Identifier, + Latitude = 48.87389, + Longitude = 2.29492, + UseHeightmap = false + } + }, + Renderable = { + Type = "RenderableModel", + GeometryFile = modelFolder .. "Fr_arch_OBJ.osmodel", + LightSources = { sunAsset.LightSource }, + }, + GUI = { + Name = "Arc de Triomphe", + Path = "/Scale Objects" + } +} + +local updatePositionAction = { + Identifier = "os.scale_models.drop_arc_de_triomphe", + Name = "Drop Arc de Triomphe under camera", + Command = [[ + openspace.globebrowsing.setNodePositionFromCamera('Scale_ArcDeTriomphe') + ]], + Documentation = "Updates the Arc de Triomphe position based on the globe location of the camera", + GuiPath = "/Scale Objects", + IsLocal = false +} + +local resetPositionAction = { + Identifier = "os.scale_models.reset_arc_de_triomphe", + Name = "Reset Arc de Triomphe position", + Command = [[ + openspace.globebrowsing.setNodePosition('Scale_ArcDeTriomphe', ']] .. earthAsset.Earth.Identifier .. [[', 48.87389, 2.29492) + ]], + Documentation = "Resets the Arc de Triomphe back to it's actual location", + GuiPath = "/Scale Objects", + IsLocal = false +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(scaleModel) + openspace.action.registerAction(updatePositionAction) + openspace.action.registerAction(resetPositionAction) +end) + +asset.onDeinitialize(function() + openspace.action.removeAction(resetPositionAction) + openspace.action.removeAction(updatePositionAction) + openspace.removeSceneGraphNode(scaleModel) +end) + +asset.export(scaleModel) +asset.export(updatePositionAction) +asset.export(resetPositionAction) diff --git a/data/assets/educational/scale/big_ben.asset b/data/assets/educational/scale/big_ben.asset new file mode 100644 index 0000000000..c0aec62079 --- /dev/null +++ b/data/assets/educational/scale/big_ben.asset @@ -0,0 +1,81 @@ +local earthAsset = asset.require('scene/solarsystem/planets/earth/earth') +local sunAsset = asset.require('scene/solarsystem/sun/sun') + +local modelFolder = asset.syncedResource({ + Name = "Scale Model Big Ben", + Type = "HttpSynchronization", + Identifier = "scale_model_big_ben", + Version = 1 +}) + +local scaleModel = { + Identifier = "Scale_BigBen", + Parent = earthAsset.Earth.Identifier, + --Note: Lat/Lon/Scale values comes from alignment with Esri World Imagery 2D layer + Transform = { + Translation = { + Type = "GlobeTranslation", + Globe = earthAsset.Earth.Identifier, + Latitude = 51.50079, + Longitude = -0.124279, + Altitude = 0.0, + UseHeightmap = true + }, + Rotation = { + Type = "GlobeRotation", + Globe = earthAsset.Earth.Identifier, + Latitude = 51.50079, + Longitude = -0.124279, + UseHeightmap = false + } + }, + Renderable = { + Type = "RenderableModel", + GeometryFile = modelFolder .. "bigben.osmodel", + RotationVector = { 0.0, 265.0, 0.0 }, + LightSources = { sunAsset.LightSource }, + ModelScale = "Millimeter" + }, + GUI = { + Name = "Big Ben", + Path = "/Scale Objects" + } +} + +local updatePositionAction = { + Identifier = "os.scale_models.drop_big_ben", + Name = "Drop Big Ben under camera", + Command = [[ + openspace.globebrowsing.setNodePositionFromCamera('Scale_BigBen') + ]], + Documentation = "Updates the Big Ben position based on the globe location of the camera", + GuiPath = "/Scale Objects", + IsLocal = false +} + +local resetPositionAction = { + Identifier = "os.scale_models.reset_big_ben", + Name = "Reset Big Ben position", + Command = [[ + openspace.globebrowsing.setNodePosition('Scale_BigBen', ']] .. earthAsset.Earth.Identifier .. [[', 51.50079, -0.124279) + ]], + Documentation = "Resets the Big Ben back to it's actual location", + GuiPath = "/Scale Objects", + IsLocal = false +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(scaleModel) + openspace.action.registerAction(updatePositionAction) + openspace.action.registerAction(resetPositionAction) +end) + +asset.onDeinitialize(function() + openspace.action.removeAction(resetPositionAction) + openspace.action.removeAction(updatePositionAction) + openspace.removeSceneGraphNode(scaleModel) +end) + +asset.export(scaleModel) +asset.export(updatePositionAction) +asset.export(resetPositionAction) diff --git a/data/assets/educational/scale/burj_khalifa.asset b/data/assets/educational/scale/burj_khalifa.asset new file mode 100644 index 0000000000..863a3eb581 --- /dev/null +++ b/data/assets/educational/scale/burj_khalifa.asset @@ -0,0 +1,82 @@ +local earthAsset = asset.require('scene/solarsystem/planets/earth/earth') +local sunAsset = asset.require('scene/solarsystem/sun/sun') + +local modelFolder = asset.syncedResource({ + Name = "Scale Burj Khalifa", + Type = "UrlSynchronization", + Identifier = "scale_model_burj_khalifa", + Url = "https://wms.openspace.amnh.org/static/sync/url/scalemodels/Burj_Khalifa.osmodel", + Filename = "Burj_Khalifa.osmodel", + Override = false +}) + +local scaleModel = { + Identifier = "Scale_BurjKhalifa", + Parent = earthAsset.Earth.Identifier, + --Note: Lat/Lon/Scale values comes from alignment with Esri World Imagery 2D layer + Transform = { + Translation = { + Type = "GlobeTranslation", + Globe = earthAsset.Earth.Identifier, + Latitude = 25.196715, + Longitude = 55.273972, + Altitude = -3.0, + UseHeightmap = true + }, + Rotation = { + Type = "GlobeRotation", + Globe = earthAsset.Earth.Identifier, + Latitude = 25.196715, + Longitude = 55.273972, + UseHeightmap = false + } + }, + Renderable = { + Type = "RenderableModel", + GeometryFile = modelFolder .. "Burj_Khalifa.osmodel", + LightSources = { sunAsset.LightSource }, + ModelScale = "Centimeter" + }, + GUI = { + Name = "Burj Khalifa", + Path = "/Scale Objects" + } +} + +local updatePositionAction = { + Identifier = "os.scale_models.drop_burj_khalifa", + Name = "Drop Burj Khalifa under camera", + Command = [[ + openspace.globebrowsing.setNodePositionFromCamera('Scale_BurjKhalifa') + ]], + Documentation = "Updates the Burj Khalifa position based on the globe location of the camera", + GuiPath = "/Scale Objects", + IsLocal = false +} + +local resetPositionAction = { + Identifier = "os.os.scale_models.reset_burj_khalifa", + Name = "Reset Burj Khalifa position", + Command = [[ + openspace.globebrowsing.setNodePosition('Scale_BurjKhalifa', ']] .. earthAsset.Earth.Identifier .. [[', 25.196715, 55.273972) + ]], + Documentation = "Resets the Burj Khalifa back to it's actual location", + GuiPath = "/Scale Objects", + IsLocal = false +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(scaleModel) + openspace.action.registerAction(updatePositionAction) + openspace.action.registerAction(resetPositionAction) +end) + +asset.onDeinitialize(function() + openspace.action.removeAction(resetPositionAction) + openspace.action.removeAction(updatePositionAction) + openspace.removeSceneGraphNode(scaleModel) +end) + +asset.export(scaleModel) +asset.export(updatePositionAction) +asset.export(resetPositionAction) diff --git a/data/assets/educational/scale/eiffeltower.asset b/data/assets/educational/scale/eiffeltower.asset index 9b16c63579..7c51b7c513 100644 --- a/data/assets/educational/scale/eiffeltower.asset +++ b/data/assets/educational/scale/eiffeltower.asset @@ -2,30 +2,30 @@ local earthAsset = asset.require('scene/solarsystem/planets/earth/earth') local sunAsset = asset.require('scene/solarsystem/sun/sun') local modelFolder = asset.syncedResource({ - Name = "Eiffel Tower Model", + Name = "Scale Eiffel Tower", Type = "HttpSynchronization", - Identifier = "eiffel_tower_model", + Identifier = "scale_model_eiffel_tower", Version = 1 }) -local eiffelTower = { - Identifier = "eiffelTower", +local scaleModel = { + Identifier = "Scale_EiffelTower", Parent = earthAsset.Earth.Identifier, --Note: Lat/Lon/Scale values comes from alignment with Esri World Imagery 2D layer Transform = { Translation = { Type = "GlobeTranslation", Globe = earthAsset.Earth.Identifier, - Longitude = 2.29448, Latitude = 48.85824, + Longitude = 2.29448, Altitude = 0.0, UseHeightmap = true }, Rotation = { Type = "GlobeRotation", Globe = earthAsset.Earth.Identifier, - Longitude = 2.29448, Latitude = 48.85824, + Longitude = 2.29448, UseHeightmap = false }, Scale = { @@ -36,9 +36,9 @@ local eiffelTower = { Renderable = { Type = "RenderableModel", GeometryFile = modelFolder .. "eiffeltower.osmodel", - ModelScale = "Centimeter", RotationVector = { 0.0, 45.0, 0.0 }, - LightSources = { sunAsset.LightSource } + LightSources = { sunAsset.LightSource }, + ModelScale = "Centimeter" }, GUI = { Name = "Eiffel Tower", @@ -47,18 +47,10 @@ local eiffelTower = { } local updatePositionAction = { - Identifier = "os.drop_eiffel_tower", - Name = "Drop Eiffel tower under camera", + Identifier = "os.scale_models.drop_eiffel_tower", + Name = "Drop Eiffel Tower under camera", Command = [[ - local lat, lon, alt = openspace.globebrowsing.getGeoPositionForCamera(); - local camera = openspace.navigation.getNavigationState(); - openspace.setParent('eiffelTower', camera.Anchor) - openspace.setPropertyValueSingle('Scene.eiffelTower.Translation.Globe', camera.Anchor); - openspace.setPropertyValueSingle('Scene.eiffelTower.Translation.Latitude', lat); - openspace.setPropertyValueSingle('Scene.eiffelTower.Translation.Longitude', lon); - openspace.setPropertyValueSingle('Scene.eiffelTower.Rotation.Globe', camera.Anchor); - openspace.setPropertyValueSingle('Scene.eiffelTower.Rotation.Latitude', lat); - openspace.setPropertyValueSingle('Scene.eiffelTower.Rotation.Longitude', lon); + openspace.globebrowsing.setNodePositionFromCamera('Scale_EiffelTower') ]], Documentation = "Updates the Eiffel Tower position based on the globe location of the camera", GuiPath = "/Scale Objects", @@ -66,29 +58,18 @@ local updatePositionAction = { } local resetPositionAction = { - Identifier = "os.reset_eiffel_tower", - Name = "Reset Eiffel tower position", + Identifier = "os.os.scale_models.reset_eiffel_tower", + Name = "Reset Eiffel Tower position", Command = [[ - -- same position as above - local lat = 48.85824 - local lon = 2.29448 - local globe = ']] .. earthAsset.Earth.Identifier .. [[' - openspace.setParent('eiffelTower', globe) - openspace.setPropertyValueSingle('Scene.eiffelTower.Translation.Globe', globe); - openspace.setPropertyValueSingle('Scene.eiffelTower.Translation.Latitude', lat); - openspace.setPropertyValueSingle('Scene.eiffelTower.Translation.Longitude', lon); - openspace.setPropertyValueSingle('Scene.eiffelTower.Rotation.Globe', globe); - openspace.setPropertyValueSingle('Scene.eiffelTower.Rotation.Latitude', lat); - openspace.setPropertyValueSingle('Scene.eiffelTower.Rotation.Longitude', lon); + openspace.globebrowsing.setNodePosition('Scale_EiffelTower', ']] .. earthAsset.Earth.Identifier .. [[', 48.85824, 2.29448) ]], - Documentation = "Updates the Eiffel Tower position based on the globe location of the camera", + Documentation = "Resets the Eiffel Tower back to it's actual location", GuiPath = "/Scale Objects", IsLocal = false } - asset.onInitialize(function() - openspace.addSceneGraphNode(eiffelTower) + openspace.addSceneGraphNode(scaleModel) openspace.action.registerAction(updatePositionAction) openspace.action.registerAction(resetPositionAction) end) @@ -96,7 +77,9 @@ end) asset.onDeinitialize(function() openspace.action.removeAction(resetPositionAction) openspace.action.removeAction(updatePositionAction) - openspace.removeSceneGraphNode(eiffelTower) + openspace.removeSceneGraphNode(scaleModel) end) -asset.export(eiffelTower) +asset.export(scaleModel) +asset.export(updatePositionAction) +asset.export(resetPositionAction) diff --git a/data/assets/educational/scale/empire_state_building.asset b/data/assets/educational/scale/empire_state_building.asset new file mode 100644 index 0000000000..b83e6c1609 --- /dev/null +++ b/data/assets/educational/scale/empire_state_building.asset @@ -0,0 +1,84 @@ +local earthAsset = asset.require('scene/solarsystem/planets/earth/earth') +local sunAsset = asset.require('scene/solarsystem/sun/sun') + +local modelFolder = asset.syncedResource({ + Name = "Scale Empire State Building", + Type = "HttpSynchronization", + Identifier = "scale_model_empire_state", + Version = 1 +}) + +local scaleModel = { + Identifier = "Scale_EmpireStateBuilding", + Parent = earthAsset.Earth.Identifier, + --Note: Lat/Lon/Scale values comes from alignment with Esri World Imagery 2D layer + Transform = { + Translation = { + Type = "GlobeTranslation", + Globe = earthAsset.Earth.Identifier, + Latitude = 40.748441, + Longitude = -73.985664, + Altitude = 0.0, + UseHeightmap = true + }, + Rotation = { + Type = "GlobeRotation", + Globe = earthAsset.Earth.Identifier, + Latitude = 40.748441, + Longitude = -73.985664, + UseHeightmap = false + }, + Scale = { + Type = "StaticScale", + Scale = 0.5 + } + }, + Renderable = { + Type = "RenderableModel", + GeometryFile = modelFolder .. "Empire_State_fbx.osmodel", + RotationVector = { 0.0, 60.0, 0.0 }, + LightSources = { sunAsset.LightSource } + }, + GUI = { + Name = "Empire State Building", + Path = "/Scale Objects" + } +} + +local updatePositionAction = { + Identifier = "os.scale_models.drop_empire_state_building", + Name = "Drop Empire State Building under camera", + Command = [[ + openspace.globebrowsing.setNodePositionFromCamera('Scale_EmpireStateBuilding') + ]], + Documentation = "Updates the Empire State Building position based on the globe location of the camera", + GuiPath = "/Scale Objects", + IsLocal = false +} + +local resetPositionAction = { + Identifier = "os.os.scale_models.reset_empire_state_building", + Name = "Reset Empire State Building position", + Command = [[ + openspace.globebrowsing.setNodePosition('Scale_EmpireStateBuilding', ']] .. earthAsset.Earth.Identifier .. [[', 40.748441, -73.985664) + ]], + Documentation = "Resets the Empire State Building back to it's actual location", + GuiPath = "/Scale Objects", + IsLocal = false +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(scaleModel) + openspace.action.registerAction(updatePositionAction) + openspace.action.registerAction(resetPositionAction) +end) + +asset.onDeinitialize(function() + openspace.action.removeAction(resetPositionAction) + openspace.action.removeAction(updatePositionAction) + openspace.removeSceneGraphNode(scaleModel) +end) + +asset.export(scaleModel) +asset.export(updatePositionAction) +asset.export(resetPositionAction) diff --git a/data/assets/educational/scale/gateway_arch.asset b/data/assets/educational/scale/gateway_arch.asset new file mode 100644 index 0000000000..f6cc29b4ec --- /dev/null +++ b/data/assets/educational/scale/gateway_arch.asset @@ -0,0 +1,86 @@ +local earthAsset = asset.require('scene/solarsystem/planets/earth/earth') +local sunAsset = asset.require('scene/solarsystem/sun/sun') + +local modelFolder = asset.syncedResource({ + Name = "Scale Gateway Arch", + Type = "UrlSynchronization", + Identifier = "scale_model_gateway_arch", + Url = "https://wms.openspace.amnh.org/static/sync/url/scalemodels/GatewayArch_fbx.osmodel", + Filename = "GatewayArch_fbx.osmodel", + Override = false +}) + +local scaleModel = { + Identifier = "Scale_GatewayArch", + Parent = earthAsset.Earth.Identifier, + --Note: Lat/Lon/Scale values comes from alignment with Esri World Imagery 2D layer + Transform = { + Translation = { + Type = "GlobeTranslation", + Globe = earthAsset.Earth.Identifier, + Latitude = 38.624880, + Longitude = -90.184939, + Altitude = 0.0, + UseHeightmap = true + }, + Rotation = { + Type = "GlobeRotation", + Globe = earthAsset.Earth.Identifier, + Latitude = 38.624880, + Longitude = -90.184939, + UseHeightmap = false + }, + Scale = { + Type = "StaticScale", + Scale = 0.5 + } + }, + Renderable = { + Type = "RenderableModel", + GeometryFile = modelFolder .. "GatewayArch_fbx.osmodel", + RotationVector = { 0.0, 157, 0.0 }, + LightSources = { sunAsset.LightSource } + }, + GUI = { + Name = "Gateway Arch", + Path = "/Scale Objects" + } +} + +local updatePositionAction = { + Identifier = "os.scale_models.drop_gateway_arch", + Name = "Drop Gateway Arch under camera", + Command = [[ + openspace.globebrowsing.setNodePositionFromCamera('Scale_GatewayArch') + ]], + Documentation = "Updates the Gateway Arch position based on the globe location of the camera", + GuiPath = "/Scale Objects", + IsLocal = false +} + +local resetPositionAction = { + Identifier = "os.os.scale_models.reset_gateway_arch", + Name = "Reset Gateway Arch position", + Command = [[ + openspace.globebrowsing.setNodePosition('Scale_GatewayArch', ']] .. earthAsset.Earth.Identifier .. [[', 38.624880, -90.184939) + ]], + Documentation = "Resets the Gateway Arch back to it's actual location", + GuiPath = "/Scale Objects", + IsLocal = false +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(scaleModel) + openspace.action.registerAction(updatePositionAction) + openspace.action.registerAction(resetPositionAction) +end) + +asset.onDeinitialize(function() + openspace.action.removeAction(resetPositionAction) + openspace.action.removeAction(updatePositionAction) + openspace.removeSceneGraphNode(scaleModel) +end) + +asset.export(scaleModel) +asset.export(updatePositionAction) +asset.export(resetPositionAction) diff --git a/data/assets/educational/scale/golden_gate_bridge.asset b/data/assets/educational/scale/golden_gate_bridge.asset new file mode 100644 index 0000000000..b362c04678 --- /dev/null +++ b/data/assets/educational/scale/golden_gate_bridge.asset @@ -0,0 +1,87 @@ +local earthAsset = asset.require('scene/solarsystem/planets/earth/earth') +local sunAsset = asset.require('scene/solarsystem/sun/sun') + +local modelFolder = asset.syncedResource({ + Name = "Scale Golden Gate Bridge", + Type = "UrlSynchronization", + Identifier = "scale_model_golden_gate_bridge", + Url = "https://wms.openspace.amnh.org/static/sync/url/scalemodels/golden_gate.osmodel", + Filename = "golden_gate.osmodel", + Override = false +}) + +local scaleModel = { + Identifier = "Scale_GoldenGateBridge", + Parent = earthAsset.Earth.Identifier, + --Note: Lat/Lon/Scale values comes from alignment with Esri World Imagery 2D layer + Transform = { + Translation = { + Type = "GlobeTranslation", + Globe = earthAsset.Earth.Identifier, + Latitude = 37.816116, + Longitude = -122.477890, + Altitude = 120.0, + UseHeightmap = true + }, + Rotation = { + Type = "GlobeRotation", + Globe = earthAsset.Earth.Identifier, + Latitude = 37.816116, + Longitude = -122.477890, + UseHeightmap = false + }, + Scale = { + Type = "StaticScale", + Scale = 0.2 + } + }, + Renderable = { + Type = "RenderableModel", + GeometryFile = modelFolder .. "golden_gate.osmodel", + ForceRenderInvisible = true, + RotationVector = { 0.0, 95.4, 0.0 }, + LightSources = { sunAsset.LightSource } + }, + GUI = { + Name = "Golden Gate Bridge", + Path = "/Scale Objects" + } +} + +local updatePositionAction = { + Identifier = "os.scale_models.drop_golden_gate_bridge", + Name = "Drop Golden Gate Bridge under camera", + Command = [[ + openspace.globebrowsing.setNodePositionFromCamera('Scale_GoldenGateBridge') + ]], + Documentation = "Updates the Golden Gate Bridge position based on the globe location of the camera", + GuiPath = "/Scale Objects", + IsLocal = false +} + +local resetPositionAction = { + Identifier = "os.os.scale_models.reset_golden_gate_bridge", + Name = "Reset Golden Gate Bridge position", + Command = [[ + openspace.globebrowsing.setNodePosition('Scale_GoldenGateBridge', ']] .. earthAsset.Earth.Identifier .. [[', 37.816116, -122.477890) + ]], + Documentation = "Resets the Golden Gate Bridge back to it's actual location", + GuiPath = "/Scale Objects", + IsLocal = false +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(scaleModel) + openspace.action.registerAction(updatePositionAction) + openspace.action.registerAction(resetPositionAction) +end) + +asset.onDeinitialize(function() + openspace.action.removeAction(resetPositionAction) + openspace.action.removeAction(updatePositionAction) + openspace.removeSceneGraphNode(scaleModel) +end) + +asset.export(scaleModel) +asset.export(updatePositionAction) +asset.export(resetPositionAction) diff --git a/data/assets/educational/scale/kuala_lumpur_tower.asset b/data/assets/educational/scale/kuala_lumpur_tower.asset new file mode 100644 index 0000000000..d009d52824 --- /dev/null +++ b/data/assets/educational/scale/kuala_lumpur_tower.asset @@ -0,0 +1,79 @@ +local earthAsset = asset.require('scene/solarsystem/planets/earth/earth') +local sunAsset = asset.require('scene/solarsystem/sun/sun') + +local modelFolder = asset.syncedResource({ + Name = "Scale Kuala Lumpur Tower", + Type = "HttpSynchronization", + Identifier = "scale_model_kuala_lumpur_tower", + Version = 1 +}) + +local scaleModel = { + Identifier = "Scale_KualaLumpurTower", + Parent = earthAsset.Earth.Identifier, + --Note: Lat/Lon/Scale values comes from alignment with Esri World Imagery 2D layer + Transform = { + Translation = { + Type = "GlobeTranslation", + Globe = earthAsset.Earth.Identifier, + Latitude = 3.152878, + Longitude = 101.703533, + Altitude = 0.0, + UseHeightmap = true + }, + Rotation = { + Type = "GlobeRotation", + Globe = earthAsset.Earth.Identifier, + Latitude = 3.152878, + Longitude = 101.703533, + UseHeightmap = false + } + }, + Renderable = { + Type = "RenderableModel", + GeometryFile = modelFolder .. "menara_kl_FBX.osmodel", + LightSources = { sunAsset.LightSource } + }, + GUI = { + Name = "Kuala Lumpur Tower", + Path = "/Scale Objects" + } +} + +local updatePositionAction = { + Identifier = "os.scale_models.drop_kuala_lumpur_tower", + Name = "Drop Kuala Lumpur Tower under camera", + Command = [[ + openspace.globebrowsing.setNodePositionFromCamera('Scale_KualaLumpurTower') + ]], + Documentation = "Updates the Kuala Lumpur Tower position based on the globe location of the camera", + GuiPath = "/Scale Objects", + IsLocal = false +} + +local resetPositionAction = { + Identifier = "os.os.scale_models.reset_kuala_lumpur_tower", + Name = "Reset Kuala Lumpur Tower position", + Command = [[ + openspace.globebrowsing.setNodePosition('Scale_KualaLumpurTower', ']] .. earthAsset.Earth.Identifier .. [[', 3.152878, 101.703533) + ]], + Documentation = "Resets the Kuala Lumpur Tower back to it's actual location", + GuiPath = "/Scale Objects", + IsLocal = false +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(scaleModel) + openspace.action.registerAction(updatePositionAction) + openspace.action.registerAction(resetPositionAction) +end) + +asset.onDeinitialize(function() + openspace.action.removeAction(resetPositionAction) + openspace.action.removeAction(updatePositionAction) + openspace.removeSceneGraphNode(scaleModel) +end) + +asset.export(scaleModel) +asset.export(updatePositionAction) +asset.export(resetPositionAction) diff --git a/data/assets/educational/scale/rose_bowl.asset b/data/assets/educational/scale/rose_bowl.asset new file mode 100644 index 0000000000..180438ad49 --- /dev/null +++ b/data/assets/educational/scale/rose_bowl.asset @@ -0,0 +1,80 @@ +local earthAsset = asset.require('scene/solarsystem/planets/earth/earth') +local sunAsset = asset.require('scene/solarsystem/sun/sun') + +local modelFolder = asset.syncedResource({ + Name = "Scale Rose Bowl", + Type = "HttpSynchronization", + Identifier = "scale_model_rose_bowl", + Version = 1 +}) + +local scaleModel = { + Identifier = "Scale_RoseBowl", + Parent = earthAsset.Earth.Identifier, + --Note: Lat/Lon/Scale values comes from alignment with Esri World Imagery 2D layer + Transform = { + Translation = { + Type = "GlobeTranslation", + Globe = earthAsset.Earth.Identifier, + Latitude = 34.161318, + Longitude = -118.167623, + Altitude = 0.0, + UseHeightmap = true + }, + Rotation = { + Type = "GlobeRotation", + Globe = earthAsset.Earth.Identifier, + Latitude = 34.161318, + Longitude = -118.167623, + UseHeightmap = false + } + }, + Renderable = { + Type = "RenderableModel", + GeometryFile = modelFolder .. "rose_bowl.gltf", + RotationVector = { 0.0, 98.68, 0.0 }, + LightSources = { sunAsset.LightSource } + }, + GUI = { + Name = "Rose Bowl", + Path = "/Scale Objects" + } +} + +local updatePositionAction = { + Identifier = "os.scale_models.drop_rose_bowl", + Name = "Drop Rose Bowl under camera", + Command = [[ + openspace.globebrowsing.setNodePositionFromCamera('Scale_RoseBowl') + ]], + Documentation = "Updates the Rose Bowl position based on the globe location of the camera", + GuiPath = "/Scale Objects", + IsLocal = false +} + +local resetPositionAction = { + Identifier = "os.os.scale_models.reset_rose_bowl", + Name = "Reset Rose Bowl position", + Command = [[ + openspace.globebrowsing.setNodePosition('Scale_RoseBowl', ']] .. earthAsset.Earth.Identifier .. [[', 34.161318, -118.167623) + ]], + Documentation = "Resets the Rose Bowl back to it's actual location", + GuiPath = "/Scale Objects", + IsLocal = false +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(scaleModel) + openspace.action.registerAction(updatePositionAction) + openspace.action.registerAction(resetPositionAction) +end) + +asset.onDeinitialize(function() + openspace.action.removeAction(resetPositionAction) + openspace.action.removeAction(updatePositionAction) + openspace.removeSceneGraphNode(scaleModel) +end) + +asset.export(scaleModel) +asset.export(updatePositionAction) +asset.export(resetPositionAction) diff --git a/data/assets/educational/scale/school_bus.asset b/data/assets/educational/scale/school_bus.asset new file mode 100644 index 0000000000..eb48b4c08d --- /dev/null +++ b/data/assets/educational/scale/school_bus.asset @@ -0,0 +1,80 @@ +local earthAsset = asset.require('scene/solarsystem/planets/earth/earth') +local sunAsset = asset.require('scene/solarsystem/sun/sun') + +local modelFolder = asset.syncedResource({ + Name = "Scale School Bus", + Type = "HttpSynchronization", + Identifier = "scale_model_school_bus", + Version = 1 +}) + +local scaleModel = { + Identifier = "Scale_SchoolBus", + Parent = earthAsset.Earth.Identifier, + --Note: Lat/Lon/Scale values comes from alignment with Esri World Imagery 2D layer + Transform = { + Translation = { + Type = "GlobeTranslation", + Globe = earthAsset.Earth.Identifier, + Latitude = 40.780671, + Longitude = -73.971701, + Altitude = 0.78, + UseHeightmap = true + }, + Rotation = { + Type = "GlobeRotation", + Globe = earthAsset.Earth.Identifier, + Latitude = 40.780671, + Longitude = -73.971701, + UseHeightmap = false + } + }, + Renderable = { + Type = "RenderableModel", + GeometryFile = modelFolder .. "school_bus.gltf", + RotationVector = { 0.0, 90.0, 0.0 }, + LightSources = { sunAsset.LightSource } + }, + GUI = { + Name = "School bus", + Path = "/Scale Objects" + } +} + +local updatePositionAction = { + Identifier = "os.scale_models.drop_school_bus", + Name = "Drop school bus under camera", + Command = [[ + openspace.globebrowsing.setNodePositionFromCamera('Scale_SchoolBus') + ]], + Documentation = "Updates the school bus position based on the globe location of the camera", + GuiPath = "/Scale Objects", + IsLocal = false +} + +local resetPositionAction = { + Identifier = "os.os.scale_models.reset_school_bus", + Name = "Reset School bus position", + Command = [[ + openspace.globebrowsing.setNodePosition('Scale_SchoolBus', ']] .. earthAsset.Earth.Identifier .. [[', 40.780671, -73.971701) + ]], + Documentation = "Resets the school bus back to it's actual location", + GuiPath = "/Scale Objects", + IsLocal = false +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(scaleModel) + openspace.action.registerAction(updatePositionAction) + openspace.action.registerAction(resetPositionAction) +end) + +asset.onDeinitialize(function() + openspace.action.removeAction(resetPositionAction) + openspace.action.removeAction(updatePositionAction) + openspace.removeSceneGraphNode(scaleModel) +end) + +asset.export(scaleModel) +asset.export(updatePositionAction) +asset.export(resetPositionAction) diff --git a/data/assets/educational/scale/scientist.asset b/data/assets/educational/scale/scientist.asset new file mode 100644 index 0000000000..ae5b5e51eb --- /dev/null +++ b/data/assets/educational/scale/scientist.asset @@ -0,0 +1,80 @@ +local earthAsset = asset.require('scene/solarsystem/planets/earth/earth') +local sunAsset = asset.require('scene/solarsystem/sun/sun') + +local modelFolder = asset.syncedResource({ + Name = "Scale Model Scientist", + Type = "HttpSynchronization", + Identifier = "scale_model_scientist", + Version = 1 +}) + +local scaleModel = { + Identifier = "Scale_Scientist", + Parent = earthAsset.Earth.Identifier, + --Note: Lat/Lon/Scale values comes from alignment with Esri World Imagery 2D layer + Transform = { + Translation = { + Type = "GlobeTranslation", + Globe = earthAsset.Earth.Identifier, + Latitude = 34.201639, + Longitude = -118.171319, + Altitude = 0.78, + UseHeightmap = true + }, + Rotation = { + Type = "GlobeRotation", + Globe = earthAsset.Earth.Identifier, + Latitude = 34.201639, + Longitude = -118.171319, + UseHeightmap = false + } + }, + Renderable = { + Type = "RenderableModel", + GeometryFile = modelFolder .. "scientist.gltf", + RotationVector = { 0.0, 90.0, 0.0 }, + LightSources = { sunAsset.LightSource } + }, + GUI = { + Name = "Scientist", + Path = "/Scale Objects" + } +} + +local updatePositionAction = { + Identifier = "os.scale_models.drop_scientist", + Name = "Drop Scientist under camera", + Command = [[ + openspace.globebrowsing.setNodePositionFromCamera('Scale_Scientist') + ]], + Documentation = "Updates the Scientist position based on the globe location of the camera", + GuiPath = "/Scale Objects", + IsLocal = false +} + +local resetPositionAction = { + Identifier = "os.os.scale_models.reset_scientist", + Name = "Reset Scientist position", + Command = [[ + openspace.globebrowsing.setNodePosition('Scale_Scientist', ']] .. earthAsset.Earth.Identifier .. [[', 34.201639, -118.171319) + ]], + Documentation = "Resets the Scientist back to it's actual location", + GuiPath = "/Scale Objects", + IsLocal = false +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(scaleModel) + openspace.action.registerAction(updatePositionAction) + openspace.action.registerAction(resetPositionAction) +end) + +asset.onDeinitialize(function() + openspace.action.removeAction(resetPositionAction) + openspace.action.removeAction(updatePositionAction) + openspace.removeSceneGraphNode(scaleModel) +end) + +asset.export(scaleModel) +asset.export(updatePositionAction) +asset.export(resetPositionAction) diff --git a/data/assets/educational/scale/statue_of_liberty.asset b/data/assets/educational/scale/statue_of_liberty.asset new file mode 100644 index 0000000000..2aedc527b6 --- /dev/null +++ b/data/assets/educational/scale/statue_of_liberty.asset @@ -0,0 +1,80 @@ +local earthAsset = asset.require('scene/solarsystem/planets/earth/earth') +local sunAsset = asset.require('scene/solarsystem/sun/sun') + +local modelFolder = asset.syncedResource({ + Name = "Scale Model Statue of Liberty", + Type = "HttpSynchronization", + Identifier = "scale_model_statue_of_liberty", + Version = 1 +}) + +local scaleModel = { + Identifier = "Scale_StatueOfLiberty", + Parent = earthAsset.Earth.Identifier, + --Note: Lat/Lon/Scale values comes from alignment with Esri World Imagery 2D layer + Transform = { + Translation = { + Type = "GlobeTranslation", + Globe = earthAsset.Earth.Identifier, + Latitude = 40.689206, + Longitude = -74.044487, + Altitude = -3, + UseHeightmap = true + }, + Rotation = { + Type = "GlobeRotation", + Globe = earthAsset.Earth.Identifier, + Latitude = 40.689206, + Longitude = -74.044487, + UseHeightmap = false + } + }, + Renderable = { + Type = "RenderableModel", + GeometryFile = modelFolder .. "STATUE_OF_LIBERTY.osmodel", + RotationVector = { 0.0, 235.0, 0.0 }, + LightSources = { sunAsset.LightSource } + }, + GUI = { + Name = "Statue of Liberty", + Path = "/Scale Objects" + } +} + +local updatePositionAction = { + Identifier = "os.scale_models.drop_statue_of_libery", + Name = "Drop Statue of Liberty under camera", + Command = [[ + openspace.globebrowsing.setNodePositionFromCamera('Scale_StatueOfLiberty') + ]], + Documentation = "Updates the Statue of Liberty position based on the globe location of the camera", + GuiPath = "/Scale Objects", + IsLocal = false +} + +local resetPositionAction = { + Identifier = "os.scale_models.reset_statue_of_libery", + Name = "Reset Statue of Liberty position", + Command = [[ + openspace.globebrowsing.setNodePosition('Scale_StatueOfLiberty', ']] .. earthAsset.Earth.Identifier .. [[', 40.689206, -74.044487) + ]], + Documentation = "Resets the Statue of Liberty back to it's actual location", + GuiPath = "/Scale Objects", + IsLocal = false +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(scaleModel) + openspace.action.registerAction(updatePositionAction) + openspace.action.registerAction(resetPositionAction) +end) + +asset.onDeinitialize(function() + openspace.action.removeAction(resetPositionAction) + openspace.action.removeAction(updatePositionAction) + openspace.removeSceneGraphNode(scaleModel) +end) + +asset.export(scaleModel) +asset.export(updatePositionAction) +asset.export(resetPositionAction) diff --git a/data/assets/util/scale_model_helper.asset b/data/assets/util/scale_model_helper.asset new file mode 100644 index 0000000000..6f728c79b7 --- /dev/null +++ b/data/assets/util/scale_model_helper.asset @@ -0,0 +1,111 @@ +local earthAsset = asset.require('scene/solarsystem/planets/earth/earth') +local sunAsset = asset.require('scene/solarsystem/sun/sun') + +local createModelFolder = function(name, syncFolder) + + local folder = asset.syncedResource({ + Name = "Scale Model " .. name, + Type = "HttpSynchronization", + Identifier = syncFolder, + Version = 1 + }) + + return folder +end + +local createModel = function(identifier, lat, lon, altitude, scale, modelScale, + rotationVector, name, modelFolder, modelFile) + + local model = { + Identifier = identifier, + Parent = earthAsset.Earth.Identifier, + --Note: Lat/Lon/Scale values comes from alignment with Esri World Imagery 2D layer + Transform = { + Translation = { + Type = "GlobeTranslation", + Globe = earthAsset.Earth.Identifier, + Latitude = lat, + Longitude = lon, + Altitude = altitude, + UseHeightmap = true + }, + Rotation = { + Type = "GlobeRotation", + Globe = earthAsset.Earth.Identifier, + Latitude = lat, + Longitude = lon, + UseHeightmap = false + }, + Scale = { + Type = "StaticScale", + Scale = scale + } + }, + Renderable = { + Type = "RenderableModel", + GeometryFile = modelFolder .. modelFile, + RotationVector = rotationVector, + ModelScale = modelScale, + LightSources = { sunAsset.LightSource } + }, + GUI = { + Name = name, + Path = "/Scale Objects" + } + } + + return model +end + +local createDropAction = function(identifier, name, guiPath) + local updatePositionAction = { + Identifier = "os.drop_" .. identifier, + Name = "Drop " .. name .. " Building under camera", + Command = [[ + local lat, lon, alt = openspace.globebrowsing.getGeoPositionForCamera(); + local camera = openspace.navigation.getNavigationState(); + openspace.setParent(']] .. identifier .. [[', camera.Anchor) + openspace.setPropertyValueSingle('Scene.]] .. identifier .. [[.Translation.Globe', camera.Anchor); + openspace.setPropertyValueSingle('Scene.]] .. identifier .. [[.Translation.Latitude', lat); + openspace.setPropertyValueSingle('Scene.]] .. identifier .. [[.Translation.Longitude', lon); + openspace.setPropertyValueSingle('Scene.]] .. identifier .. [[.Rotation.Globe', camera.Anchor); + openspace.setPropertyValueSingle('Scene.]] .. identifier .. [[.Rotation.Latitude', lat); + openspace.setPropertyValueSingle('Scene.]] .. identifier .. [[.Rotation.Longitude', lon); + ]], + Documentation = "Updates the " .. name .. " position based on the globe location of the camera", + GuiPath = "/" .. guiPath, + IsLocal = false + } + + return updatePositionAction +end + +local createResetAction = function(identifier, name, lat, lon, guiPath) + local resetPositionAction = { + Identifier = "os.reset_" .. identifier, + Name = "Reset " .. name .. " position", + Command = [[ + -- same position as above + local lat = ]] .. lat .. [[ + local lon = ]] .. lon .. [[ + local globe = ']] .. earthAsset.Earth.Identifier .. [[' + openspace.setParent(']] .. identifier .. [[', globe) + openspace.setPropertyValueSingle('Scene.]] .. identifier .. [[.Translation.Globe', globe); + openspace.setPropertyValueSingle('Scene.]] .. identifier .. [[.Translation.Latitude', lat); + openspace.setPropertyValueSingle('Scene.]] .. identifier .. [[.Translation.Longitude', lon); + openspace.setPropertyValueSingle('Scene.]] .. identifier .. [[.Rotation.Globe', globe); + openspace.setPropertyValueSingle('Scene.]] .. identifier .. [[.Rotation.Latitude', lat); + openspace.setPropertyValueSingle('Scene.]] .. identifier .. [[.Rotation.Longitude', lon); + ]], + Documentation = "Updates the " .. name .. " position based on the globe location of the camera", + GuiPath = "/" .. guiPath, + IsLocal = false + } + + return resetPositionAction +end + +asset.export("createModelFolder", createModelFolder) +asset.export("createModel", createModel) +asset.export("createDropAction", createDropAction) +asset.export("createResetAction", createResetAction) diff --git a/modules/globebrowsing/globebrowsingmodule.cpp b/modules/globebrowsing/globebrowsingmodule.cpp index 0c40c6c39b..42d5adabb6 100644 --- a/modules/globebrowsing/globebrowsingmodule.cpp +++ b/modules/globebrowsing/globebrowsingmodule.cpp @@ -705,10 +705,11 @@ scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const { codegen::lua::CapabilitiesWMS, codegen::lua::AddGeoJson, codegen::lua::DeleteGeoJson, - codegen::lua::AddGeoJsonFromFile + codegen::lua::AddGeoJsonFromFile, }, .scripts = { - absPath("${MODULE_GLOBEBROWSING}/scripts/layer_support.lua") + absPath("${MODULE_GLOBEBROWSING}/scripts/layer_support.lua"), + absPath("${MODULE_GLOBEBROWSING}/scripts/node_support.lua") } }; } diff --git a/modules/globebrowsing/scripts/node_support.lua b/modules/globebrowsing/scripts/node_support.lua new file mode 100644 index 0000000000..be7a18bc6e --- /dev/null +++ b/modules/globebrowsing/scripts/node_support.lua @@ -0,0 +1,53 @@ +openspace.globebrowsing.documentation = { + { + Name = "setNodePosition", + Arguments = { nodeIdentifer = "String", globeIdentifier = "String", latitude = "Number", longitude = "Number", altitude = "Number" }, + Documentation = + "Sets the position of a SceneGraphNode that has GlobeTranslation/GlobeRotations. " .. + "Usage: openspace.globebrowsing.setNodePosition(" .. + "\"Scale_StatueOfLiberty\", \"Earth\", 40.000, -117.5, optionalAltitude)" + }, + { + Name = "setNodePositionFromCamera", + Arguments = { nodeIdentifer = "String", useAltitude = "Number" }, + Documentation = + "Sets the position of a SceneGraphNode that has GlobeTranslation/GlobeRotations" .. + " to match the camera. Only uses camera position not rotation. If useAltitude" .. + " is true, then the position will also be updated to the camera's altitude." .. + "Usage: openspace.globebrowsing.setNodePositionFromCamera(" .. + "\"Scale_StatueOfLiberty\", optionalUseAltitude)" + } +} + +openspace.globebrowsing.setNodePosition = function (node_identifer, globe_identifier, lat, lon, altitude) + openspace.setParent(node_identifer, globe_identifier) + openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Globe', globe_identifier); + openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Latitude', lat); + openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Longitude', lon); + openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Rotation.Globe', globe_identifier); + openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Rotation.Latitude', lat); + openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Rotation.Longitude', lon); + if (altitude) then + openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Altitude', altitude); + openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Altitude', altitude); + end +end + +openspace.globebrowsing.setNodePositionFromCamera = function (node_identifer, use_altitude) + local lat, lon, alt = openspace.globebrowsing.getGeoPositionForCamera(); + local camera = openspace.navigation.getNavigationState(); + openspace.setParent(node_identifer, camera.Anchor) + openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Globe', camera.Anchor); + openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Latitude', lat); + openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Longitude', lon); + openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Rotation.Globe', camera.Anchor); + openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Rotation.Latitude', lat); + openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Rotation.Longitude', lon); + if (use_altitude) then + openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Altitude', alt); + openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Altitude', alt); + end +end + + +