mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-02-22 12:59:07 -06:00
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:
@@ -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();
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user