Camera Model

template<IsSpectral TSpectral>
class CameraModel : public huira::SceneObject<CameraModel<TSpectral>>

CameraModel represents a pinhole or thin-lens camera with configurable sensor, aperture, and distortion models.

This class provides a flexible camera abstraction for rendering and simulation, supporting various sensor types, aperture shapes, and lens distortion models. It allows configuration of focal length, f-stop, sensor resolution, pixel pitch, and more. The camera can project 3D points to the image plane, compute projected aperture area, and supports both analytic and PSF-based point spread functions. All units are SI unless otherwise noted.

Template Parameters:

TSpectral – The spectral type (e.g., float, Vec3f, etc.)

Public Functions

CameraModel()

Construct a new CameraModel with default sensor and aperture.

Initializes the camera with a default focal length, a SimpleSensor, and a CircularAperture. The aperture diameter is set based on the focal length and a default f-stop of 2.8.

CameraModel(const CameraModel&) = delete
CameraModel &operator=(const CameraModel&) = delete
void set_focal_length(units::Millimeter focal_length)

Set the focal length of the camera (in millimeters).

Updates the camera intrinsics and, if using aperture PSF, updates the PSF as well.

Parameters:

focal_length – Focal length in millimeters

inline units::Millimeter focal_length() const
void set_fstop(float fstop)

Set the f-stop (aperture ratio) of the camera.

Parameters:

fstop – F-stop value

float fstop() const

Get the f-stop (aperture ratio) of the camera.

Returns:

float F-stop value

template<IsDistortion<TSpectral> TDistortion, typename ...Args>
void set_distortion(Args&&... args)

Set the distortion model for the camera.

Template Parameters:
  • TDistortionDistortion model type

  • Args – Constructor arguments for the distortion model

Parameters:

args – Arguments to construct the distortion model

void set_brown_conrady_distortion(BrownCoefficients coeffs)

Set Brown-Conrady distortion coefficients.

Parameters:

coeffs – Brown distortion coefficients

void set_opencv_distortion(OpenCVCoefficients coeffs)

Set OpenCV distortion coefficients.

Parameters:

coeffs – OpenCV distortion coefficients

void set_owen_distortion(OwenCoefficients coeffs)

Set Owen distortion coefficients.

Parameters:

coeffs – Owen distortion coefficients

inline void delete_distortion()
template<IsSensor<TSpectral> TSensor, typename ...Args>
void set_sensor(Args&&... args)

Set the sensor model for the camera.

Template Parameters:
  • TSensor – Sensor model type

  • Args – Constructor arguments for the sensor

Parameters:

args – Arguments to construct the sensor

void configure_sensor_from_pitch(const Resolution &resolution, units::Micrometer pitch_x, std::optional<units::Micrometer> pitch_y = std::nullopt, std::optional<float> cx = std::nullopt, std::optional<float> cy = std::nullopt)

Configure the sensor using pixel pitch and resolution.

This method sets the sensor resolution, pixel pitch, and principal point. It also computes the intrinsics based on the new configuration.

Parameters:
  • resolution – Sensor resolution

  • pitch_xPixel pitch in x direction (micrometers)

  • pitch_yPixel pitch in y direction (micrometers)

  • cx – Principal point x coordinate (must be within resolution bounds)

  • cy – Principal point y coordinate (must be within resolution bounds)

void configure_sensor_from_size(const Resolution &resolution, units::Millimeter width, std::optional<units::Millimeter> height = std::nullopt, std::optional<float> cx = std::nullopt, std::optional<float> cy = std::nullopt)

Configure the sensor using physical size and resolution.

This method sets the sensor resolution, physical size, and principal point. It also computes the intrinsics based on the new configuration.

Parameters:
  • resolution – Sensor resolution

  • width – Sensor width in millimeters

  • height – Sensor height in millimeters

  • cx – Principal point x coordinate (must be within resolution bounds)

  • cy – Principal point y coordinate (must be within resolution bounds)

void set_intrinsic_matrix(const Mat3<float> &intrinsic_matrix, const Resolution &resolution, units::Millimeter anchor_focal_length)

Set the intrinsic matrix for the camera.

Parameters:
  • intrinsic_matrix – 3x3 intrinsic matrix

  • resolution – Sensor resolution

  • anchor_focal_length – Anchor focal length in millimeters

void set_intrinsics(float fx, float fy, float cx, float cy, const Resolution &resolution, units::Millimeter anchor_focal_length)

