Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mesh3D archetype #3363

Merged
merged 26 commits into from
Sep 20, 2023
Merged

Mesh3D archetype #3363

merged 26 commits into from
Sep 20, 2023

Conversation

teh-cmc
Copy link
Member

@teh-cmc teh-cmc commented Sep 19, 2023

Implements the Mesh3D archetype:

table Mesh3D {
  vertex_positions: [rerun.components.Position3D] ("attr.rerun.component_required", order: 1000);
  vertex_normals: [rerun.components.Vector3D] ("attr.rerun.component_optional", nullable, order: 3000);
  vertex_colors: [rerun.components.Color] ("attr.rerun.component_optional", nullable, order: 3100);

  mesh_material: rerun.components.Material ("attr.rerun.component_optional", nullable, order: 3200);
  mesh_properties: rerun.components.MeshProperties ("attr.rerun.component_recommended", nullable, order: 2000);

  class_ids: [rerun.components.ClassId] ("attr.rerun.component_optional", nullable, order: 3300);
  instance_keys: [rerun.components.InstanceKey] ("attr.rerun.component_optional", nullable, order: 3400);
}

An interesting facet of the Mesh3D archetype is that it's composed of two kinds of data:

  • Per-vertex data, which uses our usual query system with joins and everything, allowing the mesh's components to be viewed in different ways, partially updated, etc.
  • Per-mesh data, which is essentially global data that applies to the mesh as a whole and is kind of a splat but not really.

Because the vertices becomes the instances, meshes cannot be batched.

There's a bit of a mess here and there because the ancestors of Mesh3D & Asset3D used to be tightly coupled.
This will be fixed in the next PR that implements the next-gen Asset3D archetype.

No dedicated roundtrip tests: API examples already cover everything.

Fixes #2788


Here's an example of partial updates:

rr.init("rerun_example_mesh3d_partial_updates", spawn=True)

vertex_positions = np.array([[-1.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]], dtype=np.float32)

# Log the initial state of our triangle
rr.set_time_sequence("frame", 0)
rr2.log(
    "triangle",
    rr2.Mesh3D(
        vertex_positions,
        vertex_normals=[0.0, 0.0, 1.0],
        vertex_colors=[[255, 0, 0], [0, 255, 0], [0, 0, 255]],
    ),
)

# Only update its vertices' positions each frame
factors = np.abs(np.sin(np.arange(1, 300, dtype=np.float32) * 0.04))
for i, factor in enumerate(factors):
    rr.set_time_sequence("frame", i)
    rr2.log_components("triangle", [rr2.cmp.Position3DArray.from_similar(vertex_positions * factor)])
23-09-19_15.45.08.patched.mp4

Checklist

@teh-cmc teh-cmc added 🐍 Python API Python logging API 🦀 Rust API Rust logging API 🍏 primitives Relating to Rerun primitives 🌊 C++ API C/C++ API specific labels Sep 19, 2023
@teh-cmc teh-cmc marked this pull request as ready for review September 19, 2023 13:50
@teh-cmc
Copy link
Member Author

teh-cmc commented Sep 19, 2023

Python colors are broken now that I've fixed the nullability crash... Looking... fixed

/// Optional properties for the mesh as a whole (including indexed drawing).
//
// NOTE: We cannot have triangle indices here as that would break our instance key rules (either 0, 1 or N).
mesh_properties: rerun.components.MeshProperties ("attr.rerun.component_recommended", nullable, order: 2000);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not call this mesh_indices: rerun.components.MeshIndices instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels likely like we're gonna want to stash a few more things in there sooner than later (winding order, index format, ...) 🤷‍♂️

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MeshTriangles maybe? "properties" is very vague. I would expect there to be color stuff in there, not fundamental stuff like indices.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im not necessarily a fan of MeshProperties but I like MeshTriangles even less tbh.

  • This really has nothing to do with triangles at this point (it's now vertex_indices)
  • Indices are not "fundamental", quite the contrary they're optional :/

Anyway, time to ship this; feel free to change it in another PR.

@teh-cmc
Copy link
Member Author

teh-cmc commented Sep 19, 2023

Added vertex colors support to raw_mesh.py while I'm here fixing colors... 🌈

image
image

@teh-cmc
Copy link
Member Author

teh-cmc commented Sep 19, 2023

One thing to keep in mind: this will make large meshes (like hundreds of thousands of vertices and more) quite slower than before, since meshes are now more akin to point clouds: all vertex properties are joined etc according to their instance keys.

We could easily bypass that join (this PR actually used to do that) to regain that performance, at the cost of violating our query model and therefore user expectations.
Considering the kind of slowdown we're talking about (e.g. handful of milliseconds for ARKit scene), and the fact that #3107 would remove the join cost entirely in 99.9% use cases, I vote to keep this as-is.

For reference, arkit before:
image (15)
and arkit after:
image (16)

Copy link
Member

@emilk emilk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing!

crates/re_query/src/archetype_view.rs Outdated Show resolved Hide resolved
crates/re_renderer/src/importer/gltf.rs Show resolved Hide resolved
crates/re_renderer/src/importer/obj.rs Show resolved Hide resolved
crates/re_space_view_spatial/src/mesh_loader.rs Outdated Show resolved Hide resolved
Comment on lines +219 to +224
#[inline]
fn try_to_arrow(
&self,
) -> crate::SerializationResult<
Vec<(::arrow2::datatypes::Field, Box<dyn ::arrow2::array::Array>)>,
> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we have as_component_batches, can't try_to_arrow just call self.as_component_batches and then call try_to_arrow() on each component batch? A lot less code needs generating. I guess we get an additional dyn call per component, but that seems worth it

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

crates/re_types/src/archetypes/mesh3d_ext.rs Outdated Show resolved Hide resolved
crates/re_types_builder/src/lib.rs Show resolved Hide resolved
examples/rust/raw_mesh/Cargo.toml Outdated Show resolved Hide resolved
examples/rust/raw_mesh/src/main.rs Outdated Show resolved Hide resolved
@teh-cmc
Copy link
Member Author

teh-cmc commented Sep 20, 2023

One thing to keep in mind: this will make large meshes (like hundreds of thousands of vertices and more) quite slower than before, since meshes are now more akin to point clouds: all vertex properties are joined etc according to their instance keys.

We could easily bypass that join (this PR actually used to do that) to regain that performance, at the cost of violating our query model and therefore user expectations. Considering the kind of slowdown we're talking about (e.g. handful of milliseconds for ARKit scene), and the fact that #3107 would remove the join cost entirely in 99.9% use cases, I vote to keep this as-is.

For reference, arkit before: image (15) and arkit after: image (16)

#3377 wins us back a millisecond:
image

The only way to do better at this point would be to not deserialize at all when we take the optimized path, instead working with raw ArrowBuffers in that case (which is effectively what the legacy view did):

@emilk
Copy link
Member

emilk commented Sep 20, 2023

There's almost 2ms not covered by puffin scopes

image

@teh-cmc
Copy link
Member Author

teh-cmc commented Sep 20, 2023

There's almost 2ms not covered by puffin scopes

image

image

(Yes, this is much faster than previous screenshots... because this is a debug build (???!!!!))

It makes no sense why we're spending so much time where we're spending it but whatever, that's a problem for another day.

@teh-cmc teh-cmc merged commit f73a137 into main Sep 20, 2023
@teh-cmc teh-cmc deleted the cmc/mesh_archetype branch September 20, 2023 16:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🌊 C++ API C/C++ API specific 🍏 primitives Relating to Rerun primitives 🐍 Python API Python logging API 🦀 Rust API Rust logging API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Mesh migration to archetypes
2 participants