Instance

template<IsSpectral TSpectral>
class Instance : public huira::Node<TSpectral>

Scene graph node representing an instantiable asset (mesh, light, unresolved object, camera model, or model).

Instance nodes are leaf nodes in the scene graph and wrap a single asset pointer.

Template Parameters:

TSpectral – The spectral type (e.g., RGB, Visible8)

Public Functions

inline Instance(Scene<TSpectral> *scene, const Instantiable<TSpectral> &asset)

Construct an Instance node for a given asset.

Parameters:
  • scene – Pointer to the owning Scene

  • asset – Asset to wrap (mesh, light, etc.)

Instance(const Instance&) = delete
Instance &operator=(const Instance&) = delete
inline const Instantiable<TSpectral> &asset() const
void set_indirect_source(bool enabled = true)

Designates this instance as an indirect illumination source (reflector).

Designated instances are directly sampled during next event estimation: they do not emit light, but their (sun)lit surfaces are importance-sampled as if they were light sources, which is essential for capturing e.g. earthshine or moonshine that undirected path sampling would rarely find.

Instances containing a Primitive or a Model may be designated. A designated Model acts as a single source: the sampling proxy bounds every Primitive in its sub-graph, and a sample landing on any of them counts as a hit on this source. Lights, camera models and unresolved objects cannot be designated.

Parameters:

enabled – Whether this instance acts as an indirect source (default true).

Throws:

std::runtime_error – if enabled and the instance contains neither a Primitive nor a Model.

inline bool is_indirect_source() const

Whether this instance is designated as an indirect illumination source.

inline virtual std::string type() const override

Get the object’s type string.

Returns:

std::string Type

virtual std::string get_info() const override

Get a descriptive string for this instance, including asset info.

Returns:

std::string Info string

void look_at(const Node<TSpectral> &target, const Vec3<double> &up = {0.0, 0.0, 1.0}, std::optional<ObservationMode> observation_mode = std::nullopt)

Orient the instance to look at a target node, with an optional up vector.

The target is followed through the exposure. It is aimed at where it is seen from this instance in an observation mode: by default the scene view’s, so that a camera keeps the target where the scene view renders it, or the one given, to aim by another model (where the target truly is, say, while rendering where it appears).

Parameters:
  • target – Target node to look at

  • up – Up vector for orientation (default: {0, 0, 1})

  • observation_mode – The observation mode to aim in, or none (the default) for the scene view’s

Throws:

std::runtime_error – if the target is this instance, or up is not finite.

void look_at(const Vec3<double> &target_position, const Vec3<double> &up = {0.0, 0.0, 1.0}, TargetFrame frame = TargetFrame::PARENT, std::optional<ObservationMode> observation_mode = ObservationMode::TRUE_STATE)

Orient the instance to look at a fixed point, with an optional up vector.

The point is in the instance’s parent’s frame by default, as a position set by set_position() is, so it moves with the parent: an instance under a frame centered on the Earth looks at the Earth with {0, 0, 0}. Given TargetFrame::ROOT, it is in the scene’s root frame (the solar system barycenter, with the J2000 axes).

The point is aimed at where it is (TRUE_STATE, the default; a point has no light time, so GEOMETRIC_STATE is the same), or where it is seen by the moving instance, shifted by the aberration of its velocity (ABERRATED_STATE), or, given no mode, as the scene view observes.

Parameters:
  • target_position – The point to look at, in meters

  • up – Up vector for orientation (default: {0, 0, 1})

  • frame – The frame the point is in (default: the parent’s)

  • observation_mode – The observation mode to aim in (default: TRUE_STATE), or none for the scene view’s

Throws:

std::runtime_error – if the target or up is not finite.

void set_position(const Vec3<double> &position)

Set the node’s position manually.

Parameters:

position – Position vector in meters

void set_position(units::Meter x, units::Meter y, units::Meter z)

Set the node’s position manually using unit types.

Parameters:
  • x – X position (meters)

  • y – Y position (meters)

  • z – Z position (meters)

void set_rotation(const Rotation<double> &rotation)

Set the node’s rotation manually.

Parameters:

rotation – Rotation object

void set_scale(const Vec3<double> &scale)

Set the node’s scale.

Parameters:

scale – Scale vector: each component finite and not 0 (a negative one mirrors).

Throws:

std::runtime_error – if a component is 0, too small to invert, or not finite.

void set_scale(double sx, double sy, double sz)

Set the node’s scale using individual values.

Parameters:
  • sx – X scale

  • sy – Y scale

  • sz – Z scale

Throws:

std::runtime_error – if one is 0, too small to invert, or not finite.

void set_velocity(const Vec3<double> &velocity)

Set the node’s velocity manually.

Parameters:

velocity – Velocity vector in m/s

