Struct Hierarchy

Source
pub struct Hierarchy;
Expand description

This class represents a stack of transform matrices that build up a transform hierarchy! This can be used like an object-less parent-child system, where you push a parent’s transform onto the stack, render child objects relative to that parent transform and then pop it off the stack.

Performance note: if any matrices are on the hierarchy stack, any render will cause a matrix multiplication to occur! So if you have a collection of objects with their transforms baked and cached into matrices for performance reasons, you’ll want to ensure there are no matrices in the hierarchy stack, or that the hierarchy is disabled! It’ll save you a matrix multiplication in that case :) https://stereokit.net/Pages/StereoKit/Hierarchy.html

§Examples

use stereokit_rust::{maths::Matrix, system::{Hierarchy, HierarchyParent}, mesh::Mesh,
                     material::Material, util::named_colors};

let sphere = Mesh::generate_sphere(0.2, None);
let material = Material::pbr();
let transform = Matrix::t([0.4, 0.4, 0.4]);

filename_scr = "screenshots/hierarchy.jpeg";
test_screenshot!( // !!!! Get a proper main loop !!!!
    sphere.draw(token, &material, transform, None, None);

    assert!(Hierarchy::is_enabled(&token));

    Hierarchy::push(token, Matrix::t([0.0, -0.5, -0.5]), None);
    sphere.draw(token, &material, transform, Some(named_colors::RED.into()), None);
    assert_eq!(Hierarchy::to_local_point(&token, [0.4, 0.4, 0.4]), [0.4, 0.9, 0.9].into());
    assert_eq!(Hierarchy::to_world_point(&token, [0.4, 0.9, 0.9]), [0.4, 0.4, 0.4].into());
    Hierarchy::pop(token);

    Hierarchy::push(token, Matrix::t([-0.5, -0.5, 0.25]), Some(HierarchyParent::Ignore));
    sphere.draw(token, &material, transform, Some(named_colors::GREEN.into()), None);
    assert_eq!(Hierarchy::to_local_point(&token, [0.4, 0.4, 0.4]), [0.9, 0.9, 0.15].into());
    assert_eq!(Hierarchy::to_world_point(&token, [0.9, 0.9, 0.15]), [0.4, 0.4, 0.4].into());

    Hierarchy::enabled(token, false);
    sphere.draw(token, &material, Matrix::IDENTITY, Some(named_colors::BLUE.into()), None);
    assert_eq!(Hierarchy::to_local_point(&token, [0.4, 0.4, 0.4]), [0.4, 0.4, 0.4].into());
    Hierarchy::enabled(token, true);
    Hierarchy::pop(&token);
);
screenshot

Implementations§

Source§

impl Hierarchy

Source

pub fn enabled(_token: &MainThreadToken, enable: bool)

This is enabled by default. Disabling this will cause any draw call to ignore any Matrices that are on the Hierarchy stack. https://stereokit.net/Pages/StereoKit/Hierarchy/Enabled.html

see also hierarchy_set_enabled Hierarchy::is_enabled

Source

pub fn is_enabled(_token: &MainThreadToken) -> bool

This is enabled by default. Disabling this will cause any draw call to ignore any Matrices that are on the Hierarchy stack. https://stereokit.net/Pages/StereoKit/Hierarchy/Enabled.html

see also hierarchy_is_enabled Hierarchy::enabled

Source

pub fn pop(_token: &MainThreadToken)

Source

pub fn push<M: Into<Matrix>>( _token: &MainThreadToken, transform: M, parent_behavior: Option<HierarchyParent>, )

Pushes a transform Matrix (eventually a Pose) onto the stack, and combines it with the Matrix below it. Any draw operation’s Matrix will now be combined with this Matrix to make it relative to the current hierarchy. Use Hierarchy.pop to remove it from the Hierarchy stack! All Push calls must have an accompanying Pop call. https://stereokit.net/Pages/StereoKit/Hierarchy/Push.html

  • parent_behavior - This determines how this matrix combines with the parent matrix below it. Normal behavior is to “inherit” the parent matrix, but there are cases where you may wish to entirely ignore the parent transform. For example, if you’re in UI space, and wish to do some world space rendering. If None, has default value “Inherit”

see also hierarchy_push Hierarchy::pop

§Examples
use stereokit_rust::{maths::Matrix, system::{Hierarchy, HierarchyParent}};

test_steps! { // !!!! Get a proper main loop !!!!
    Hierarchy::push(token, Matrix::t([0.0, -0.5, -0.5]), None);
    assert_eq!(Hierarchy::to_local_point(token, [0.4, 0.4, 0.4]), [0.4, 0.9, 0.9].into());
    assert_eq!(Hierarchy::to_world_point(token, [0.4, 0.9, 0.9]), [0.4, 0.4, 0.4].into());
    Hierarchy::pop(token);
}
Source

