Rename goToGeo -> jumpToGeo (#3296)

* Remove unused bool argument in globebrowsing functions
* Refactor some globe browsing functions
* Start updating goToGeo function to fade instead of just jump
* Add choice for whtehr to use default or arrival height when flying to a geo2
* Update / add docs for fly-to and go-to functions
* Rename function and add deprecated version of `goToGeo`
This commit is contained in:
Emma Broman
2024-06-04 16:18:03 +02:00
committed by GitHub
parent aaab3fae46
commit 09a40f62dc
6 changed files with 204 additions and 115 deletions

View File

@@ -81,6 +81,8 @@ public:
double minValidBoundingSphere() const;
double findValidBoundingSphere(const SceneGraphNode* node) const;
double defaultArrivalHeight(const std::string& sgnIdentifier) const;
const std::vector<SceneGraphNode*>& relevantNodes();
/**

View File

@@ -356,8 +356,7 @@ void GlobeBrowsingModule::goToChunk(const globebrowsing::RenderableGlobe& globe,
goToChunk(
globe,
globebrowsing::TileIndex(x, y, static_cast<uint8_t>(level)),
glm::vec2(0.5f, 0.5f),
true
glm::vec2(0.5f, 0.5f)
);
}
@@ -367,8 +366,7 @@ void GlobeBrowsingModule::goToGeo(const globebrowsing::RenderableGlobe& globe,
using namespace globebrowsing;
goToGeodetic2(
globe,
Geodetic2{ glm::radians(latitude), glm::radians(longitude) },
true
Geodetic2{ glm::radians(latitude), glm::radians(longitude) }
);
}
@@ -381,20 +379,19 @@ void GlobeBrowsingModule::goToGeo(const globebrowsing::RenderableGlobe& globe,
{
Geodetic2{ glm::radians(latitude), glm::radians(longitude) },
altitude
},
true
}
);
}
glm::vec3 GlobeBrowsingModule::cartesianCoordinatesFromGeo(
const globebrowsing::RenderableGlobe& globe,
double latitude, double longitude, double altitude)
double latitude, double longitude, std::optional<double> altitude)
{
using namespace globebrowsing;
const Geodetic3 pos = {
{ .lat = glm::radians(latitude), .lon = glm::radians(longitude) },
altitude
altitude.value_or(altitudeFromCamera(globe))
};
return glm::vec3(globe.ellipsoid().cartesianPosition(pos));
@@ -440,9 +437,43 @@ glm::dvec3 GlobeBrowsingModule::geoPosition() const {
return glm::dvec3(lat, lon, altitude);
}
double GlobeBrowsingModule::altitudeFromCamera(
const globebrowsing::RenderableGlobe& globe,
bool useHeightMap) const
{
using namespace globebrowsing;
const glm::dvec3 cameraPosition = global::navigationHandler->camera()->positionVec3();
SceneGraphNode* sgn = dynamic_cast<SceneGraphNode*>(globe.owner());
if (!sgn) {
LERROR("Could not find scene graph node for globe");
return 0.0;
}
const glm::dmat4 inverseModelTransform = glm::inverse(sgn->modelTransform());
const glm::dvec3 cameraPositionModelSpace =
glm::dvec3(inverseModelTransform * glm::dvec4(cameraPosition, 1.0));
SurfacePositionHandle posHandle = globe.calculateSurfacePositionHandle(
cameraPositionModelSpace
);
if (useHeightMap) {
const glm::dvec3 centerToActualSurface = posHandle.centerToReferenceSurface +
posHandle.referenceSurfaceOutDirection * posHandle.heightToSurface;
return glm::length(cameraPositionModelSpace - centerToActualSurface);
}
else {
// Do not use height map => compute distance to reference surface
return glm::length(cameraPositionModelSpace - posHandle.centerToReferenceSurface);
}
}
void GlobeBrowsingModule::goToChunk(const globebrowsing::RenderableGlobe& globe,
const globebrowsing::TileIndex& ti,
const glm::vec2& uv, bool doResetCameraDirection)
const glm::vec2& uv)
{
using namespace globebrowsing;
@@ -456,61 +487,23 @@ void GlobeBrowsingModule::goToChunk(const globebrowsing::RenderableGlobe& globe,
.lon = corner.lon + positionOnPatch.lon
};
// Compute altitude
const glm::dvec3 cameraPosition = global::navigationHandler->camera()->positionVec3();
SceneGraphNode* globeSceneGraphNode = dynamic_cast<SceneGraphNode*>(globe.owner());
if (!globeSceneGraphNode) {
LERROR("Cannot go to chunk. The renderable is not attached to scene graph node");
return;
}
const glm::dmat4 inverseModelTransform = glm::inverse(
globeSceneGraphNode->modelTransform()
);
const glm::dvec3 cameraPositionModelSpace =
glm::dvec3(inverseModelTransform * glm::dvec4(cameraPosition, 1.0));
const SurfacePositionHandle posHandle = globe.calculateSurfacePositionHandle(
cameraPositionModelSpace
);
const double altitude = altitudeFromCamera(globe);
const double altitude = glm::length(
cameraPositionModelSpace - posHandle.centerToReferenceSurface
);
goToGeodetic3(globe, { pointPosition, altitude }, doResetCameraDirection);
goToGeodetic3(globe, { pointPosition, altitude });
}
void GlobeBrowsingModule::goToGeodetic2(const globebrowsing::RenderableGlobe& globe,
globebrowsing::Geodetic2 geo2,
bool doResetCameraDirection)
globebrowsing::Geodetic2 geo2)
{
using namespace globebrowsing;
const glm::dvec3 cameraPosition = global::navigationHandler->camera()->positionVec3();
SceneGraphNode* globeSceneGraphNode = dynamic_cast<SceneGraphNode*>(globe.owner());
if (!globeSceneGraphNode) {
LERROR("Error when going to Geodetic2");
return;
}
const double altitude = altitudeFromCamera(globe);
const glm::dmat4 inverseModelTransform = glm::inverse(
globeSceneGraphNode->modelTransform()
);
const glm::dvec3 cameraPositionModelSpace =
glm::dvec3(inverseModelTransform * glm::dvec4(cameraPosition, 1.0));
const SurfacePositionHandle posHandle = globe.calculateSurfacePositionHandle(
cameraPositionModelSpace
);
const glm::dvec3 centerToActualSurface = posHandle.centerToReferenceSurface +
posHandle.referenceSurfaceOutDirection * posHandle.heightToSurface;
const double altitude = glm::length(cameraPositionModelSpace - centerToActualSurface);
goToGeodetic3(globe, { geo2, altitude }, doResetCameraDirection);
goToGeodetic3(globe, { geo2, altitude });
}
void GlobeBrowsingModule::goToGeodetic3(const globebrowsing::RenderableGlobe& globe,
globebrowsing::Geodetic3 geo3, bool)
globebrowsing::Geodetic3 geo3)
{
using namespace globebrowsing;
const glm::dvec3 positionModelSpace = globe.ellipsoid().cartesianPosition(geo3);
@@ -671,9 +664,9 @@ scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
codegen::lua::LayersDeprecated,
codegen::lua::MoveLayer,
codegen::lua::GoToChunk,
codegen::lua::GoToGeo,
// @TODO (2021-06-23, emmbr) Combine with the above function when the camera
// paths work really well close to surfaces
codegen::lua::JumpToGeo,
codegen::lua::GoToGeoDeprecated,
codegen::lua::FlyToGeo2,
codegen::lua::FlyToGeo,
codegen::lua::LocalPositionFromGeo,
codegen::lua::LocalPositionFromGeoDeprecated,

View File

@@ -29,10 +29,10 @@
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/uintproperty.h>
#include <openspace/util/openspacemodule.h>
#include <ghoul/glm.h>
#include <memory>
#include <future>
#include <memory>
#include <optional>
namespace openspace::globebrowsing {
class RenderableGlobe;
@@ -61,10 +61,13 @@ public:
double latitude, double longitude, double altitude);
glm::vec3 cartesianCoordinatesFromGeo(const globebrowsing::RenderableGlobe& globe,
double latitude, double longitude, double altitude);
double latitude, double longitude, std::optional<double> altitude = std::nullopt);
glm::dvec3 geoPosition() const;
double altitudeFromCamera(const globebrowsing::RenderableGlobe& globe,
bool useHeightMap = false) const;
globebrowsing::cache::MemoryAwareTileCache* tileCache();
scripting::LuaLibrary luaLibrary() const override;
std::vector<documentation::Documentation> documentations() const override;
@@ -103,14 +106,13 @@ protected:
private:
void goToChunk(const globebrowsing::RenderableGlobe& globe,
const globebrowsing::TileIndex& ti, const glm::vec2& uv,
bool doResetCameraDirection);
const globebrowsing::TileIndex& ti, const glm::vec2& uv);
void goToGeodetic2(const globebrowsing::RenderableGlobe& globe,
globebrowsing::Geodetic2 geo2, bool doResetCameraDirection);
globebrowsing::Geodetic2 geo2);
void goToGeodetic3(const globebrowsing::RenderableGlobe& globe,
globebrowsing::Geodetic3 geo3, bool doResetCameraDirection);
globebrowsing::Geodetic3 geo3);
properties::UIntProperty _tileCacheSizeMB;

View File

@@ -278,72 +278,87 @@ namespace {
}
/**
* Go to geographic coordinates of a globe. The first (optional) argument is the
* identifier of a scene graph node that has a RenderableGlobe attached. If the name of
* the globe is empty, the current anchor will be used. The second argument is latitude
* and the third is longitude (degrees). North and East are expressed as positive angles,
* while South and West are negative. The optional fourth argument is the altitude in
* meters. If no altitude is provided, the altitude will be kept as the current distance
* to the surface of the specified globe.
* Immediately move the camera to a geographic coordinate on a globe by first fading the
* rendering to black, jump to the specified coordinate, and then fade in.
*
* This is done by triggering another script that handles the logic.
*
* \param globe The identifier of a scene graph node that has a RenderableGlobe attached.
* If an empty string is provided, the current anchor node is used
* \param latitude The latitude of the target coordinate, in degrees
* \param longitude The longitude of the target coordinate, in degrees
* \param altitude An optional altitude, given in meters over the reference surface of
* the globe. If no altitude is provided, the altitude will be kept as
* the current distance to the reference surface of the specified globe.
* \param fadeDuration An optional duration for the fading. If not included, the
* property in Navigation Handler will be used
*/
[[codegen::luawrap]] void goToGeo(std::string globe, double latitude, double longitude,
std::optional<double> altitude)
[[codegen::luawrap]] void jumpToGeo(std::string globe, double latitude, double longitude,
std::optional<double> altitude,
std::optional<double> fadeDuration)
{
using namespace openspace;
using namespace globebrowsing;
const SceneGraphNode* n;
if (!globe.empty()) {
n = sceneGraphNode(globe);
if (!n) {
throw ghoul::lua::LuaError("Unknown globe name: " + globe);
}
}
else {
n = global::navigationHandler->orbitalNavigator().anchorNode();
if (!n) {
throw ghoul::lua::LuaError("No anchor node is set");
}
}
const RenderableGlobe* gl = dynamic_cast<const RenderableGlobe*>(n->renderable());
if (!gl) {
throw ghoul::lua::LuaError(
"Current anchor node is not a RenderableGlobe. Either change the anchor "
"to a globe, or specify a globe identifier as the first argument"
);
}
std::string script;
if (altitude.has_value()) {
global::moduleEngine->module<GlobeBrowsingModule>()->goToGeo(
*gl,
latitude,
longitude,
*altitude
script = std::format(
"openspace.globebrowsing.flyToGeo('{}', {}, {}, {}, 0)",
globe, latitude, longitude, *altitude
);
}
else {
global::moduleEngine->module<GlobeBrowsingModule>()->goToGeo(
*gl,
latitude,
longitude
script = std::format(
"openspace.globebrowsing.flyToGeo2('{}', {}, {}, true, 0)",
globe, latitude, longitude
);
}
if (fadeDuration.has_value()) {
global::navigationHandler->triggerFadeToTransition(
std::move(script),
static_cast<float>(*fadeDuration)
);
}
else {
global::navigationHandler->triggerFadeToTransition(script);
}
}
/**
* Fly the camera to geographic coordinates of a globe, using the path navigation system.
* The first (optional) argument is the identifier of a scene graph node with a
* RenderableGlobe. If the globe name is empty, the current anchor will be used. The
* second and third argument is latitude and longitude (degrees). The fourth argument is
* the altitude, in meters. The last two optional arguments are: a bool specifying whether
* the up vector at the target position should be set to the globe's North vector, and a
* duration for the motion, in seconds. Either of the two can be left out.
* Immediately move the camera to a geographic coordinate on a globe.
*
* \param globe The identifier of a scene graph node that has a RenderableGlobe attached.
* If an empty string is provided, the current anchor node is used
* \param latitude The latitude of the target coordinate, in degrees
* \param longitude The longitude of the target coordinate, in degrees
* \param altitude An optional altitude, given in meters over the reference surface of
* the globe. If no altitude is provided, the altitude will be kept as
* the current distance to the reference surface of the specified globe.
*/
[[codegen::luawrap]] void flyToGeo(std::string globe, double latitude,
double longitude, double altitude,
std::optional<double> duration,
std::optional<bool> shouldUseUpVector)
[[codegen::luawrap("goToGeo")]] void goToGeoDeprecated(std::string globe, double latitude,
double longitude,
std::optional<double> altitude)
{
LWARNINGC(
"Deprecation",
"'goToGeo' function is deprecated and should be replaced with 'jumpToGeo'"
);
return jumpToGeo(
std::move(globe),
latitude,
longitude,
altitude,
0
);
}
void flyToGeoInternal(std::string globe, double latitude,
double longitude, std::optional<double> altitude,
std::optional<double> duration,
std::optional<bool> shouldUseUpVector)
{
using namespace openspace;
using namespace globebrowsing;
@@ -364,7 +379,7 @@ namespace {
const RenderableGlobe* gl = dynamic_cast<const RenderableGlobe*>(n->renderable());
if (!gl) {
throw ghoul::lua::LuaError("Current anchor node is not a RenderableGlobe");
throw ghoul::lua::LuaError("The targetted node is not a RenderableGlobe");
}
auto module = global::moduleEngine->module<GlobeBrowsingModule>();
@@ -407,6 +422,72 @@ namespace {
global::navigationHandler->pathNavigator().startPath();
}
/**
* Fly the camera to a geographic coordinate (latitude and longitude) on a globe, using
* the path navigation system.
*
* The distance to fly to can either be set to be the current distance of the camera to
* the target object, or the default distance from the path navigation system.
*
* \param globe The identifier of a scene graph node that has a RenderableGlobe attached.
* If an empty string is provided, the current anchor node is used
* \param latitude The latitude of the target coordinate, in degrees
* \param longitude The longitude of the target coordinate, in degrees
* \param useCurrentDistance If true, use the current distance of the camera to the
* target globe when going to the specified position. If false,
* or not specified, set the distance based on the bounding
* sphere and the distance factor setting in Path Navigator
* \param duration An optional duration for the motion to take, in seconds. For example,
* a value of 5 means "fly to this position over a duration of 5 seconds"
* \param shouldUseUpVector If true, try to use the up-direction when computing the
* target position for the camera. For globes, this means that
* North should be up, in relation to the camera's view
* direction. Note that for this to take effect, rolling motions
* must be enabled in the Path Navigator settings.
*/
[[codegen::luawrap]] void flyToGeo2(std::string globe, double latitude, double longitude,
std::optional<bool> useCurrentDistance,
std::optional<double> duration,
std::optional<bool> shouldUseUpVector)
{
using namespace openspace;
std::optional<double> altitude;
if (useCurrentDistance.has_value() && *useCurrentDistance) {
altitude = std::nullopt;
}
else {
altitude = global::navigationHandler->pathNavigator().defaultArrivalHeight(globe);
}
flyToGeoInternal(globe, latitude, longitude, std::nullopt, duration, shouldUseUpVector);
}
/**
* Fly the camera to a geographic coordinate (latitude, longitude and altitude) on a globe,
* using the path navigation system.
*
* \param globe The identifier of a scene graph node that has a RenderableGlobe attached.
* If an empty string is provided, the current anchor node is used
* \param latitude The latitude of the target coordinate, in degrees
* \param longitude The longitude of the target coordinate, in degrees
* \param altitude The altitude of the target coordinate, in meters
* \param duration An optional duration for the motion to take, in seconds. For example,
* a value of 5 means "fly to this position over a duration of 5 seconds"
* \param shouldUseUpVector If true, try to use the up-direction when computing the
* target position for the camera. For globes, this means that
* North should be up, in relation to the camera's view
* direction. Note that for this to take effect, rolling motions
* must be enabled in the Path Navigator settings.
*/
[[codegen::luawrap]] void flyToGeo(std::string globe, double latitude,
double longitude, double altitude,
std::optional<double> duration,
std::optional<bool> shouldUseUpVector)
{
flyToGeoInternal(globe, latitude, longitude, altitude, duration, shouldUseUpVector);
}
/**
* Returns a position in the local Cartesian coordinate system of the globe identified by
* the first argument, that corresponds to the given geographic coordinates: latitude,

View File

@@ -446,6 +446,17 @@ double PathNavigator::findValidBoundingSphere(const SceneGraphNode* node) const
return result;
}
double PathNavigator::defaultArrivalHeight(const std::string& sgnIdentifier) const {
const SceneGraphNode* node = sceneGraphNode(sgnIdentifier);
if (!node) {
LERROR(std::format("Could not find scene graph node '{}'", sgnIdentifier));
return 0.0;
}
const double radius = findValidBoundingSphere(node);
return radius * arrivalDistanceFactor();
}
const std::vector<SceneGraphNode*>& PathNavigator::relevantNodes() {
if (!_hasInitializedRelevantNodes) {
findRelevantNodes();

View File

@@ -197,7 +197,7 @@ Waypoint computeWaypointFromNodeInfo(const NodeCameraStateSpec& spec,
const PathNavigator& navigator = global::navigationHandler->pathNavigator();
const double radius = navigator.findValidBoundingSphere(targetNode);
const double defaultHeight = radius * navigator.arrivalDistanceFactor();
const double defaultHeight = navigator.defaultArrivalHeight(spec.identifier);
const double height = spec.height.value_or(defaultHeight);
const double distanceFromNodeCenter = radius + height;