void set_velocity(units::MetersPerSecond vx, units::MetersPerSecond vy, units::MetersPerSecond vz)

Set the node’s velocity manually using unit types.

Parameters:
  • vx – X velocity (m/s)

  • vy – Y velocity (m/s)

  • vz – Z velocity (m/s)

void set_angular_velocity(const Vec3<double> &angular_velocity)

Set the node’s angular velocity manually, expressed in the PARENT frame.

The angular velocity vector is interpreted in the axes of this node’s parent frame, and the node’s orientation evolves as q(t) = delta(t) * q_0. This is only an “inertial” rate if every ancestor of this node is itself static. To command rates about the node’s own axes (e.g. a roll about a camera boresight), use set_body_angular_velocity() instead.

Parameters:

angular_velocity – Angular velocity vector in rad/s, parent-frame axes

void set_angular_velocity(units::RadiansPerSecond wx, units::RadiansPerSecond wy, units::RadiansPerSecond wz)

Set the node’s angular velocity manually using unit types, expressed in the PARENT frame.

The (wx, wy, wz) components are interpreted in the axes of this node’s parent frame, and the node’s orientation evolves as q(t) = delta(t) * q_0. This is only an “inertial” rate if every ancestor of this node is itself static. To command rates about the node’s own axes (e.g. a roll about a camera boresight), use set_body_angular_velocity() instead.

Parameters:
  • wx – X angular velocity about the parent-frame x-axis (rad/s)

  • wy – Y angular velocity about the parent-frame y-axis (rad/s)

  • wz – Z angular velocity about the parent-frame z-axis (rad/s)

void set_body_angular_velocity(units::RadiansPerSecond wx, units::RadiansPerSecond wy, units::RadiansPerSecond wz)

Set the node’s angular velocity manually using unit types, expressed in the node’s own BODY frame.

The (wx, wy, wz) components are interpreted in this node’s own axes, and the node’s orientation evolves as q(t) = q_0 * delta(t). For a camera (OpenCV convention, +z = boresight), a pure wz therefore produces a roll about the boresight regardless of how the camera is oriented relative to its parent. To command rates in the parent frame’s axes, use set_angular_velocity() instead.

Parameters:
  • wx – X-body angular velocity (rad/s)

  • wy – Y-body angular velocity (rad/s)

  • wz – Z-body angular velocity (rad/s)

void set_manual_transform(const Transform<double> &transform)
void set_spice_origin(const std::string &spice_origin)

Set the node’s SPICE origin for ephemeris-based transforms.

Parameters:

spice_origin – SPICE origin string

void set_spice_frame(const std::string &spice_frame)

Set the node’s SPICE frame for rotation-based transforms.

Parameters:

spice_frame – SPICE frame string

void set_spice(const std::string &spice_origin, const std::string &spice_frame)

Set both SPICE origin and frame for the node.

Parameters:
  • spice_origin – SPICE origin string

  • spice_frame – SPICE frame string

template<IsPositionCallback TCallback, typename ...Args>
void set_custom_position_callback(Args&&... args)

Place the node by a position callback of a class of one’s own, made from the arguments given.

Its evaluate() gives the node’s position and velocity in its parent’s frame for a pose context (see PositionCallback). It replaces the node’s position source: a position set by hand, a SPICE origin, or another callback.

Template Parameters:

TCallback – A class derived from PositionCallback.

Throws:

std::runtime_error – if a child of the node is placed by SPICE, which places its children only under nodes placed by SPICE.

template<typename TFunction>
void set_position_function(TFunction function)

Place the node by a function of the pose context.

The function is called with a PoseContext, whose time is when the position is wanted, and returns the node’s position in its parent’s frame, in meters: a Vec3<double>, whose velocity is then estimated from nearby times, or a PositionState (position and velocity, in meters per second), or a PositionSample. It is called many times while a scene view is built, at times in any order, and never while it renders. It must give the same answer for the same context.

Throws:

std::runtime_error – if a child of the node is placed by SPICE.

void set_position_table(const std::vector<Time> &times, std::vector<Vec3<double>> positions, std::vector<Vec3<double>> velocities = {})

Place the node by a table of times and positions, with or without velocities, in its parent’s frame (see PositionTableCallback).

Parameters:
  • times – When each entry is: at least two, each later than the one before.

  • positions – The position at each time, in meters.

  • velocities – The velocity at each time, in meters per second, or none (the default) to estimate them from the positions.

Throws:

std::runtime_error – if the table is not valid, or a child of the node is placed by SPICE.

void set_keplerian_orbit(units::Meter semi_major_axis, double eccentricity, units::Radian inclination, units::Radian raan, units::Radian arg_periapsis, units::Radian mean_anomaly, Time epoch, units::CubicKilometersPerSecondSquared mu)