pub fn to_local_point<V: Into<Vec3>>( _token: &MainThreadToken, world_point: V, ) -> Vec3

Converts a world space point into the local space of the current Hierarchy stack! https://stereokit.net/Pages/StereoKit/Hierarchy/ToLocal.html

  • world_point - A point in world space.

Returns the provided point now in local hierarchy space see also hierarchy_to_local_point Hierarchy::to_world_point

§Examples
use stereokit_rust::{maths::Pose, system::{Hierarchy, HierarchyParent}};

test_steps! { // !!!! Get a proper main loop !!!!
    Hierarchy::push(token, Pose::new([0.0, -0.5, -0.5], None), None);
    assert_eq!(Hierarchy::to_local_point(token, [0.4, 0.4, 0.4]), [0.4, 0.9, 0.9].into());
    assert_eq!(Hierarchy::to_world_point(token, [0.4, 0.9, 0.9]), [0.4, 0.4, 0.4].into());
    Hierarchy::pop(token);
}
Source

pub fn to_local_rotation<Q: Into<Quat>>( _token: &MainThreadToken, world_orientation: Q, ) -> Quat

Converts a world space rotation into the local space of the current Hierarchy stack! https://stereokit.net/Pages/StereoKit/Hierarchy/ToLocal.html

  • world_orientation - A rotation in world space

Returns the provided rotation now in local hierarchy space see also hierarchy_to_local_rotation Hierarchy::to_world_rotation

§Examples
use stereokit_rust::{maths::{Matrix, Quat, Vec3}, system::{Hierarchy, HierarchyParent}};

test_steps! { // !!!! Get a proper main loop !!!!
    Hierarchy::push(token, Matrix::r([0.0, 0.0, 180.0]), None);
    let local: Vec3 = Hierarchy::to_local_rotation(token, [90.0, 180.0, 0.0])
                          .to_angles_degrees().into();
    assert_eq!(local, [-90.0, 0.0, 0.0].into());

    let world: Vec3 = Hierarchy::to_world_rotation(token, [90.0, 180.0, 0.0])
                          .to_angles_degrees().into();
    assert_eq!(world, [-90.0, 0.0, 0.0].into());
    Hierarchy::pop(token);
}
Source

pub fn to_local_pose<P: Into<Pose>>( _token: &MainThreadToken, world_pose: P, ) -> Pose

Converts a world pose relative to the current hierarchy stack into local space! https://stereokit.net/Pages/StereoKit/Hierarchy/ToLocal.html

  • world_pose - A pose in world space.

Returns the provided pose now in local hierarchy space! see also hierarchy_to_local_pose Hierarchy::to_local_pose

§Examples
use stereokit_rust::{maths::{Matrix, Quat, Pose}, system::{Hierarchy, HierarchyParent}};

test_steps! { // !!!! Get a proper main loop !!!!
    Hierarchy::push(token, Matrix::t([0.0, -0.5, -0.5]), None);
    let pose = Pose::new([10.0, 20.0, 30.0], None);
    assert_eq!(Hierarchy::to_local_pose(token, pose), Pose::new([10.0, 20.5, 30.5], None));
    assert_eq!(Hierarchy::to_world_pose(token, Pose::new([10.0, 20.5, 30.5], None)), pose);
    Hierarchy::pop(token);
}
Source

pub fn to_local_ray<R: Into<Ray>>(_token: &MainThreadToken, world_ray: R) -> Ray

Converts a world ray relative to the current hierarchy stack into local space! https://stereokit.net/Pages/StereoKit/Hierarchy/ToLocal.html

  • world_ray - A ray in world space

Returns the provided ray now in local hierarchy space see also hierarchy_to_local_ray Hierarchy::to_world_ray

§Examples
use stereokit_rust::{maths::{Vec3, Matrix, Quat, Ray}, system::{Lines, Hierarchy},
    util::{named_colors}, mesh::Mesh, material::{Material, Cull}};

// Create Meshes
let cube = Mesh::generate_cube(Vec3::ONE * 0.8, None);
let sphere = Mesh::generate_sphere(1.0, Some(4));

let material = Material::pbr().copy();
let transform = Matrix::r(Quat::from_angles(40.0, 50.0, 20.0));
let inv = transform.get_inverse();

let ray = Ray::new([1.0, 2.0, 2.5 ], [-1.0, -2.0, -2.25]);

