Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
04a2d46
feat: Add yaw, azimuth, and elevation methods to camera implementation
AbbasReads Sep 15, 2025
6789df3
Update camera tests for yaw, elevation, and add getAzimuth method and…
AbbasReads Sep 15, 2025
c13cf2e
Update library/testing/TestSDKCamera.cxx
AbbasReads Sep 15, 2025
e4f037c
Update library/testing/TestSDKCamera.cxx
AbbasReads Sep 15, 2025
d0bdf55
Update library/testing/TestSDKCamera.cxx
AbbasReads Sep 15, 2025
2e0a6e5
Update library/testing/TestSDKCamera.cxx
AbbasReads Sep 15, 2025
d111df7
Update library/src/camera_impl.cxx
AbbasReads Sep 15, 2025
689642e
Update library/src/camera_impl.cxx
AbbasReads Sep 15, 2025
6ea92d7
Refactor camera angle methods for improved clarity
AbbasReads Sep 15, 2025
b36aff6
Update library/testing/TestSDKCamera.cxx
AbbasReads Sep 15, 2025
78e4018
Update library/testing/TestSDKCamera.cxx
AbbasReads Sep 15, 2025
a0bd210
Enhance camera angle method documentation and fix test variable initi…
AbbasReads Sep 22, 2025
46a8140
Add camera getter methods to Python bindings
AbbasReads Sep 22, 2025
6700db9
Update library/public/camera.h
AbbasReads Sep 22, 2025
0558b69
Update library/public/camera.h
AbbasReads Sep 22, 2025
fb34881
Add combined camera movement tests for yaw, elevation, and azimuth an…
AbbasReads Sep 22, 2025
7c687aa
Refactor getAzimuth method to call getYaw directly =
AbbasReads Sep 22, 2025
2eae0ee
Update library/public/camera.h
AbbasReads Sep 23, 2025
952d074
Edited getAzimuth documentation
AbbasReads Sep 24, 2025
fde0219
Fix formatting in getYaw documentation comment
AbbasReads Sep 24, 2025
4ab9bad
Fix formatting in camera_impl.cxx and test_camera.py
AbbasReads Sep 24, 2025
e6303f4
Printing test values for debugging
AbbasReads Sep 25, 2025
edec2e6
Refactor compareDouble for better tolerance handling and update test …
AbbasReads Sep 29, 2025
e740b13
Update compareDouble tolerance in TestSDKCamera in yaw, elevation, an…
AbbasReads Sep 30, 2025
6974af7
Update elevation test in TestSDKCamera to check for correct values
AbbasReads Sep 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions library/private/camera_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ class camera_impl : public camera
camera& elevation(angle_deg_t angle) override;
camera& pitch(angle_deg_t angle) override;

angle_deg_t getYaw() override;
angle_deg_t getAzimuth() override;
angle_deg_t getElevation() override;

camera& setCurrentAsDefault() override;
camera& resetToDefault() override;
camera& resetToBounds(double zoomFactor = 0.9) override;
Expand Down
19 changes: 18 additions & 1 deletion library/public/camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,26 @@ class F3D_EXPORT camera
virtual camera& elevation(angle_deg_t angle) = 0;
/** Rotate the camera about its horizontal axis, centered the camera's position. */
virtual camera& pitch(angle_deg_t angle) = 0;

///@}

///@{ @name Getters
/// Yaw, azimuth and elevation getter methods(calculated on call). Angles are in degrees.

/** Calculates angle between the projection of the forward vector (on
* the plane perpendicular to the up vector) and the right vector (-180 to 180 degrees)
*/
[[nodiscard]] virtual angle_deg_t getYaw() = 0;

/** Calculates the horizontal rotation angle of the forward vector
* around the up vector, measured from the right vector. (-180 to 180 degrees)
*/
[[nodiscard]] virtual angle_deg_t getAzimuth() = 0;


/** Calculates the angle between the forward vector and the up vector (-90 to +90 degrees) */
[[nodiscard]] virtual angle_deg_t getElevation() = 0;
///@}

/**
* Store the current camera configuration as default.
*/
Expand Down
68 changes: 68 additions & 0 deletions library/src/camera_impl.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ void camera_impl::getState(camera_state_t& state)
cam->GetViewUp(state.viewUp.data());
state.viewAngle = cam->GetViewAngle();
}

//----------------------------------------------------------------------------
camera& camera_impl::dolly(double val)
{
Expand Down Expand Up @@ -282,6 +283,73 @@ camera& camera_impl::pitch(angle_deg_t angle)
return *this;
}

//----------------------------------------------------------------------------
angle_deg_t camera_impl::getYaw()
{
point3_t pos, foc;
vector3_t dir, projectedAlongUp, projected;
double* up = this->Internals->VTKRenderer->GetEnvironmentUp();
double* right = this->Internals->VTKRenderer->GetEnvironmentRight();
this->getPosition(pos);
this->getFocalPoint(foc);

// Forward vector (focal - position)
vtkMath::Subtract(foc, pos, dir);
vtkMath::Normalize(dir.data());
vtkMath::Normalize(up);

// Project forward vector onto up vector
vtkMath::ProjectVector(dir.data(), up, projectedAlongUp.data());
vtkMath::Normalize(projectedAlongUp.data());

// Projection of forward vector along the plane perpendicular to up vector
vtkMath::Subtract(dir,projectedAlongUp,projected);

vector3_t cross;
vtkMath::Cross(right, projected.data(), cross.data());
double sign = (vtkMath::Dot(cross.data(), up) >= 0) ? 1.0 : -1.0;
double angleRad = vtkMath::AngleBetweenVectors(right, projected.data());
return sign * vtkMath::DegreesFromRadians(angleRad);
}

