diff --git a/examples/raw_mesh/src/main.rs b/examples/raw_mesh/src/main.rs index 1632ecbc7009..7230ad2663ea 100644 --- a/examples/raw_mesh/src/main.rs +++ b/examples/raw_mesh/src/main.rs @@ -8,12 +8,12 @@ #![allow(clippy::doc_markdown)] -use anyhow::{bail, Context}; +use anyhow::{anyhow, bail, Context}; use bytes::Bytes; use rerun::{ - reexports::{re_log, re_memory::AccountingAllocator}, - EntityPath, LogMsg, Mesh3D, MeshId, MsgBundle, MsgId, RawMesh3D, Session, Time, TimePoint, - TimeType, Timeline, Transform, Vec4D, ViewCoordinates, + external::{re_log, re_memory::AccountingAllocator}, + EntityPath, Mesh3D, MeshId, MsgSender, RawMesh3D, Session, TimeType, Timeline, Transform, + Vec4D, ViewCoordinates, }; // TODO(cmc): This example needs to support animations to showcase Rerun's time capabilities. @@ -66,18 +66,9 @@ impl From for Transform { } /// Log a glTF node with Rerun. -fn log_node(session: &mut Session, node: GltfNode) { +fn log_node(session: &mut Session, node: GltfNode) -> anyhow::Result<()> { let ent_path = EntityPath::from(node.name.as_str()); - // What time is it? - let timeline_keyframe = Timeline::new("keyframe", TimeType::Sequence); - let time_point = TimePoint::from([ - // TODO(cmc): this _has_ to be inserted by the SDK - (Timeline::log_time(), Time::now().into()), - // TODO(cmc): animations! - (timeline_keyframe, 0.into()), - ]); - // Convert glTF objects into Rerun components. let transform = node.transform.map(Transform::from); let primitives = node @@ -86,61 +77,36 @@ fn log_node(session: &mut Session, node: GltfNode) { .map(Mesh3D::from) .collect::>(); - // TODO(cmc): Transforms have to be logged separately because they are neither batches nor - // splats... the user shouldn't have to know that though! - // The SDK needs to split things up as needed when it sees a Transform component. - // - // We're going to have the same issue with splats: the SDK needs to automagically detect the - // user intention to use splats and do the necessary (like the python SDK does iirc). - if let Some(transform) = transform { - let bundle = MsgBundle::new( - MsgId::random(), - ent_path.clone(), - time_point.clone(), - // TODO(cmc): need to reproduce the viewer crash I had earlier and fix/log-an-issue for - // it. - vec![vec![transform].try_into().unwrap()], - ); - // TODO(cmc): These last conversion details need to be hidden in the SDK. - let msg = bundle.try_into().unwrap(); - session.send(LogMsg::ArrowMsg(msg)); - } - - // TODO(cmc): Working at the `ComponentBundle`/`TryIntoArrow` layer feels too low-level, - // something like a MsgBuilder kinda thing would probably be quite nice. - let bundle = MsgBundle::new( - MsgId::random(), - ent_path, - time_point, - vec![primitives.try_into().unwrap()], - ); - - // Create and send one message to the sdk - // TODO(cmc): These last conversion details need to be hidden in the SDK. - let msg = bundle.try_into().unwrap(); - session.send(LogMsg::ArrowMsg(msg)); + let timeline_keyframe = Timeline::new("keyframe", TimeType::Sequence); + MsgSender::new(ent_path) + .with_time(timeline_keyframe, 0) + .with_component(&primitives)? + .with_component(transform.as_ref())? + .send(session)?; // Recurse through all of the node's children! for mut child in node.children { child.name = [node.name.as_str(), child.name.as_str()].join("/"); - log_node(session, child); + log_node(session, child)?; } -} -// TODO(cmc): The SDK should make this call so trivial that it doesn't require this helper at all. -fn log_axis(session: &mut Session, ent_path: &EntityPath) { - // glTF always uses a right-handed coordinate system when +Y is up and meshes face +Z. - let view_coords: ViewCoordinates = "RUB".parse().unwrap(); - - let bundle = MsgBundle::new( - MsgId::random(), - ent_path.clone(), - [].into(), // TODO(cmc): doing timeless stuff shouldn't be so weird - vec![vec![view_coords].try_into().unwrap()], - ); + Ok(()) +} - let msg = bundle.try_into().unwrap(); - session.send(LogMsg::ArrowMsg(msg)); +fn log_coordinate_space( + session: &mut Session, + ent_path: impl Into, + axes: &str, +) -> anyhow::Result<()> { + let view_coords: ViewCoordinates = axes + .parse() + .map_err(|err| anyhow!("couldn't parse {axes:?} as ViewCoordinates: {err}"))?; + + MsgSender::new(ent_path) + .with_timeless(true) + .with_component(&[view_coords])? + .send(session) + .map_err(Into::into) } // --- Init --- @@ -174,8 +140,8 @@ fn main() -> anyhow::Result<()> { let mut session = Session::new(); for root in nodes { re_log::info!(scene = root.name, "logging glTF scene"); - log_axis(&mut session, &root.name.as_str().into()); - log_node(&mut session, root); + log_coordinate_space(&mut session, root.name.as_str(), "RUB")?; + log_node(&mut session, root).unwrap(); } // TODO(cmc): provide high-level tools to pick and handle the different modes.