Feature/timeline translation (#931)

* Work on timeline translations
* Add Apollo 11 Descent data
* Ability to display negative altitudes
* Expose globe translation properties
* Added timeline rotation, and some scene updates. 
* Cleaning up apollo_sites scene; fixing boulder 1 in place to adress heightmap issue
* Use quaternion slerp instaet of linear interpolation + Cleanup
* Change to old lem model while waiting for new version to be pushed to data repo
* Small fixes
This commit is contained in:
Emil Axelsson
2019-07-17 15:21:13 +02:00
committed by Alexander Bock
parent 87df4a11a9
commit c97d5126ec
22 changed files with 4085 additions and 158 deletions

View File

@@ -2,12 +2,10 @@ asset.require('./base')
--moonrocks.scene
local sceneHelper = asset.require('util/scene_helper')
-- local station2 = asset.require('scene/solarsystem/missions/apollo/bouldersstation2')
-- local station6 = asset.require('scene/solarsystem/missions/apollo/bouldersstation6')
-- local station7 = asset.require('scene/solarsystem/missions/apollo/bouldersstation7')
asset.require('scene/solarsystem/missions/apollo/apollo11')
asset.require('scene/solarsystem/missions/apollo/a11_lem')
asset.require('scene/solarsystem/missions/apollo/a17_lem')
asset.require('scene/solarsystem/missions/apollo/apollo_globebrowsing')
asset.require('scene/solarsystem/missions/apollo/apollo_11_lem_flipbook')
@@ -37,11 +35,11 @@ local Keybindings = {
},
{
Key = "F11",
Command = "openspace.time.setTime('1969 JUL 20 20:17:40');" ..
Command = "openspace.time.setTime('1969 JUL 20 20:17:40');" ..
"openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.HeightLayers.LRO_NAC_Apollo_11.Enabled', true);" ..
"openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A11_M177481212_p_longlat.Enabled', true);" ..
"openspace.setPropertyValueSingle('Scene.Moon.Renderable.LodScaleFactor', 20.11);" ..
"openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'Apollo11LemModel');" ..
"openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.Anchor', 'Apollo11LemPosition');" ..
"openspace.setPropertyValue('NavigationHandler.OrbitalNavigator.RetargetAnchor', nil);" ..
"openspace.setPropertyValueSingle('Scene.Apollo11MoonTrail.Renderable.Enabled', true);" ..
"openspace.setPropertyValueSingle('Scene.Apollo11LemTrail.Renderable.Enabled', true);",
@@ -82,8 +80,11 @@ asset.onInitialize(function ()
sceneHelper.bindKeys(Keybindings)
openspace.markInterestingNodes({ "Moon", "Apollo11LemModel", "Apollo17LemModel", "Apollo11", "Apollo11LunarLander" })
openspace.markInterestingNodes({
"Moon", "Apollo11LemModel", "Apollo17LemModel",
"Apollo11", "Apollo11LunarLander",
-- "Station_2_Boulder2", "Station_6_Fragment1"
})
-- To enable both sites by default, uncomment these lines
-- openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_travmap.BlendMode', 0.000000);
-- openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_travmap.Enabled', true);
@@ -95,12 +96,19 @@ asset.onInitialize(function ()
-- openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A17_station7.BlendMode', 0.000000);
-- openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.HeightLayers.LRO_NAC_Apollo_11.Enabled', true);
-- openspace.setPropertyValueSingle('Scene.Moon.Renderable.Layers.ColorLayers.A11_M177481212_p_longlat.Enabled', true);
openspace.setPropertyValueSingle('Scene.Apollo11LemDescentModel.Renderable.RotationVector', { 273.205475,6.904110,308.712311 });
openspace.setPropertyValueSingle('Scene.Apollo11LemLandedModel.Renderable.RotationVector', { 273.205475,6.904110,308.712311 });
openspace.globebrowsing.goToGeo(moonAsset.Moon.Identifier, 20, -60, 15000000)
openspace.setPropertyValueSingle("Scene.Moon.Renderable.PerformShading", false)
end)
asset.onDeinitialize(function ()
openspace.removeInterestingNodes({ "Moon", "Apollo11Lem", "Apollo17Lem", "Apollo11", "Apollo11LunarLander" })
openspace.removeInterestingNodes({
"Moon", "Apollo11Lem", "Apollo17Lem",
"Apollo11", "Apollo11LemPosition",
-- "Station_6_Fragment1", "Station_6_Fragments_2_3"
})
end)

View File

@@ -15,8 +15,8 @@ local Apollo11Lem = {
Globe = moonAsset.Moon.Identifier,
Longitude = -360+23.47306,
Latitude = 0.67402,
FixedAltitude = -1927.65,
UseFixedAltitude = true
Altitude = -1927.65,
UseHeightMap = false
},
},
GUI = {

View File

@@ -14,6 +14,7 @@ local Apollo17Lem = {
Globe = moonAsset.Moon.Identifier,
Longitude = -329.22833,
Latitude = 20.19092,
UseHeightmap = true
},
},
GUI = {

View File

@@ -1,5 +1,8 @@
local assetHelper = asset.require('util/asset_helper')
local sunTransforms = asset.require('scene/solarsystem/sun/transforms')
local descentKeyframes = asset.require('./apollo11_lem_descent.asset')
local descentRotationKeyframes = asset.require('./apollo11_lem_descent_rotation.asset')
local model = asset.require('scene/solarsystem/missions/apollo/lem_model')
asset.require('spice/base')
@@ -24,7 +27,7 @@ local kernels = {
kernelsFolder .. '/apollo11_orbits_full9km.bsp',
kernelsFolder .. '/apollo11_orbits_lm9km.bsp',
}
--landing - 1969-07-20T20:17:40
local apolloSpiceId = "-911"
local apolloLemSpiceId = "-911500"
@@ -107,81 +110,44 @@ local Apollo11MoonTrail = {
}
}
-- Uncomment if you want to follow the mock decent
-- local Apollo11LemPosition = {
-- Identifier = "Apollo11LemPosition",
-- Parent = "Moon",
-- TimeFrame = {
-- Type = "TimeFrameInterval",
-- Start = "1969 JUL 20 19:10:25.183",
-- End = "1969 JUL 20 20:17:46.183"
-- },
-- Transform = {
-- Translation = {
-- Type = "SpiceTranslation",
-- Target = apolloLemSpiceId,
-- Observer = "MOON",
-- Frame = "MOON_ME",
-- Kernels = kernels
-- },
-- },
-- GUI = {
-- Hidden = true,
-- Name = "Apollo 11 Lunar Lander Position",
-- Path = "/Solar System/Missions/Apollo/11"
-- }
-- }
-- local Apollo11LunarLanderModel = {
-- Identifier = "Apollo11LunarLander",
-- Parent = Apollo11LemPosition.Identifier,
-- Transform = {
-- Rotation = {
-- Type = "StaticRotation",
-- Rotation = {0.0, 0.0, -3.1415/2}
-- },
-- Scale = {
-- Type = "StaticScale",
-- Scale = 100.0
-- }
-- },
-- TimeFrame = {
-- Type = "TimeFrameInterval",
-- Start = "1969 JUL 20 19:10:25.183",
-- End = "1969 JUL 20 20:17:46.183"
-- },
-- Renderable = {
-- Type = "RenderableModel",
-- Geometry = {
-- Type = "MultiModelGeometry",
-- GeometryFile = modelFolder .. "/lem_nasa.obj"
-- },
-- ColorTexture = modelFolder .. "/gray.png",
-- LightSources = assetHelper.getDefaultLightSources(sunTransforms.SolarSystemBarycenter.Identifier)
-- },
-- GUI = {
-- Hidden = false,
-- Name = "Apollo 11 Lunar Lander",
-- Path = "/Solar System/Missions/Apollo/11"
-- }
-- }
local Apollo11LemTrail = {
Identifier = "Apollo11LemTrail",
Parent = "Moon",
Renderable = {
Type = "RenderableTrailTrajectory",
Translation = {
local lemTranslation = {
Type = "TimelineTranslation",
Keyframes = {
-- 20:14:30 is an arbitrary cutoff, but last 4 minutes data in descentKeyframes
-- begins at 20.14.40. Due to linear interpolation, we will get
-- a 10s linear transition to the location where the descentKeyframes start.
['1969 JUL 20 20:14:30'] = {
Type = "SpiceTranslation",
Target = apolloLemSpiceId,
Observer = "MOON",
Frame = "IAU_MOON",
Kernels = kernels
},
Color = {0.780000,0.940000,0.340000 },
['1969 JUL 20 20:14:40'] = {
Type = "TimelineTranslation",
Keyframes = descentKeyframes.keyframes
}
}
}
local lemRotation = {
Type = "TimelineRotation",
Keyframes = descentRotationKeyframes.keyframes
}
local Apollo11LemTrail = {
Identifier = "Apollo11LemTrail",
Parent = "Moon",
Renderable = {
Type = "RenderableTrailTrajectory",
Translation = lemTranslation,
Color = { 0.780000,0.940000,0.340000 },
StartTime = "1969 JUL 20 19:10:25.183",
EndTime = "1969 JUL 20 20:17:46.183",
SampleInterval = 60,
SampleInterval = 2,
EnableFade = false,
Enabled = false,
},
@@ -191,11 +157,91 @@ local Apollo11LemTrail = {
}
}
local Apollo11LemPosition = {
Identifier = "Apollo11LemPosition",
Parent = "Moon",
TimeFrame = {
Type = "TimeFrameInterval",
Start = "1969 JUL 20 19:10:25.183"
},
Transform = {
Translation = lemTranslation,
Rotation = lemRotation
},
GUI = {
Hidden = false,
Name = "Apollo 11 Lunar Lander Position",
Path = "/Solar System/Missions/Apollo/11"
}
}
--landing - 1969-07-20T20:17:40
local Apollo11LemDescentModel = {
Identifier = "Apollo11LemDescentModel",
Parent = Apollo11LemPosition.Identifier,
TimeFrame = {
Type = "TimeFrameInterval",
Start = "1969 JUL 19 19:38:29.183",
End = "1969 JUL 20 20:17:40.0"
},
Transform = {
Scale = {
Type = "StaticScale",
Scale = 0.24
}
},
Renderable = {
Type = "RenderableModel",
Geometry = {
Type = "MultiModelGeometry",
GeometryFile = model.modelFolder .. "/LM-2_ver2clean.obj"
},
ColorTexture = model.modelFolder .. "/LM-2_ver2clean_u1_v1.jpeg",
LightSources = assetHelper.getDefaultLightSources(sunTransforms.SolarSystemBarycenter.Identifier)
},
GUI = {
Hidden = false,
Name = "Apollo 11 Descent Lem",
Path = "/Solar System/Missions/Apollo/11"
}
}
local Apollo11LemLandedModel = {
Identifier = "Apollo11LemLandedModel",
Parent = Apollo11LemPosition.Identifier,
TimeFrame = {
Type = "TimeFrameInterval",
Start = "1969 JUL 20 20:17:40.0"
},
Transform = {
Scale = {
Type = "StaticScale",
Scale = 0.24
}
},
Renderable = {
Type = "RenderableModel",
Geometry = {
Type = "MultiModelGeometry",
GeometryFile = model.modelFolder .. "/LM-2_ver2clean.obj"
},
ColorTexture = model.modelFolder .. "/LM-2_ver2clean_u1_v1.jpeg",
LightSources = assetHelper.getDefaultLightSources(sunTransforms.SolarSystemBarycenter.Identifier)
},
GUI = {
Hidden = false,
Name = "Apollo 11 Landed Lem",
Path = "/Solar System/Missions/Apollo/11"
}
}
local exportList = {
Apollo11Position,
-- Apollo11LemPosition,
Apollo11Position,
Apollo11LemPosition,
Apollo11Model,
-- Apollo11LunarLanderModel,
Apollo11LemDescentModel,
Apollo11LemLandedModel,
Apollo11MoonTrail,
Apollo11LemTrail,
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,74 @@
local assetHelper = asset.require('util/asset_helper')
local sunTransforms = asset.require('scene/solarsystem/sun/transforms')
local kernelsFolder = asset.syncedResource({
Name = "Apollo Kernels",
Type = "HttpSynchronization",
Identifier = "apollo_spice",
Version = 1
})
local kernels = {
kernelsFolder .. "/moon_080317.tf",
kernelsFolder .. "/apollo8.tf",
kernelsFolder .. "/moon_pa_de421_1900-2050.bpc",
kernelsFolder .. '/apollo8.tsc',
kernelsFolder .. '/apollo8.bsp',
kernelsFolder .. '/apollo8_earthrise.bc',
}
local apolloSpiceId = "-908"
local Apollo8LaunchTrail = {
Identifier = "Apollo8LaunchTrail",
Parent = "Earth",
Renderable = {
Type = "RenderableTrailTrajectory",
Translation = {
Type = "SpiceTranslation",
Target = apolloSpiceId,
Observer = "EARTH",
Frame = "IAU_EARTH",
Kernels = kernels
},
Color = { 0.70, 0.50, 0.20 },
StartTime = "1968 DEC 21 12:51:00",
EndTime = "1968 DEC 21 23:23:22",
SampleInterval = 30
},
GUI = {
Name = "Apollo 8 Launch Trail",
Path = "/Solar System/Missions/Apollo"
}
}
local Apollo8EarthBarycenterTrail = {
Identifier = "Apollo8EarthBarycenterTrail",
Parent = "EarthBarycenter",
Renderable = {
Type = "RenderableTrailTrajectory",
Translation = {
Type = "SpiceTranslation",
Target = apolloSpiceId,
Observer = "EARTH BARYCENTER",
Frame = "GALACTIC",
Kernels = kernels
},
Color = { 1, 0.0, 0.0 },
StartTime = "1968 DEC 21",
EndTime = "1968 DEC 28",
SampleInterval = 30,
Enabled = false,
},
GUI = {
Name = "Apollo 8 Earth Barycenter Trail",
Path = "/Solar System/Missions/Apollo"
}
}
local exportList = {
Apollo8LaunchTrail,
Apollo8EarthBarycenterTrail,
}
assetHelper.registerSceneGraphNodesAndExport(asset, exportList)

View File

@@ -33,8 +33,8 @@ local Station2Boulder1Holder = {
Globe = moonAsset.Moon.Identifier,
Longitude = -360+30.5294692,
Latitude = 20.098824,
FixedAltitude = -2442.8,
UseFixedAltitude = true
Altitude = -2442.8,
UseHeightMap = false
}
},
GUI = {
@@ -78,8 +78,8 @@ local Station2Boulder2Holder = {
Globe = moonAsset.Moon.Identifier,
Longitude = -360+30.5287892,
Latitude = 20.098240,
FixedAltitude = -2434.6,
UseFixedAltitude = true
Altitude = -2434.6,
UseHeightMap = false
}
},
GUI = {
@@ -123,8 +123,8 @@ local Station2Boulder3Holder = {
Globe = moonAsset.Moon.Identifier,
Longitude = -360+30.5294692,
Latitude = 20.098610,
FixedAltitude = -2441.55,
UseFixedAltitude = true
Altitude = -2441.55,
UseHeightMap = false
}
},
GUI = {

View File

@@ -37,6 +37,8 @@ local Station6Frag1Holder = {
Globe = moonAsset.Moon.Identifier,
Longitude = -360+30.80068,
Latitude = 20.2903,
Altitude = -2562.6,
UseHeightmap = false
}
},
GUI = {
@@ -54,6 +56,8 @@ local Station6Frag1Model = {
Globe = moonAsset.Moon.Identifier,
Longitude = -360+30.8007,
Latitude = 20.2903,
Altitude = -2562.6,
UseHeightmap = false
}
},
Transform = {
@@ -104,8 +108,8 @@ local Station6Frag2Model = {
Globe = moonAsset.Moon.Identifier,
Longitude = -360+30.80055,
Latitude = 20.289808,
FixedAltitude = -2566.5,
UseFixedAltitude = true
Altitude = -2566.5,
UseHeightmap = false
}
},
Renderable = {
@@ -140,8 +144,8 @@ local Station6Frag3Model = {
Globe = moonAsset.Moon.Identifier,
Longitude = -360+30.80053,
Latitude = 20.29030,
FixedAltitude = -2563.0,
UseFixedAltitude = true
Altitude = -2563.0,
UseHeightMap = false
}
},
Renderable = {

View File

@@ -34,8 +34,8 @@ local Station7BoulderHolder = {
Globe = moonAsset.Moon.Identifier,
Longitude = -360+30.8165882,
Latitude = 20.2908556,
FixedAltitude = -2593.5,
UseFixedAltitude = true
Altitude = -2593.5,
UseHeightMap = true
}
},
GUI = {

View File

@@ -44,7 +44,12 @@ struct KeyframeBase {
*/
template <typename T>
struct Keyframe : public KeyframeBase {
Keyframe(size_t i, double t, T p);
Keyframe(size_t i, double t, T d);
Keyframe(Keyframe const&) = default;
Keyframe(Keyframe&&) = default;
Keyframe& operator=(Keyframe&&) = default;
Keyframe& operator=(Keyframe const&) = default;
T data;
};
@@ -56,7 +61,8 @@ class Timeline {
public:
virtual ~Timeline() = default;
void addKeyframe(double time, T data);
void addKeyframe(double time, const T& data);
void addKeyframe(double time, T&& data);
void clearKeyframes();
void removeKeyframe(size_t id);
void removeKeyframesBefore(double timestamp, bool inclusive = false);
@@ -66,6 +72,7 @@ public:
size_t nKeyframes() const;
const Keyframe<T>* firstKeyframeAfter(double timestamp, bool inclusive = false) const;
const Keyframe<T>* lastKeyframeBefore(double timestamp, bool inclusive = false) const;
const std::deque<Keyframe<T>>& keyframes() const;
private:

View File

@@ -25,13 +25,25 @@
namespace openspace {
template <typename T>
Keyframe<T>::Keyframe(size_t i, double t, T p)
Keyframe<T>::Keyframe(size_t i, double t, T d)
: KeyframeBase{ i, t }
, data(p)
, data(std::move(d))
{}
template <typename T>
void Timeline<T>::addKeyframe(double timestamp, T data) {
void Timeline<T>::addKeyframe(double timestamp, T&& data) {
Keyframe<T> keyframe(++_nextKeyframeId, timestamp, std::move(data));
const auto iter = std::upper_bound(
_keyframes.cbegin(),
_keyframes.cend(),
keyframe,
&compareKeyframeTimes
);
_keyframes.insert(iter, std::move(keyframe));
}
template <typename T>
void Timeline<T>::addKeyframe(double timestamp, const T& data) {
Keyframe<T> keyframe(++_nextKeyframeId, timestamp, data);
const auto iter = std::upper_bound(
_keyframes.cbegin(),
@@ -39,7 +51,7 @@ void Timeline<T>::addKeyframe(double timestamp, T data) {
keyframe,
&compareKeyframeTimes
);
_keyframes.insert(iter, keyframe);
_keyframes.insert(iter, std::move(keyframe));
}
template <typename T>
@@ -143,7 +155,7 @@ void Timeline<T>::removeKeyframe(size_t id) {
std::remove_if(
_keyframes.begin(),
_keyframes.end(),
[id] (Keyframe<T> keyframe) { return keyframe.id == id; }
[id] (const Keyframe<T>& keyframe) { return keyframe.id == id; }
),
_keyframes.end()
);
@@ -209,7 +221,7 @@ const Keyframe<T>* Timeline<T>::lastKeyframeBefore(double timestamp, bool inclus
return &(*it);
}
template<typename T>
template <typename T>
const std::deque<Keyframe<T>>& Timeline<T>::keyframes() const {
return _keyframes;
}

View File

@@ -54,8 +54,7 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceframebuffer.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceimagelocal.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceimageonline.h
${CMAKE_CURRENT_SOURCE_DIR}/translation/luatranslation.h
${CMAKE_CURRENT_SOURCE_DIR}/translation/statictranslation.h
${CMAKE_CURRENT_SOURCE_DIR}/rotation/timelinerotation.h
${CMAKE_CURRENT_SOURCE_DIR}/rotation/constantrotation.h
${CMAKE_CURRENT_SOURCE_DIR}/rotation/fixedrotation.h
${CMAKE_CURRENT_SOURCE_DIR}/rotation/luarotation.h
@@ -65,6 +64,10 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/scale/timedependentscale.h
${CMAKE_CURRENT_SOURCE_DIR}/timeframe/timeframeinterval.h
${CMAKE_CURRENT_SOURCE_DIR}/timeframe/timeframeunion.h
${CMAKE_CURRENT_SOURCE_DIR}/translation/luatranslation.h
${CMAKE_CURRENT_SOURCE_DIR}/translation/statictranslation.h
${CMAKE_CURRENT_SOURCE_DIR}/translation/timelinetranslation.h
)
source_group("Header Files" FILES ${HEADER_FILES})
@@ -98,8 +101,7 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceframebuffer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceimagelocal.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/screenspaceimageonline.cpp
${CMAKE_CURRENT_SOURCE_DIR}/translation/luatranslation.cpp
${CMAKE_CURRENT_SOURCE_DIR}/translation/statictranslation.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rotation/timelinerotation.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rotation/constantrotation.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rotation/fixedrotation.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rotation/luarotation.cpp
@@ -109,6 +111,9 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/scale/timedependentscale.cpp
${CMAKE_CURRENT_SOURCE_DIR}/timeframe/timeframeinterval.cpp
${CMAKE_CURRENT_SOURCE_DIR}/timeframe/timeframeunion.cpp
${CMAKE_CURRENT_SOURCE_DIR}/translation/luatranslation.cpp
${CMAKE_CURRENT_SOURCE_DIR}/translation/statictranslation.cpp
${CMAKE_CURRENT_SOURCE_DIR}/translation/timelinetranslation.cpp
)
source_group("Source Files" FILES ${SOURCE_FILES})

View File

@@ -55,9 +55,11 @@
#include <modules/base/rotation/fixedrotation.h>
#include <modules/base/rotation/luarotation.h>
#include <modules/base/rotation/staticrotation.h>
#include <modules/base/rotation/timelinerotation.h>
#include <modules/base/scale/luascale.h>
#include <modules/base/scale/staticscale.h>
#include <modules/base/scale/timedependentscale.h>
#include <modules/base/translation/timelinetranslation.h>
#include <modules/base/translation/luatranslation.h>
#include <modules/base/translation/statictranslation.h>
#include <modules/base/timeframe/timeframeinterval.h>
@@ -131,6 +133,7 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) {
auto fTranslation = FactoryManager::ref().factory<Translation>();
ghoul_assert(fTranslation, "Ephemeris factory was not created");
fTranslation->registerClass<TimelineTranslation>("TimelineTranslation");
fTranslation->registerClass<LuaTranslation>("LuaTranslation");
fTranslation->registerClass<StaticTranslation>("StaticTranslation");
@@ -141,6 +144,8 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) {
fRotation->registerClass<FixedRotation>("FixedRotation");
fRotation->registerClass<LuaRotation>("LuaRotation");
fRotation->registerClass<StaticRotation>("StaticRotation");
fRotation->registerClass<TimelineRotation>("TimelineRotation");
auto fScale = FactoryManager::ref().factory<Scale>();
ghoul_assert(fScale, "Scale factory was not created");
@@ -198,6 +203,7 @@ std::vector<documentation::Documentation> BaseModule::documentations() const {
FixedRotation::Documentation(),
LuaRotation::Documentation(),
StaticRotation::Documentation(),
TimelineRotation::Documentation(),
LuaScale::Documentation(),
StaticScale::Documentation(),
@@ -205,6 +211,7 @@ std::vector<documentation::Documentation> BaseModule::documentations() const {
LuaTranslation::Documentation(),
StaticTranslation::Documentation(),
TimelineTranslation::Documentation(),
TimeFrameInterval::Documentation(),
TimeFrameUnion::Documentation(),

View File

@@ -0,0 +1,118 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2019 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/base/rotation/timelinerotation.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/util/updatestructures.h>
#include <openspace/util/time.h>
namespace {
constexpr const char* KeyType = "Type";
constexpr const char* KeyKeyframes = "Keyframes";
} // namespace
namespace openspace {
documentation::Documentation TimelineRotation::Documentation() {
using namespace documentation;
return {
"Timeline Rotation",
"base_transform_rotation_keyframe",
{
{
KeyType,
new StringEqualVerifier("TimelineRotation"),
Optional::No
},
{
KeyKeyframes,
new TableVerifier({
{ "*", new TableVerifier(), Optional::No, "Any translation object" }
}),
Optional::No,
"A table of keyframes, with keys formatted as YYYY-MM-DDTHH:MM:SS"
"and values that are valid Rotation objects."
}
}
};
}
TimelineRotation::TimelineRotation(const ghoul::Dictionary& dictionary) {
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"TimelineTranslation"
);
const ghoul::Dictionary& keyframes =
dictionary.value<ghoul::Dictionary>(KeyKeyframes);
std::vector<std::string> timeStrings = keyframes.keys();
for (const std::string& timeString : timeStrings) {
const double t = Time::convertTime(timeString);
std::unique_ptr<Rotation> rotation =
Rotation::createFromDictionary(
keyframes.value<ghoul::Dictionary>(timeString)
);
if (rotation) {
_timeline.addKeyframe(t, std::move(rotation));
}
}
}
glm::dmat3 TimelineRotation::matrix(const UpdateData& data) const {
const double now = data.time.j2000Seconds();
using KeyframePointer = const Keyframe<std::unique_ptr<Rotation>>*;
KeyframePointer prev = _timeline.lastKeyframeBefore(now, true);
KeyframePointer next = _timeline.firstKeyframeAfter(now, true);
if (!prev && !next) {
return glm::dmat3(0.0);
}
if (!prev) {
prev = next;
}
if (!next) {
next = prev;
}
const double prevTime = prev->timestamp;
const double nextTime = next->timestamp;
double t = 0.0;
if (nextTime - prevTime > 0.0) {
t = (now - prevTime) / (nextTime - prevTime);
}
const glm::dquat nextRot = glm::quat_cast(next->data->matrix(data));
const glm::dquat prevRot = glm::quat_cast(prev->data->matrix(data));
return glm::dmat3(glm::slerp(prevRot, nextRot, t));
}
} // namespace openspace

View File

@@ -0,0 +1,49 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2019 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_BASE___TIMELINEROTATION___H__
#define __OPENSPACE_MODULE_BASE___TIMELINEROTATION___H__
#include <openspace/scene/rotation.h>
#include <openspace/util/timeline.h>
namespace openspace {
struct UpdateData;
namespace documentation { struct Documentation; }
class TimelineRotation : public Rotation {
public:
TimelineRotation(const ghoul::Dictionary& dictionary);
glm::dmat3 matrix(const UpdateData& data) const override;
static documentation::Documentation Documentation();
private:
Timeline<std::unique_ptr<Rotation>> _timeline;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_BASE___TIMELINEROTATION___H__

View File

@@ -0,0 +1,114 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2019 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/base/translation/timelinetranslation.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/util/updatestructures.h>
#include <openspace/util/time.h>
namespace {
constexpr const char* KeyType = "Type";
constexpr const char* KeyKeyframes = "Keyframes";
} // namespace
namespace openspace {
documentation::Documentation TimelineTranslation::Documentation() {
using namespace documentation;
return {
"Timeline Translation",
"base_transform_translation_keyframe",
{
{
KeyType,
new StringEqualVerifier("TimelineTranslation"),
Optional::No
},
{
KeyKeyframes,
new TableVerifier({
{ "*", new TableVerifier(), Optional::No, "Any translation object" }
}),
Optional::No,
"A table of keyframes, with keys formatted as YYYY-MM-DDTHH:MM:SS"
"and values that are valid Translation objects."
}
}
};
}
TimelineTranslation::TimelineTranslation(const ghoul::Dictionary& dictionary) {
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"TimelineTranslation"
);
const ghoul::Dictionary& keyframes =
dictionary.value<ghoul::Dictionary>(KeyKeyframes);
std::vector<std::string> timeStrings = keyframes.keys();
for (const std::string& timeString : timeStrings) {
const double t = Time::convertTime(timeString);
std::unique_ptr<Translation> translation =
Translation::createFromDictionary(
keyframes.value<ghoul::Dictionary>(timeString)
);
if (translation) {
_timeline.addKeyframe(t, std::move(translation));
}
}
}
glm::dvec3 TimelineTranslation::position(const UpdateData& data) const {
const double now = data.time.j2000Seconds();
using KeyframePointer = const Keyframe<std::unique_ptr<Translation>>*;
KeyframePointer prev = _timeline.lastKeyframeBefore(now, true);
KeyframePointer next = _timeline.firstKeyframeAfter(now, true);
if (!prev && !next) {
return glm::dvec3(0.0);
}
if (!prev) {
prev = next;
}
if (!next) {
next = prev;
}
const double prevTime = prev->timestamp;
const double nextTime = next->timestamp;
double t = 0.0;
if (nextTime - prevTime > 0.0) {
t = (now - prevTime) / (nextTime - prevTime);
}
return t * next->data->position(data) + (1.0 - t) * prev->data->position(data);
}
} // namespace openspace

View File

@@ -0,0 +1,50 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2019 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_BASE___TIMELINETRANSLATION___H__
#define __OPENSPACE_MODULE_BASE___TIMELINETRANSLATION___H__
#include <openspace/scene/translation.h>
#include <openspace/util/timeline.h>
namespace openspace {
struct UpdateData;
namespace documentation { struct Documentation; }
class TimelineTranslation : public Translation {
public:
TimelineTranslation(const ghoul::Dictionary& dictionary);
glm::dvec3 position(const UpdateData& data) const override;
static documentation::Documentation Documentation();
private:
Timeline<std::unique_ptr<Translation>> _timeline;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_BASE___TIMELINETRANSLATION___H__

View File

@@ -173,9 +173,16 @@ void DashboardItemGlobeLocation::render(glm::vec2& penPosition) {
bool isEast = lon > 0.0;
lon = std::abs(lon);
const double altitude = glm::length(
double altitude = glm::length(
cameraPositionModelSpace - posHandle.centerToReferenceSurface
);
if (glm::length(cameraPositionModelSpace) <
glm::length(posHandle.centerToReferenceSurface))
{
altitude = -altitude;
}
std::pair<double, std::string> dist = simplifyDistance(altitude);
penPosition.y -= _font->height();

View File

@@ -58,20 +58,21 @@ namespace {
"globe. The default value is 0.0"
};
constexpr openspace::properties::Property::PropertyInfo FixedAltitudeInfo = {
"FixedAltitude",
"Fixed Altitude",
"The altitude in meters of the location on the globe's surface. This value is "
"used if the 'UseFixedAltitude' property is 'true'. The default value is 10000km."
constexpr openspace::properties::Property::PropertyInfo AltitudeInfo = {
"Altitude",
"Altitude",
"The altitude in meters. "
"If the 'UseHeightmap' property is 'true', this is an offset from the actual "
"surface of the globe. If not, this is an offset from the reference ellipsoid."
"The default value is 0.0"
};
constexpr openspace::properties::Property::PropertyInfo UseFixedAltitudeInfo = {
"UseFixedAltitude",
"Use Fixed Altitude",
"If this value is 'true', the altitude specified in 'FixedAltitude' is used for "
"this translation. If it is 'false', the altitude will be computed based on the "
"height information that is available about the globe to which this translation "
"is attached. The default value is 'true'."
constexpr openspace::properties::Property::PropertyInfo UseHeightmapInfo = {
"UseHeightmap",
"Use Heightmap",
"If this value is 'true', the altitude specified in 'Altitude' will be treated "
"as an offset from the heightmap. Otherwise, it will be an offset from the "
"globe's reference ellipsoid. The default value is 'false'."
};
} // namespace
@@ -81,8 +82,8 @@ documentation::Documentation GlobeTranslation::Documentation() {
using namespace openspace::documentation;
return {
"Spice Translation",
"space_translation_spicetranslation",
"Globe Translation",
"space_translation_globetranslation",
{
{
"Type",
@@ -110,16 +111,16 @@ documentation::Documentation GlobeTranslation::Documentation() {
LatitudeInfo.description,
},
{
FixedAltitudeInfo.identifier,
AltitudeInfo.identifier,
new DoubleVerifier,
Optional::Yes,
FixedAltitudeInfo.description
AltitudeInfo.description
},
{
UseFixedAltitudeInfo.identifier,
UseHeightmapInfo.identifier,
new BoolVerifier,
Optional::Yes,
UseFixedAltitudeInfo.description
UseHeightmapInfo.description
}
}
};
@@ -129,8 +130,8 @@ GlobeTranslation::GlobeTranslation(const ghoul::Dictionary& dictionary)
: _globe(GlobeInfo)
, _longitude(LongitudeInfo, 0.0, -180.0, 180.0)
, _latitude(LatitudeInfo, 0.0, -90.0, 90.0)
, _fixedAltitude(FixedAltitudeInfo, 1e8, 0.0, 1e12)
, _useFixedAltitude(UseFixedAltitudeInfo, false)
, _altitude(AltitudeInfo, 0.0, 0.0, 1e12)
, _useHeightmap(UseHeightmapInfo, false)
{
documentation::testSpecificationAndThrow(
Documentation(),
@@ -145,11 +146,11 @@ GlobeTranslation::GlobeTranslation(const ghoul::Dictionary& dictionary)
if (dictionary.hasKey(LatitudeInfo.identifier)) {
_latitude = dictionary.value<double>(LatitudeInfo.identifier);
}
if (dictionary.hasKey(FixedAltitudeInfo.identifier)) {
_fixedAltitude = dictionary.value<double>(FixedAltitudeInfo.identifier);
if (dictionary.hasKey(AltitudeInfo.identifier)) {
_altitude = dictionary.value<double>(AltitudeInfo.identifier);
}
if (dictionary.hasKey(UseFixedAltitudeInfo.identifier)) {
_useFixedAltitude = dictionary.value<bool>(UseFixedAltitudeInfo.identifier);
if (dictionary.hasKey(UseHeightmapInfo.identifier)) {
_useHeightmap = dictionary.value<bool>(UseHeightmapInfo.identifier);
}
_globe.onChange([this]() {
@@ -159,13 +160,13 @@ GlobeTranslation::GlobeTranslation(const ghoul::Dictionary& dictionary)
_longitude.onChange([this]() { _positionIsDirty = true; });
_latitude.onChange([this]() { _positionIsDirty = true; });
_fixedAltitude.onChange([this]() { _positionIsDirty = true; });
_useFixedAltitude.onChange([this]() { _positionIsDirty = true; });
_altitude.onChange([this]() { _positionIsDirty = true; });
_useHeightmap.onChange([this]() { _positionIsDirty = true; });
addProperty(_longitude);
addProperty(_latitude);
addProperty(_fixedAltitude);
addProperty(_useFixedAltitude);
addProperty(_altitude);
addProperty(_useHeightmap);
}
void GlobeTranslation::fillAttachedNode() {
@@ -195,8 +196,8 @@ glm::dvec3 GlobeTranslation::position(const UpdateData&) const {
_positionIsDirty = true;
}
if (!_useFixedAltitude) {
// If we don't use the fixed altitude, we have to compute the height every frame
if (_useHeightmap) {
// If we use the heightmap, we have to compute the height every frame
_positionIsDirty = true;
}
@@ -204,33 +205,35 @@ glm::dvec3 GlobeTranslation::position(const UpdateData&) const {
return _position;
}
GlobeBrowsingModule& mod = *(global::moduleEngine.module<GlobeBrowsingModule>());
glm::vec3 pos = mod.cartesianCoordinatesFromGeo(
*_attachedNode,
_latitude,
_longitude,
_fixedAltitude
);
if (_useFixedAltitude) {
_position = glm::dvec3(pos);
_positionIsDirty = true;
return _position;
}
else {
SurfacePositionHandle h = _attachedNode->calculateSurfacePositionHandle(pos);
pos = mod.cartesianCoordinatesFromGeo(
if (_useHeightmap) {
glm::vec3 groundPos = mod.cartesianCoordinatesFromGeo(
*_attachedNode,
_latitude,
_longitude,
h.heightToSurface
0.0
);
_position = glm::dvec3(pos);
SurfacePositionHandle h =
_attachedNode->calculateSurfacePositionHandle(groundPos);
_position = mod.cartesianCoordinatesFromGeo(
*_attachedNode,
_latitude,
_longitude,
h.heightToSurface + _altitude
);
return _position;
}
else {
_position = mod.cartesianCoordinatesFromGeo(
*_attachedNode,
_latitude,
_longitude,
_altitude
);
_positionIsDirty = false;
return _position;
}
}

View File

@@ -49,8 +49,8 @@ private:
properties::StringProperty _globe;
properties::DoubleProperty _longitude;
properties::DoubleProperty _latitude;
properties::DoubleProperty _fixedAltitude;
properties::BoolProperty _useFixedAltitude;
properties::DoubleProperty _altitude;
properties::BoolProperty _useHeightmap;
RenderableGlobe* _attachedNode = nullptr;

View File

@@ -179,7 +179,7 @@ void HorizonsTranslation::readHorizonsTextFile(const std::string& horizonsTextFi
);
// Add position to stored timeline.
_timeline.addKeyframe(timeInJ2000, gPos);
_timeline.addKeyframe(timeInJ2000, std::move(gPos));
std::getline(fileStream, line);
}