Set the intrinsic parameters for the camera.

Parameters:
  • fx – Focal length in x direction

  • fy – Focal length in y direction

  • cx – Principal point x coordinate

  • cy – Principal point y coordinate

  • resolution – Sensor resolution

  • anchor_focal_length – Anchor focal length in millimeters

Rotation<double> sensor_rotation() const

Get the sensor rotation as a Rotation object.

Returns:

Rotation<double> Sensor rotation

template<IsAperture TAperture, typename ...Args>
void set_aperture(Args&&... args)

Set the aperture model for the camera.

Template Parameters:
  • TApertureAperture model type

  • Args – Constructor arguments for the aperture

Parameters:

args – Arguments to construct the aperture

template<IsPSF TPSF, typename ...Args>
void set_psf(Args&&... args)

Set the point spread function (PSF) model for the camera.

Template Parameters:
  • TPSFPSF model type

  • Args – Constructor arguments for the PSF

Parameters:

args – Arguments to construct the PSF

void set_measured_psf(const Image<TSpectral> &data, float samples_per_pixel, int radius = 0, int banks = 16)

Sets a measured (user-supplied) PSF as the core PSF of the camera.

Convenience wrapper around set_psf<MeasuredPSF>() that is also exposed through the Python bindings. See MeasuredPSF for the data conventions (centered measurement, sampling density, extent limits).

Parameters:
  • data – Measured PSF samples, centered on the image.

  • samples_per_pixel – Measurement samples per sensor pixel per axis.

  • radius – Polyphase stamping kernel radius in sensor pixels (0 = auto).

  • banks – Number of polyphase banks per axis for subpixel stamping.

void use_aperture_psf(int radius = 64, int banks = 16)

Use the aperture to generate a PSF (point spread function).

Parameters:
  • radiusPSF kernel radius

  • banks – Number of PSF banks

inline void enable_psf_convolution(bool convolve_psf = true)
void set_psf_convolution_radius(int radius)

Sets the radius of the whole-image PSF convolution kernel.

The convolution kernel is a single centered kernel built via PSF::generate_convolution_kernel() and is independent of the polyphase stamping cache, so it may be much larger (e.g. spanning the full frame to model scattered-light wings). A radius of 0 matches the polyphase radius.

Parameters:

radius – Convolution kernel radius in pixels (kernel dimension is 2 * radius + 1)

void delete_psf()

Delete the PSF and disable aperture PSF usage.

void set_veiling_glare(float alpha)

Set the veiling glare alpha value.

Parameters:

alpha – Veiling glare alpha (0 to 1)

void disable_veiling_glare()

Disable veiling glare effects.

void set_harvey_shack_scatter(float scatter_fraction, float falloff_exponent, float r0 = 0.5f, float radius = 0.f)

Set Harvey-Shack scatter parameters.

Parameters:
  • scatter_fraction – Fraction of light scattered (0 to 1)

  • falloff_exponent – Exponent for scatter falloff (typically > 1)

  • r0 – Radius at which scatter fraction is measured (default 0.5)

  • radius – Maximum scatter radius in pixels (default 0, meaning infinite)

void disable_harvey_shack_scatter()

Disable Harvey-Shack scatter effects.

inline bool has_psf() const
inline const Image<TSpectral> &get_psf_kernel(float u, float v) const
inline int get_psf_radius() const
const Image<TSpectral> &get_psf_convolution_kernel()

Returns the total-system PSF kernel for whole-image convolution.

The total point spread function of the optical system is the energy-weighted sum of its components: the diffraction-limited core (from the aperture or a user-provided PSF) and the Harvey-Shack scattered-light wings. Veiling glare, the third component, is uniform across the image and is applied separately by the renderer for efficiency. The kernel is built lazily and cached; any change to the core PSF, convolution radius, or scatter parameters invalidates it.

Returns:

Reference to the cached total-system convolution kernel (unit energy per channel).

const Image<TSpectral> &get_psf_wings_kernel()

Returns the scattered-light wings kernel alone, building it lazily if needed.

This is the Harvey-Shack component of the total system PSF, normalized to unit energy and NOT scaled by the scatter fraction. The renderer uses it to apply wings to unresolved sources: their compact core is stamped via the polyphase cache, their raw energy is splatted into a separate buffer, and that buffer is convolved with this kernel before the two are blended by (1 - f_s) and f_s. Requires scattering to be enabled.

Returns:

