diff --git a/CMakeLists.txt b/CMakeLists.txt index 93af9a50cca1..6d8383144df5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,9 @@ function(rerun_strict_warning_settings target) # CMAKE_COMPILE_WARNING_AS_ERROR is only directly supported starting in CMake `3.24` # https://cmake.org/cmake/help/latest/prop_tgt/COMPILE_WARNING_AS_ERROR.html if(CMAKE_COMPILE_WARNING_AS_ERROR) - target_compile_options(${target} PRIVATE /WX) + target_compile_options(${target} PRIVATE /WX + /w15038 # Initialization order. https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/c5038 + ) endif() if(RERUN_USE_ASAN) diff --git a/crates/store/re_types/definitions/rerun/archetypes/transform3d.fbs b/crates/store/re_types/definitions/rerun/archetypes/transform3d.fbs index d63ad42a2657..d6589c24c340 100644 --- a/crates/store/re_types/definitions/rerun/archetypes/transform3d.fbs +++ b/crates/store/re_types/definitions/rerun/archetypes/transform3d.fbs @@ -8,9 +8,9 @@ namespace rerun.archetypes; /// A transform between two 3D spaces, i.e. a pose. /// -/// All components are applied in the order they are listed here. +/// All components are applied in the inverse order they are listed here. /// E.g. if both a 4x4 matrix with a translation and a translation vector are present, -/// the matrix is applied first, then the translation vector on top. +/// the translation is applied first, followed by the matrix. /// /// Each transform component can be listed multiple times, but transform tree propagation is only possible /// if there's only one instance for each transform component. @@ -21,6 +21,7 @@ namespace rerun.archetypes; // TODO(#6831): provide example with out of tree transform. table Transform3D ( "attr.rust.derive": "Default, PartialEq", + "attr.rust.generate_field_info", "attr.docs.category": "Spatial 3D", "attr.docs.view_types": "Spatial3DView, Spatial2DView: if logged above active projection" ) { @@ -28,11 +29,14 @@ table Transform3D ( // TODO(#6831): remove. transform: rerun.components.Transform3D ("attr.rerun.component_optional", order: 1000); - /// 3x3 transformation matrices. - mat3x3: [rerun.components.TransformMat3x3] ("attr.rerun.component_optional", nullable, order: 1100); - /// Translation vectors. - translation: [rerun.components.Translation3D] ("attr.rerun.component_optional", nullable, order: 1200); + translation: [rerun.components.Translation3D] ("attr.rerun.component_optional", nullable, order: 1100); + + /// Scaling factor. + scale: [rerun.components.Scale3D] ("attr.rerun.component_optional", nullable, order: 1200); + + /// 3x3 transformation matrices. + mat3x3: [rerun.components.TransformMat3x3] ("attr.rerun.component_optional", nullable, order: 1300); // --- visual representation diff --git a/crates/store/re_types/definitions/rerun/components.fbs b/crates/store/re_types/definitions/rerun/components.fbs index 35e30c3971f3..fd820f0edc46 100644 --- a/crates/store/re_types/definitions/rerun/components.fbs +++ b/crates/store/re_types/definitions/rerun/components.fbs @@ -33,6 +33,7 @@ include "./components/range1d.fbs"; include "./components/resolution.fbs"; include "./components/rotation3d.fbs"; include "./components/scalar.fbs"; +include "./components/scale3d.fbs"; include "./components/stroke_width.fbs"; include "./components/tensor_data.fbs"; include "./components/tensor_dimension_selection.fbs"; diff --git a/crates/store/re_types/definitions/rerun/components/scale3d.fbs b/crates/store/re_types/definitions/rerun/components/scale3d.fbs new file mode 100644 index 000000000000..43acd0905fff --- /dev/null +++ b/crates/store/re_types/definitions/rerun/components/scale3d.fbs @@ -0,0 +1,14 @@ +namespace rerun.components; + +/// A 3D scale factor. +/// +/// A scale of 1.0 means no scaling. +/// A scale of 2.0 means doubling the size. +/// Each component scales along the corresponding axis. +struct Scale3D ( + "attr.docs.unreleased", + "attr.rust.derive": "Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable", + "attr.rust.repr": "transparent" +) { + scale: rerun.datatypes.Vec3D (order: 100); +} diff --git a/crates/store/re_types/definitions/rerun/datatypes/mat3x3.fbs b/crates/store/re_types/definitions/rerun/datatypes/mat3x3.fbs index 72e5a7ffd881..f0b811b5a85d 100644 --- a/crates/store/re_types/definitions/rerun/datatypes/mat3x3.fbs +++ b/crates/store/re_types/definitions/rerun/datatypes/mat3x3.fbs @@ -43,6 +43,7 @@ namespace rerun.datatypes; struct Mat3x3 ( "attr.arrow.transparent", "attr.python.aliases": "npt.ArrayLike", + "attr.python.array_aliases": "npt.ArrayLike", "attr.rust.derive": "Copy, PartialEq, PartialOrd, bytemuck::Pod, bytemuck::Zeroable", "attr.rust.repr": "transparent", "attr.rust.tuple_struct" diff --git a/crates/store/re_types/src/archetypes/transform3d.rs b/crates/store/re_types/src/archetypes/transform3d.rs index 0c0837394ce3..c5efc6629fa9 100644 --- a/crates/store/re_types/src/archetypes/transform3d.rs +++ b/crates/store/re_types/src/archetypes/transform3d.rs @@ -20,9 +20,9 @@ use ::re_types_core::{DeserializationError, DeserializationResult}; /// **Archetype**: A transform between two 3D spaces, i.e. a pose. /// -/// All components are applied in the order they are listed here. +/// All components are applied in the inverse order they are listed here. /// E.g. if both a 4x4 matrix with a translation and a translation vector are present, -/// the matrix is applied first, then the translation vector on top. +/// the translation is applied first, followed by the matrix. /// /// Each transform component can be listed multiple times, but transform tree propagation is only possible /// if there's only one instance for each transform component. @@ -168,12 +168,15 @@ pub struct Transform3D { /// The transform pub transform: crate::components::Transform3D, - /// 3x3 transformation matrices. - pub mat3x3: Option>, - /// Translation vectors. pub translation: Option>, + /// Scaling factor. + pub scale: Option>, + + /// 3x3 transformation matrices. + pub mat3x3: Option>, + /// Visual length of the 3 axes. /// /// The length is interpreted in the local coordinate system of the transform. @@ -185,16 +188,18 @@ impl ::re_types_core::SizeBytes for Transform3D { #[inline] fn heap_size_bytes(&self) -> u64 { self.transform.heap_size_bytes() - + self.mat3x3.heap_size_bytes() + self.translation.heap_size_bytes() + + self.scale.heap_size_bytes() + + self.mat3x3.heap_size_bytes() + self.axis_length.heap_size_bytes() } #[inline] fn is_pod() -> bool { ::is_pod() - && >>::is_pod() && >>::is_pod() + && >>::is_pod() + && >>::is_pod() && >::is_pod() } } @@ -205,30 +210,32 @@ static REQUIRED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 0usize]> = static RECOMMENDED_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 1usize]> = once_cell::sync::Lazy::new(|| ["rerun.components.Transform3DIndicator".into()]); -static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 4usize]> = +static OPTIONAL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 5usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.Transform3D".into(), - "rerun.components.TransformMat3x3".into(), "rerun.components.Translation3D".into(), + "rerun.components.Scale3D".into(), + "rerun.components.TransformMat3x3".into(), "rerun.components.AxisLength".into(), ] }); -static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 5usize]> = +static ALL_COMPONENTS: once_cell::sync::Lazy<[ComponentName; 6usize]> = once_cell::sync::Lazy::new(|| { [ "rerun.components.Transform3DIndicator".into(), "rerun.components.Transform3D".into(), - "rerun.components.TransformMat3x3".into(), "rerun.components.Translation3D".into(), + "rerun.components.Scale3D".into(), + "rerun.components.TransformMat3x3".into(), "rerun.components.AxisLength".into(), ] }); impl Transform3D { - /// The total number of components in the archetype: 0 required, 1 recommended, 4 optional - pub const NUM_COMPONENTS: usize = 5usize; + /// The total number of components in the archetype: 0 required, 1 recommended, 5 optional + pub const NUM_COMPONENTS: usize = 6usize; } /// Indicator component for the [`Transform3D`] [`::re_types_core::Archetype`] @@ -296,27 +303,39 @@ impl ::re_types_core::Archetype for Transform3D { .ok_or_else(DeserializationError::missing_data) .with_context("rerun.archetypes.Transform3D#transform")? }; - let mat3x3 = if let Some(array) = arrays_by_name.get("rerun.components.TransformMat3x3") { + let translation = if let Some(array) = arrays_by_name.get("rerun.components.Translation3D") + { Some({ - ::from_arrow_opt(&**array) - .with_context("rerun.archetypes.Transform3D#mat3x3")? + ::from_arrow_opt(&**array) + .with_context("rerun.archetypes.Transform3D#translation")? .into_iter() .map(|v| v.ok_or_else(DeserializationError::missing_data)) .collect::>>() - .with_context("rerun.archetypes.Transform3D#mat3x3")? + .with_context("rerun.archetypes.Transform3D#translation")? }) } else { None }; - let translation = if let Some(array) = arrays_by_name.get("rerun.components.Translation3D") - { + let scale = if let Some(array) = arrays_by_name.get("rerun.components.Scale3D") { Some({ - ::from_arrow_opt(&**array) - .with_context("rerun.archetypes.Transform3D#translation")? + ::from_arrow_opt(&**array) + .with_context("rerun.archetypes.Transform3D#scale")? .into_iter() .map(|v| v.ok_or_else(DeserializationError::missing_data)) .collect::>>() - .with_context("rerun.archetypes.Transform3D#translation")? + .with_context("rerun.archetypes.Transform3D#scale")? + }) + } else { + None + }; + let mat3x3 = if let Some(array) = arrays_by_name.get("rerun.components.TransformMat3x3") { + Some({ + ::from_arrow_opt(&**array) + .with_context("rerun.archetypes.Transform3D#mat3x3")? + .into_iter() + .map(|v| v.ok_or_else(DeserializationError::missing_data)) + .collect::>>() + .with_context("rerun.archetypes.Transform3D#mat3x3")? }) } else { None @@ -332,8 +351,9 @@ impl ::re_types_core::Archetype for Transform3D { }; Ok(Self { transform, - mat3x3, translation, + scale, + mat3x3, axis_length, }) } @@ -346,10 +366,13 @@ impl ::re_types_core::AsComponents for Transform3D { [ Some(Self::indicator()), Some((&self.transform as &dyn ComponentBatch).into()), - self.mat3x3 + self.translation .as_ref() .map(|comp_batch| (comp_batch as &dyn ComponentBatch).into()), - self.translation + self.scale + .as_ref() + .map(|comp_batch| (comp_batch as &dyn ComponentBatch).into()), + self.mat3x3 .as_ref() .map(|comp_batch| (comp_batch as &dyn ComponentBatch).into()), self.axis_length @@ -362,35 +385,48 @@ impl ::re_types_core::AsComponents for Transform3D { } } +impl ::re_types_core::ArchetypeReflectionMarker for Transform3D {} + impl Transform3D { /// Create a new `Transform3D`. #[inline] pub fn new(transform: impl Into) -> Self { Self { transform: transform.into(), - mat3x3: None, translation: None, + scale: None, + mat3x3: None, axis_length: None, } } - /// 3x3 transformation matrices. + /// Translation vectors. #[inline] - pub fn with_mat3x3( + pub fn with_translation( mut self, - mat3x3: impl IntoIterator>, + translation: impl IntoIterator>, ) -> Self { - self.mat3x3 = Some(mat3x3.into_iter().map(Into::into).collect()); + self.translation = Some(translation.into_iter().map(Into::into).collect()); self } - /// Translation vectors. + /// Scaling factor. #[inline] - pub fn with_translation( + pub fn with_scale( mut self, - translation: impl IntoIterator>, + scale: impl IntoIterator>, ) -> Self { - self.translation = Some(translation.into_iter().map(Into::into).collect()); + self.scale = Some(scale.into_iter().map(Into::into).collect()); + self + } + + /// 3x3 transformation matrices. + #[inline] + pub fn with_mat3x3( + mut self, + mat3x3: impl IntoIterator>, + ) -> Self { + self.mat3x3 = Some(mat3x3.into_iter().map(Into::into).collect()); self } diff --git a/crates/store/re_types/src/archetypes/transform3d_ext.rs b/crates/store/re_types/src/archetypes/transform3d_ext.rs index 4fc5cfff0174..6c3baa307342 100644 --- a/crates/store/re_types/src/archetypes/transform3d_ext.rs +++ b/crates/store/re_types/src/archetypes/transform3d_ext.rs @@ -1,6 +1,6 @@ use crate::{ - components::{TransformMat3x3, Translation3D}, - datatypes::{Rotation3D, Scale3D, TranslationRotationScale3D}, + components::{Scale3D, TransformMat3x3, Translation3D}, + datatypes::{Rotation3D, TranslationRotationScale3D}, }; use super::Transform3D; @@ -37,7 +37,7 @@ impl Transform3D { #[inline] pub fn from_scale(scale: impl Into) -> Self { Self { - transform: TranslationRotationScale3D::from_scale(scale).into(), + scale: Some(vec![scale.into()]), ..Self::default() } } @@ -75,7 +75,7 @@ impl Transform3D { scale: impl Into, ) -> Self { Self { - transform: TranslationRotationScale3D::from_scale(scale).into(), + scale: Some(vec![scale.into()]), translation: Some(vec![translation.into()]), ..Self::default() } @@ -89,7 +89,8 @@ impl Transform3D { scale: impl Into, ) -> Self { Self { - transform: TranslationRotationScale3D::from_rotation_scale(rotation, scale).into(), + transform: TranslationRotationScale3D::from_rotation(rotation).into(), + scale: Some(vec![scale.into()]), translation: Some(vec![translation.into()]), ..Self::default() } @@ -99,7 +100,8 @@ impl Transform3D { #[inline] pub fn from_rotation_scale(rotation: impl Into, scale: impl Into) -> Self { Self { - transform: TranslationRotationScale3D::from_rotation_scale(rotation, scale).into(), + transform: TranslationRotationScale3D::from_rotation(rotation).into(), + scale: Some(vec![scale.into()]), ..Self::default() } } diff --git a/crates/store/re_types/src/components/.gitattributes b/crates/store/re_types/src/components/.gitattributes index 1d68d890fbef..6da6a752cdb5 100644 --- a/crates/store/re_types/src/components/.gitattributes +++ b/crates/store/re_types/src/components/.gitattributes @@ -36,6 +36,7 @@ range1d.rs linguist-generated=true resolution.rs linguist-generated=true rotation3d.rs linguist-generated=true scalar.rs linguist-generated=true +scale3d.rs linguist-generated=true stroke_width.rs linguist-generated=true tensor_data.rs linguist-generated=true tensor_dimension_index_selection.rs linguist-generated=true diff --git a/crates/store/re_types/src/components/mod.rs b/crates/store/re_types/src/components/mod.rs index 5f5e1795b9c0..6a040e47f5c3 100644 --- a/crates/store/re_types/src/components/mod.rs +++ b/crates/store/re_types/src/components/mod.rs @@ -62,6 +62,8 @@ mod rotation3d; mod rotation3d_ext; mod scalar; mod scalar_ext; +mod scale3d; +mod scale3d_ext; mod stroke_width; mod stroke_width_ext; mod tensor_data; @@ -124,6 +126,7 @@ pub use self::range1d::Range1D; pub use self::resolution::Resolution; pub use self::rotation3d::Rotation3D; pub use self::scalar::Scalar; +pub use self::scale3d::Scale3D; pub use self::stroke_width::StrokeWidth; pub use self::tensor_data::TensorData; pub use self::tensor_dimension_index_selection::TensorDimensionIndexSelection; diff --git a/crates/store/re_types/src/components/scale3d.rs b/crates/store/re_types/src/components/scale3d.rs new file mode 100644 index 000000000000..05e5b420b6f0 --- /dev/null +++ b/crates/store/re_types/src/components/scale3d.rs @@ -0,0 +1,117 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/rust/api.rs +// Based on "crates/store/re_types/definitions/rerun/components/scale3d.fbs". + +#![allow(unused_imports)] +#![allow(unused_parens)] +#![allow(clippy::clone_on_copy)] +#![allow(clippy::cloned_instead_of_copied)] +#![allow(clippy::map_flatten)] +#![allow(clippy::needless_question_mark)] +#![allow(clippy::new_without_default)] +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::too_many_lines)] + +use ::re_types_core::external::arrow2; +use ::re_types_core::ComponentName; +use ::re_types_core::SerializationResult; +use ::re_types_core::{ComponentBatch, MaybeOwnedComponentBatch}; +use ::re_types_core::{DeserializationError, DeserializationResult}; + +/// **Component**: A 3D scale factor. +/// +/// A scale of 1.0 means no scaling. +/// A scale of 2.0 means doubling the size. +/// Each component scales along the corresponding axis. +#[derive(Clone, Debug, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable)] +#[repr(transparent)] +pub struct Scale3D(pub crate::datatypes::Vec3D); + +impl ::re_types_core::SizeBytes for Scale3D { + #[inline] + fn heap_size_bytes(&self) -> u64 { + self.0.heap_size_bytes() + } + + #[inline] + fn is_pod() -> bool { + ::is_pod() + } +} + +impl> From for Scale3D { + fn from(v: T) -> Self { + Self(v.into()) + } +} + +impl std::borrow::Borrow for Scale3D { + #[inline] + fn borrow(&self) -> &crate::datatypes::Vec3D { + &self.0 + } +} + +impl std::ops::Deref for Scale3D { + type Target = crate::datatypes::Vec3D; + + #[inline] + fn deref(&self) -> &crate::datatypes::Vec3D { + &self.0 + } +} + +impl std::ops::DerefMut for Scale3D { + #[inline] + fn deref_mut(&mut self) -> &mut crate::datatypes::Vec3D { + &mut self.0 + } +} + +::re_types_core::macros::impl_into_cow!(Scale3D); + +impl ::re_types_core::Loggable for Scale3D { + type Name = ::re_types_core::ComponentName; + + #[inline] + fn name() -> Self::Name { + "rerun.components.Scale3D".into() + } + + #[inline] + fn arrow_datatype() -> arrow2::datatypes::DataType { + crate::datatypes::Vec3D::arrow_datatype() + } + + fn to_arrow_opt<'a>( + data: impl IntoIterator>>>, + ) -> SerializationResult> + where + Self: Clone + 'a, + { + crate::datatypes::Vec3D::to_arrow_opt(data.into_iter().map(|datum| { + datum.map(|datum| match datum.into() { + ::std::borrow::Cow::Borrowed(datum) => ::std::borrow::Cow::Borrowed(&datum.0), + ::std::borrow::Cow::Owned(datum) => ::std::borrow::Cow::Owned(datum.0), + }) + })) + } + + fn from_arrow_opt( + arrow_data: &dyn arrow2::array::Array, + ) -> DeserializationResult>> + where + Self: Sized, + { + crate::datatypes::Vec3D::from_arrow_opt(arrow_data) + .map(|v| v.into_iter().map(|v| v.map(Self)).collect()) + } + + #[inline] + fn from_arrow(arrow_data: &dyn arrow2::array::Array) -> DeserializationResult> + where + Self: Sized, + { + crate::datatypes::Vec3D::from_arrow(arrow_data).map(bytemuck::cast_vec) + } +} diff --git a/crates/store/re_types/src/components/scale3d_ext.rs b/crates/store/re_types/src/components/scale3d_ext.rs new file mode 100644 index 000000000000..322f17631276 --- /dev/null +++ b/crates/store/re_types/src/components/scale3d_ext.rs @@ -0,0 +1,54 @@ +use crate::datatypes::Vec3D; + +use super::Scale3D; + +impl Scale3D { + /// Scale the same amount along all axis. + #[inline] + pub fn uniform(value: f32) -> Self { + Self(Vec3D([value, value, value])) + } + + /// Scale the same amount along all axis. + /// + /// Deprecated method to mimic previous enum variant. + #[allow(non_snake_case)] + #[deprecated(since = "0.18.0", note = "Use `Scale3D::uniform` instead.")] + pub fn Uniform(value: f32) -> Self { + Self::uniform(value) + } + + /// Scale individually along each axis. + /// + /// Deprecated method to mimic previous enum variant. + #[allow(non_snake_case)] + #[deprecated(since = "0.18.0", note = "Use `Scale3D::from` instead.")] + pub fn ThreeD(value: impl Into) -> Self { + Self::from(value.into()) + } +} + +impl From for Scale3D { + #[inline] + fn from(value: f32) -> Self { + Self(crate::datatypes::Vec3D([value, value, value])) + } +} + +#[cfg(feature = "glam")] +impl From for glam::Affine3A { + #[inline] + fn from(v: Scale3D) -> Self { + Self { + matrix3: glam::Mat3A::from_diagonal(v.0.into()), + translation: v.0.into(), + } + } +} + +impl Default for Scale3D { + #[inline] + fn default() -> Self { + Self(crate::datatypes::Vec3D([1.0, 1.0, 1.0])) + } +} diff --git a/crates/store/re_types/src/datatypes/vec3d_ext.rs b/crates/store/re_types/src/datatypes/vec3d_ext.rs index 57d9a1b1fd25..ed1e9881db01 100644 --- a/crates/store/re_types/src/datatypes/vec3d_ext.rs +++ b/crates/store/re_types/src/datatypes/vec3d_ext.rs @@ -93,6 +93,14 @@ impl From for glam::Vec3 { } } +#[cfg(feature = "glam")] +impl From for glam::Vec3A { + #[inline] + fn from(v: Vec3D) -> Self { + Self::from_slice(&v.0) + } +} + #[cfg(feature = "glam")] impl From for Vec3D { #[inline] diff --git a/crates/store/re_types/tests/transform3d.rs b/crates/store/re_types/tests/transform3d.rs index 72edeaed9b6c..a8b5cfc77ee7 100644 --- a/crates/store/re_types/tests/transform3d.rs +++ b/crates/store/re_types/tests/transform3d.rs @@ -2,10 +2,9 @@ use std::{collections::HashMap, f32::consts::TAU}; use re_types::{ archetypes::Transform3D, - components, + components::{self, Scale3D}, datatypes::{ - self, Angle, Mat3x3, Rotation3D, RotationAxisAngle, Scale3D, TranslationRotationScale3D, - Vec3D, + self, Angle, Mat3x3, Rotation3D, RotationAxisAngle, TranslationRotationScale3D, Vec3D, }, Archetype as _, AsComponents as _, }; @@ -23,6 +22,7 @@ fn roundtrip() { }, )), mat3x3: None, + scale: None, translation: None, axis_length: None, }, // @@ -31,11 +31,12 @@ fn roundtrip() { TranslationRotationScale3D { translation: None, rotation: None, - scale: Some(Scale3D::Uniform(42.0)), + scale: None, from_parent: true, }, )), mat3x3: None, + scale: Some(vec![Scale3D::uniform(42.0)]), translation: Some(vec![Vec3D([1.0, 2.0, 3.0]).into()]), axis_length: None, }, // @@ -52,7 +53,8 @@ fn roundtrip() { }, )), mat3x3: None, - translation: Some(vec![Vec3D([1.0, 2.0, 3.0]).into()]), + scale: None, + translation: Some(vec![[1.0, 2.0, 3.0].into()]), axis_length: None, }, // Transform3D { @@ -63,11 +65,12 @@ fn roundtrip() { axis: Vec3D([0.2, 0.2, 0.8]), angle: Angle::Radians(0.5 * TAU), })), - scale: Some(Scale3D::Uniform(42.0)), + scale: None, from_parent: true, }, )), mat3x3: None, + scale: Some(vec![Scale3D::uniform(42.0)]), translation: Some(vec![Vec3D([1.0, 2.0, 3.0]).into()]), axis_length: None, }, // @@ -81,6 +84,7 @@ fn roundtrip() { }, )), mat3x3: None, + scale: None, translation: Some(vec![Vec3D([1.0, 2.0, 3.0]).into()]), axis_length: None, }, // @@ -96,6 +100,7 @@ fn roundtrip() { mat3x3: Some(vec![ Mat3x3([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]).into() ]), + scale: None, translation: None, axis_length: None, }, // @@ -103,7 +108,7 @@ fn roundtrip() { let all_arch = [ Transform3D::default(), - Transform3D::from_translation_scale([1.0, 2.0, 3.0], Scale3D::Uniform(42.0)).from_parent(), // + Transform3D::from_translation_scale([1.0, 2.0, 3.0], Scale3D::uniform(42.0)).from_parent(), // Transform3D::from_translation_rotation( [1.0, 2.0, 3.0], RotationAxisAngle::new([0.2, 0.2, 0.8], Angle::Radians(0.5 * TAU)), diff --git a/crates/top/rerun/src/sdk.rs b/crates/top/rerun/src/sdk.rs index 3c9704c10749..1277be52e29e 100644 --- a/crates/top/rerun/src/sdk.rs +++ b/crates/top/rerun/src/sdk.rs @@ -24,12 +24,12 @@ mod prelude { pub use re_chunk::ChunkTimeline; pub use re_types::components::{ AlbedoFactor, Color, HalfSize2D, HalfSize3D, LineStrip2D, LineStrip3D, MediaType, - OutOfTreeTransform3D, Position2D, Position3D, Radius, Text, TextLogLevel, TriangleIndices, - Vector2D, Vector3D, + OutOfTreeTransform3D, Position2D, Position3D, Radius, Scale3D, Text, TextLogLevel, + TriangleIndices, Vector2D, Vector3D, }; pub use re_types::datatypes::{ Angle, AnnotationInfo, ClassDescription, Float32, KeypointPair, Mat3x3, Quaternion, Rgba32, - Rotation3D, RotationAxisAngle, Scale3D, TensorBuffer, TensorData, TensorDimension, + Rotation3D, RotationAxisAngle, TensorBuffer, TensorData, TensorDimension, TranslationRotationScale3D, Vec2D, Vec3D, Vec4D, }; } diff --git a/crates/viewer/re_edit_ui/src/lib.rs b/crates/viewer/re_edit_ui/src/lib.rs index c23dbeebe4a4..5bf687b67230 100644 --- a/crates/viewer/re_edit_ui/src/lib.rs +++ b/crates/viewer/re_edit_ui/src/lib.rs @@ -23,7 +23,7 @@ use re_types::{ components::{ AggregationPolicy, AlbedoFactor, AxisLength, Color, Colormap, DepthMeter, DrawOrder, FillRatio, GammaCorrection, ImagePlaneDistance, MagnificationFilter, MarkerSize, Name, - Opacity, StrokeWidth, Text, Translation3D, + Opacity, Scale3D, StrokeWidth, Text, Translation3D, }, Loggable as _, }; @@ -90,4 +90,5 @@ pub fn register_editors(registry: &mut re_viewer_context::ComponentUiRegistry) { registry.add_singleline_edit_or_view(transforms::singleline_view_transform_mat3x3); registry.add_singleline_edit_or_view::(edit_or_view_vec3d); + registry.add_singleline_edit_or_view::(edit_or_view_vec3d); } diff --git a/crates/viewer/re_space_view_spatial/src/contexts/transform_context.rs b/crates/viewer/re_space_view_spatial/src/contexts/transform_context.rs index ece8c9a9fc4f..28a188062e28 100644 --- a/crates/viewer/re_space_view_spatial/src/contexts/transform_context.rs +++ b/crates/viewer/re_space_view_spatial/src/contexts/transform_context.rs @@ -6,8 +6,8 @@ use re_space_view::DataResultQuery as _; use re_types::{ archetypes::Pinhole, components::{ - DisconnectedSpace, ImagePlaneDistance, PinholeProjection, Transform3D, TransformMat3x3, - Translation3D, ViewCoordinates, + DisconnectedSpace, ImagePlaneDistance, PinholeProjection, Scale3D, Transform3D, + TransformMat3x3, Translation3D, ViewCoordinates, }, ComponentNameSet, Loggable as _, }; @@ -96,6 +96,8 @@ impl ViewContextSystem for TransformContext { ) { re_tracing::profile_function!(); + debug_assert_transform_field_order(ctx.viewer_ctx.reflection); + let entity_tree = ctx.recording().tree(); self.space_origin = query.space_origin.clone(); @@ -300,6 +302,44 @@ impl TransformContext { } } +#[cfg(debug_assertions)] +fn debug_assert_transform_field_order(reflection: &re_types::reflection::Reflection) { + let expected_order = vec![ + Transform3D::name(), + Translation3D::name(), + Scale3D::name(), + TransformMat3x3::name(), + ]; + + use re_types::Archetype as _; + let transform3d_reflection = reflection + .archetypes + .get(&re_types::archetypes::Transform3D::name()) + .expect("Transform3D archetype not found in reflection"); + + let mut remaining_fields = expected_order.clone(); + for field in transform3d_reflection.fields.iter().rev() { + if Some(&field.component_name) == remaining_fields.last() { + remaining_fields.pop(); + } + } + + if !remaining_fields.is_empty() { + let actual_order = transform3d_reflection + .fields + .iter() + .map(|f| f.component_name) + .collect::>(); + panic!( + "Expected transform fields in the following order:\n{expected_order:?}\n +But they are instead ordered like this:\n{actual_order:?}" + ); + } +} + +#[cfg(not(debug_assertions))] +fn debug_assert_transform_field_order(_: &re_types::reflection::Reflection) {} + fn get_parent_from_child_transform( entity_path: &EntityPath, entity_db: &EntityDb, @@ -312,18 +352,24 @@ fn get_parent_from_child_transform( entity_path, [ Transform3D::name(), - TransformMat3x3::name(), Translation3D::name(), + Scale3D::name(), + TransformMat3x3::name(), ], ); if result.components.is_empty() { return None; } + // Order is specified by order of components in the Transform3D archetype. + // See `has_transform_expected_order` let mut transform = glam::Affine3A::IDENTITY; if let Some(mat3x3) = result.get_instance::(resolver, 0) { transform *= glam::Affine3A::from(mat3x3); } + if let Some(scale) = result.get_instance::(resolver, 0) { + transform *= glam::Affine3A::from(scale); + } if let Some(translation) = result.get_instance::(resolver, 0) { transform *= glam::Affine3A::from(translation); } diff --git a/crates/viewer/re_viewer/src/reflection/mod.rs b/crates/viewer/re_viewer/src/reflection/mod.rs index 96cad1e93701..720774c6214b 100644 --- a/crates/viewer/re_viewer/src/reflection/mod.rs +++ b/crates/viewer/re_viewer/src/reflection/mod.rs @@ -475,6 +475,13 @@ fn generate_component_reflection() -> Result::name(), + ComponentReflection { + docstring_md: "A 3D scale factor.\n\nA scale of 1.0 means no scaling.\nA scale of 2.0 means doubling the size.\nEach component scales along the corresponding axis.", + placeholder: Some(Scale3D::default().to_arrow()?), + }, + ), ( ::name(), ComponentReflection { @@ -591,6 +598,30 @@ fn generate_component_reflection() -> Result ArchetypeReflectionMap { re_tracing::profile_function!(); let array = [ + ( + ArchetypeName::new("rerun.archetypes.Transform3D"), + ArchetypeReflection { + display_name: "Transform 3D", + docstring_md: "A transform between two 3D spaces, i.e. a pose.\n\nAll components are applied in the inverse order they are listed here.\nE.g. if both a 4x4 matrix with a translation and a translation vector are present,\nthe translation is applied first, followed by the matrix.\n\nEach transform component can be listed multiple times, but transform tree propagation is only possible\nif there's only one instance for each transform component.\nTODO(#6831): write more about the exact interaction with the to be written `OutOfTreeTransform` component.\n\n## Examples\n\n### Variety of 3D transforms\n```ignore\nuse std::f32::consts::TAU;\n\nfn main() -> Result<(), Box> {\n let rec = rerun::RecordingStreamBuilder::new(\"rerun_example_transform3d\").spawn()?;\n\n let arrow = rerun::Arrows3D::from_vectors([(0.0, 1.0, 0.0)]).with_origins([(0.0, 0.0, 0.0)]);\n\n rec.log(\"base\", &arrow)?;\n\n rec.log(\n \"base/translated\",\n &rerun::Transform3D::from_translation([1.0, 0.0, 0.0]),\n )?;\n\n rec.log(\"base/translated\", &arrow)?;\n\n rec.log(\n \"base/rotated_scaled\",\n &rerun::Transform3D::from_rotation_scale(\n rerun::RotationAxisAngle::new([0.0, 0.0, 1.0], rerun::Angle::Radians(TAU / 8.0)),\n rerun::Scale3D::from(2.0),\n ),\n )?;\n\n rec.log(\"base/rotated_scaled\", &arrow)?;\n\n Ok(())\n}\n```\n
\n\n \n \n \n \n \n\n
\n\n### Transform hierarchy\n```ignore\nfn main() -> Result<(), Box> {\n let rec = rerun::RecordingStreamBuilder::new(\"rerun_example_transform3d_hierarchy\").spawn()?;\n\n // TODO(#5521): log two space views as in the python example\n\n rec.set_time_seconds(\"sim_time\", 0.0);\n\n // Planetary motion is typically in the XY plane.\n rec.log_static(\"/\", &rerun::ViewCoordinates::RIGHT_HAND_Z_UP)?;\n\n // Setup points, all are in the center of their own space:\n rec.log(\n \"sun\",\n &rerun::Points3D::new([[0.0, 0.0, 0.0]])\n .with_radii([1.0])\n .with_colors([rerun::Color::from_rgb(255, 200, 10)]),\n )?;\n rec.log(\n \"sun/planet\",\n &rerun::Points3D::new([[0.0, 0.0, 0.0]])\n .with_radii([0.4])\n .with_colors([rerun::Color::from_rgb(40, 80, 200)]),\n )?;\n rec.log(\n \"sun/planet/moon\",\n &rerun::Points3D::new([[0.0, 0.0, 0.0]])\n .with_radii([0.15])\n .with_colors([rerun::Color::from_rgb(180, 180, 180)]),\n )?;\n\n // Draw fixed paths where the planet & moon move.\n let d_planet = 6.0;\n let d_moon = 3.0;\n let angles = (0..=100).map(|i| i as f32 * 0.01 * std::f32::consts::TAU);\n let circle: Vec<_> = angles.map(|angle| [angle.sin(), angle.cos()]).collect();\n rec.log(\n \"sun/planet_path\",\n &rerun::LineStrips3D::new([rerun::LineStrip3D::from_iter(\n circle\n .iter()\n .map(|p| [p[0] * d_planet, p[1] * d_planet, 0.0]),\n )]),\n )?;\n rec.log(\n \"sun/planet/moon_path\",\n &rerun::LineStrips3D::new([rerun::LineStrip3D::from_iter(\n circle.iter().map(|p| [p[0] * d_moon, p[1] * d_moon, 0.0]),\n )]),\n )?;\n\n // Movement via transforms.\n for i in 0..(6 * 120) {\n let time = i as f32 / 120.0;\n rec.set_time_seconds(\"sim_time\", time);\n let r_moon = time * 5.0;\n let r_planet = time * 2.0;\n\n rec.log(\n \"sun/planet\",\n &rerun::Transform3D::from_translation_rotation(\n [r_planet.sin() * d_planet, r_planet.cos() * d_planet, 0.0],\n rerun::RotationAxisAngle {\n axis: [1.0, 0.0, 0.0].into(),\n angle: rerun::Angle::Degrees(20.0),\n },\n ),\n )?;\n rec.log(\n \"sun/planet/moon\",\n &rerun::Transform3D::from_translation([\n r_moon.cos() * d_moon,\n r_moon.sin() * d_moon,\n 0.0,\n ])\n .from_parent(),\n )?;\n }\n\n Ok(())\n}\n```\n
\n\n \n \n \n \n \n\n
", + fields: vec![ + ArchetypeFieldReflection { component_name : + "rerun.components.Transform3D".into(), display_name : "Transform", + docstring_md : "The transform", }, ArchetypeFieldReflection { + component_name : "rerun.components.Translation3D".into(), + display_name : "Translation", docstring_md : "Translation vectors.", + }, ArchetypeFieldReflection { component_name : + "rerun.components.Scale3D".into(), display_name : "Scale", + docstring_md : "Scaling factor.", }, ArchetypeFieldReflection { + component_name : "rerun.components.TransformMat3x3".into(), + display_name : "Mat 3x 3", docstring_md : + "3x3 transformation matrices.", }, ArchetypeFieldReflection { + component_name : "rerun.components.AxisLength".into(), display_name : + "Axis length", docstring_md : + "Visual length of the 3 axes.\n\nThe length is interpreted in the local coordinate system of the transform.\nIf the transform is scaled, the axes will be scaled accordingly.", + }, + ], + }, + ), ( ArchetypeName::new("rerun.blueprint.archetypes.Background"), ArchetypeReflection { diff --git a/docs/content/reference/migration/migration-0-18.md b/docs/content/reference/migration/migration-0-18.md index 7106a1eec321..49423e0dcc92 100644 --- a/docs/content/reference/migration/migration-0-18.md +++ b/docs/content/reference/migration/migration-0-18.md @@ -46,8 +46,10 @@ For this purpose `TranslationRotationScale3D` and `TranslationAndMat3x3` datatyp * [`TransformMat3x3`](https://rerun.io/docs/reference/types/components/transform_mat3x3#speculative-link) * TODO(andreas): More! -All components are applied to the final transform in order. E.g. if both a 4x4 matrix and a translation is set, the entity is first transformed with the matrix and then translated. +All components are applied to the final transform in the opposite order they're listed in. E.g. if both a 4x4 matrix and a translation is set, the entity is first translated and then transformed with the matrix. +If translation, rotation & scale are applied, then (just as in prior versions), from the point of view of the parent space the object is first scaled, then rotated and then translated. +Scaling no longer distinguishes uniform and 3D scaling in its data representation. Uniform scaling is now always expressed as 3 floats with the same value. TODO(andreas): Write about OutOfTreeTransform changes and how `Transform3D` has now arrays of components. @@ -85,7 +87,6 @@ Before: ```cpp rec.log("myentity", rerun::Transform3D({1.0f, 2.0f, 3.0f})); ``` - After: ```cpp rec.log("myentity", rerun::Transform3D::from_translation({1.0f, 2.0f, 3.0f})); @@ -101,6 +102,18 @@ Note that the order of the method calls does _not_ affect the order in which tra an empty archetype instead that you can populate (e.g. `rerun::Transform3D().with_mat3x3(rerun::datatypes::Mat3x3::IDENTITY)`). +Scale is no longer an enum datatype but a component with a 3D vec: +Before: +```rust +let scale_uniform = rerun::Scale3D::Uniform(2.0); +let scale_y = rerun::Scale3D::ThreeD([1.0, 2.0, 1.0]); +``` +After: +```rust +let scale_uniform = rerun::Scale3D::uniform(2.0); +let scale_y = rerun::Scale3D::from([1.0, 2.0, 1.0]); +``` + TODO(andreas): Talk about OutOfTreeTransform TODO(andreas): … and Asset3D specifically diff --git a/docs/content/reference/types/archetypes/transform3d.md b/docs/content/reference/types/archetypes/transform3d.md index c9c705944bbe..d20b90aaa4af 100644 --- a/docs/content/reference/types/archetypes/transform3d.md +++ b/docs/content/reference/types/archetypes/transform3d.md @@ -5,9 +5,9 @@ title: "Transform3D" A transform between two 3D spaces, i.e. a pose. -All components are applied in the order they are listed here. +All components are applied in the inverse order they are listed here. E.g. if both a 4x4 matrix with a translation and a translation vector are present, -the matrix is applied first, then the translation vector on top. +the translation is applied first, followed by the matrix. Each transform component can be listed multiple times, but transform tree propagation is only possible if there's only one instance for each transform component. @@ -15,7 +15,7 @@ TODO(#6831): write more about the exact interaction with the to be written `OutO ## Components -**Optional**: [`Transform3D`](../components/transform3d.md), [`TransformMat3x3`](../components/transform_mat3x3.md), [`Translation3D`](../components/translation3d.md), [`AxisLength`](../components/axis_length.md) +**Optional**: [`Transform3D`](../components/transform3d.md), [`Translation3D`](../components/translation3d.md), [`Scale3D`](../components/scale3d.md), [`TransformMat3x3`](../components/transform_mat3x3.md), [`AxisLength`](../components/axis_length.md) ## Shown in * [Spatial3DView](../views/spatial3d_view.md) diff --git a/docs/content/reference/types/components.md b/docs/content/reference/types/components.md index 2fffa5d8fa71..b587ef76edf1 100644 --- a/docs/content/reference/types/components.md +++ b/docs/content/reference/types/components.md @@ -48,6 +48,7 @@ on [Entities and Components](../../concepts/entity-component.md). * [`Resolution`](components/resolution.md): Pixel resolution width & height, e.g. of a camera sensor. * [`Rotation3D`](components/rotation3d.md): A 3D rotation, represented either by a quaternion or a rotation around axis. * [`Scalar`](components/scalar.md): A scalar value, encoded as a 64-bit floating point. +* [`Scale3D`](components/scale3d.md): A 3D scale factor. * [`StrokeWidth`](components/stroke_width.md): The width of a stroke specified in UI points. * [`TensorData`](components/tensor_data.md): An N-dimensional array of numbers. * [`TensorDimensionIndexSelection`](components/tensor_dimension_index_selection.md): Specifies a concrete index on a tensor dimension. diff --git a/docs/content/reference/types/components/.gitattributes b/docs/content/reference/types/components/.gitattributes index 22e077e0ec90..29480f8c0892 100644 --- a/docs/content/reference/types/components/.gitattributes +++ b/docs/content/reference/types/components/.gitattributes @@ -36,6 +36,7 @@ range1d.md linguist-generated=true resolution.md linguist-generated=true rotation3d.md linguist-generated=true scalar.md linguist-generated=true +scale3d.md linguist-generated=true stroke_width.md linguist-generated=true tensor_data.md linguist-generated=true tensor_dimension_index_selection.md linguist-generated=true diff --git a/docs/content/reference/types/components/scale3d.md b/docs/content/reference/types/components/scale3d.md new file mode 100644 index 000000000000..e0739fe2094d --- /dev/null +++ b/docs/content/reference/types/components/scale3d.md @@ -0,0 +1,24 @@ +--- +title: "Scale3D" +--- + + +A 3D scale factor. + +A scale of 1.0 means no scaling. +A scale of 2.0 means doubling the size. +Each component scales along the corresponding axis. + +## Fields + +* scale: [`Vec3D`](../datatypes/vec3d.md) + +## API reference links + * 🌊 [C++ API docs for `Scale3D`](https://ref.rerun.io/docs/cpp/stable/structrerun_1_1components_1_1Scale3D.html?speculative-link) + * 🐍 [Python API docs for `Scale3D`](https://ref.rerun.io/docs/python/stable/common/components?speculative-link#rerun.components.Scale3D) + * 🦀 [Rust API docs for `Scale3D`](https://docs.rs/rerun/latest/rerun/components/struct.Scale3D.html?speculative-link) + + +## Used by + +* [`Transform3D`](../archetypes/transform3d.md) diff --git a/docs/content/reference/types/datatypes/vec3d.md b/docs/content/reference/types/datatypes/vec3d.md index 82fce3541c2f..ddd38d6f02f4 100644 --- a/docs/content/reference/types/datatypes/vec3d.md +++ b/docs/content/reference/types/datatypes/vec3d.md @@ -21,6 +21,7 @@ A vector in 3D space. * [`LineStrip3D`](../components/line_strip3d.md) * [`Position3D`](../components/position3d.md) * [`RotationAxisAngle`](../datatypes/rotation_axis_angle.md) +* [`Scale3D`](../components/scale3d.md?speculative-link) * [`Scale3D`](../datatypes/scale3d.md) * [`Translation3D`](../components/translation3d.md?speculative-link) * [`TranslationRotationScale3D`](../datatypes/translation_rotation_scale3d.md) diff --git a/docs/snippets/all/archetypes/transform3d_axes.cpp b/docs/snippets/all/archetypes/transform3d_axes.cpp index dd5997b45f3a..b68ed562c024 100644 --- a/docs/snippets/all/archetypes/transform3d_axes.cpp +++ b/docs/snippets/all/archetypes/transform3d_axes.cpp @@ -23,12 +23,15 @@ int main() { rec.log( "base/rotated", - rerun::Transform3D(rerun::RotationAxisAngle( + rerun::Transform3D::from_rotation(rerun::RotationAxisAngle( {1.0f, 1.0f, 1.0f}, rerun::Angle::degrees(static_cast(deg)) )) ); - rec.log("base/rotated/translated", rerun::Transform3D({2.0f, 0.0f, 0.0f})); + rec.log( + "base/rotated/translated", + rerun::Transform3D::from_translation({2.0f, 0.0f, 0.0f}) + ); } } diff --git a/docs/snippets/all/archetypes/transform3d_hierarchy.cpp b/docs/snippets/all/archetypes/transform3d_hierarchy.cpp index e5a2d4b4c8c4..7e06892e64bd 100644 --- a/docs/snippets/all/archetypes/transform3d_hierarchy.cpp +++ b/docs/snippets/all/archetypes/transform3d_hierarchy.cpp @@ -58,7 +58,7 @@ int main() { rec.log( "sun/planet", - rerun::Transform3D( + rerun::Transform3D::from_translation_rotation( {std::sin(r_planet) * d_planet, std::cos(r_planet) * d_planet, 0.0f}, rerun::RotationAxisAngle{ {1.0, 0.0f, 0.0f}, @@ -68,14 +68,10 @@ int main() { ); rec.log( "sun/planet/moon", - rerun::Transform3D( - { - std::cos(r_moon) * d_moon, - std::sin(r_moon) * d_moon, - 0.0f, - }, - true + rerun::Transform3D::from_translation( + {std::cos(r_moon) * d_moon, std::sin(r_moon) * d_moon, 0.0f} ) + .with_from_parent(true) ); } } diff --git a/docs/snippets/all/archetypes/transform3d_simple.cpp b/docs/snippets/all/archetypes/transform3d_simple.cpp index 5d3feb8beeae..3324e6ba5620 100644 --- a/docs/snippets/all/archetypes/transform3d_simple.cpp +++ b/docs/snippets/all/archetypes/transform3d_simple.cpp @@ -13,12 +13,12 @@ int main() { rec.log("base", arrow); - rec.log("base/translated", rerun::Transform3D({1.0f, 0.0f, 0.0f})); + rec.log("base/translated", rerun::Transform3D::from_translation({1.0f, 0.0f, 0.0f})); rec.log("base/translated", arrow); rec.log( "base/rotated_scaled", - rerun::Transform3D( + rerun::Transform3D::from_rotation_scale( rerun::RotationAxisAngle({0.0f, 0.0f, 1.0f}, rerun::Angle::radians(TAU / 8.0f)), 2.0f ) diff --git a/lychee.toml b/lychee.toml index 68ca63425cb9..0e5491f68e84 100644 --- a/lychee.toml +++ b/lychee.toml @@ -60,9 +60,10 @@ exclude_path = [ "venv", # Actually ignored files beyond .gitignore - "crates/utils/re_analytics/src/event.rs", # Contains test with malformed urls - "scripts/lint.py", # Contains url-matching regexes that aren't actual urls + "crates/utils/re_analytics/src/event.rs", # Contains test with malformed urls + "scripts/lint.py", # Contains url-matching regexes that aren't actual urls "scripts/screenshot_compare/assets/templates/", + "crates/viewer/re_viewer/src/reflection/mod.rs", # Checker struggles how links from examples are escaped here. They are all checked elsewhere, so not an issue. ] # Exclude URLs and mail addresses from checking (supports regex). diff --git a/rerun_cpp/src/rerun/archetypes/transform3d.cpp b/rerun_cpp/src/rerun/archetypes/transform3d.cpp index e178c2206abf..3376c7631464 100644 --- a/rerun_cpp/src/rerun/archetypes/transform3d.cpp +++ b/rerun_cpp/src/rerun/archetypes/transform3d.cpp @@ -14,20 +14,25 @@ namespace rerun { ) { using namespace archetypes; std::vector cells; - cells.reserve(5); + cells.reserve(6); { auto result = DataCell::from_loggable(archetype.transform); RR_RETURN_NOT_OK(result.error); cells.push_back(std::move(result.value)); } - if (archetype.mat3x3.has_value()) { - auto result = DataCell::from_loggable(archetype.mat3x3.value()); + if (archetype.translation.has_value()) { + auto result = DataCell::from_loggable(archetype.translation.value()); RR_RETURN_NOT_OK(result.error); cells.push_back(std::move(result.value)); } - if (archetype.translation.has_value()) { - auto result = DataCell::from_loggable(archetype.translation.value()); + if (archetype.scale.has_value()) { + auto result = DataCell::from_loggable(archetype.scale.value()); + RR_RETURN_NOT_OK(result.error); + cells.push_back(std::move(result.value)); + } + if (archetype.mat3x3.has_value()) { + auto result = DataCell::from_loggable(archetype.mat3x3.value()); RR_RETURN_NOT_OK(result.error); cells.push_back(std::move(result.value)); } diff --git a/rerun_cpp/src/rerun/archetypes/transform3d.hpp b/rerun_cpp/src/rerun/archetypes/transform3d.hpp index ffa804e54b63..d14e182327ec 100644 --- a/rerun_cpp/src/rerun/archetypes/transform3d.hpp +++ b/rerun_cpp/src/rerun/archetypes/transform3d.hpp @@ -6,6 +6,7 @@ #include "../collection.hpp" #include "../compiler_utils.hpp" #include "../components/axis_length.hpp" +#include "../components/scale3d.hpp" #include "../components/transform3d.hpp" #include "../components/transform_mat3x3.hpp" #include "../components/translation3d.hpp" @@ -22,9 +23,9 @@ namespace rerun::archetypes { /// **Archetype**: A transform between two 3D spaces, i.e. a pose. /// - /// All components are applied in the order they are listed here. + /// All components are applied in the inverse order they are listed here. /// E.g. if both a 4x4 matrix with a translation and a translation vector are present, - /// the matrix is applied first, then the translation vector on top. + /// the translation is applied first, followed by the matrix. /// /// Each transform component can be listed multiple times, but transform tree propagation is only possible /// if there's only one instance for each transform component. @@ -49,12 +50,12 @@ namespace rerun::archetypes { /// /// rec.log("base", arrow); /// - /// rec.log("base/translated", rerun::Transform3D({1.0f, 0.0f, 0.0f})); + /// rec.log("base/translated", rerun::Transform3D::from_translation({1.0f, 0.0f, 0.0f})); /// rec.log("base/translated", arrow); /// /// rec.log( /// "base/rotated_scaled", - /// rerun::Transform3D( + /// rerun::Transform3D::from_rotation_scale( /// rerun::RotationAxisAngle({0.0f, 0.0f, 1.0f}, rerun::Angle::radians(TAU / 8.0f)), /// 2.0f /// ) @@ -125,7 +126,7 @@ namespace rerun::archetypes { /// /// rec.log( /// "sun/planet", - /// rerun::Transform3D( + /// rerun::Transform3D::from_translation_rotation( /// {std::sin(r_planet) * d_planet, std::cos(r_planet) * d_planet, 0.0f}, /// rerun::RotationAxisAngle{ /// {1.0, 0.0f, 0.0f}, @@ -135,14 +136,10 @@ namespace rerun::archetypes { /// ); /// rec.log( /// "sun/planet/moon", - /// rerun::Transform3D( - /// { - /// std::cos(r_moon) * d_moon, - /// std::sin(r_moon) * d_moon, - /// 0.0f, - /// }, - /// true + /// rerun::Transform3D::from_translation( + /// {std::cos(r_moon) * d_moon, std::sin(r_moon) * d_moon, 0.0f} /// ) + /// .with_from_parent(true) /// ); /// } /// } @@ -151,12 +148,15 @@ namespace rerun::archetypes { /// The transform rerun::components::Transform3D transform; - /// 3x3 transformation matrices. - std::optional> mat3x3; - /// Translation vectors. std::optional> translation; + /// Scaling factor. + std::optional> scale; + + /// 3x3 transformation matrices. + std::optional> mat3x3; + /// Visual length of the 3 axes. /// /// The length is interpreted in the local coordinate system of the transform. @@ -180,34 +180,34 @@ namespace rerun::archetypes { /// Creates a new 3D transform from translation and matrix provided as 3 columns. /// - /// \param _translation \çopydoc Transform3D::translation + /// \param translation_ \çopydoc Transform3D::translation /// \param columns Column vectors of 3x3 matrix. /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent /// /// _Implementation note:_ This overload is necessary, otherwise the array may be /// interpreted as bool and call the wrong overload. Transform3D( - const components::Translation3D& _translation, const datatypes::Vec3D (&columns)[3], + const components::Translation3D& translation_, const datatypes::Vec3D (&columns)[3], bool from_parent = false ) : transform(datatypes::TranslationRotationScale3D(from_parent)), + translation(Collection::take_ownership(translation_)), mat3x3(Collection::take_ownership( components::TransformMat3x3(columns) - )), - translation(Collection::take_ownership(_translation)) {} + )) {} /// Creates a new 3D transform from translation/matrix. /// - /// \param _translation \çopydoc Transform3D::translation - /// \param _mat3x3 \copydoc Transform3D::mat3x3 + /// \param translation_ \çopydoc Transform3D::translation + /// \param mat3x3_ \copydoc Transform3D::mat3x3 /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent Transform3D( - const components::Translation3D& _translation, - const components::TransformMat3x3& _mat3x3, bool from_parent = false + const components::Translation3D& translation_, + const components::TransformMat3x3& mat3x3_, bool from_parent = false ) : transform(datatypes::TranslationRotationScale3D(from_parent)), - mat3x3(Collection::take_ownership(_mat3x3)), - translation(Collection::take_ownership(_translation)) {} + translation(Collection::take_ownership(translation_)), + mat3x3(Collection::take_ownership(mat3x3_)) {} /// From a translation applied after a 3x3 matrix. /// @@ -234,11 +234,11 @@ namespace rerun::archetypes { /// From translation only. /// - /// \param _translation \çopydoc Transform3D::translation + /// \param translation_ \çopydoc Transform3D::translation /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent - Transform3D(const components::Translation3D& _translation, bool from_parent = false) + Transform3D(const components::Translation3D& translation_, bool from_parent = false) : transform(datatypes::TranslationRotationScale3D(from_parent)), - translation(Collection::take_ownership(_translation)) {} + translation(Collection::take_ownership(translation_)) {} /// From a translation. /// @@ -249,11 +249,11 @@ namespace rerun::archetypes { /// From 3x3 matrix only. /// - /// \param _mat3x3 \copydoc Transform3D::mat3x3 + /// \param mat3x3_ \copydoc Transform3D::mat3x3 /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent - Transform3D(const components::TransformMat3x3& _mat3x3, bool from_parent = false) + Transform3D(const components::TransformMat3x3& mat3x3_, bool from_parent = false) : transform(datatypes::TranslationRotationScale3D(from_parent)), - mat3x3(Collection::take_ownership(_mat3x3)) {} + mat3x3(Collection::take_ownership(mat3x3_)) {} /// From 3x3 matrix only. /// @@ -281,20 +281,21 @@ namespace rerun::archetypes { /// Creates a new 3D transform from translation/rotation/scale. /// - /// \param _translation \copydoc Transform3D::translation + /// \param translation_ \copydoc Transform3D::translation /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation - /// \param scale \copydoc datatypes::TranslationRotationScale3D::scale + /// \param scale_ \copydoc Transform3D::scale /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent Transform3D( - const components::Translation3D& _translation, const datatypes::Rotation3D& rotation, - const datatypes::Scale3D& scale, bool from_parent = false + const components::Translation3D& translation_, const datatypes::Rotation3D& rotation, + const components::Scale3D& scale_, bool from_parent = false ) - : transform(datatypes::TranslationRotationScale3D(rotation, scale, from_parent)), - translation(Collection::take_ownership(_translation)) {} + : transform(datatypes::TranslationRotationScale3D(rotation, from_parent)), + translation(Collection::take_ownership(translation_)), + scale(Collection::take_ownership(scale_)) {} /// Creates a new 3D transform from translation/rotation/uniform-scale. /// - /// \param _translation \copydoc Transform3D::translation + /// \param translation_ \copydoc Transform3D::translation /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation /// \param uniform_scale Uniform scale factor that is applied to all axis equally. /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent @@ -302,36 +303,47 @@ namespace rerun::archetypes { /// _Implementation note:_ This explicit overload prevents interpretation of the float as /// bool, leading to a call to the wrong overload. Transform3D( - const components::Translation3D& _translation, const datatypes::Rotation3D& rotation, + const components::Translation3D& translation_, const datatypes::Rotation3D& rotation, float uniform_scale, bool from_parent = false ) - : transform(datatypes::TranslationRotationScale3D(rotation, uniform_scale, from_parent) - ), - translation(Collection::take_ownership(_translation)) {} + : Transform3D(translation_, rotation, components::Scale3D(uniform_scale), from_parent) { + } /// From a translation, applied after a rotation & scale, known as an affine transformation. /// /// \param translation \copydoc Transform3D::translation /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation - /// \param scale \copydoc datatypes::TranslationRotationScale3D::scale + /// \param scale \copydoc Transform3D::scale static Transform3D from_translation_rotation_scale( const components::Translation3D& translation, const datatypes::Rotation3D& rotation, - const datatypes::Scale3D& scale + const components::Scale3D& scale ) { return Transform3D(translation, rotation, scale, false); } + /// From a translation, applied after a rotation & scale, known as an affine transformation. + /// + /// \param translation \copydoc Transform3D::translation + /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation + /// \param uniform_scale Uniform scale factor that is applied to all axis equally. + static Transform3D from_translation_rotation_scale( + const components::Translation3D& translation, const datatypes::Rotation3D& rotation, + float uniform_scale + ) { + return Transform3D(translation, rotation, components::Scale3D(uniform_scale), false); + } + /// Creates a new rigid transform (translation & rotation only). /// - /// \param _translation \copydoc Transform3D::translation + /// \param translation_ \copydoc Transform3D::translation /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent Transform3D( - const components::Translation3D& _translation, const datatypes::Rotation3D& rotation, + const components::Translation3D& translation_, const datatypes::Rotation3D& rotation, bool from_parent = false ) : transform(datatypes::TranslationRotationScale3D(rotation, from_parent)), - translation(Collection::take_ownership(_translation)) {} + translation(Collection::take_ownership(translation_)) {} /// From a rotation & scale. /// @@ -345,51 +357,52 @@ namespace rerun::archetypes { /// From translation & scale only. /// - /// \param _translation \copydoc Transform3D::translation - /// \param scale datatypes::TranslationRotationScale3D::scale + /// \param translation_ \copydoc Transform3D::translation + /// \param scale_ Transform3D::scale /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent Transform3D( - const components::Translation3D& _translation, const datatypes::Scale3D& scale, + const components::Translation3D& translation_, const components::Scale3D& scale_, bool from_parent = false ) - : transform(datatypes::TranslationRotationScale3D(scale, from_parent)), - translation(Collection::take_ownership(_translation)) {} + : transform(datatypes::TranslationRotationScale3D(from_parent)), + translation(Collection::take_ownership(translation_)), + scale(Collection::take_ownership(scale_)) {} /// From a translation applied after a scale. /// /// \param translation \copydoc Transform3D::translation - /// \param scale datatypes::TranslationRotationScale3D::scale + /// \param scale Transform3D::scale static Transform3D from_translation_scale( - const components::Translation3D& translation, const datatypes::Scale3D& scale + const components::Translation3D& translation, const components::Scale3D& scale ) { return Transform3D(translation, scale, false); } /// From translation & uniform scale only. /// - /// \param _translation \copydoc Transform3D::translation + /// \param translation_ \copydoc Transform3D::translation /// \param uniform_scale Uniform scale factor that is applied to all axis equally. /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent /// /// _Implementation note:_ This explicit overload prevents interpretation of the float as /// bool, leading to a call to the wrong overload. Transform3D( - const components::Translation3D& _translation, float uniform_scale, + const components::Translation3D& translation_, float uniform_scale, bool from_parent = false ) - : transform(datatypes::TranslationRotationScale3D(uniform_scale, from_parent)), - translation(Collection::take_ownership(_translation)) {} + : Transform3D(translation_, components::Scale3D(uniform_scale), from_parent) {} /// From rotation & scale. /// /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation - /// \param scale datatypes::TranslationRotationScale3D::scale + /// \param scale_ Transform3D::scale /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent Transform3D( - const datatypes::Rotation3D& rotation, const datatypes::Scale3D& scale, + const datatypes::Rotation3D& rotation, const components::Scale3D& scale_, bool from_parent = false ) - : transform(datatypes::TranslationRotationScale3D(rotation, scale, from_parent)) {} + : transform(datatypes::TranslationRotationScale3D(rotation, from_parent)), + scale(Collection::take_ownership(scale_)) {} /// From rotation & uniform scale. /// @@ -402,19 +415,28 @@ namespace rerun::archetypes { Transform3D( const datatypes::Rotation3D& rotation, float uniform_scale, bool from_parent = false ) - : transform(datatypes::TranslationRotationScale3D(rotation, uniform_scale, from_parent) - ) {} + : Transform3D(rotation, components::Scale3D(uniform_scale), from_parent) {} /// From a rotation & scale. /// /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation - /// \param scale datatypes::TranslationRotationScale3D::scale + /// \param scale Transform3D::scale static Transform3D from_rotation_scale( - const datatypes::Rotation3D& rotation, const datatypes::Scale3D& scale + const datatypes::Rotation3D& rotation, const components::Scale3D& scale ) { return Transform3D(rotation, scale, false); } + /// From a rotation & uniform scale. + /// + /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation + /// \param uniform_scale Uniform scale factor that is applied to all axis equally. + static Transform3D from_rotation_scale( + const datatypes::Rotation3D& rotation, float uniform_scale + ) { + return Transform3D(rotation, components::Scale3D(uniform_scale), false); + } + /// From rotation only. /// /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation @@ -431,18 +453,26 @@ namespace rerun::archetypes { /// From scale only. /// - /// \param scale \copydoc datatypes::TranslationRotationScale3D::from_parent - /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::scale - Transform3D(const datatypes::Scale3D& scale, bool from_parent = false) - : transform(datatypes::TranslationRotationScale3D(scale, from_parent)) {} + /// \param scale_ \copydoc datatypes::TranslationRotationScale3D::from_parent + /// \param from_parent \copydoc Transform3D::scale + Transform3D(const components::Scale3D& scale_, bool from_parent = false) + : transform(datatypes::TranslationRotationScale3D(from_parent)), + scale(Collection::take_ownership(scale_)) {} /// From scale only. /// - /// \param scale datatypes::TranslationRotationScale3D::scale - static Transform3D from_scale(const datatypes::Scale3D& scale) { + /// \param scale Transform3D::scale + static Transform3D from_scale(const components::Scale3D& scale) { return Transform3D(scale, false); } + /// From scale only. + /// + /// \param uniform_scale Uniform scale factor that is applied to all axis equally. + static Transform3D from_scale(float uniform_scale) { + return Transform3D(components::Scale3D(uniform_scale), false); + } + /// TODO(#6831): Should be autogenerated once from_parent component is introduced Transform3D with_from_parent(bool from_parent) && { auto translation_rotation_scale = transform.repr.get_translation_rotation_scale(); @@ -462,16 +492,23 @@ namespace rerun::archetypes { explicit Transform3D(rerun::components::Transform3D _transform) : transform(std::move(_transform)) {} - /// 3x3 transformation matrices. - Transform3D with_mat3x3(Collection _mat3x3) && { - mat3x3 = std::move(_mat3x3); + /// Translation vectors. + Transform3D with_translation(Collection _translation) && { + translation = std::move(_translation); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } - /// Translation vectors. - Transform3D with_translation(Collection _translation) && { - translation = std::move(_translation); + /// Scaling factor. + Transform3D with_scale(Collection _scale) && { + scale = std::move(_scale); + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } + + /// 3x3 transformation matrices. + Transform3D with_mat3x3(Collection _mat3x3) && { + mat3x3 = std::move(_mat3x3); // See: https://github.com/rerun-io/rerun/issues/4027 RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) } diff --git a/rerun_cpp/src/rerun/archetypes/transform3d_ext.cpp b/rerun_cpp/src/rerun/archetypes/transform3d_ext.cpp index b432b657397d..9ff2878947c6 100644 --- a/rerun_cpp/src/rerun/archetypes/transform3d_ext.cpp +++ b/rerun_cpp/src/rerun/archetypes/transform3d_ext.cpp @@ -5,296 +5,321 @@ // -namespace rerun { - namespace archetypes { - +namespace rerun::archetypes { #if 0 - // - - /// Identity transformation. - /// - /// Applying this transform does not alter an entity's transformation. - RERUN_SDK_EXPORT static const Transform3D IDENTITY; - - /// Creates a new 3D transform from translation and matrix provided as 3 columns. - /// - /// \param _translation \çopydoc Transform3D::translation - /// \param columns Column vectors of 3x3 matrix. - /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent - /// - /// _Implementation note:_ This overload is necessary, otherwise the array may be - /// interpreted as bool and call the wrong overload. - Transform3D( - const components::Translation3D& _translation, const datatypes::Vec3D (&columns)[3], - bool from_parent = false - ) - : transform(datatypes::TranslationRotationScale3D(from_parent)), - mat3x3(Collection::take_ownership( - components::TransformMat3x3(columns) - )), - translation(Collection::take_ownership(_translation)) {} - - /// Creates a new 3D transform from translation/matrix. - /// - /// \param _translation \çopydoc Transform3D::translation - /// \param _mat3x3 \copydoc Transform3D::mat3x3 - /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent - Transform3D( - const components::Translation3D& _translation, - const components::TransformMat3x3& _mat3x3, bool from_parent = false - ) - : transform(datatypes::TranslationRotationScale3D(from_parent)), - mat3x3(Collection::take_ownership(_mat3x3)), - translation(Collection::take_ownership(_translation)) {} - - /// From a translation applied after a 3x3 matrix. - /// - /// \param translation \çopydoc Transform3D::translation - /// \param mat3x3 \copydoc Transform3D::mat3x3 - static Transform3D from_translation_mat3x3( - const components::Translation3D& translation, const components::TransformMat3x3& mat3x3 - ) { - return Transform3D(translation, mat3x3, false); - } - - /// From a translation applied after a 3x3 matrix provided as 3 columns. - /// - /// \param translation \çopydoc Transform3D::translation - /// \param columns Column vectors of 3x3 matrix. - static Transform3D from_translation_mat3x3( - const components::Translation3D& translation, const datatypes::Vec3D (&columns)[3] - ) { - return Transform3D::from_translation_mat3x3( - translation, - components::TransformMat3x3(columns) - ); - } - - /// From translation only. - /// - /// \param _translation \çopydoc Transform3D::translation - /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent - Transform3D(const components::Translation3D& _translation, bool from_parent = false) - : transform(datatypes::TranslationRotationScale3D(from_parent)), - translation(Collection::take_ownership(_translation)) {} - - /// From a translation. - /// - /// \param translation \çopydoc Transform3D::translation - static Transform3D from_translation(const components::Translation3D& translation) { - return Transform3D(translation, false); - } - - /// From 3x3 matrix only. - /// - /// \param _mat3x3 \copydoc Transform3D::mat3x3 - /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent - Transform3D(const components::TransformMat3x3& _mat3x3, bool from_parent = false) - : transform(datatypes::TranslationRotationScale3D(from_parent)), - mat3x3(Collection::take_ownership(_mat3x3)) {} - - /// From 3x3 matrix only. - /// - /// \param mat3x3 \copydoc Transform3D::mat3x3 - static Transform3D from_mat3x3(const components::TransformMat3x3& mat3x3) { - return Transform3D(mat3x3, false); - } - - /// From 3x3 matrix provided as 3 columns only. - /// - /// \param columns Column vectors of 3x3 matrix. - /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent - Transform3D(const datatypes::Vec3D (&columns)[3], bool from_parent = false) - : transform(datatypes::TranslationRotationScale3D(from_parent)), - mat3x3(Collection::take_ownership( - components::TransformMat3x3(columns) - )) {} - - /// From 3x3 matrix provided as 3 columns only. - /// - /// \param columns Column vectors of 3x3 matrix. - static Transform3D from_mat3x3(const datatypes::Vec3D (&columns)[3]) { - return Transform3D::from_mat3x3(components::TransformMat3x3(columns)); - } - - /// Creates a new 3D transform from translation/rotation/scale. - /// - /// \param _translation \copydoc Transform3D::translation - /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation - /// \param scale \copydoc datatypes::TranslationRotationScale3D::scale - /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent - Transform3D( - const components::Translation3D& _translation, const datatypes::Rotation3D& rotation, - const datatypes::Scale3D& scale, bool from_parent = false - ) - : transform(datatypes::TranslationRotationScale3D(rotation, scale, from_parent)), - translation(Collection::take_ownership(_translation)) {} - - /// Creates a new 3D transform from translation/rotation/uniform-scale. - /// - /// \param _translation \copydoc Transform3D::translation - /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation - /// \param uniform_scale Uniform scale factor that is applied to all axis equally. - /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent - /// - /// _Implementation note:_ This explicit overload prevents interpretation of the float as - /// bool, leading to a call to the wrong overload. - Transform3D( - const components::Translation3D& _translation, const datatypes::Rotation3D& rotation, - float uniform_scale, bool from_parent = false - ) - : transform(datatypes::TranslationRotationScale3D(rotation, uniform_scale, from_parent) - ), - translation(Collection::take_ownership(_translation)) {} - - /// From a translation, applied after a rotation & scale, known as an affine transformation. - /// - /// \param translation \copydoc Transform3D::translation - /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation - /// \param scale \copydoc datatypes::TranslationRotationScale3D::scale - static Transform3D from_translation_rotation_scale( - const components::Translation3D& translation, const datatypes::Rotation3D& rotation, - const datatypes::Scale3D& scale - ) { - return Transform3D(translation, rotation, scale, false); - } - - /// Creates a new rigid transform (translation & rotation only). - /// - /// \param _translation \copydoc Transform3D::translation - /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation - /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent - Transform3D( - const components::Translation3D& _translation, const datatypes::Rotation3D& rotation, - bool from_parent = false - ) - : transform(datatypes::TranslationRotationScale3D(rotation, from_parent)), - translation(Collection::take_ownership(_translation)) {} - - /// From a rotation & scale. - /// - /// \param translation \copydoc Transform3D::translation - /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation - static Transform3D from_translation_rotation( - const components::Translation3D& translation, const datatypes::Rotation3D& rotation - ) { - return Transform3D(translation, rotation, false); - } - - /// From translation & scale only. - /// - /// \param _translation \copydoc Transform3D::translation - /// \param scale datatypes::TranslationRotationScale3D::scale - /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent - Transform3D( - const components::Translation3D& _translation, const datatypes::Scale3D& scale, - bool from_parent = false - ) - : transform(datatypes::TranslationRotationScale3D(scale, from_parent)), - translation(Collection::take_ownership(_translation)) {} - - /// From a translation applied after a scale. - /// - /// \param translation \copydoc Transform3D::translation - /// \param scale datatypes::TranslationRotationScale3D::scale - static Transform3D from_translation_scale( - const components::Translation3D& translation, const datatypes::Scale3D& scale - ) { - return Transform3D(translation, scale, false); - } - - /// From translation & uniform scale only. - /// - /// \param _translation \copydoc Transform3D::translation - /// \param uniform_scale Uniform scale factor that is applied to all axis equally. - /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent - /// - /// _Implementation note:_ This explicit overload prevents interpretation of the float as - /// bool, leading to a call to the wrong overload. - Transform3D( - const components::Translation3D& _translation, float uniform_scale, - bool from_parent = false - ) - : transform(datatypes::TranslationRotationScale3D(uniform_scale, from_parent)), - translation(Collection::take_ownership(_translation)) {} - - /// From rotation & scale. - /// - /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation - /// \param scale datatypes::TranslationRotationScale3D::scale - /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent - Transform3D( - const datatypes::Rotation3D& rotation, const datatypes::Scale3D& scale, - bool from_parent = false - ) - : transform(datatypes::TranslationRotationScale3D(rotation, scale, from_parent)) {} - - /// From rotation & uniform scale. - /// - /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation - /// \param uniform_scale Uniform scale factor that is applied to all axis equally. - /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent - /// - /// _Implementation note:_ This explicit overload prevents interpretation of the float as - /// bool, leading to a call to the wrong overload. - Transform3D( - const datatypes::Rotation3D& rotation, float uniform_scale, bool from_parent = false - ) - : transform(datatypes::TranslationRotationScale3D(rotation, uniform_scale, from_parent) - ) {} - - /// From a rotation & scale. - /// - /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation - /// \param scale datatypes::TranslationRotationScale3D::scale - static Transform3D from_rotation_scale( - const datatypes::Rotation3D& rotation, const datatypes::Scale3D& scale - ) { - return Transform3D(rotation, scale, false); - } - - /// From rotation only. - /// - /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation - /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent - Transform3D(const datatypes::Rotation3D& rotation, bool from_parent = false) - : transform(datatypes::TranslationRotationScale3D(rotation, from_parent)) {} - - /// From rotation only. - /// - /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation - static Transform3D from_rotation(const datatypes::Rotation3D& rotation) { - return Transform3D(rotation, false); - } - - /// From scale only. - /// - /// \param scale \copydoc datatypes::TranslationRotationScale3D::from_parent - /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::scale - Transform3D(const datatypes::Scale3D& scale, bool from_parent = false) - : transform(datatypes::TranslationRotationScale3D(scale, from_parent)) {} - - /// From scale only. - /// - /// \param scale datatypes::TranslationRotationScale3D::scale - static Transform3D from_scale(const datatypes::Scale3D& scale) { - return Transform3D(scale, false); - } - - /// TODO(#6831): Should be autogenerated once from_parent component is introduced - Transform3D with_from_parent(bool from_parent) && { - auto translation_rotation_scale = transform.repr.get_translation_rotation_scale(); - if (translation_rotation_scale != nullptr) { - auto cpy = *translation_rotation_scale; - cpy.from_parent = from_parent; - transform = cpy; - } - // See: https://github.com/rerun-io/rerun/issues/4027 - RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + // + + /// Identity transformation. + /// + /// Applying this transform does not alter an entity's transformation. + RERUN_SDK_EXPORT static const Transform3D IDENTITY; + + /// Creates a new 3D transform from translation and matrix provided as 3 columns. + /// + /// \param translation_ \çopydoc Transform3D::translation + /// \param columns Column vectors of 3x3 matrix. + /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent + /// + /// _Implementation note:_ This overload is necessary, otherwise the array may be + /// interpreted as bool and call the wrong overload. + Transform3D( + const components::Translation3D& translation_, const datatypes::Vec3D (&columns)[3], + bool from_parent = false + ) + : transform(datatypes::TranslationRotationScale3D(from_parent)), + translation(Collection::take_ownership(translation_)), + mat3x3(Collection::take_ownership( + components::TransformMat3x3(columns) + )) {} + + /// Creates a new 3D transform from translation/matrix. + /// + /// \param translation_ \çopydoc Transform3D::translation + /// \param mat3x3_ \copydoc Transform3D::mat3x3 + /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent + Transform3D( + const components::Translation3D& translation_, const components::TransformMat3x3& mat3x3_, + bool from_parent = false + ) + : transform(datatypes::TranslationRotationScale3D(from_parent)), + translation(Collection::take_ownership(translation_)), + mat3x3(Collection::take_ownership(mat3x3_)) {} + + /// From a translation applied after a 3x3 matrix. + /// + /// \param translation \çopydoc Transform3D::translation + /// \param mat3x3 \copydoc Transform3D::mat3x3 + static Transform3D from_translation_mat3x3( + const components::Translation3D& translation, const components::TransformMat3x3& mat3x3 + ) { + return Transform3D(translation, mat3x3, false); + } + + /// From a translation applied after a 3x3 matrix provided as 3 columns. + /// + /// \param translation \çopydoc Transform3D::translation + /// \param columns Column vectors of 3x3 matrix. + static Transform3D from_translation_mat3x3( + const components::Translation3D& translation, const datatypes::Vec3D (&columns)[3] + ) { + return Transform3D::from_translation_mat3x3( + translation, + components::TransformMat3x3(columns) + ); + } + + /// From translation only. + /// + /// \param translation_ \çopydoc Transform3D::translation + /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent + Transform3D(const components::Translation3D& translation_, bool from_parent = false) + : transform(datatypes::TranslationRotationScale3D(from_parent)), + translation(Collection::take_ownership(translation_)) {} + + /// From a translation. + /// + /// \param translation \çopydoc Transform3D::translation + static Transform3D from_translation(const components::Translation3D& translation) { + return Transform3D(translation, false); + } + + /// From 3x3 matrix only. + /// + /// \param mat3x3_ \copydoc Transform3D::mat3x3 + /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent + Transform3D(const components::TransformMat3x3& mat3x3_, bool from_parent = false) + : transform(datatypes::TranslationRotationScale3D(from_parent)), + mat3x3(Collection::take_ownership(mat3x3_)) {} + + /// From 3x3 matrix only. + /// + /// \param mat3x3 \copydoc Transform3D::mat3x3 + static Transform3D from_mat3x3(const components::TransformMat3x3& mat3x3) { + return Transform3D(mat3x3, false); + } + + /// From 3x3 matrix provided as 3 columns only. + /// + /// \param columns Column vectors of 3x3 matrix. + /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent + Transform3D(const datatypes::Vec3D (&columns)[3], bool from_parent = false) + : transform(datatypes::TranslationRotationScale3D(from_parent)), + mat3x3(Collection::take_ownership( + components::TransformMat3x3(columns) + )) {} + + /// From 3x3 matrix provided as 3 columns only. + /// + /// \param columns Column vectors of 3x3 matrix. + static Transform3D from_mat3x3(const datatypes::Vec3D (&columns)[3]) { + return Transform3D::from_mat3x3(components::TransformMat3x3(columns)); + } + + /// Creates a new 3D transform from translation/rotation/scale. + /// + /// \param translation_ \copydoc Transform3D::translation + /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation + /// \param scale_ \copydoc Transform3D::scale + /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent + Transform3D( + const components::Translation3D& translation_, const datatypes::Rotation3D& rotation, + const components::Scale3D& scale_, bool from_parent = false + ) + : transform(datatypes::TranslationRotationScale3D(rotation, from_parent)), + translation(Collection::take_ownership(translation_)), + scale(Collection::take_ownership(scale_)) {} + + /// Creates a new 3D transform from translation/rotation/uniform-scale. + /// + /// \param translation_ \copydoc Transform3D::translation + /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation + /// \param uniform_scale Uniform scale factor that is applied to all axis equally. + /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent + /// + /// _Implementation note:_ This explicit overload prevents interpretation of the float as + /// bool, leading to a call to the wrong overload. + Transform3D( + const components::Translation3D& translation_, const datatypes::Rotation3D& rotation, + float uniform_scale, bool from_parent = false + ) + : Transform3D(translation_, rotation, components::Scale3D(uniform_scale), from_parent) {} + + /// From a translation, applied after a rotation & scale, known as an affine transformation. + /// + /// \param translation \copydoc Transform3D::translation + /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation + /// \param scale \copydoc Transform3D::scale + static Transform3D from_translation_rotation_scale( + const components::Translation3D& translation, const datatypes::Rotation3D& rotation, + const components::Scale3D& scale + ) { + return Transform3D(translation, rotation, scale, false); + } + + /// From a translation, applied after a rotation & scale, known as an affine transformation. + /// + /// \param translation \copydoc Transform3D::translation + /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation + /// \param uniform_scale Uniform scale factor that is applied to all axis equally. + static Transform3D from_translation_rotation_scale( + const components::Translation3D& translation, const datatypes::Rotation3D& rotation, + float uniform_scale + ) { + return Transform3D(translation, rotation, components::Scale3D(uniform_scale), false); + } + + /// Creates a new rigid transform (translation & rotation only). + /// + /// \param translation_ \copydoc Transform3D::translation + /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation + /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent + Transform3D( + const components::Translation3D& translation_, const datatypes::Rotation3D& rotation, + bool from_parent = false + ) + : transform(datatypes::TranslationRotationScale3D(rotation, from_parent)), + translation(Collection::take_ownership(translation_)) {} + + /// From a rotation & scale. + /// + /// \param translation \copydoc Transform3D::translation + /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation + static Transform3D from_translation_rotation( + const components::Translation3D& translation, const datatypes::Rotation3D& rotation + ) { + return Transform3D(translation, rotation, false); + } + + /// From translation & scale only. + /// + /// \param translation_ \copydoc Transform3D::translation + /// \param scale_ Transform3D::scale + /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent + Transform3D( + const components::Translation3D& translation_, const components::Scale3D& scale_, + bool from_parent = false + ) + : transform(datatypes::TranslationRotationScale3D(from_parent)), + translation(Collection::take_ownership(translation_)), + scale(Collection::take_ownership(scale_)) {} + + /// From a translation applied after a scale. + /// + /// \param translation \copydoc Transform3D::translation + /// \param scale Transform3D::scale + static Transform3D from_translation_scale( + const components::Translation3D& translation, const components::Scale3D& scale + ) { + return Transform3D(translation, scale, false); + } + + /// From translation & uniform scale only. + /// + /// \param translation_ \copydoc Transform3D::translation + /// \param uniform_scale Uniform scale factor that is applied to all axis equally. + /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent + /// + /// _Implementation note:_ This explicit overload prevents interpretation of the float as + /// bool, leading to a call to the wrong overload. + Transform3D( + const components::Translation3D& translation_, float uniform_scale, bool from_parent = false + ) + : Transform3D(translation_, components::Scale3D(uniform_scale), from_parent) {} + + /// From rotation & scale. + /// + /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation + /// \param scale_ Transform3D::scale + /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent + Transform3D( + const datatypes::Rotation3D& rotation, const components::Scale3D& scale_, + bool from_parent = false + ) + : transform(datatypes::TranslationRotationScale3D(rotation, from_parent)), + scale(Collection::take_ownership(scale_)) {} + + /// From rotation & uniform scale. + /// + /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation + /// \param uniform_scale Uniform scale factor that is applied to all axis equally. + /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent + /// + /// _Implementation note:_ This explicit overload prevents interpretation of the float as + /// bool, leading to a call to the wrong overload. + Transform3D( + const datatypes::Rotation3D& rotation, float uniform_scale, bool from_parent = false + ) + : Transform3D(rotation, components::Scale3D(uniform_scale), from_parent) {} + + /// From a rotation & scale. + /// + /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation + /// \param scale Transform3D::scale + static Transform3D from_rotation_scale( + const datatypes::Rotation3D& rotation, const components::Scale3D& scale + ) { + return Transform3D(rotation, scale, false); + } + + /// From a rotation & uniform scale. + /// + /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation + /// \param uniform_scale Uniform scale factor that is applied to all axis equally. + static Transform3D from_rotation_scale( + const datatypes::Rotation3D& rotation, float uniform_scale + ) { + return Transform3D(rotation, components::Scale3D(uniform_scale), false); + } + + /// From rotation only. + /// + /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation + /// \param from_parent \copydoc datatypes::TranslationRotationScale3D::from_parent + Transform3D(const datatypes::Rotation3D& rotation, bool from_parent = false) + : transform(datatypes::TranslationRotationScale3D(rotation, from_parent)) {} + + /// From rotation only. + /// + /// \param rotation \copydoc datatypes::TranslationRotationScale3D::rotation + static Transform3D from_rotation(const datatypes::Rotation3D& rotation) { + return Transform3D(rotation, false); + } + + /// From scale only. + /// + /// \param scale_ \copydoc datatypes::TranslationRotationScale3D::from_parent + /// \param from_parent \copydoc Transform3D::scale + Transform3D(const components::Scale3D& scale_, bool from_parent = false) + : transform(datatypes::TranslationRotationScale3D(from_parent)), + scale(Collection::take_ownership(scale_)) {} + + /// From scale only. + /// + /// \param scale Transform3D::scale + static Transform3D from_scale(const components::Scale3D& scale) { + return Transform3D(scale, false); + } + + /// From scale only. + /// + /// \param uniform_scale Uniform scale factor that is applied to all axis equally. + static Transform3D from_scale(float uniform_scale) { + return Transform3D(components::Scale3D(uniform_scale), false); + } + + /// TODO(#6831): Should be autogenerated once from_parent component is introduced + Transform3D with_from_parent(bool from_parent) && { + auto translation_rotation_scale = transform.repr.get_translation_rotation_scale(); + if (translation_rotation_scale != nullptr) { + auto cpy = *translation_rotation_scale; + cpy.from_parent = from_parent; + transform = cpy; } + // See: https://github.com/rerun-io/rerun/issues/4027 + RR_WITH_MAYBE_UNINITIALIZED_DISABLED(return std::move(*this);) + } - // + // #endif - } // namespace archetypes -} // namespace rerun +} // namespace rerun::archetypes diff --git a/rerun_cpp/src/rerun/components.hpp b/rerun_cpp/src/rerun/components.hpp index 15403881ad98..8f15c59b02bc 100644 --- a/rerun_cpp/src/rerun/components.hpp +++ b/rerun_cpp/src/rerun/components.hpp @@ -37,6 +37,7 @@ #include "components/resolution.hpp" #include "components/rotation3d.hpp" #include "components/scalar.hpp" +#include "components/scale3d.hpp" #include "components/stroke_width.hpp" #include "components/tensor_data.hpp" #include "components/tensor_dimension_index_selection.hpp" diff --git a/rerun_cpp/src/rerun/components/.gitattributes b/rerun_cpp/src/rerun/components/.gitattributes index 076543400d6c..1edc81a2d2e4 100644 --- a/rerun_cpp/src/rerun/components/.gitattributes +++ b/rerun_cpp/src/rerun/components/.gitattributes @@ -43,6 +43,7 @@ range1d.hpp linguist-generated=true resolution.hpp linguist-generated=true rotation3d.hpp linguist-generated=true scalar.hpp linguist-generated=true +scale3d.hpp linguist-generated=true stroke_width.hpp linguist-generated=true tensor_data.hpp linguist-generated=true tensor_dimension_index_selection.hpp linguist-generated=true diff --git a/rerun_cpp/src/rerun/components/scale3d.hpp b/rerun_cpp/src/rerun/components/scale3d.hpp new file mode 100644 index 000000000000..8a707cf34466 --- /dev/null +++ b/rerun_cpp/src/rerun/components/scale3d.hpp @@ -0,0 +1,89 @@ +// DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/cpp/mod.rs +// Based on "crates/store/re_types/definitions/rerun/components/scale3d.fbs". + +#pragma once + +#include "../datatypes/vec3d.hpp" +#include "../result.hpp" + +#include +#include +#include + +namespace rerun::components { + /// **Component**: A 3D scale factor. + /// + /// A scale of 1.0 means no scaling. + /// A scale of 2.0 means doubling the size. + /// Each component scales along the corresponding axis. + struct Scale3D { + rerun::datatypes::Vec3D scale; + + public: + // Extensions to generated type defined in 'scale3d_ext.cpp' + + /// Construct `Scale3D` from x/y/z values. + Scale3D(float x, float y, float z) : scale{x, y, z} {} + + /// Construct `Scale3D` from x/y/z float pointer. + explicit Scale3D(const float* xyz) : scale{xyz[0], xyz[1], xyz[2]} {} + + /// Construct a `Scale3D` from a uniform scale factor. + explicit Scale3D(float uniform_scale) + : Scale3D(datatypes::Vec3D{uniform_scale, uniform_scale, uniform_scale}) {} + + /// Explicitly construct a `Scale3D` from a uniform scale factor. + static Scale3D uniform(float uniform_scale) { + return Scale3D(uniform_scale); + } + + /// Explicitly construct a `Scale3D` from a 3D scale factor. + static Scale3D three_d(datatypes::Vec3D scale) { + return Scale3D(scale); + } + + public: + Scale3D() = default; + + Scale3D(rerun::datatypes::Vec3D scale_) : scale(scale_) {} + + Scale3D& operator=(rerun::datatypes::Vec3D scale_) { + scale = scale_; + return *this; + } + + Scale3D(std::array xyz_) : scale(xyz_) {} + + Scale3D& operator=(std::array xyz_) { + scale = xyz_; + return *this; + } + + /// Cast to the underlying Vec3D datatype + operator rerun::datatypes::Vec3D() const { + return scale; + } + }; +} // namespace rerun::components + +namespace rerun { + static_assert(sizeof(rerun::datatypes::Vec3D) == sizeof(components::Scale3D)); + + /// \private + template <> + struct Loggable { + static constexpr const char Name[] = "rerun.components.Scale3D"; + + /// Returns the arrow data type this type corresponds to. + static const std::shared_ptr& arrow_datatype() { + return Loggable::arrow_datatype(); + } + + /// Serializes an array of `rerun::components::Scale3D` into an arrow array. + static Result> to_arrow( + const components::Scale3D* instances, size_t num_instances + ) { + return Loggable::to_arrow(&instances->scale, num_instances); + } + }; +} // namespace rerun diff --git a/rerun_cpp/src/rerun/components/scale3d_ext.cpp b/rerun_cpp/src/rerun/components/scale3d_ext.cpp new file mode 100644 index 000000000000..cf727e74b4db --- /dev/null +++ b/rerun_cpp/src/rerun/components/scale3d_ext.cpp @@ -0,0 +1,27 @@ +namespace rerun::components { +#if 0 + // + + /// Construct `Scale3D` from x/y/z values. + Scale3D(float x, float y, float z) : scale{x, y, z} {} + + /// Construct `Scale3D` from x/y/z float pointer. + explicit Scale3D(const float* xyz) : scale{xyz[0], xyz[1], xyz[2]} {} + + /// Construct a `Scale3D` from a uniform scale factor. + explicit Scale3D(float uniform_scale) : Scale3D(datatypes::Vec3D{uniform_scale, uniform_scale, uniform_scale}) {} + + /// Explicitly construct a `Scale3D` from a uniform scale factor. + static Scale3D uniform(float uniform_scale) { + return Scale3D(uniform_scale); + } + + /// Explicitly construct a `Scale3D` from a 3D scale factor. + static Scale3D three_d(datatypes::Vec3D scale) { + return Scale3D(scale); + } + + // + +#endif +} // namespace rerun::components diff --git a/rerun_cpp/src/rerun/components/translation3d.hpp b/rerun_cpp/src/rerun/components/translation3d.hpp index edfcc89ae287..6256295dfc0e 100644 --- a/rerun_cpp/src/rerun/components/translation3d.hpp +++ b/rerun_cpp/src/rerun/components/translation3d.hpp @@ -18,10 +18,10 @@ namespace rerun::components { public: // Extensions to generated type defined in 'translation3d_ext.cpp' - /// Construct Translation3D from x/y/z values. + /// Construct `Translation3D` from x/y/z values. Translation3D(float x, float y, float z) : vector{x, y, z} {} - /// Construct Vec3D from x/y/z float pointer. + /// Construct `Translation3D` from x/y/z float pointer. explicit Translation3D(const float* xyz) : vector{xyz[0], xyz[1], xyz[2]} {} float x() const { diff --git a/rerun_cpp/src/rerun/components/translation3d_ext.cpp b/rerun_cpp/src/rerun/components/translation3d_ext.cpp index 75f2fd31259d..45e95d685669 100644 --- a/rerun_cpp/src/rerun/components/translation3d_ext.cpp +++ b/rerun_cpp/src/rerun/components/translation3d_ext.cpp @@ -1,38 +1,25 @@ -#include "translation3d.hpp" +namespace rerun::components { +#if 0 + // -// Uncomment for better auto-complete while editing the extension. -// #define EDIT_EXTENSION + /// Construct `Translation3D` from x/y/z values. + Translation3D(float x, float y, float z) : vector{x, y, z} {} -namespace rerun { - namespace components { + /// Construct `Translation3D` from x/y/z float pointer. + explicit Translation3D(const float* xyz) : vector{xyz[0], xyz[1], xyz[2]} {} -#ifdef EDIT_EXTENSION - struct Translation3DExt { - float vector[3]; -#define Translation3D Translation3DExt + float x() const { + return vector.x(); + } - // + float y() const { + return vector.y(); + } - /// Construct Translation3D from x/y/z values. - Translation3D(float x, float y, float z) : vector{x, y, z} {} + float z() const { + return vector.z(); + } - /// Construct Vec3D from x/y/z float pointer. - explicit Translation3D(const float* xyz) : vector{xyz[0], xyz[1], xyz[2]} {} - - float x() const { - return vector.x(); - } - - float y() const { - return vector.y(); - } - - float z() const { - return vector.z(); - } - - // - }; + // #endif - } // namespace components -} // namespace rerun +} // namespace rerun::components diff --git a/rerun_cpp/tests/archetypes/transform3d.cpp b/rerun_cpp/tests/archetypes/transform3d.cpp index 98ca05e307a7..d271a09df333 100644 --- a/rerun_cpp/tests/archetypes/transform3d.cpp +++ b/rerun_cpp/tests/archetypes/transform3d.cpp @@ -35,7 +35,7 @@ SCENARIO( rrd::TranslationRotationScale3D manual_translation_rotation_scale; manual_translation_rotation_scale.translation = std::nullopt; manual_translation_rotation_scale.rotation = std::nullopt; - manual_translation_rotation_scale.scale = std::nullopt; + manual.scale = std::nullopt; manual_translation_rotation_scale.from_parent = from_parent; manual.transform = rrd::Transform3D::translation_rotation_scale(manual_translation_rotation_scale); @@ -70,13 +70,9 @@ SCENARIO( } GIVEN("Transform3D from scale and from_parent==" << from_parent) { - auto utility = Transform3D::from_scale( + auto utility = Transform3D::from_scale({3.0f, 2.0f, 1.0f}).with_from_parent(from_parent); - rrd::Scale3D::three_d({3.0f, 2.0f, 1.0f}) - ) - .with_from_parent(from_parent); - - manual_translation_rotation_scale.scale = rrd::Scale3D::three_d({3.0f, 2.0f, 1.0f}); + manual.scale = rerun::components::Scale3D(3.0f, 2.0f, 1.0f); manual.transform.repr = rrd::Transform3D::translation_rotation_scale(manual_translation_rotation_scale); @@ -103,14 +99,11 @@ SCENARIO( } GIVEN("Transform3D from translation & scale and from_parent==" << from_parent) { - auto utility = Transform3D::from_translation_scale( - {1.0f, 2.0f, 3.0f}, - rrd::Scale3D::three_d({3.0f, 2.0f, 1.0f}) - ) + auto utility = Transform3D::from_translation_scale({1.0f, 2.0f, 3.0f}, {3.0f, 2.0f, 1.0f}) .with_from_parent(from_parent); manual.translation = rerun::components::Translation3D(1.0f, 2.0f, 3.0f); - manual_translation_rotation_scale.scale = rrd::Scale3D::three_d({3.0f, 2.0f, 1.0f}); + manual.scale = rerun::components::Scale3D(3.0f, 2.0f, 1.0f); manual.transform.repr = rrd::Transform3D::translation_rotation_scale(manual_translation_rotation_scale); @@ -121,13 +114,13 @@ SCENARIO( auto utility = Transform3D::from_translation_rotation_scale( {1.0f, 2.0f, 3.0f}, rotation, - rrd::Scale3D::three_d({3.0f, 2.0f, 1.0f}) + {3.0f, 2.0f, 1.0f} ) .with_from_parent(from_parent); manual.translation = rerun::components::Translation3D(1.0f, 2.0f, 3.0f); manual_translation_rotation_scale.rotation = rotation; - manual_translation_rotation_scale.scale = rrd::Scale3D::three_d({3.0f, 2.0f, 1.0f}); + manual.scale = rerun::components::Scale3D(3.0f, 2.0f, 1.0f); manual.transform.repr = rrd::Transform3D::translation_rotation_scale(manual_translation_rotation_scale); @@ -135,12 +128,11 @@ SCENARIO( } GIVEN("Transform3D from rotation & scale and from_parent==" << from_parent) { - auto utility = - Transform3D::from_rotation_scale(rotation, rrd::Scale3D::three_d({3.0f, 2.0f, 1.0f})) - .with_from_parent(from_parent); + auto utility = Transform3D::from_rotation_scale(rotation, {3.0f, 2.0f, 1.0f}) + .with_from_parent(from_parent); manual_translation_rotation_scale.rotation = rotation; - manual_translation_rotation_scale.scale = rrd::Scale3D::three_d({3.0f, 2.0f, 1.0f}); + manual.scale = rerun::components::Scale3D(3.0f, 2.0f, 1.0f); manual.transform.repr = rrd::Transform3D::translation_rotation_scale(manual_translation_rotation_scale); diff --git a/rerun_py/rerun_sdk/rerun/__init__.py b/rerun_py/rerun_sdk/rerun/__init__.py index 072f42f9796b..d5ccc0c492b6 100644 --- a/rerun_py/rerun_sdk/rerun/__init__.py +++ b/rerun_py/rerun_sdk/rerun/__init__.py @@ -79,6 +79,7 @@ OutOfTreeTransform3D as OutOfTreeTransform3D, OutOfTreeTransform3DBatch as OutOfTreeTransform3DBatch, Radius as Radius, + Scale3D as Scale3D, TensorDimensionIndexSelection as TensorDimensionIndexSelection, TextLogLevel as TextLogLevel, ) @@ -87,7 +88,6 @@ ClassDescription as ClassDescription, Quaternion as Quaternion, RotationAxisAngle as RotationAxisAngle, - Scale3D as Scale3D, TensorData as TensorData, TensorDimensionSelection as TensorDimensionSelection, TimeInt as TimeInt, diff --git a/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py b/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py index bcb0d512c47e..26c531ad9a6c 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/transform3d.py @@ -21,9 +21,9 @@ class Transform3D(Transform3DExt, Archetype): """ **Archetype**: A transform between two 3D spaces, i.e. a pose. - All components are applied in the order they are listed here. + All components are applied in the inverse order they are listed here. E.g. if both a 4x4 matrix with a translation and a translation vector are present, - the matrix is applied first, then the translation vector on top. + the translation is applied first, followed by the matrix. Each transform component can be listed multiple times, but transform tree propagation is only possible if there's only one instance for each transform component. @@ -138,8 +138,9 @@ def __attrs_clear__(self) -> None: """Convenience method for calling `__attrs_init__` with all `None`s.""" self.__attrs_init__( transform=None, # type: ignore[arg-type] - mat3x3=None, # type: ignore[arg-type] translation=None, # type: ignore[arg-type] + scale=None, # type: ignore[arg-type] + mat3x3=None, # type: ignore[arg-type] axis_length=None, # type: ignore[arg-type] ) @@ -158,21 +159,30 @@ def _clear(cls) -> Transform3D: # # (Docstring intentionally commented out to hide this field from the docs) - mat3x3: components.TransformMat3x3Batch | None = field( + translation: components.Translation3DBatch | None = field( metadata={"component": "optional"}, default=None, - converter=components.TransformMat3x3Batch._optional, # type: ignore[misc] + converter=components.Translation3DBatch._optional, # type: ignore[misc] ) - # 3x3 transformation matrices. + # Translation vectors. # # (Docstring intentionally commented out to hide this field from the docs) - translation: components.Translation3DBatch | None = field( + scale: components.Scale3DBatch | None = field( metadata={"component": "optional"}, default=None, - converter=components.Translation3DBatch._optional, # type: ignore[misc] + converter=components.Scale3DBatch._optional, # type: ignore[misc] ) - # Translation vectors. + # Scaling factor. + # + # (Docstring intentionally commented out to hide this field from the docs) + + mat3x3: components.TransformMat3x3Batch | None = field( + metadata={"component": "optional"}, + default=None, + converter=components.TransformMat3x3Batch._optional, # type: ignore[misc] + ) + # 3x3 transformation matrices. # # (Docstring intentionally commented out to hide this field from the docs) diff --git a/rerun_py/rerun_sdk/rerun/archetypes/transform3d_ext.py b/rerun_py/rerun_sdk/rerun/archetypes/transform3d_ext.py index 14c515e4df3d..9c3febf1c035 100644 --- a/rerun_py/rerun_sdk/rerun/archetypes/transform3d_ext.py +++ b/rerun_py/rerun_sdk/rerun/archetypes/transform3d_ext.py @@ -2,13 +2,13 @@ from typing import Any +from rerun.components import Scale3D from rerun.datatypes import ( Float32Like, - Mat3x3Like, + Mat3x3ArrayLike, Rotation3DLike, - Scale3DLike, TranslationRotationScale3D, - Vec3DLike, + Vec3DArrayLike, ) from ..error_utils import catch_and_log_exceptions @@ -21,10 +21,10 @@ class Transform3DExt: def __init__( self: Any, *, - mat3x3: Mat3x3Like | None = None, - translation: Vec3DLike | None = None, - rotation: Rotation3DLike | None = None, - scale: Scale3DLike | None = None, + translation: Vec3DArrayLike | None = None, + rotation: Rotation3DLike | None = None, # TODO(#6831): Should allow arrays. + scale: Vec3DArrayLike | Float32Like | None = None, + mat3x3: Mat3x3ArrayLike | None = None, from_parent: bool | None = None, axis_length: Float32Like | None = None, ): @@ -33,16 +33,16 @@ def __init__( Parameters ---------- + translation: + 3D translation vector. + rotation: + 3D rotation. + scale: + 3D scale. mat3x3: 3x3 matrix representing scale and rotation, applied after translation. Not compatible with `rotation` and `scale` parameters. TODO(#3559): Support 4x4 and 4x3 matrices. - translation: - 3D translation vector, applied last. - rotation: - 3D rotation, applied second. - scale: - 3D scale, applied last. from_parent: If true, the transform maps from the parent space to the space where the transform was logged. Otherwise, the transform maps from the space to its parent. @@ -58,15 +58,17 @@ def __init__( if from_parent is None: from_parent = False + if scale is not None and (not hasattr(scale, "__len__") or len(scale) == 1): # type: ignore[arg-type] + scale = Scale3D(scale) # type: ignore[arg-type] + self.__attrs_init__( # TODO(#6831): Remove. transform=TranslationRotationScale3D( - translation=None, rotation=rotation, - scale=scale, from_parent=from_parent, ), mat3x3=mat3x3, + scale=scale, translation=translation, axis_length=axis_length, ) diff --git a/rerun_py/rerun_sdk/rerun/components/.gitattributes b/rerun_py/rerun_sdk/rerun/components/.gitattributes index 87cecac0c68a..4c9a67021e11 100644 --- a/rerun_py/rerun_sdk/rerun/components/.gitattributes +++ b/rerun_py/rerun_sdk/rerun/components/.gitattributes @@ -37,6 +37,7 @@ range1d.py linguist-generated=true resolution.py linguist-generated=true rotation3d.py linguist-generated=true scalar.py linguist-generated=true +scale3d.py linguist-generated=true stroke_width.py linguist-generated=true tensor_data.py linguist-generated=true tensor_dimension_index_selection.py linguist-generated=true diff --git a/rerun_py/rerun_sdk/rerun/components/__init__.py b/rerun_py/rerun_sdk/rerun/components/__init__.py index 9a18d8cc3301..59e0ed1c258f 100644 --- a/rerun_py/rerun_sdk/rerun/components/__init__.py +++ b/rerun_py/rerun_sdk/rerun/components/__init__.py @@ -55,6 +55,7 @@ from .resolution import Resolution, ResolutionBatch, ResolutionType from .rotation3d import Rotation3D, Rotation3DBatch, Rotation3DType from .scalar import Scalar, ScalarBatch, ScalarType +from .scale3d import Scale3D, Scale3DBatch, Scale3DType from .stroke_width import StrokeWidth, StrokeWidthBatch, StrokeWidthType from .tensor_data import TensorData, TensorDataBatch, TensorDataType from .tensor_dimension_index_selection import ( @@ -195,6 +196,9 @@ "Scalar", "ScalarBatch", "ScalarType", + "Scale3D", + "Scale3DBatch", + "Scale3DType", "StrokeWidth", "StrokeWidthBatch", "StrokeWidthType", diff --git a/rerun_py/rerun_sdk/rerun/components/scale3d.py b/rerun_py/rerun_sdk/rerun/components/scale3d.py new file mode 100644 index 000000000000..1849b04b73cf --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/components/scale3d.py @@ -0,0 +1,43 @@ +# DO NOT EDIT! This file was auto-generated by crates/build/re_types_builder/src/codegen/python/mod.rs +# Based on "crates/store/re_types/definitions/rerun/components/scale3d.fbs". + +# You can extend this class by creating a "Scale3DExt" class in "scale3d_ext.py". + +from __future__ import annotations + +from .. import datatypes +from .._baseclasses import ( + ComponentBatchMixin, + ComponentMixin, +) +from .scale3d_ext import Scale3DExt + +__all__ = ["Scale3D", "Scale3DBatch", "Scale3DType"] + + +class Scale3D(Scale3DExt, datatypes.Vec3D, ComponentMixin): + """ + **Component**: A 3D scale factor. + + A scale of 1.0 means no scaling. + A scale of 2.0 means doubling the size. + Each component scales along the corresponding axis. + """ + + _BATCH_TYPE = None + # __init__ can be found in scale3d_ext.py + + # Note: there are no fields here because Scale3D delegates to datatypes.Vec3D + pass + + +class Scale3DType(datatypes.Vec3DType): + _TYPE_NAME: str = "rerun.components.Scale3D" + + +class Scale3DBatch(datatypes.Vec3DBatch, ComponentBatchMixin): + _ARROW_TYPE = Scale3DType() + + +# This is patched in late to avoid circular dependencies. +Scale3D._BATCH_TYPE = Scale3DBatch # type: ignore[assignment] diff --git a/rerun_py/rerun_sdk/rerun/components/scale3d_ext.py b/rerun_py/rerun_sdk/rerun/components/scale3d_ext.py new file mode 100644 index 000000000000..706f33bd4672 --- /dev/null +++ b/rerun_py/rerun_sdk/rerun/components/scale3d_ext.py @@ -0,0 +1,32 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Union + +if TYPE_CHECKING: + from rerun.datatypes import Float32Like, Vec3DLike + + +class Scale3DExt: + """Extension for [Scale3D][rerun.components.Scale3D].""" + + def __init__( + self: Any, + uniform_or_per_axis: Union[Vec3DLike, Float32Like] = True, + ): + """ + 3D scaling factor. + + A scale of 1.0 means no scaling. + A scale of 2.0 means doubling the size. + Each component scales along the corresponding axis. + + Parameters + ---------- + uniform_or_per_axis: + If a single value is given, it is applied the same to all three axis (uniform scaling). + + """ + if not hasattr(uniform_or_per_axis, "__len__") or len(uniform_or_per_axis) == 1: # type: ignore[arg-type] + self.__attrs_init__([uniform_or_per_axis, uniform_or_per_axis, uniform_or_per_axis]) + else: + self.__attrs_init__(uniform_or_per_axis) diff --git a/rerun_py/rerun_sdk/rerun/datatypes/mat3x3.py b/rerun_py/rerun_sdk/rerun/datatypes/mat3x3.py index 013262189910..0beaff581ba5 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/mat3x3.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/mat3x3.py @@ -78,10 +78,7 @@ def __array__(self, dtype: npt.DTypeLike = None) -> npt.NDArray[Any]: else: Mat3x3Like = Any -Mat3x3ArrayLike = Union[ - Mat3x3, - Sequence[Mat3x3Like], -] +Mat3x3ArrayLike = Union[Mat3x3, Sequence[Mat3x3Like], npt.ArrayLike] class Mat3x3Type(BaseExtensionType): diff --git a/rerun_py/rerun_sdk/rerun/datatypes/mat3x3_ext.py b/rerun_py/rerun_sdk/rerun/datatypes/mat3x3_ext.py index e25544cc7e28..aeb2d4c82709 100644 --- a/rerun_py/rerun_sdk/rerun/datatypes/mat3x3_ext.py +++ b/rerun_py/rerun_sdk/rerun/datatypes/mat3x3_ext.py @@ -42,7 +42,7 @@ def native_to_pa_array_override(data: Mat3x3ArrayLike, data_type: pa.DataType) - if isinstance(data, Mat3x3): matrices = [data] - elif len(data) == 0: + elif len(data) == 0: # type: ignore[arg-type] matrices = [] else: try: @@ -51,12 +51,12 @@ def native_to_pa_array_override(data: Mat3x3ArrayLike, data_type: pa.DataType) - matrices = [Mat3x3(data)] # type: ignore[arg-type] except ValueError: # If the data can't be possibly more than one Mat3x3, raise the original ValueError. - if isinstance(data[0], numbers.Number): + if isinstance(data[0], numbers.Number): # type: ignore[arg-type, index] raise # Otherwise try to convert it to a sequence of Mat3x3s # Let this value error propagate as the fallback - matrices = [Mat3x3(d) for d in data] + matrices = [Mat3x3(d) for d in data] # type: ignore[arg-type, union-attr] float_arrays = np.asarray([matrix.flat_columns for matrix in matrices], dtype=np.float32).reshape(-1) return pa.FixedSizeListArray.from_arrays(float_arrays, type=data_type) diff --git a/rerun_py/tests/unit/test_transform3d.py b/rerun_py/tests/unit/test_transform3d.py index d8ceb7a17b6f..4860af67a37c 100644 --- a/rerun_py/tests/unit/test_transform3d.py +++ b/rerun_py/tests/unit/test_transform3d.py @@ -98,12 +98,16 @@ def test_angle() -> None: def test_transform3d() -> None: + # TODO(#6831): Test with arrays of all fields. + axis_lengths = [None, 1, 1.0] from_parent_arrays = [None, True, False] + scale_arrays = [None, 1.0, 1, [1.0, 2.0, 3.0]] # TODO(#6831): repopulate this list with all transform variants all_arrays = itertools.zip_longest( MAT_3X3_INPUT + [None], + scale_arrays, VEC_3D_INPUT + [None], from_parent_arrays, axis_lengths, @@ -111,11 +115,13 @@ def test_transform3d() -> None: for ( mat3x3, + scale, translation, from_parent, axis_length, ) in all_arrays: mat3x3 = cast(Optional[rr.datatypes.Mat3x3Like], mat3x3) + scale = cast(Optional[rr.datatypes.Vec3DLike | rr.datatypes.Float32Like], scale) translation = cast(Optional[rr.datatypes.Vec3DLike], translation) from_parent = cast(Optional[bool], from_parent) axis_length = cast(Optional[rr.datatypes.Float32Like], axis_length) @@ -124,6 +130,7 @@ def test_transform3d() -> None: f"rr.Transform3D(\n" f" mat3x3={mat3x3!r}\n" # f" translation={translation!r}\n" # + f" scale={scale!r}\n" # f" from_parent={from_parent!r}\n" # f" axis_length={axis_length!r}\n" # f")" @@ -131,6 +138,7 @@ def test_transform3d() -> None: arch = rr.Transform3D( mat3x3=mat3x3, translation=translation, + scale=scale, from_parent=from_parent, axis_length=axis_length, ) @@ -142,6 +150,9 @@ def test_transform3d() -> None: assert arch.translation == rr.components.Translation3DBatch._optional( none_empty_or_value(translation, rr.components.Translation3D([1, 2, 3])) ) + assert arch.scale == rr.components.Scale3DBatch._optional( + none_empty_or_value(scale, rr.components.Scale3D(scale)) # type: ignore[arg-type] + ) assert arch.axis_length == rr.components.AxisLengthBatch._optional( none_empty_or_value(axis_length, rr.components.AxisLength(1.0)) ) diff --git a/tests/cpp/roundtrips/transform3d/main.cpp b/tests/cpp/roundtrips/transform3d/main.cpp index 8c28e19cb6c7..bfa84f92d460 100644 --- a/tests/cpp/roundtrips/transform3d/main.cpp +++ b/tests/cpp/roundtrips/transform3d/main.cpp @@ -27,7 +27,7 @@ int main(int, char** argv) { "transform/translation_scale", rerun::archetypes::Transform3D::from_translation_scale( {1.0f, 2.0f, 3.0f}, - rerun::datatypes::Scale3D::uniform(42.0f) + rerun::components::Scale3D::uniform(42.0f) ) .with_from_parent(true) ); @@ -51,7 +51,7 @@ int main(int, char** argv) { {0.2f, 0.2f, 0.8f}, rerun::datatypes::Angle::radians(PI) ), - rerun::datatypes::Scale3D::uniform(42.0) + rerun::components::Scale3D::uniform(42.0) ) .with_from_parent(true) ); diff --git a/tests/rust/roundtrips/transform3d/src/main.rs b/tests/rust/roundtrips/transform3d/src/main.rs index 8d106f284277..d3a385bd1d60 100644 --- a/tests/rust/roundtrips/transform3d/src/main.rs +++ b/tests/rust/roundtrips/transform3d/src/main.rs @@ -4,7 +4,8 @@ use std::f32::consts::TAU; use rerun::{ archetypes::Transform3D, - datatypes::{Angle, RotationAxisAngle, Scale3D}, + components::Scale3D, + datatypes::{Angle, RotationAxisAngle}, RecordingStream, }; @@ -28,7 +29,7 @@ fn run(rec: &RecordingStream, _args: &Args) -> anyhow::Result<()> { rec.log( "transform/translation_scale", - &Transform3D::from_translation_scale([1.0, 2.0, 3.0], Scale3D::Uniform(42.0)).from_parent(), + &Transform3D::from_translation_scale([1.0, 2.0, 3.0], Scale3D::uniform(42.0)).from_parent(), )?; rec.log(