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

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

Parameters:
  • target – Target node to look at

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

void look_at(const Vec3<double> &target_position, const Vec3<double> &up = {0.0, 0.0, 1.0})

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

Parameters:
  • target_position – Target position to look at

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

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:

rotationRotation object

void set_scale(const Vec3<double> &scale)

Set the node’s scale.

Parameters:

scale – Scale vector

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

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)
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, double mu)
template<IsRotationCallback TCallback, typename ...Args>
void set_custom_rotation_callback(Args&&... args)
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)
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)

  • epochTime 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
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.

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.

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

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

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

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 Time &epoch, const Time &t_obs, const Transform<double> &observer_ssb_state, bool iterate, double tol = 1e-12) const

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

Parameters:
  • epochTime that the manually set transform corresponds to

  • t_obs – Observation time

  • observer_ssb_state – Observer’s SSB transform

  • iterate – Whether to iterate for aberration

  • tol – Tolerance for iteration

Returns:

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

Transform<double> get_ssb_transform_(const Time &epoch, const Time &t_obs, double dt = 0.0) const

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

Parameters:
  • epochTime that the manually set transform corresponds to

  • t_obs – Observation time

  • dtLight 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:
  • epochTime that the manually set transform corresponds to

  • t_obs – Observation time

  • dtLight 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:
  • epochTime that the manually set transform corresponds to

  • t_obs – Observation time

  • dtLight 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