Move the node on a Keplerian orbit about its parent, by CSPICE’s conics_c().

Parameters:
  • semi_major_axis – The semi-major axis: positive for an ellipse (eccentricity under 1), negative for a hyperbola (over 1).

  • eccentricity – Non-negative, and not 1: a parabola has no semi-major axis.

  • inclination, raan, arg_periapsis, mean_anomaly – Angles, finite.

  • epoch – When the body is at mean_anomaly.

  • mu – The central body’s standard gravitational parameter, GM (the Earth’s is 398600.4418_Km3ps2); positive.

Throws:

std::runtime_error – if any element is not finite, or they do not describe an orbit whose periapsis is a positive distance away, about a body of positive mass.

template<IsRotationCallback TCallback, typename ...Args>
void set_custom_rotation_callback(Args&&... args)

Orient the node by a rotation callback of a class of one’s own, made from the arguments given.

Its evaluate() gives the node’s rotation and angular velocity relative to its parent for a pose context and the node’s position (see RotationCallback). It replaces the node’s rotation source: a rotation set by hand, a SPICE frame, or another callback, such as look_at().

Template Parameters:

TCallback – A class derived from RotationCallback.

Throws:

std::runtime_error – if a child of the node is oriented by SPICE, which orients its children only under nodes oriented by SPICE.

template<typename TFunction>
void set_rotation_function(TFunction function)

Orient the node by a function of the pose context.

The function is called with a PoseContext, whose time is when the rotation is wanted, and returns the node’s rotation relative to its parent: a Rotation<double>, whose angular velocity is then estimated from nearby times, or a RotationState (rotation and angular velocity, in radians per second about the parent’s axes), or a RotationSample. It is called many times while a scene view is built, at times in any order, and never while it renders. It must give the same answer for the same context.

Throws:

std::runtime_error – if a child of the node is oriented by SPICE.

void set_rotation_table(const std::vector<Time> &times, std::vector<Rotation<double>> rotations, std::vector<Vec3<double>> angular_velocities = {})

Orient the node by a table of times and rotations, with or without angular velocities, relative to its parent (see RotationTableCallback).

Parameters:
  • times – When each entry is: at least two, each later than the one before.

  • rotations – The rotation at each time, from the node’s frame to its parent’s.

  • angular_velocities – The angular velocity at each time, in radians per second about the parent’s axes, or none (the default) to take the steady rate between entries.

Throws:

std::runtime_error – if the table is not valid, or a child of the node is oriented by SPICE.

void set_z_up_y_forward_callback()
void set_z_down_y_forward_callback()
template<IsTransformCallback TCallback, typename ...Args>
void set_custom_state_callback(Args&&... args)

Place and orient the node by a state callback of a class of one’s own, made from the arguments given.

Its evaluate() gives the node’s whole pose relative to its parent for a pose context (see StateCallback). It replaces both the node’s position source and its rotation source. A position source set afterwards, such as set_position(), replaces only the position, and the callback still gives the rotation; likewise the other way round.

Template Parameters:

TCallback – A class derived from StateCallback.

inline TransformMode get_position_mode() const
inline TransformMode get_rotation_mode() const
Transform<double> get_apparent_transform(ObservationMode obs_mode, const Time &epoch, const Time &t_obs, const Transform<double> &observer_ssb_state) const

Get the apparent transform of the node for a given observation mode and time.

Parameters:
  • obs_mode – Observation mode (true, geometric, aberrated)

  • epoch – Time that the manually set transform corresponds to

  • t_obs – Observation time

  • observer_ssb_state – Observer’s SSB transform

Returns:

Transform<double> Apparent transform

Vec3<double> get_static_position() const
Rotation<double> get_static_rotation() const
Vec3<double> get_static_scale() const
Vec3<double> get_static_velocity() const
Vec3<double> get_static_angular_velocity() const
std::string get_spice_origin() const
std::string get_spice_frame() const
NodeHandle<TSpectral, Node<TSpectral>> get_parent() const

Gets a handle to the parent node.

Returns a base NodeHandle to the parent. This always returns the parent as a base Node type, even if the parent is actually a more specific type like FrameNode.

Throws:

std::runtime_error – If this node has no parent (e.g., root node)

Returns:

NodeHandle<TSpectral, Node<TSpectral>> Handle to the parent node

template<typename TParentNode>
NodeHandle<TSpectral, TParentNode> get_parent_as() const

Gets a handle to the parent node with a specific type.

Returns a handle to the parent cast to the specified node type. This performs a dynamic cast to verify the parent is actually of the requested type at runtime.

Template Parameters:

TParentNode – The expected type of the parent node (e.g., FrameNode<TSpectral>)

Throws:
  • std::runtime_error – If this node has no parent

  • std::runtime_error – If the parent is not of type TParentNode

