Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
10 changes: 10 additions & 0 deletions library/private/camera_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ class camera_impl : public camera
camera& setState(const camera_state_t& state) override;
camera_state_t getState() const override;
void getState(camera_state_t& state) const override;
double getWorldAzimuth() const override;
double getWorldElevation() const override;
double getDistance() const override;

camera& dolly(double val) override;
camera& pan(double right, double up, double forward) override;
Expand Down Expand Up @@ -85,6 +88,13 @@ class camera_impl : public camera
bool GetSuccessfullyReset() const;

private:
/**
* This helper computes the direction vector pointing from the camera position
* toward the focal point in world coordinates:
* view = focal_point - position
*/
void getPositionToFocalVector(vector3_t& vec) const;

class internals;
std::unique_ptr<internals> Internals;
};
Expand Down
7 changes: 6 additions & 1 deletion library/public/camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,12 @@ class F3D_EXPORT camera
[[nodiscard]] virtual camera_state_t getState() const = 0;
/** Get the complete state of the camera into the provided arg */
virtual void getState(camera_state_t& state) const = 0;

/** Return the camera azimuth angle in degrees */
[[nodiscard]] virtual double getWorldAzimuth() const = 0;
/** Return the camera elevation angle in degrees */
[[nodiscard]] virtual double getWorldElevation() const = 0;
/** Return the distance between the camera position and its focal point */
[[nodiscard]] virtual double getDistance() const = 0;
///@}

///@{ @name Manipulation
Expand Down
70 changes: 70 additions & 0 deletions library/src/camera_impl.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkVersion.h>
#include <cmath>


namespace f3d::detail
{
Expand Down Expand Up @@ -103,6 +105,74 @@ void camera_impl::getFocalPoint(point3_t& foc) const
cam->GetFocalPoint(foc.data());
}

//----------------------------------------------------------------------------
void camera_impl::getPositionToFocalVector(vector3_t& vec) const
{
point3_t pos, focal;
this->getPosition(pos);
this->getFocalPoint(focal);

vtkMath::Subtract(pos.data(), focal.data(), vec.data());
}

//----------------------------------------------------------------------------
double camera_impl::getWorldAzimuth() const
{
vector3_t view;
this->getPositionToFocalVector(view);
vtkMath::Normalize(view.data());

vtkRenderer* ren = this->Internals->VTKRenderer;
double* up = ren->GetEnvironmentUp();
double* right = ren->GetEnvironmentRight();

// Project view vector onto plane orthogonal to up
vector3_t projUp;
vtkMath::ProjectVector(view.data(), up, projUp.data());

vector3_t horizontal;
vtkMath::Subtract(view.data(), projUp.data(), horizontal.data());

static constexpr double EPS = 128 * std::numeric_limits<double>::epsilon();
if (vtkMath::Norm(horizontal.data()) < EPS)
{
return 0.0;
}

vtkMath::Normalize(horizontal.data());
Comment on lines +136 to +142
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

Copy link
Member

Choose a reason for hiding this comment

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

so, is it needed @Dtsitos ?


// Signed angle between right and horizontal projection
double angleRad = vtkMath::SignedAngleBetweenVectors(right, horizontal.data(), up);

return vtkMath::DegreesFromRadians(angleRad);

}

//----------------------------------------------------------------------------
double camera_impl::getWorldElevation() const
{
vector3_t view;
this->getPositionToFocalVector(view);
vtkMath::Normalize(view.data());

vtkRenderer* ren = this->Internals->VTKRenderer;
double* up = ren->GetEnvironmentUp();

// 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));
}

//----------------------------------------------------------------------------
double camera_impl::getDistance() const
{
vector3_t v;
this->getPositionToFocalVector(v);
return vtkMath::Norm(v.data());
}

//----------------------------------------------------------------------------
camera& camera_impl::setViewUp(const vector3_t& up)
{
Expand Down
27 changes: 27 additions & 0 deletions library/testing/TestSDKCamera.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,33 @@ int TestSDKCamera([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
return EXIT_FAILURE;
}

// Test getters: azimuth / elevation / distance
cam.setPosition({ 0., -11., -1. });
cam.setFocalPoint({ 0., 0., -1. });
cam.setViewUp({ 1., 0., 0. });

double azimuth = cam.getWorldAzimuth();
double elevation = cam.getWorldElevation();
double distance = cam.getDistance();

if (!compareDouble(distance, 11.0))
{
std::cerr << "getDistance is not behaving as expected: " << distance << "\n";
return EXIT_FAILURE;
}

if (!compareDouble(azimuth, 90.0))
{
std::cerr << "getAzimuth is not behaving as expected: " << azimuth << "\n";
return EXIT_FAILURE;
}

if (!compareDouble(elevation, 0.0))
{
std::cerr << "getElevation is not behaving as expected: " << elevation << "\n";
return EXIT_FAILURE;
}

// Test dolly
cam.dolly(10);
expectedPos = { 20.9, -11., -12. };
Expand Down