filename_scr = "screenshots/hierarchy_ray.jpeg";
test_screenshot!( // !!!! Get a proper main loop !!!!
    let world_space_ray = Hierarchy::to_world_ray(token, ray);
    assert_eq!(world_space_ray, ray);
    Lines::add_ray(token, world_space_ray, 2.2, named_colors::WHITE, None, 0.02);

    Hierarchy::push(token, transform, None);
    let local_transform = Matrix::t([-0.1, 0.1, 0.1]);
    cube.draw(token, &material, local_transform, Some(named_colors::MAGENTA.into()), None);

    let local_space_ray = Hierarchy::to_local_ray(token, world_space_ray);
    let mesh_space_ray = local_transform.get_inverse().transform_ray(local_space_ray);
    let (contact_cube, ind_cube) = cube.intersect( mesh_space_ray, Some(Cull::Back))
                                       .expect("Ray should touch cube");
    assert_eq!(ind_cube, 15);

    let local_contact_cube = local_transform.transform_point(contact_cube);
    let transform_contact = Matrix::t_s(local_contact_cube, Vec3::ONE * 0.1);
    sphere.draw(token, &material, transform_contact, Some(named_colors::YELLOW.into()), None );
    Hierarchy::pop(token);
);
screenshot
Source

pub fn to_local_direction<V: Into<Vec3>>( _token: &MainThreadToken, world_direction: V, ) -> Vec3

Converts a world space direction into the local space of the current Hierarchy stack! This excludes the translation component normally applied to vectors, so it’s still a valid direction. https://stereokit.net/Pages/StereoKit/Hierarchy/ToLocalDirection.html

  • world_direction - A direction in world space

Returns the provided direction now in local hierarchy space see also hierarchy_to_local_direction Hierarchy::to_world_direction

§Examples
use stereokit_rust::{maths::{Matrix, Vec3}, system::{Hierarchy, HierarchyParent}};

test_steps! { // !!!! Get a proper main loop !!!!
    Hierarchy::push(token, Matrix::r([0.0, 0.0, 180.0]), None);
    assert_eq!(Hierarchy::to_local_direction(token, [1.0, 0.0, 0.0]), [-1.0, 0.0, 0.0].into());
    assert_eq!(Hierarchy::to_world_direction(token, [-1.0, 0.0, 0.0]), [1.0, 0.0, 0.0].into());
    Hierarchy::pop(token);
}

see also hierarchy_to_local_direction hierarchy_to_world_direction

Source

pub fn to_world_point<V: Into<Vec3>>( _token: &MainThreadToken, local_point: V, ) -> Vec3

Converts a local point relative to the current hierarchy stack into world space! https://stereokit.net/Pages/StereoKit/Hierarchy/ToWorld.html

  • local_point - A point in local space

Returns the provided point now in world space

see also hierarchy_to_world_point see example in Hierarchy::to_local_point

Source

pub fn to_world_rotation<Q: Into<Quat>>( _token: &MainThreadToken, local_orientation: Q, ) -> Quat

Converts a local rotation relative to the current hierarchy stack into world space! https://stereokit.net/Pages/StereoKit/Hierarchy/ToWorld.html

  • local_orientaion - A rotation in local space

Returns the provided rotation now in world space

see also hierarchy_to_world_rotation see example in Hierarchy::to_local_rotation

Source

pub fn to_world_pose<P: Into<Pose>>( _token: &MainThreadToken, local_pose: P, ) -> Pose

Converts a local pose relative to the current hierarchy stack into world space! https://stereokit.net/Pages/StereoKit/Hierarchy/ToWorld.html

  • local_pose - A pose in local space

Returns the provided pose now in world space

see also hierarchy_to_world_pose see example in Hierarchy::to_local_pose

Source

pub fn to_world_ray<P: Into<Ray>>(_token: &MainThreadToken, local_ray: P) -> Ray

Converts a local ray relative to the current hierarchy stack into world space! https://stereokit.net/Pages/StereoKit/Hierarchy/ToWorld.html

  • local_ray - A ray in local space

Returns the provided ray now in world space

see also hierarchy_to_world_ray see example in Hierarchy::to_local_ray

Source

pub fn to_world_direction<V: Into<Vec3>>( _token: &MainThreadToken, local_direction: V, ) -> Vec3

Converts a local direction relative to the current hierarchy stack into world space! This excludes the translation component normally applied to vectors, so it’s still a valid direction. https://stereokit.net/Pages/StereoKit/Hierarchy/ToWorldDirection.html

  • local_direction - A direction in local space

Returns the provided direction now in world space

see also hierarchy_to_world_direction see example in Hierarchy::to_local_direction

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more