Returns:

NodeHandle<TSpectral, TParentNode> Handle to the parent with the specified type

inline virtual std::span<const std::shared_ptr<Node<TSpectral>>> get_children() const
inline void set_visible(bool visible = true)

Set whether this node is collected into a SceneView.

Read once, while a SceneView is constructed. An existing SceneView holds its own copy of the collected geometry and its own TLAS, so it is unaffected; construct a new SceneView to render the change.

A hidden node’s descendants are skipped along with it, but their own flags are left alone, so showing this node again restores whatever each descendant was individually set to.

Hiding a light removes its illumination as well as its appearance, and hiding a designated indirect source removes it from next event estimation. Hiding the instance that a SceneView is constructed against does not disable that camera: the observer pose is read from the instance directly rather than through the traversal.

Parameters:

visible – True to collect this node, false to skip it and its descendants.

inline bool is_visible() const

This node’s own flag, which ignores whether an ancestor is hidden.

bool is_effectively_visible() const

True only when this node and every one of its ancestors are visible.

Walk up to the root, checking each node’s visibility flag.

Returns:

bool True only if this node and every ancestor are visible

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

Protected Functions

void check_scale_(const Vec3<double> &scale) const

Throws unless each component of a scale is finite, and so is its inverse, which the inverse transform takes: 0 would flatten the node.

bool position_can_be_spice_() const
inline virtual bool position_must_be_spice_() const
bool rotation_can_be_spice_() const
inline virtual bool rotation_must_be_spice_() const
inline void set_parent_(Node<TSpectral> *parent)
std::pair<const Node<TSpectral>*, Transform<double>> find_spice_origin_ancestor_() const

Find the first ancestor (including self) with a SPICE origin.

Throws:

std::runtime_error – if no SPICE origin found in ancestry

Returns:

Pair of (ancestor node, accumulated transform from this to ancestor)

std::pair<const Node<TSpectral>*, std::pair<Rotation<double>, Vec3<double>>> find_spice_frame_ancestor_() const

Find the first ancestor (including self) with a SPICE frame.

Throws:

std::runtime_error – if no SPICE frame found in ancestry

Returns:

Pair of (ancestor node, accumulated rotation from this to ancestor)

std::pair<Transform<double>, double> get_geometric_state_(const PoseContext &context, const Transform<double> &observer_ssb_state, double tol = 1e-12) const

Get the geometric state (transform and light time) of the node.

Parameters:
  • context – The observation time, the time poses set by hand hold at, and the observation mode: light time is solved for unless it is TRUE_STATE

  • observer_ssb_state – Observer’s SSB transform

  • tol – Tolerance for iteration

Returns:

std::pair<Transform<double>, double> {transform, light time}

Transform<double> get_ssb_transform_(const PoseContext &context, double dt = 0.0) const

Get the node’s transform in the Solar System Barycenter (SSB) frame.

Parameters:
  • context – The observation time, the time poses set by hand hold at, and the observation mode, which callbacks are given (at the emission time)

  • dt – Light time delay

Returns:

Transform<double> SSB transform

Transform<double> get_local_position_at_(const Time &epoch, const Time &t_obs, double dt) const

Get the node’s local position transform at a given time.

Parameters:
  • epoch – Time that the manually set transform corresponds to

  • t_obs – Observation time

  • dt – Light time delay

Returns:

Transform<double> Local position transform

Transform<double> get_local_rotation_at_(const Time &epoch, const Time &t_obs, double dt) const

Get the node’s local rotation transform at a given time.

Parameters:
  • epoch – Time that the manually set transform corresponds to

  • t_obs – Observation time

  • dt – Light time delay

Returns:

Transform<double> Local rotation transform

Protected Attributes

Transform<double> local_transform_
bool body_frame_rates_ = false

When true, local_transform_.angular_velocity was supplied via set_body_angular_velocity() and is expressed in the node’s own body axes; orientation propagates as q(t) = q_0 * delta. When false (the default), the rates are expressed in the parent frame’s axes and orientation propagates as q(t) = delta * q_0. Note that get_local_rotation_at_() always re-expresses the angular velocity in parent axes before storing it in the returned Transform (the frame Transform::operator* expects).

bool visible_ = true
TransformMode position_mode_ = TransformMode::MANUAL_TRANSFORM
TransformMode rotation_mode_ = TransformMode::MANUAL_TRANSFORM
std::string spice_origin_ = ""
std::string spice_frame_ = ""
std::unique_ptr<PositionCallback> position_callback_
std::unique_ptr<RotationCallback> rotation_callback_
std::unique_ptr<StateCallback> transform_callback_
Scene<TSpectral> *scene_
Node<TSpectral> *parent_ = nullptr