Skip to content

Conversation

@Dtsitos
Copy link

@Dtsitos Dtsitos commented Jan 2, 2026

Describe your changes

This PR adds read-only getters to the camera API to retrieve derived world-space
camera parameters (azimuth, elevation, and distance).

The values are computed from the camera position and focal point and do not
modify camera state. This enables external applications and bindings to query
camera orientation consistently without duplicating math.

No existing behavior is changed.

Original PR: #2724

Issue ticket number and link if any

Fixes #1419

Checklist for finalizing the PR

  • I have performed a self-review of my code
  • I have added tests for new features and bugfixes
  • I have added documentation for new features
  • If it is a modifying the libf3d API, I have updated bindings
  • If it is a modifying the .github/workflows/versions.json, I have updated docker_timestamp

Continuous integration

Please write a comment to run CI, eg: \ci fast.
See here for more info.

…ickly for further processing

(cherry picked from commit 935740b)
…n to compute the distance from the camera position to the focal point

(cherry picked from commit a54c71e)
(cherry picked from commit 3f8671b)
…mproved getWorldAzimuth using SignedAngleBetweenVectors
@github-actions
Copy link

github-actions bot commented Jan 2, 2026

You are modifying libf3d public API! ⚠️Please update bindings accordingly⚠️!
You can find them in their respective directories: c, python, java, webassembly.

@Dtsitos
Copy link
Author

Dtsitos commented Jan 2, 2026

I think this should be correct now, will work on better testing ASAP

Comment on lines +161 to +165
// Elevation is angle above the horizontal plane
double dot = vtkMath::Dot(view.data(), up);
dot = std::clamp(dot, -1.0, 1.0);

return vtkMath::DegreesFromRadians(std::asin(dot));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to check if that can be done with AngleBetweenVectors to avoid the raw trig. Maybe something like 90° - angle_between(view, up)?

Comment on lines +136 to +142
static constexpr double EPS = 128 * std::numeric_limits<double>::epsilon();
if (vtkMath::Norm(horizontal.data()) < EPS)
{
return 0.0;
}

vtkMath::Normalize(horizontal.data());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once you've got the tests you can double check if this is actually needed

@mwestphal
Copy link
Member

please let us know when its ready for review @Dtsitos

@Dtsitos
Copy link
Author

Dtsitos commented Jan 4, 2026

@mwestphal Hello there, I have implemented all the bindings and some basic testing for them. Full disclosure, I have never worked with bindings again and mostly deduced what to do based on the patterns from the existing implementations. Thank you for your patience

@mwestphal
Copy link
Member

@mwestphal Hello there, I have implemented all the bindings and some basic testing for them. Full disclosure, I have never worked with bindings again and mostly deduced what to do based on the patterns from the existing implementations. Thank you for your patience

Thats perfectly fine and it looks good to me :)

@mwestphal
Copy link
Member

@Dtsitos can you adress and resolve the suggestions made by @snoyer above ?
If you did adress them already, please resolve the discussions.

@mwestphal
Copy link
Member

\ci full

@github-actions
Copy link

github-actions bot commented Jan 4, 2026

Style Checks CI failed:

diff --git a/library/src/camera_impl.cxx b/library/src/camera_impl.cxx
index fb8d8ee..5e35fb7 100644
--- a/library/src/camera_impl.cxx
+++ b/library/src/camera_impl.cxx
@@ -1,12 +1,11 @@
 #include "camera_impl.h"
 
+#include <cmath>
 #include <vtkCamera.h>
 #include <vtkMatrix4x4.h>
 #include <vtkRenderWindow.h>
 #include <vtkRenderer.h>
 #include <vtkVersion.h>
-#include <cmath>
-
 
 namespace f3d::detail
 {
@@ -106,7 +105,7 @@ void camera_impl::getFocalPoint(point3_t& foc) const
 }
 
 //----------------------------------------------------------------------------
-  void camera_impl::getPositionToFocalVector(vector3_t& vec) const
+void camera_impl::getPositionToFocalVector(vector3_t& vec) const
 {
   point3_t pos, focal;
   this->getPosition(pos);
@@ -116,7 +115,7 @@ void camera_impl::getFocalPoint(point3_t& foc) const
 }
 
 //----------------------------------------------------------------------------