Reference to the cached wings kernel (unit energy per channel).

inline void enable_depth_of_field(bool depth_of_field = true)
void set_focus_distance(units::Meter focus_distance)

Set the focus distance for depth of field calculations.

Parameters:

focus_distance – Focus distance in meters

inline units::Meter get_focus_distance() const
void set_diopters(units::Diopter diopters)

Set the focus distance using diopters.

Converts the given diopter value to a focus distance in meters and forwards it to set_focus_distance().

Parameters:

diopters – Focus distance expressed in diopters

units::Diopter get_diopters() const

Get the current focus distance in diopters.

Returns:

units::Diopter Focus distance expressed in diopters

Pixel project_point(const Vec3<float> &point_camera_coords) const

Project a 3D point in camera coordinates onto the image plane.

Uses the pinhole camera model and applies distortion if present.

Parameters:

point_camera_coords – 3D point in camera coordinates (meters)

Returns:

Pixel 2D point on the image plane (pixels)

Pixel try_project_point(const Vec3<float> &point_camera_coords) const
Ray<TSpectral> cast_ray(const Pixel &pixel, Sampler<float> &sampler) const
Ray<TSpectral> cast_ray(const Pixel &pixel) const
Ray<TSpectral> cast_ray(int x, int y) const
inline const Frustum<TSpectral> &view_frustum() const
float pixel_radiance_to_power(int x, int y) const
bool in_fov(const Vec3<float> &point) const
inline void readout(FrameBuffer<TSpectral> &fb, units::Second exposure_time) const
float get_projected_aperture_area(const Vec3<float> &direction) const

Get the projected aperture area for a given direction.

Parameters:

direction – Direction vector

Returns:

float Projected aperture area

inline Resolution resolution() const
inline virtual std::string type() const override

Get the object’s type string.

Returns:

std::string Type

inline FrameBuffer<TSpectral> make_frame_buffer() const
inline void use_blender_convention(bool value = true)
inline bool is_blender_convention() const
inline bool is_scene_owned() const

Check if the object is owned by the scene.

Returns:

bool True if owned

inline void set_scene_owned(bool owned)

Set scene ownership flag.

Parameters:

owned – True if owned

inline std::string name() const

Get the object’s name.

Returns:

std::string Name

inline virtual std::uint64_t id() const

Get the object’s unique ID.

Returns:

std::uint64_t ID

inline virtual std::string get_info() const

Get a descriptive info string for the object.

Returns:

std::string Info string

Protected Functions

inline void invalidate_psf_kernels_()
void compute_intrinsics_()

Compute the camera intrinsic parameters (focal lengths, principal point, resolution).

template<IsFloatingPoint TFloat>
Vec3<TFloat> pixel_to_direction_(const Pixel &pixel) const
void compute_distortion_field_()
void compute_pixel_solid_angles_()
Vec3<double> tangent_(const Vec3<double> &p0, const Vec3<double> &p1) const
double triangle_solid_angle_(const Vec3<double> &c0, const Vec3<double> &c1, const Vec3<double> &c2) const
void compute_frustum_()

Protected Attributes

float focal_length_ = .05f
std::unique_ptr<SensorModel<TSpectral>> sensor_
std::unique_ptr<Aperture<TSpectral>> aperture_
std::unique_ptr<Distortion<TSpectral>> distortion_ = nullptr
std::unique_ptr<PSF<TSpectral>> psf_ = nullptr
bool convolve_psf_ = false
int psf_convolution_radius_ = 0
Image<TSpectral> psf_convolution_kernel_
bool psf_convolution_kernel_valid_ = false
Image<TSpectral> psf_wings_kernel_
bool psf_wings_kernel_valid_ = false
bool use_aperture_psf_ = false
float d_ = std::numeric_limits<float>::infinity()
float veiling_alpha_ = 0.f
bool veiling_glare_enabled_ = false
float scatter_fraction_ = 0.f
float scatter_falloff_exponent_ = 2.f
float r0_ = 0.5f
float scatter_radius_ = 0.f
bool scatter_enabled_ = false
float fx_
float fy_
float cx_
float cy_
float rx_
float ry_
bool is_explicit_matrix_ = false
bool depth_of_field_ = false
Image<Vec3<float>> distortion_field_
Image<float> pixel_solid_angles_
Frustum<TSpectral> view_frustum_
bool blender_convention_ = false

Friends

friend class CameraModelHandle< TSpectral >
friend class Renderer< TSpectral >