mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-02-25 14:29:03 -06:00
Feature/navigation state (#930)
* Replace setCameraState with setNavigationState + equivalents * Add documentation and verification of NavigationState-related interfaces * Documentation and verification fixes * Change reference frame behavior * Scene fixes * Replace earthrise recording with navigation state and time
This commit is contained in:
committed by
Alexander Bock
parent
b25b205e99
commit
f43bcadee3
@@ -38,6 +38,7 @@
|
||||
#include <openspace/util/factorymanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/fmt.h>
|
||||
#include <ghoul/misc/templatefactory.h>
|
||||
#include <ghoul/misc/assert.h>
|
||||
#include <ghoul/systemcapabilities/generalcapabilitiescomponent.h>
|
||||
@@ -338,16 +339,24 @@ scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
|
||||
"goToGeo",
|
||||
&globebrowsing::luascriptfunctions::goToGeo,
|
||||
{},
|
||||
"number, number, number",
|
||||
"Go to geographic coordinates latitude and longitude"
|
||||
"[string], number, number, [number]",
|
||||
"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 no globe is passed in, 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 fourh 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."
|
||||
},
|
||||
{
|
||||
"getGeoPosition",
|
||||
&globebrowsing::luascriptfunctions::getGeoPosition,
|
||||
{},
|
||||
"name, latitude, longitude, altitude",
|
||||
"Returns the specified surface position on the globe as three floating point "
|
||||
"values"
|
||||
"string, number, number, number",
|
||||
"Returns the specified surface position on the globe identified by the first "
|
||||
"argument, as three floating point values - latitude, longitude and altitude "
|
||||
"(degrees and meters)."
|
||||
},
|
||||
{
|
||||
"getGeoPositionForCamera",
|
||||
@@ -355,7 +364,7 @@ scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
|
||||
{},
|
||||
"void",
|
||||
"Get geographic coordinates of the camera poosition in latitude, "
|
||||
"longitude, and altitude"
|
||||
"longitude, and altitude (degrees and meters)."
|
||||
},
|
||||
{
|
||||
"loadWMSCapabilities",
|
||||
@@ -395,29 +404,29 @@ scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
|
||||
return res;
|
||||
}
|
||||
|
||||
void GlobeBrowsingModule::goToChunk(int x, int y, int level) {
|
||||
Camera* cam = global::navigationHandler.camera();
|
||||
goToChunk(*cam, globebrowsing::TileIndex(x,y,level), glm::vec2(0.5f, 0.5f), true);
|
||||
void GlobeBrowsingModule::goToChunk(const globebrowsing::RenderableGlobe& globe,
|
||||
int x, int y, int level)
|
||||
{
|
||||
goToChunk(globe, globebrowsing::TileIndex(x, y, level), glm::vec2(0.5f, 0.5f), true);
|
||||
}
|
||||
|
||||
void GlobeBrowsingModule::goToGeo(double latitude, double longitude) {
|
||||
void GlobeBrowsingModule::goToGeo(const globebrowsing::RenderableGlobe& globe,
|
||||
double latitude, double longitude)
|
||||
{
|
||||
using namespace globebrowsing;
|
||||
Camera* cam = global::navigationHandler.camera();
|
||||
goToGeodetic2(
|
||||
*cam,
|
||||
globe,
|
||||
Geodetic2{ glm::radians(latitude), glm::radians(longitude) },
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
void GlobeBrowsingModule::goToGeo(double latitude, double longitude,
|
||||
double altitude)
|
||||
void GlobeBrowsingModule::goToGeo(const globebrowsing::RenderableGlobe& globe,
|
||||
double latitude, double longitude, double altitude)
|
||||
{
|
||||
using namespace globebrowsing;
|
||||
|
||||
Camera* cam = global::navigationHandler.camera();
|
||||
goToGeodetic3(
|
||||
*cam,
|
||||
globe,
|
||||
{
|
||||
Geodetic2{ glm::radians(latitude), glm::radians(longitude) },
|
||||
altitude
|
||||
@@ -437,32 +446,15 @@ glm::vec3 GlobeBrowsingModule::cartesianCoordinatesFromGeo(
|
||||
altitude
|
||||
};
|
||||
|
||||
const glm::dvec3 positionModelSpace = globe.ellipsoid().cartesianPosition(pos);
|
||||
//glm::dmat4 modelTransform = globe.modelTransform();
|
||||
//glm::dvec3 positionWorldSpace = glm::dvec3(modelTransform *
|
||||
//glm::dvec4(positionModelSpace, 1.0));
|
||||
|
||||
return glm::vec3(positionModelSpace);
|
||||
return glm::vec3(globe.ellipsoid().cartesianPosition(pos));
|
||||
}
|
||||
|
||||
void GlobeBrowsingModule::goToChunk(Camera& camera, const globebrowsing::TileIndex& ti,
|
||||
void GlobeBrowsingModule::goToChunk(const globebrowsing::RenderableGlobe& globe,
|
||||
const globebrowsing::TileIndex& ti,
|
||||
glm::vec2 uv, bool doResetCameraDirection)
|
||||
{
|
||||
using namespace globebrowsing;
|
||||
|
||||
const RenderableGlobe* globe = castFocusNodeRenderableToGlobe();
|
||||
if (!globe) {
|
||||
LERROR("Focus node must have a RenderableGlobe renderable.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Camera position in model space
|
||||
const glm::dvec3 camPos = camera.positionVec3();
|
||||
const glm::dmat4 inverseModelTransform = glm::inverse(globe->modelTransform());
|
||||
const glm::dvec3 cameraPositionModelSpace = glm::dvec3(
|
||||
inverseModelTransform * glm::dvec4(camPos, 1)
|
||||
);
|
||||
|
||||
const GeodeticPatch patch(ti);
|
||||
const Geodetic2 corner = patch.corner(SOUTH_WEST);
|
||||
Geodetic2 positionOnPatch = patch.size();
|
||||
@@ -473,32 +465,50 @@ void GlobeBrowsingModule::goToChunk(Camera& camera, const globebrowsing::TileInd
|
||||
corner.lon + positionOnPatch.lon
|
||||
};
|
||||
|
||||
const glm::dvec3 positionOnEllipsoid = globe->ellipsoid().geodeticSurfaceProjection(
|
||||
// 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 a scene graph node."
|
||||
);
|
||||
return;
|
||||
}
|
||||
const glm::dmat4 inverseModelTransform = globeSceneGraphNode->inverseModelTransform();
|
||||
const glm::dvec3 cameraPositionModelSpace =
|
||||
glm::dvec3(inverseModelTransform * glm::dvec4(cameraPosition, 1.0));
|
||||
const SurfacePositionHandle posHandle = globe.calculateSurfacePositionHandle(
|
||||
cameraPositionModelSpace
|
||||
);
|
||||
const double altitude = glm::length(cameraPositionModelSpace - positionOnEllipsoid);
|
||||
|
||||
const Geodetic2 geo2 = globe.ellipsoid().cartesianToGeodetic2(
|
||||
posHandle.centerToReferenceSurface
|
||||
);
|
||||
|
||||
goToGeodetic3(camera, {pointPosition, altitude}, doResetCameraDirection);
|
||||
const double altitude = glm::length(
|
||||
cameraPositionModelSpace - posHandle.centerToReferenceSurface
|
||||
);
|
||||
|
||||
goToGeodetic3(globe, { pointPosition, altitude }, doResetCameraDirection);
|
||||
}
|
||||
|
||||
void GlobeBrowsingModule::goToGeodetic2(Camera& camera, globebrowsing::Geodetic2 geo2,
|
||||
void GlobeBrowsingModule::goToGeodetic2(const globebrowsing::RenderableGlobe& globe,
|
||||
globebrowsing::Geodetic2 geo2,
|
||||
bool doResetCameraDirection)
|
||||
{
|
||||
using namespace globebrowsing;
|
||||
|
||||
const RenderableGlobe* globe = castFocusNodeRenderableToGlobe();
|
||||
if (!globe) {
|
||||
LERROR("Focus node must have a RenderableGlobe renderable.");
|
||||
return;
|
||||
const glm::dvec3 cameraPosition = global::navigationHandler.camera()->positionVec3();
|
||||
SceneGraphNode* globeSceneGraphNode = dynamic_cast<SceneGraphNode*>(globe.owner());
|
||||
if (!globeSceneGraphNode) {
|
||||
LERROR("Error when going to Geodetic2");
|
||||
}
|
||||
|
||||
interaction::NavigationHandler& nav = global::navigationHandler;
|
||||
const glm::dvec3 cameraPosition = nav.camera()->positionVec3();
|
||||
const glm::dmat4 inverseModelTransform =
|
||||
nav.orbitalNavigator().anchorNode()->inverseModelTransform();
|
||||
const glm::dmat4 inverseModelTransform = globeSceneGraphNode->inverseModelTransform();
|
||||
|
||||
const glm::dvec3 cameraPositionModelSpace =
|
||||
glm::dvec3(inverseModelTransform * glm::dvec4(cameraPosition, 1.0));
|
||||
const SurfacePositionHandle posHandle = globe->calculateSurfacePositionHandle(
|
||||
const SurfacePositionHandle posHandle = globe.calculateSurfacePositionHandle(
|
||||
cameraPositionModelSpace
|
||||
);
|
||||
|
||||
@@ -506,71 +516,58 @@ void GlobeBrowsingModule::goToGeodetic2(Camera& camera, globebrowsing::Geodetic2
|
||||
posHandle.referenceSurfaceOutDirection * posHandle.heightToSurface;
|
||||
const double altitude = glm::length(cameraPositionModelSpace - centerToActualSurface);
|
||||
|
||||
goToGeodetic3(camera, { geo2, altitude }, doResetCameraDirection);
|
||||
goToGeodetic3(globe, { geo2, altitude }, doResetCameraDirection);
|
||||
}
|
||||
|
||||
void GlobeBrowsingModule::goToGeodetic3(Camera& camera, globebrowsing::Geodetic3 geo3,
|
||||
void GlobeBrowsingModule::goToGeodetic3(const globebrowsing::RenderableGlobe& globe,
|
||||
globebrowsing::Geodetic3 geo3,
|
||||
bool doResetCameraDirection)
|
||||
{
|
||||
using namespace globebrowsing;
|
||||
const glm::dvec3 positionModelSpace = globe.ellipsoid().cartesianPosition(geo3);
|
||||
|
||||
const RenderableGlobe* globe = castFocusNodeRenderableToGlobe();
|
||||
if (!globe) {
|
||||
LERROR("Focus node must have a RenderableGlobe renderable.");
|
||||
return;
|
||||
}
|
||||
|
||||
const glm::dvec3 positionModelSpace = globe->ellipsoid().cartesianPosition(geo3);
|
||||
const glm::dmat4 modelTransform = globe->modelTransform();
|
||||
const glm::dvec3 positionWorldSpace = glm::dvec3(modelTransform *
|
||||
glm::dvec4(positionModelSpace, 1.0));
|
||||
camera.setPositionVec3(positionWorldSpace);
|
||||
const glm::dvec3 slightlyNorth = globe.ellipsoid().cartesianSurfacePosition(
|
||||
Geodetic2{ geo3.geodetic2.lat + 0.001, geo3.geodetic2.lon }
|
||||
);
|
||||
|
||||
if (doResetCameraDirection) {
|
||||
resetCameraDirection(camera, geo3.geodetic2);
|
||||
}
|
||||
interaction::NavigationHandler::NavigationState state;
|
||||
state.anchor = globe.owner()->identifier();
|
||||
state.referenceFrame = globe.owner()->identifier();
|
||||
state.position = positionModelSpace;
|
||||
state.up = slightlyNorth;
|
||||
|
||||
global::navigationHandler.setNavigationStateNextFrame(state);
|
||||
}
|
||||
|
||||
void GlobeBrowsingModule::resetCameraDirection(Camera& camera,
|
||||
globebrowsing::Geodetic2 geo2)
|
||||
glm::dquat GlobeBrowsingModule::lookDownCameraRotation(
|
||||
const globebrowsing::RenderableGlobe& globe,
|
||||
glm::dvec3 cameraModelSpace,
|
||||
globebrowsing::Geodetic2 geo2)
|
||||
{
|
||||
using namespace globebrowsing;
|
||||
|
||||
const RenderableGlobe* globe = castFocusNodeRenderableToGlobe();
|
||||
if (!globe) {
|
||||
LERROR("Focus node must have a RenderableGlobe renderable.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Camera is described in world space
|
||||
const glm::dmat4 modelTransform = globe->modelTransform();
|
||||
const glm::dmat4 modelTransform = globe.modelTransform();
|
||||
|
||||
// Lookup vector
|
||||
const glm::dvec3 positionModelSpace = globe->ellipsoid().cartesianSurfacePosition(
|
||||
const glm::dvec3 positionModelSpace = globe.ellipsoid().cartesianSurfacePosition(
|
||||
geo2
|
||||
);
|
||||
const glm::dvec3 slightlyNorth = globe->ellipsoid().cartesianSurfacePosition(
|
||||
const glm::dvec3 slightlyNorth = globe.ellipsoid().cartesianSurfacePosition(
|
||||
Geodetic2{ geo2.lat + 0.001, geo2.lon }
|
||||
);
|
||||
const glm::dvec3 lookUpModelSpace = glm::normalize(
|
||||
slightlyNorth - positionModelSpace
|
||||
);
|
||||
const glm::dvec3 lookUpWorldSpace = glm::dmat3(modelTransform) * lookUpModelSpace;
|
||||
|
||||
// Lookat vector
|
||||
const glm::dvec3 lookAtWorldSpace = glm::dvec3(
|
||||
modelTransform * glm::dvec4(positionModelSpace, 1.0)
|
||||
);
|
||||
|
||||
// Eye position
|
||||
const glm::dvec3 eye = camera.positionVec3();
|
||||
|
||||
// Matrix
|
||||
const glm::dmat4 lookAtMatrix = glm::lookAt(eye, lookAtWorldSpace, lookUpWorldSpace);
|
||||
const glm::dmat4 lookAtMatrix =
|
||||
glm::lookAt(cameraModelSpace, positionModelSpace, lookUpModelSpace);
|
||||
|
||||
// Set rotation
|
||||
const glm::dquat rotation = glm::quat_cast(inverse(lookAtMatrix));
|
||||
camera.setRotation(rotation);
|
||||
return rotation;
|
||||
}
|
||||
|
||||
const globebrowsing::RenderableGlobe*
|
||||
@@ -732,5 +729,4 @@ uint64_t GlobeBrowsingModule::wmsCacheSize() const {
|
||||
return size * 1024 * 1024;
|
||||
}
|
||||
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
Reference in New Issue
Block a user