-  double camera_impl::getWorldAzimuth() const
+double camera_impl::getWorldAzimuth() const
 {
   vector3_t view;
   this->getPositionToFocalVector(view);
@@ -145,11 +144,10 @@ void camera_impl::getFocalPoint(point3_t& foc) const
   double angleRad = vtkMath::SignedAngleBetweenVectors(right, horizontal.data(), up);
 
   return vtkMath::DegreesFromRadians(angleRad);
-
 }
 
 //----------------------------------------------------------------------------
-  double camera_impl::getWorldElevation() const
+double camera_impl::getWorldElevation() const
 {
   vector3_t view;
   this->getPositionToFocalVector(view);
@@ -166,7 +164,7 @@ void camera_impl::getFocalPoint(point3_t& foc) const
 }
 
 //----------------------------------------------------------------------------
-  double camera_impl::getDistance() const
+double camera_impl::getDistance() const
 {
   vector3_t v;
   this->getPositionToFocalVector(v);
diff --git a/library/testing/TestSDKCamera.cxx b/library/testing/TestSDKCamera.cxx
index 74670fc..7bb46e0 100644
--- a/library/testing/TestSDKCamera.cxx
+++ b/library/testing/TestSDKCamera.cxx
@@ -243,7 +243,8 @@ int TestSDKCamera([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
 
   if (!compareDouble(elevation, 0.0))
   {
-    std::cerr << "getWorldElevation (horizontal) is not behaving as expected: " << elevation << "\n";
+    std::cerr << "getWorldElevation (horizontal) is not behaving as expected: " << elevation
+              << "\n";
     return EXIT_FAILURE;
   }
 
@@ -258,13 +259,15 @@ int TestSDKCamera([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
 
   if (!compareDouble(distance, std::sqrt(11.0 * 11.0 + 11.0 * 11.0)))
   {
-    std::cerr << "getDistance (positive elevation) is not behaving as expected: " << distance << "\n";
+    std::cerr << "getDistance (positive elevation) is not behaving as expected: " << distance
+              << "\n";
     return EXIT_FAILURE;
   }
 
   if (!compareDouble(azimuth, 90.0))
   {
-    std::cerr << "getWorldAzimuth (positive elevation) is not behaving as expected: " << azimuth << "\n";
+    std::cerr << "getWorldAzimuth (positive elevation) is not behaving as expected: " << azimuth
+              << "\n";
     return EXIT_FAILURE;
   }
 
@@ -286,7 +289,8 @@ int TestSDKCamera([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
 
   if (!compareDouble(distance, std::sqrt(11.0 * 11.0 + 11.0 * 11.0)))
   {
-    std::cerr << "getDistance (negative elevation) is not behaving as expected: " << distance << "\n";
+    std::cerr << "getDistance (negative elevation) is not behaving as expected: " << distance
+              << "\n";
     return EXIT_FAILURE;
   }
 
@@ -341,15 +345,14 @@ int TestSDKCamera([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
 
   if (!compareDouble(azimuth, 0.0))
   {
-    std::cerr << "getWorldAzimuth with zero direction vector should return 0: "
-              << azimuth << "\n";
+    std::cerr << "getWorldAzimuth with zero direction vector should return 0: " << azimuth << "\n";
     return EXIT_FAILURE;
   }
 
   if (!compareDouble(elevation, 0.0))
   {
-    std::cerr << "getWorldElevation with zero direction vector should return 0: "
-              << elevation << "\n";
+    std::cerr << "getWorldElevation with zero direction vector should return 0: " << elevation
+              << "\n";
     return EXIT_FAILURE;
   }
 
@@ -363,15 +366,14 @@ int TestSDKCamera([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
 
   if (!compareDouble(azimuth, 0.0))
   {
-    std::cerr << "getWorldAzimuth with forward parallel to up should return 0: "
-              << azimuth << "\n";
+    std::cerr << "getWorldAzimuth with forward parallel to up should return 0: " << azimuth << "\n";
     return EXIT_FAILURE;
   }
 
   if (!compareDouble(elevation, 90.0))
   {
-    std::cerr << "getWorldElevation with forward parallel to up should be 90: "
-              << elevation << "\n";
+    std::cerr << "getWorldElevation with forward parallel to up should be 90: " << elevation
+              << "\n";
     return EXIT_FAILURE;
   }
 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add getters for camera parameters

3 participants