Struct pasture_core::layout::PointLayout [−][src]
Describes the data layout of a single point in a point cloud
Detailed explanation
To understand PointLayout
, it is necessary to understand the memory model of Pasture. Pasture is a library
for handling point cloud data, so the first thing worth understanding is what ‘point cloud data’ means in the context
of Pasture:
A point cloud in Pasture is modeled as a collection of tuples of attributes (a_1, a_2, …, a_n). An
attribute can be any datum associated with a point, such as its position in 3D space, an intensity value, an object
classification etc. The set of all unique attributes in a point cloud make up the point clouds point layout, which
is represented in Pasture by the PointLayout
type. The Pasture memory model describes how the attributes for each
point in a point cloud are layed out in memory. There are two major memory layouts supported by Pasture: Interleaved
and PerAttribute. In an Interleaved layout, all attributes for a single point are stored together in memory:
[a_1(p_1), a_2(p_1), …, a_n(p_1), a_1(p_2), a_2(p_2), …, a_n(p_2), …]
This layout is equivalent to storing a type T
inside a Vec
, where T
has members a_1, a_2, …, a_n and is packed
tightly.
In a PerAttribute layout, all attributes of a single type are stored together in memory, often in separate memory regions:
[a_1(p_1), a_1(p_2), …, a_1(p_n)] [a_2(p_1), a_2(p_2), …, a_2(p_n)] … [a_n(p_1), a_n(p_2), …, a_n(p_n)]
These layouts are sometimes called ‘Array of Structs’ (Interleaved) and ‘Struct of Arrays’ (PerAttribute).
Most code in Pasture supports point clouds with either of these memory layouts. To correctly handle memory layout and access
in both Interleaved and PerAttribute layout, each buffer in Pasture that stores point cloud data requires a piece of metadata
that describes the attributes of the point cloud with their respective Rust types, their order, their memory alignment
and their potential offset within a single point entry in Interleaved format. All this information is stored inside the PointLayout
structure.
To support the different memory layouts, Pasture buffers store point data as raw binary buffers internally. To work with the data,
you will want to use strongly typed Rust structures. Any type T
that you want to use for accessing point data in a strongly typed manner
must implement the PointType
trait and thus provide Pasture with a way of figuring out the attributes and memory layout of this type T
.
Implementations
impl PointLayout
[src]
pub fn from_attributes(attributes: &[PointAttributeDefinition]) -> Self
[src]
Creates a new PointLayout from the given sequence of attributes. The attributes will be aligned using the
default alignments for their respective datatypes, in accordance with the Rust alignment rules for repr(C)
structs
#Panics
If any two attributes within the sequence share the same attribute name.
let layout = PointLayout::from_attributes(&[attributes::POSITION_3D, attributes::INTENSITY]);
pub fn from_attributes_packed(
attributes: &[PointAttributeDefinition],
max_alignment: u64
) -> Self
[src]
attributes: &[PointAttributeDefinition],
max_alignment: u64
) -> Self
Creates a new PointLayout from the given sequence of attributes. The attributes will be aligned to a 1 byte boundary
in accordance with the Rust alignment rules for repr(packed)
structs
#Panics
If any two attributes within the sequence share the same attribute name.
// Default INTENSITY attribute uses u16 datatype. In a packed(1) struct, the next field will have offset 2 // even though the POSITION_3D attribute has an alignment requirement of 8 let layout_packed_1 = PointLayout::from_attributes_packed(&[attributes::INTENSITY, attributes::POSITION_3D], 1); assert_eq!(0, layout_packed_1.at(0).offset()); assert_eq!(2, layout_packed_1.at(1).offset()); // If we use packed(4), POSITION_3D will start at byte 4: let layout_packed_4 = PointLayout::from_attributes_packed(&[attributes::INTENSITY, attributes::POSITION_3D], 4); assert_eq!(4, layout_packed_4.at(1).offset());
pub fn from_members_and_alignment(
attributes: &[PointAttributeMember],
type_alignment: u64
) -> Self
[src]
attributes: &[PointAttributeMember],
type_alignment: u64
) -> Self
Creates a new PointLayout from the given PointAttributeMember
sequence as well as the given type_alignment
.
#Panics
If any two attributes within the sequence share the same attribute name, or if there is overlap between any two attributes based on their sizes and offsets.
let layout = PointLayout::from_members_and_alignment(&[attributes::INTENSITY.at_offset_in_type(2), attributes::POSITION_3D.at_offset_in_type(8)], 8); assert_eq!(2, layout.at(0).offset()); assert_eq!(8, layout.at(1).offset()); assert_eq!(32, layout.size_of_point_entry());
pub fn add_attribute(
&mut self,
point_attribute: PointAttributeDefinition,
field_alignment: FieldAlignment
)
[src]
&mut self,
point_attribute: PointAttributeDefinition,
field_alignment: FieldAlignment
)
Adds the given PointAttributeDefinition to this PointLayout. Sets the offset of the new attribute
within the PointLayout
based on the given FieldAlignment
#Panics
If an attribute with the same name is already part of this PointLayout.
let mut layout = PointLayout::default(); layout.add_attribute(attributes::INTENSITY, FieldAlignment::Default); layout.add_attribute(attributes::POSITION_3D, FieldAlignment::Default); // Default field alignment respects the 8-byte alignment requirement of default POSITION_3D (Vector3<f64>), even though default INTENSITY takes only 2 bytes assert_eq!(8, layout.at(1).offset());
pub fn has_attribute_with_name(&self, attribute_name: &str) -> bool
[src]
Returns true if an attribute with the given name is part of this PointLayout.
let mut layout = PointLayout::default(); layout.add_attribute(attributes::POSITION_3D, FieldAlignment::Default); assert!(layout.has_attribute_with_name(attributes::POSITION_3D.name()));
pub fn has_attribute(&self, attribute: &PointAttributeDefinition) -> bool
[src]
Returns true
if the associated PointLayout
contains the given attribute
. Both the name of attribute
as well as
its datatype must match for this method to return true
. This is a more strict form of has_attribute_with_name
Example
let mut layout = PointLayout::default(); layout.add_attribute(attributes::POSITION_3D, FieldAlignment::Default); assert!(layout.has_attribute(&attributes::POSITION_3D)); layout.add_attribute(attributes::INTENSITY.with_custom_datatype(PointAttributeDataType::U32), FieldAlignment::Default); assert!(!layout.has_attribute(&attributes::INTENSITY));
pub fn get_attribute(
&self,
attribute: &PointAttributeDefinition
) -> Option<&PointAttributeMember>
[src]
&self,
attribute: &PointAttributeDefinition
) -> Option<&PointAttributeMember>
Returns the attribute that matches the given attribute
in name and datatype from the associated PointLayout
. Returns None
if
no attribute with the same name and datatype exists
let mut layout = PointLayout::default(); layout.add_attribute(attributes::POSITION_3D, FieldAlignment::Default); let attribute = layout.get_attribute(&attributes::POSITION_3D); assert!(attribute.is_some()); let invalid_attribute = layout.get_attribute(&attributes::POSITION_3D.with_custom_datatype(PointAttributeDataType::U32)); assert!(invalid_attribute.is_none());
pub fn get_attribute_by_name(
&self,
attribute_name: &str
) -> Option<&PointAttributeMember>
[src]
&self,
attribute_name: &str
) -> Option<&PointAttributeMember>
Returns the attribute with the given name from this PointLayout. Returns None if no such attribute exists.
let mut layout = PointLayout::default(); layout.add_attribute(attributes::POSITION_3D, FieldAlignment::Default); let attribute = layout.get_attribute_by_name(attributes::POSITION_3D.name()); assert_eq!(attributes::POSITION_3D.at_offset_in_type(0), *attribute.unwrap());
pub fn at(&self, index: usize) -> &PointAttributeMember
[src]
Returns the attribute at the given index from the associated PointLayout
Panics
If index
is out of bounds
pub fn attributes<'a>(
&'a self
) -> impl Iterator<Item = &'a PointAttributeMember> + 'a
[src]
&'a self
) -> impl Iterator<Item = &'a PointAttributeMember> + 'a
Returns an iterator over all attributes in this PointLayout
. The attributes are returned in the order
in which they were added to this PointLayout
:
let mut layout = PointLayout::default(); layout.add_attribute(attributes::POSITION_3D, FieldAlignment::Default); layout.add_attribute(attributes::INTENSITY, FieldAlignment::Default); let attributes = layout.attributes().collect::<Vec<_>>(); assert_eq!(attributes::POSITION_3D.at_offset_in_type(0), *attributes[0]); assert_eq!(attributes::INTENSITY.at_offset_in_type(24), *attributes[1]);
pub fn size_of_point_entry(&self) -> u64
[src]
Returns the size in bytes of a single point entry with the associated PointLayout
. Note that the size can be
larger than the sum of the sizes of all attributes because of alignment requirements!
Example
let layout = PointLayout::from_attributes(&[attributes::POSITION_3D, attributes::INTENSITY]); // from_attributes respects the alignment requirements of each attribute. Default POSITION_3D uses Vector3<f64> and as such // has an 8-byte minimum alignment, so the whole PointLayout is aligned to an 8-byte boundary. This is reflected in its size: assert_eq!(32, layout.size_of_point_entry());
pub fn index_of(&self, attribute: &PointAttributeDefinition) -> Option<usize>
[src]
Returns the index of the given attribute within the associated PointLayout
, or None
if the attribute is not
part of the PointLayout
. The index depends on the order in which the attributes have been added to the associated
PointLayout
, but does not necessarily reflect the order of the attributes in memory.
Example
let layout = PointLayout::from_attributes(&[attributes::POSITION_3D, attributes::INTENSITY]); assert_eq!(Some(0), layout.index_of(&attributes::POSITION_3D)); assert_eq!(Some(1), layout.index_of(&attributes::INTENSITY)); // Create a layout where we add INTENSITY as first attribute, however in memory, INTENSITY comes after POSITION_3D let reordered_layout = PointLayout::from_members_and_alignment(&[attributes::INTENSITY.at_offset_in_type(24), attributes::POSITION_3D.at_offset_in_type(0)], 8); assert_eq!(Some(0), reordered_layout.index_of(&attributes::INTENSITY)); assert_eq!(Some(1), reordered_layout.index_of(&attributes::POSITION_3D));
pub fn compare_without_offsets(&self, other: &PointLayout) -> bool
[src]
Compares the associated PointLayout
with the other
layout, ignoring the attribute offsets. This way, only the names and datatypes
of the attributes are compared. This method is useful when dealing with data in a non-interleaved format, where offsets are irrelevant
Trait Implementations
impl Clone for PointLayout
[src]
fn clone(&self) -> PointLayout
[src]
pub fn clone_from(&mut self, source: &Self)
1.0.0[src]
impl Debug for PointLayout
[src]
impl Default for PointLayout
[src]
impl Display for PointLayout
[src]
impl PartialEq<PointLayout> for PointLayout
[src]
fn eq(&self, other: &PointLayout) -> bool
[src]
fn ne(&self, other: &PointLayout) -> bool
[src]
impl StructuralPartialEq for PointLayout
[src]
Auto Trait Implementations
impl RefUnwindSafe for PointLayout
impl Send for PointLayout
impl Sync for PointLayout
impl Unpin for PointLayout
impl UnwindSafe for PointLayout
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
pub fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T> Pointable for T
pub const ALIGN: usize
type Init = T
The type for initializers.
pub unsafe fn init(init: <T as Pointable>::Init) -> usize
pub unsafe fn deref<'a>(ptr: usize) -> &'a T
pub unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T
pub unsafe fn drop(ptr: usize)
impl<T> Same<T> for T
type Output = T
Should always be Self
impl<SS, SP> SupersetOf<SS> for SP where
SS: SubsetOf<SP>,
SS: SubsetOf<SP>,
pub fn to_subset(&self) -> Option<SS>
pub fn is_in_subset(&self) -> bool
pub fn to_subset_unchecked(&self) -> SS
pub fn from_subset(element: &SS) -> SP
impl<T> ToOwned for T where
T: Clone,
[src]
T: Clone,
type Owned = T
The resulting type after obtaining ownership.
pub fn to_owned(&self) -> T
[src]
pub fn clone_into(&self, target: &mut T)
[src]
impl<T> ToString for T where
T: Display + ?Sized,
[src]
T: Display + ?Sized,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
The type returned in the event of a conversion error.
pub fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>
[src]
impl<V, T> VZip<V> for T where
V: MultiLane<T>,
V: MultiLane<T>,