Skip to content

Commit

Permalink
Deprecate DisconnectedSpace archetype/component in favor of implici…
Browse files Browse the repository at this point in the history
…t invalid transforms (#8459)

### Related

* Fixes #7868

### What

See title. In detail:
* `RotationAxisAngle` will no longer be ignored when axis is
non-normalizable
* deprecation of `DisconnectedSpace`
   * slight fixes to codegen for handling this smoothly
* lots of doc updates
* wherever we had constants for identity, we now also have one for
invalid
* python didn't have any at all so far, but I didn't want to add this in
this iteration since generally constants there are a bit tricky
    * we should have more of those generally

---------

Co-authored-by: Jeremy Leibs <[email protected]>
  • Loading branch information
Wumpf and jleibs authored Dec 16, 2024
1 parent 8466c45 commit 6288d04
Show file tree
Hide file tree
Showing 68 changed files with 335 additions and 109 deletions.
57 changes: 43 additions & 14 deletions crates/build/re_types_builder/src/codegen/cpp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -567,23 +567,27 @@ impl QuotedObject {
format!("{}Indicator", obj.fqname).replace("archetypes", "components");
let doc_hide_comment = quote_hide_from_docs();
let deprecation_notice = quote_deprecation_notice(obj);

// Note that GCC doesn't like using deprecated fields even if the archetype itself is deprecated.
// In that case we're just being generous with the ignore warnings, making it finegrained is hard and not really worth it anyways.
let has_any_deprecated_fields = obj.fields.iter().any(|field| {
field
.typ
.fqname()
.and_then(|fqname| objects.get(fqname))
.map_or(false, |obj| obj.deprecation_notice().is_some())
});
let (deprecation_ignore_start, deprecation_ignore_end) =
if obj.deprecation_notice().is_some() {
hpp_includes.insert_rerun("compiler_utils.hpp");
(
quote! {
RR_PUSH_WARNINGS #NEWLINE_TOKEN
RR_DISABLE_DEPRECATION_WARNING #NEWLINE_TOKEN
},
quote! { RR_POP_WARNINGS },
)
} else {
(quote!(), quote!())
};
quote_deprecation_ignore_start_and_end(
&mut hpp_includes,
obj.deprecation_notice().is_some() || has_any_deprecated_fields,
);

let hpp = quote! {
#hpp_includes

#deprecation_ignore_start

namespace rerun::#quoted_namespace {
#quoted_docs
struct #deprecation_notice #type_ident {
Expand Down Expand Up @@ -622,9 +626,9 @@ impl QuotedObject {
struct AsComponents<#quoted_namespace::#type_ident> {
#serialize_hpp
};

#deprecation_ignore_end
}

#deprecation_ignore_end
};

let cpp = quote! {
Expand Down Expand Up @@ -2591,7 +2595,12 @@ fn quote_loggable_hpp_and_cpp(

hpp_includes.insert_rerun("component_descriptor.hpp");

let (deprecation_ignore_start, deprecation_ignore_end) =
quote_deprecation_ignore_start_and_end(hpp_includes, obj.deprecation_notice().is_some());

let hpp = quote! {
#deprecation_ignore_start

namespace rerun {
#predeclarations_and_static_assertions

Expand All @@ -2604,6 +2613,8 @@ fn quote_loggable_hpp_and_cpp(
#(#methods_hpp)*
};
}

#deprecation_ignore_end
};

let cpp = if methods.iter().any(|m| !m.inline) {
Expand All @@ -2629,3 +2640,21 @@ fn quote_deprecation_notice(obj: &Object) -> TokenStream {
quote! {}
}
}

fn quote_deprecation_ignore_start_and_end(
includes: &mut Includes,
should_deprecate: bool,
) -> (TokenStream, TokenStream) {
if should_deprecate {
includes.insert_rerun("compiler_utils.hpp");
(
quote! {
RR_PUSH_WARNINGS #NEWLINE_TOKEN
RR_DISABLE_DEPRECATION_WARNING #NEWLINE_TOKEN
},
quote! { RR_POP_WARNINGS },
)
} else {
(quote!(), quote!())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ fn generate_component_reflection(
#[doc = "Generates reflection about all known components."]
#[doc = ""]
#[doc = "Call only once and reuse the results."]
#[allow(deprecated)]
fn generate_component_reflection() -> Result<ComponentReflectionMap, SerializationError> {
re_tracing::profile_function!();
let array = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace rerun.archetypes;
///
/// \example archetypes/disconnected_space title="Disconnected space" image="https://static.rerun.io/disconnected_space/709041fc304b50c74db773b780e32294fe90c95f/1200w.png"
table DisconnectedSpace (
"attr.rerun.deprecated": "Use [archetypes.Transform3D] with an invalid transform instead",
"attr.rust.derive": "Copy, PartialEq, Eq",
"attr.docs.view_types": "Spatial2DView, Spatial3DView"
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace rerun.components;
/// It *only* applies to views that work with spatial transformations, i.e. 2D & 3D views.
/// This is useful for specifying that a subgraph is independent of the rest of the scene.
struct DisconnectedSpace (
"attr.rerun.deprecated": "Use [archetypes.Transform3D] with an invalid transform instead.",
"attr.python.aliases": "bool",
"attr.python.array_aliases": "bool, npt.NDArray[np.bool_]",
"attr.rust.derive": "Copy, PartialEq, Eq"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
namespace rerun.components;

/// 3D rotation represented by a rotation around a given axis.
///
/// If normalization of the rotation axis fails the rotation is treated as an invalid transform.
table RotationAxisAngle (
"attr.rust.derive": "Default, Copy, PartialEq",
"attr.rust.repr": "transparent"
Expand All @@ -9,6 +11,8 @@ table RotationAxisAngle (
}

/// 3D rotation represented by a rotation around a given axis that doesn't propagate in the transform hierarchy.
///
/// If normalization of the rotation axis fails the rotation is treated as an invalid transform.
table PoseRotationAxisAngle (
"attr.rust.derive": "Default, Copy, PartialEq",
"attr.rust.repr": "transparent"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace rerun.components;
///
/// Note: although the x,y,z,w components of the quaternion will be passed through to the
/// datastore as provided, when used in the Viewer, quaternions will always be normalized.
/// If normalization fails the rotation is treated as an invalid transform.
struct RotationQuat (
"attr.rust.derive": "Default, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable",
"attr.rust.repr": "transparent"
Expand All @@ -15,6 +16,7 @@ struct RotationQuat (
///
/// Note: although the x,y,z,w components of the quaternion will be passed through to the
/// datastore as provided, when used in the Viewer, quaternions will always be normalized.
/// If normalization fails the rotation is treated as an invalid transform.
struct PoseRotationQuat (
"attr.rust.derive": "Default, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable",
"attr.rust.repr": "transparent"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ table RotationAxisAngle (
/// Axis to rotate around.
///
/// This is not required to be normalized.
/// If normalization fails (typically because the vector is length zero), the rotation is silently
/// ignored.
/// However, if normalization of the rotation axis fails (typically due to a zero vector)
/// the rotation is treated as an invalid transform.
axis: rerun.datatypes.Vec3D (order: 100);

/// How much to rotate around the axis.
Expand Down
6 changes: 6 additions & 0 deletions crates/store/re_types/src/archetypes/disconnected_space.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion crates/store/re_types/src/archetypes/mod.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/store/re_types/src/components/disconnected_space.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![allow(deprecated)]

use super::DisconnectedSpace;

impl Default for DisconnectedSpace {
Expand Down
4 changes: 3 additions & 1 deletion crates/store/re_types/src/components/mod.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ impl PoseRotationAxisAngle {
}

#[cfg(feature = "glam")]
impl From<PoseRotationAxisAngle> for glam::Affine3A {
impl TryFrom<PoseRotationAxisAngle> for glam::Affine3A {
type Error = ();

#[inline]
fn from(val: PoseRotationAxisAngle) -> Self {
if let Some(normalized) = glam::Vec3::from(val.0.axis).try_normalize() {
Self::from_axis_angle(normalized, val.0.angle.radians())
} else {
// If the axis is zero length, we can't normalize it, so we just use the identity rotation.
Self::IDENTITY
}
fn try_from(val: PoseRotationAxisAngle) -> Result<Self, Self::Error> {
glam::Vec3::from(val.0.axis)
.try_normalize()
.map(|normalized| Self::from_axis_angle(normalized, val.0.angle.radians()))
.ok_or(())
}
}
1 change: 1 addition & 0 deletions crates/store/re_types/src/components/pose_rotation_quat.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 11 additions & 3 deletions crates/store/re_types/src/components/pose_rotation_quat_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,21 @@ use super::PoseRotationQuat;

impl PoseRotationQuat {
/// The identity rotation, representing no rotation.
///
/// Keep in mind that logging an identity rotation is different from logging no rotation at all
/// in thus far that it will write data to the store.
pub const IDENTITY: Self = Self(crate::datatypes::Quaternion::IDENTITY);

/// A rotation that represents an invalid transform.
pub const INVALID: Self = Self(crate::datatypes::Quaternion::INVALID);
}

#[cfg(feature = "glam")]
impl From<PoseRotationQuat> for glam::Affine3A {
impl TryFrom<PoseRotationQuat> for glam::Affine3A {
type Error = ();

#[inline]
fn from(val: PoseRotationQuat) -> Self {
Self::from_quat(val.0.into())
fn try_from(val: PoseRotationQuat) -> Result<Self, Self::Error> {
Ok(Self::from_quat(glam::Quat::try_from(val.0)?))
}
}
2 changes: 2 additions & 0 deletions crates/store/re_types/src/components/rotation_axis_angle.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 8 additions & 8 deletions crates/store/re_types/src/components/rotation_axis_angle_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ impl RotationAxisAngle {
}

#[cfg(feature = "glam")]
impl From<RotationAxisAngle> for glam::Affine3A {
impl TryFrom<RotationAxisAngle> for glam::Affine3A {
type Error = ();

#[inline]
fn from(val: RotationAxisAngle) -> Self {
if let Some(normalized) = glam::Vec3::from(val.0.axis).try_normalize() {
Self::from_axis_angle(normalized, val.0.angle.radians())
} else {
// If the axis is zero length, we can't normalize it, so we just use the identity rotation.
Self::IDENTITY
}
fn try_from(val: RotationAxisAngle) -> Result<Self, Self::Error> {
glam::Vec3::from(val.0.axis)
.try_normalize()
.map(|normalized| Self::from_axis_angle(normalized, val.0.angle.radians()))
.ok_or(())
}
}
1 change: 1 addition & 0 deletions crates/store/re_types/src/components/rotation_quat.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 8 additions & 3 deletions crates/store/re_types/src/components/rotation_quat_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ impl RotationQuat {
/// Keep in mind that logging an identity rotation is different from logging no rotation at all
/// in thus far that it will write data to the store.
pub const IDENTITY: Self = Self(crate::datatypes::Quaternion::IDENTITY);

/// A rotation that represents an invalid transform.
pub const INVALID: Self = Self(crate::datatypes::Quaternion::INVALID);
}

#[cfg(feature = "glam")]
impl From<RotationQuat> for glam::Affine3A {
impl TryFrom<RotationQuat> for glam::Affine3A {
type Error = ();

#[inline]
fn from(val: RotationQuat) -> Self {
Self::from_quat(val.0.into())
fn try_from(val: RotationQuat) -> Result<Self, Self::Error> {
Ok(Self::from_quat(glam::Quat::try_from(val.0)?))
}
}
15 changes: 11 additions & 4 deletions crates/store/re_types/src/datatypes/quaternion_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ impl Quaternion {
/// The identity quaternion representing no rotation.
pub const IDENTITY: Self = Self([0.0, 0.0, 0.0, 1.0]);

/// A quaternion that represents an invalid transform.
pub const INVALID: Self = Self([0.0, 0.0, 0.0, 0.0]);

/// From XYZW.
#[inline]
pub const fn from_xyzw(xyzw: [f32; 4]) -> Self {
Expand All @@ -33,11 +36,15 @@ impl Quaternion {
}

#[cfg(feature = "glam")]
impl From<Quaternion> for glam::Quat {
impl TryFrom<Quaternion> for glam::Quat {
type Error = ();

#[inline]
fn from(q: Quaternion) -> Self {
let [x, y, z, w] = q.0;
Self::from_xyzw(x, y, z, w).normalize()
fn try_from(q: Quaternion) -> Result<Self, ()> {
glam::Vec4::from(q.0)
.try_normalize()
.map(Self::from_vec4)
.ok_or(())
}
}

Expand Down
Loading

0 comments on commit 6288d04

Please sign in to comment.