//----------------------------------------------------------------------------
angle_deg_t camera_impl::getAzimuth()
{
point3_t pos, foc;
vector3_t dir, projectedAlongUp, projected;
double* up = this->Internals->VTKRenderer->GetEnvironmentUp();
double* right = this->Internals->VTKRenderer->GetEnvironmentRight();
this->getPosition(pos);
this->getFocalPoint(foc);

// Forward vector (focal - position)
vtkMath::Subtract(foc, pos, dir);
vtkMath::Normalize(dir.data());
vtkMath::Normalize(up);

// Project forward vector onto up vector
vtkMath::ProjectVector(dir.data(), up, projectedAlongUp.data());
vtkMath::Normalize(projectedAlongUp.data());

//Projection of forward vector along the plane perpendicular to up vector
vtkMath::Subtract(dir,projectedAlongUp,projected);

double angleRad = vtkMath::AngleBetweenVectors(right, projected.data());
vector3_t cross;
vtkMath::Cross(right, projected.data(), cross.data());
double sign = vtkMath::Dot(cross.data(), up) >= 0 ? 1.0 : -1.0;
return sign * vtkMath::DegreesFromRadians(angleRad);
}

//----------------------------------------------------------------------------
angle_deg_t camera_impl::getElevation()
{
double* up = this->Internals->VTKRenderer->GetEnvironmentUp();
vtkCamera* cam = this->GetVTKCamera();
return vtkMath::DegreesFromRadians(
vtkMath::AngleBetweenVectors(up, cam->GetDirectionOfProjection()) - vtkMath::Pi() / 2);
}

//----------------------------------------------------------------------------
camera& camera_impl::setCurrentAsDefault()
{
Expand Down
60 changes: 60 additions & 0 deletions library/testing/TestSDKCamera.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,66 @@ int TestSDKCamera([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
return EXIT_FAILURE;
}

// Test getYaw
cam.setPosition({ -1, 0, 0 });
cam.setFocalPoint({ 0, 0, 0 });
cam.setViewUp({ 0, 1, 0 });
f3d::angle_deg_t yaw = cam.getYaw();
if (!compareDouble(yaw, 0.))
{
std::cerr << "get yaw is not behaving as expected: " << yaw << " " << "\n";
return EXIT_FAILURE;
}
f3d::angle_deg_t testYaw = 90.0;
cam.yaw(testYaw);
yaw = cam.getYaw();
if (!compareDouble(yaw, testYaw))
{
std::cerr << "Yaw after +90° yaw() is incorrect: " << yaw << "\n";
return EXIT_FAILURE;
}

// Test getElevation
cam.setPosition({ 0, 0, -1 });
cam.setFocalPoint({ 0, 0, 0 });
cam.setViewUp({ 0, 1, 0 });
f3d::angle_deg_t elevation = cam.getElevation();
if (!compareDouble(elevation, 0.))
{
std::cerr << "get elevation is not behaving as expected: " << elevation << " != " << 0.0
<< "\n";
return EXIT_FAILURE;
}
f3d::angle_deg_t testElevation = -45.0;
cam.elevation(testElevation);
elevation = cam.getElevation();
if (!compareDouble(elevation, testElevation))
{
std::cerr << "get elevation after elevation +45 is not behaving as expected: " << elevation
<< " != " << testElevation << "\n";
return EXIT_FAILURE;
}

// Test getAzimuth
cam.setPosition({ -1, 0, 0 });
cam.setFocalPoint({ 0, 0, 0 });
cam.setViewUp({ 0, 1, 0 });
f3d::angle_deg_t azimuth = cam.getAzimuth();
if (!compareDouble(azimuth, 0.))
{
std::cerr << "get azimuth is not behaving as expected: " << azimuth << " != " << 0.0 << "\n";
return EXIT_FAILURE;
}
f3d::angle_deg_t testAzimuth = 90.0;
cam.azimuth(testAzimuth);
azimuth = cam.getAzimuth();
if (!compareDouble(azimuth, testAzimuth))
{
std::cerr << "get azimuth after azimuth +90 is not behaving as expected: " << azimuth
<< " != " << testAzimuth << "\n";
return EXIT_FAILURE;
}

// Test position
f3d::point3_t testPos = { 0., 0., 10. };
f3d::point3_t pos = cam.setPosition(testPos).getPosition();
Expand Down
3 changes: 3 additions & 0 deletions python/F3DPythonBindings.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,9 @@ PYBIND11_MODULE(pyf3d, module)
.def("yaw", &f3d::camera::yaw)
.def("elevation", &f3d::camera::elevation)
.def("pitch", &f3d::camera::pitch)
.def("get_yaw", &f3d::camera::getYaw)
.def("get_azimuth", &f3d::camera::getAzimuth)
.def("get_elevation", &f3d::camera::getElevation)
.def("set_current_as_default", &f3d::camera::setCurrentAsDefault)
.def("reset_to_default", &f3d::camera::resetToDefault)
.def("reset_to_bounds", &f3d::camera::resetToBounds, py::arg("zoom_factor") = 0.9);
Expand Down