Add camera view direction to camera topic (#3741)

* Add camera view direction to camera topic
* Add subsolar coordinates to topic

---------

Co-authored-by: Alexander Bock <alexander.bock@liu.se>
Co-authored-by: Ylva Selling <ylva.selling@gmail.com>
This commit is contained in:
Andreas Engberg
2025-07-16 13:21:12 +02:00
committed by GitHub
parent 6a1568ec15
commit 4dffe7c7b2
4 changed files with 115 additions and 5 deletions
+12
View File
@@ -28,6 +28,14 @@ local showcomposer = asset.resource({
})
local maps = asset.resource({
Identifier = "userinterface_maps",
Name = "Userinterface Maps",
Type = "HttpSynchronization",
Version = 1
})
asset.onInitialize(function()
-- Unzip the frontend bundle
local destFrontend = frontend .. "frontend"
@@ -66,6 +74,10 @@ asset.onInitialize(function()
directories[#directories + 1] = "showcomposer/projects"
directories[#directories + 1] = openspace.absPath("${USER_SHOWCOMPOSER_PROJECTS}")
-- Add asset folders
directories[#directories + 1] = "assets/maps"
directories[#directories + 1] = maps
openspace.setPropertyValueSingle("Modules.WebGui.Directories", directories)
openspace.setPropertyValueSingle("Modules.WebGui.DefaultEndpoint", "gui")
openspace.setPropertyValueSingle("Modules.WebGui.ServerProcessEnabled", enabled)
+13
View File
@@ -71,6 +71,19 @@ glm::vec3 cartesianCoordinatesFromGeo(const SceneGraphNode& sgn, double latitude
*/
glm::dvec3 geoPositionFromCamera();
/**
* Returns the camera view direction relative to the current anchor node as geodetic
* coordinates. The returned value contains the latitude and longitude in degrees in the
* x, and y-coordinate respectively.
*/
glm::dvec3 geoViewFromCamera();
/**
* Return the coordinates where the sun is at its zenith at the current anchor at the
* current time. The returned value contains the latitude and longitude in degrees.
*/
glm::dvec2 subSolarCoordinates();
/**
* Returns the height of the camera relative to the provided SceneGraphNode \p sgn in
* meters. If \p useHeightMap is provided as `true` and \p sgn is a globe with an existing
+17 -2
View File
@@ -84,13 +84,28 @@ void CameraTopic::handleJson(const nlohmann::json& json) {
void CameraTopic::sendCameraData() {
#ifdef OPENSPACE_MODULE_SPACE_ENABLED
glm::dvec3 position = geoPositionFromCamera();
glm::dvec3 direction = geoViewFromCamera();
const double viewLength = direction.z;
std::pair<double, std::string_view> altSimplified = simplifyDistance(position.z);
glm::dvec2 subSolar = subSolarCoordinates();
const nlohmann::json jsonData = {
glm::dvec2 dir = glm::dvec2(direction) - glm::dvec2(position);
if (glm::length(dir) > 1e-6) {
// Avoid sending NaNs/null from bad normalization
dir = glm::normalize(dir);
}
nlohmann::json jsonData = {
{ "latitude", position.x },
{ "longitude", position.y },
{ "altitude", altSimplified.first },
{ "altitudeUnit", altSimplified.second }
{ "altitudeUnit", altSimplified.second },
{ "altitudeMeters", position.z },
{ "viewLatitude", dir.x },
{ "viewLongitude", dir.y },
{ "viewLength", viewLength },
{ "subSolarLatitude", subSolar.x },
{ "subSolarLongitude", subSolar.y },
};
_connection->sendJson(wrappedPayload(jsonData));
+73 -3
View File
@@ -83,12 +83,12 @@ glm::dvec3 geoPositionFromCamera() {
cameraPositionModelSpace
);
const Geodetic2 geo2 = renderable->ellipsoid().cartesianToGeodetic2(
const Geodetic2 geo = renderable->ellipsoid().cartesianToGeodetic2(
posHandle.centerToReferenceSurface
);
const double lat = glm::degrees(geo2.lat);
const double lon = glm::degrees(geo2.lon);
const double lat = glm::degrees(geo.lat);
const double lon = glm::degrees(geo.lon);
double altitude = glm::length(
cameraPositionModelSpace - posHandle.centerToReferenceSurface
@@ -103,6 +103,76 @@ glm::dvec3 geoPositionFromCamera() {
return glm::dvec3(lat, lon, altitude);
}
glm::dvec3 geoViewFromCamera() {
const SceneGraphNode* n = global::navigationHandler->orbitalNavigator().anchorNode();
if (!n) {
return glm::dvec3(0.0);
}
const glm::dmat4 inverseModelTransform = glm::inverse(n->modelTransform());
// Get the position of the camera in model space
const glm::dvec3 cameraPosition = global::navigationHandler->camera()->positionVec3();
const glm::dvec3 cameraPositionModelSpace =
glm::dvec3(inverseModelTransform * glm::dvec4(cameraPosition, 1.0));
// Get the direction of the camera in model space
const glm::dvec3 cameraViewDirection =
global::navigationHandler->camera()->viewDirectionWorldSpace();
// Scaling the cameraViewDirection to move the precision up a few decimals
const glm::dvec3 cameraViewPoint = cameraPosition + 10000.0 * cameraViewDirection;
glm::dvec3 cameraViewDirectionModelSpace =
glm::dvec3(inverseModelTransform * glm::dvec4(cameraViewPoint, 1.0));
// `d` represents how much we are looking towards the center of the scene graph node
// The closer `d` is to -1 or 1, the more we are looking either towards the center or
// away from it
const glm::dmat3 rotationOnly = glm::mat3_cast(glm::quat_cast(n->modelTransform()));
const double d = glm::dot(
glm::normalize(cameraPositionModelSpace),
glm::normalize(glm::transpose(rotationOnly) * cameraViewDirection)
);
const SurfacePositionHandle posHandle = n->calculateSurfacePositionHandle(
cameraViewDirectionModelSpace
);
const Geodetic2 geo = n->ellipsoid().cartesianToGeodetic2(
posHandle.centerToReferenceSurface
);
const double lat = glm::degrees(geo.lat);
const double lon = glm::degrees(geo.lon);
return glm::dvec3(lat, lon, d);
}
glm::dvec2 subSolarCoordinates() {
const SceneGraphNode* n = global::navigationHandler->orbitalNavigator().anchorNode();
if (!n) {
return glm::dvec3(0.0);
}
const glm::dmat4 inverseModelTransform = glm::inverse(n->modelTransform());
// @TODO (2025-07-16, abock): For now we use the position of the SolarSystemBarycenter
// to calculate the Sun position. While this is not completely correct and precludes
// the calculation of subsolar coordinates on exoplanets, that is a problem left for
// later
const glm::dvec3 ssbPositionModelSpace =
glm::dvec3(inverseModelTransform * glm::dvec4(-n->worldPosition(), 1.0));
const SurfacePositionHandle sunPosition = n->calculateSurfacePositionHandle(
ssbPositionModelSpace
);
const Geodetic2 subsolarCoordinates = n->ellipsoid().cartesianToGeodetic2(
sunPosition.centerToReferenceSurface
);
const double lat = glm::degrees(subsolarCoordinates.lat);
const double lon = glm::degrees(subsolarCoordinates.lon);
return glm::dvec2(lat, lon);
}
double altitudeFromCamera(const SceneGraphNode& sgn, bool useHeightMap) {
const glm::dvec3 cameraPosition = global::navigationHandler->camera()->positionVec3();