Skip to content
Open
19 changes: 19 additions & 0 deletions java/Camera.java
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,25 @@ public Camera pan(double right, double up) {
public Camera resetToBounds() {
return resetToBounds(0.9);
}
/**
* Get the world-space azimuth angle of the camera in degrees.
*
* @return azimuth angle in degrees
*/
public native double getWorldAzimuth();

/**
* Get the world-space elevation angle of the camera in degrees.
*
* @return elevation angle in degrees
*/
public native double getWorldElevation();

/**
* Get the distance between the camera position and its focal point.
*
* @return distance value
*/
public native double getDistance();
private long mNativeAddress;
}
17 changes: 16 additions & 1 deletion java/F3DCameraBindings.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,21 @@ extern "C"
return GetEngine(env, self)->getWindow().getCamera().getViewAngle();
}

JNIEXPORT jdouble JAVA_BIND(Camera, getDistance)(JNIEnv* env, jobject self)
{
return GetEngine(env, self)->getWindow().getCamera().getDistance();
}

JNIEXPORT jdouble JAVA_BIND(Camera, getWorldAzimuth)(JNIEnv* env, jobject self)
{
return GetEngine(env, self)->getWindow().getCamera().getWorldAzimuth();
}

JNIEXPORT jdouble JAVA_BIND(Camera, getWorldElevation)(JNIEnv* env, jobject self)
{
return GetEngine(env, self)->getWindow().getCamera().getWorldElevation();
}

JNIEXPORT jobject JAVA_BIND(Camera, setState)(JNIEnv* env, jobject self, jobject state)
{
jclass stateClass = env->GetObjectClass(state);
Expand Down Expand Up @@ -193,4 +208,4 @@ extern "C"
GetEngine(env, self)->getWindow().getCamera().resetToBounds(zoomFactor);
return self;
}
}
}
6 changes: 5 additions & 1 deletion library/private/camera_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ class camera_impl : public camera
camera_state_t getState() const override;
void getState(camera_state_t& state) const override;

double getDistance() const override;
double getWorldAzimuth() const override;
double getWorldElevation() const override;

camera& dolly(double val) override;
camera& pan(double right, double up, double forward) override;
camera& zoom(double factor) override;
Expand Down Expand Up @@ -90,4 +94,4 @@ class camera_impl : public camera
};
}

#endif
#endif
9 changes: 8 additions & 1 deletion library/public/camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ class F3D_EXPORT camera
/** Get the complete state of the camera into the provided arg */
virtual void getState(camera_state_t& state) const = 0;

/** Return the distance from the camera to the focal point */
[[nodiscard]] virtual double getDistance() const = 0;
/** Return the azimuth of the camera in world coordinates */
[[nodiscard]] virtual double getWorldAzimuth() const = 0;
/** Return the elevation of the camera in world coordinates */
[[nodiscard]] virtual double getWorldElevation() const = 0;

///@}

///@{ @name Manipulation
Expand Down Expand Up @@ -123,4 +130,4 @@ class F3D_EXPORT camera
};
}

#endif
#endif
46 changes: 46 additions & 0 deletions library/src/camera_impl.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <vtkCamera.h>
#include <vtkMatrix4x4.h>
#include <vtkPlane.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkVersion.h>
Expand Down Expand Up @@ -346,4 +347,49 @@ bool camera_impl::GetSuccessfullyReset() const
return this->Internals->SuccessfullyReset;
}

//----------------------------------------------------------------------------
double camera_impl::getDistance() const
{
return this->GetVTKCamera()->GetDistance();
}

//----------------------------------------------------------------------------
double camera_impl::getWorldAzimuth() const
{
vtkRenderer* ren = this->Internals->VTKRenderer;
const double* up = ren->GetEnvironmentUp();

double projectedView[3];
vtkPlane::ProjectVector(this->GetVTKCamera()->GetDirectionOfProjection(),
this->getFocalPoint().data(), up, projectedView);

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

const double angleRad =
vtkMath::SignedAngleBetweenVectors(ren->GetEnvironmentRight(), projectedView, up);

return vtkMath::DegreesFromRadians(angleRad) - 90.0;
}

//----------------------------------------------------------------------------
double camera_impl::getWorldElevation() const
{
double* view = this->GetVTKCamera()->GetDirectionOfProjection();

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

vtkRenderer* ren = this->Internals->VTKRenderer;
const double angleRad = vtkMath::AngleBetweenVectors(ren->GetEnvironmentUp(), view);

return vtkMath::DegreesFromRadians(angleRad) - 90.0;
}

};
58 changes: 57 additions & 1 deletion library/testing/TestSDKCamera.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
#include <camera.h>
#include <engine.h>
#include <log.h>
#include <options.h>
#include <window.h>

#include <iomanip>
#include <iostream>
#include <limits>
#include <sstream>
#include <vector>
#include <utility>

int TestSDKCamera([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
{
Expand Down Expand Up @@ -163,5 +166,58 @@ int TestSDKCamera([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
test("foc when cross product of pos->foc and up is 0 - test 4", cam.getFocalPoint(), { 1, 0, 0 });
test("up when cross product of pos->foc and up is 0 - test 4", cam.getViewUp(), { 0, 1, 0 });

// -------------------------------------------------------------------------
// New Camera Parameter Getter Unit Tests
// -------------------------------------------------------------------------

cam.setPosition({ 0., -10., 0. });
cam.setFocalPoint({ 0., 0., 0. });
test("Distance: 10", cam.getDistance(), approx(10.0));

cam.setPosition({ -10., 0., 0. });
cam.setFocalPoint({ 0., 0., 0. });
cam.setViewUp({ 0., 1., 0. });
test("Azimuth (Y-up): environment forward (+X)", cam.getWorldAzimuth(), approx(90.0));

// Equivalence matrix tests (setter/getter verification)
std::vector<f3d::direction_t> up_directions = {
{ 0, 0, +1 },
{ 0, +1, 0 },
{ +1, 0, 0 },
{ 0, 0, -1 },
{ 0, -1, 0 },
{ -1, 0, 0 },
{ -1, +2, +3 },
{ +4, -5, -6 },
};

const std::vector<std::pair<double, double>> azimuths_elevations = {
{ 0, 0 },
{ +12, +34 },
{ +12, -34 },
{ -12, +34 },
{ -12, -34 },
};

for (const auto up_dir : up_directions)
{
for (auto [a, e] : azimuths_elevations)
{
f3d::engine matrix_eng = f3d::engine::create(true);
f3d::window& matrix_win = matrix_eng.getWindow();
f3d::camera& matrix_cam = matrix_win.getCamera();
f3d::options& opt = matrix_eng.getOptions();

opt.scene.up_direction = up_dir;
matrix_win.render();

matrix_cam.azimuth(a).elevation(e);
const std::string title = " after .azimuth(" + f3d::options::format(a) + ").elevation(" +
f3d::options::format(e) + ") with up = " + f3d::options::format(up_dir);
test("azimuth " + title, matrix_cam.getWorldAzimuth(), approx(a, 1e-10));
test("elevation" + title, matrix_cam.getWorldElevation(), approx(e, 1e-10));
}
}

return test.result();
}
}
Loading