chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:05:14 +08:00
commit 2a547be7fe
7904 changed files with 1000926 additions and 0 deletions
+90
View File
@@ -0,0 +1,90 @@
<!--[metadata]
title = "Raw mesh"
tags = ["Mesh"]
thumbnail = "https://static.rerun.io/raw-mesh/7731418dda47e15dbfc0f9a2c32673909071cb40/480w.png"
thumbnail_dimensions = [480, 480]
channel = "release"
include_in_manifest = true
-->
Demonstrates logging of raw 3D mesh data (so-called "triangle soups") with simple material properties and their transform hierarchy.
Note that while this example loads GLTF meshes to illustrate [`Mesh3D`](https://rerun.io/docs/reference/types/archetypes/mesh3d)'s abilitites, you can also send various kinds of mesh assets
directly via [`Asset3D`](https://rerun.io/docs/reference/types/archetypes/asset3d).
<!-- TODO(#1957): How about we load something elseto avoid confusion? -->
<picture data-inline-viewer="examples/raw_mesh">
<img src="https://static.rerun.io/raw_mesh/d5d008b9f1b53753a86efe2580443a9265070b77/full.png" alt="">
<source media="(max-width: 480px)" srcset="https://static.rerun.io/raw_mesh/d5d008b9f1b53753a86efe2580443a9265070b77/480w.png">
<source media="(max-width: 768px)" srcset="https://static.rerun.io/raw_mesh/d5d008b9f1b53753a86efe2580443a9265070b77/768w.png">
<source media="(max-width: 1024px)" srcset="https://static.rerun.io/raw_mesh/d5d008b9f1b53753a86efe2580443a9265070b77/1024w.png">
<source media="(max-width: 1200px)" srcset="https://static.rerun.io/raw_mesh/d5d008b9f1b53753a86efe2580443a9265070b77/1200w.png">
</picture>
## Used Rerun types
[`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), [`Mesh3D`](https://www.rerun.io/docs/reference/types/archetypes/mesh3d)
## Background
Raw 3D mesh data refers to the basic geometric representation of a three-dimensional object, typically composed of interconnected triangles.
These triangles collectively form the surface of the object, defining its shape and structure in a digital environment.
Rerun was employed to visualize and manage this raw mesh data, along with its associated simple material properties and transform hierarchy.
## Logging and visualizing with Rerun
The visualizations in this example were created with the following Rerun code:
### 3D mesh data
The raw 3D mesh data are logged as [`Mesh3D`](https://www.rerun.io/docs/reference/types/archetypes/mesh3d) objects, and includes details about vertex positions, colors, normals, texture coordinates, material properties, and face indices for an accurate reconstruction and visualization.
```python
rr.log(
path,
rr.Mesh3D(
vertex_positions=mesh.vertices,
vertex_colors=vertex_colors,
vertex_normals=mesh.vertex_normals,
vertex_texcoords=vertex_texcoords,
albedo_texture=albedo_texture,
triangle_indices=mesh.faces,
albedo_factor=albedo_factor,
),
)
```
Through Rerun's [`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d) archetype, essential details are captured to ensure precise positioning and orientation of meshes within the 3D scene.
```python
rr.log(
path,
rr.Transform3D(
translation=trimesh.transformations.translation_from_matrix(world_from_mesh),
mat3x3=world_from_mesh[0:3, 0:3],
),
)
```
## Run the code
To run this example, make sure you have the Rerun repository checked out and the latest SDK installed:
```bash
pip install --upgrade rerun-sdk # install the latest Rerun SDK
git clone git@github.com:rerun-io/rerun.git # Clone the repository
cd rerun
git checkout latest # Check out the commit matching the latest SDK release
```
Install the necessary libraries specified in the requirements file:
```bash
pip install -e examples/python/raw_mesh
```
To experiment with the provided example, simply execute the main Python script:
```bash
python -m raw_mesh # run the example
```
You can specify scene:
```bash
python -m raw_mesh --scene {lantern,avocado,buggy,brain_stem}
```
If you wish to customize it, explore additional features, or save it use the CLI with the `--help` option for guidance:
```bash
python -m raw_mesh --help
```
+13
View File
@@ -0,0 +1,13 @@
[project]
name = "raw_mesh"
version = "0.1.0"
readme = "README.md"
dependencies = ["numpy", "requests>=2.31,<3", "rerun-sdk", "trimesh"]
[project.scripts]
raw_mesh = "raw_mesh.__main__:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
+155
View File
@@ -0,0 +1,155 @@
#!/usr/bin/env python3
"""
Shows how to use the Rerun SDK to log raw 3D meshes (so-called "triangle soups") and their transform hierarchy.
Note that while this example loads GLTF meshes to illustrate
[`Mesh3D`](https://rerun.io/docs/reference/types/archetypes/mesh3d)'s abilitites,
you can also send various kinds of mesh assets directly via
[`Asset3D`](https://rerun.io/docs/reference/types/archetypes/asset3d).
"""
from __future__ import annotations
import argparse
from pathlib import Path
from typing import cast
import numpy as np
import trimesh
import rerun as rr # pip install rerun-sdk
import rerun.blueprint as rrb
from .download_dataset import AVAILABLE_MESHES, ensure_mesh_downloaded
DESCRIPTION = """
# Raw meshes
This example shows how you can log a hierarchical 3D mesh, including its transform hierarchy.
The full source code for this example is available [on GitHub](https://github.com/rerun-io/rerun/blob/latest/examples/python/raw_mesh).
"""
def load_scene(path: Path) -> trimesh.Scene:
print(f"loading scene {path}")
mesh = trimesh.load(path, force="scene")
return cast("trimesh.Scene", mesh)
# NOTE: The scene hierarchy will look different compared to the Rust example, as this is using the
# trimesh hierarchy, not the raw glTF hierarchy.
def log_scene(scene: trimesh.Scene, node: str, path: str | None = None) -> None:
path = path + "/" + node if path else node
parent = scene.graph.transforms.parents.get(node)
children = scene.graph.transforms.children.get(node)
node_data = scene.graph.get(frame_to=node, frame_from=parent)
if node_data:
# Log the transform between this node and its direct parent (if it has one!).
if parent:
# TODO(#3559): We should support 4x4 matrices directly
world_from_mesh = node_data[0]
rr.log(
path,
rr.Transform3D(
translation=trimesh.transformations.translation_from_matrix(world_from_mesh),
mat3x3=world_from_mesh[0:3, 0:3],
),
)
# Log this node's mesh, if it has one.
mesh = cast("trimesh.Trimesh", scene.geometry.get(node_data[1]))
if mesh is not None:
vertex_colors = None
vertex_texcoords = None
albedo_factor = None
albedo_texture = None
try:
vertex_texcoords = mesh.visual.uv # type: ignore[union-attr]
# trimesh uses the OpenGL convention for UV coordinates, so we need to flip the V coordinate
# since Rerun uses the Vulkan/Metal/DX12/WebGPU convention.
vertex_texcoords[:, 1] = 1.0 - vertex_texcoords[:, 1]
except Exception:
pass
try:
albedo_texture = mesh.visual.material.baseColorTexture # type: ignore[union-attr]
if mesh.visual.material.baseColorTexture is None: # type: ignore[union-attr]
raise ValueError()
except Exception:
# Try vertex colors instead.
try:
colors = mesh.visual.to_color().vertex_colors # type: ignore[union-attr]
if len(colors) == 4:
# If trimesh gives us a single vertex color for the entire mesh, we can interpret that
# as an albedo factor for the whole primitive.
albedo_factor = np.array(colors)
else:
vertex_colors = colors
except Exception:
pass
rr.log(
path,
rr.Mesh3D(
vertex_positions=mesh.vertices,
vertex_colors=vertex_colors,
vertex_normals=mesh.vertex_normals,
vertex_texcoords=vertex_texcoords,
albedo_texture=albedo_texture,
triangle_indices=mesh.faces,
albedo_factor=albedo_factor,
),
)
if children:
for child in children:
log_scene(scene, child, path)
def main() -> None:
parser = argparse.ArgumentParser(
description="Logs raw 3D meshes and their transform hierarchy using the Rerun SDK.",
)
parser.add_argument(
"--scene",
type=str,
choices=AVAILABLE_MESHES,
default=AVAILABLE_MESHES[0],
help="The name of the scene to load",
)
parser.add_argument(
"--scene-path",
type=Path,
help="Path to a scene to analyze. If set, overrides the `--scene` argument.",
)
rr.script_add_args(parser)
args = parser.parse_args()
scene_path = args.scene_path
if scene_path is None:
scene_path = ensure_mesh_downloaded(args.scene)
scene = load_scene(scene_path)
root = next(iter(scene.graph.nodes))
blueprint = rrb.Horizontal(
rrb.Spatial3DView(name="Mesh", origin="/world"),
rrb.TextDocumentView(name="Description", origin="/description"),
column_shares=[3, 1],
)
rr.script_setup(args, "rerun_example_raw_mesh", default_blueprint=blueprint)
rr.log("description", rr.TextDocument(DESCRIPTION, media_type=rr.MediaType.MARKDOWN), static=True)
# glTF always uses a right-handed coordinate system when +Y is up and meshes face +Z.
rr.log(root, rr.ViewCoordinates.RUB, static=True)
log_scene(scene, root)
rr.script_teardown(args)
if __name__ == "__main__":
main()
+80
View File
@@ -0,0 +1,80 @@
#!/usr/bin/env python3
from __future__ import annotations
import os
from pathlib import Path
from typing import Final
import requests
DATASET_URL_BASE: Final = "https://storage.googleapis.com/rerun-example-datasets/raw_mesh"
# TODO(cmc): re-enable obj meshes when we support those on the viewer's side
AVAILABLE_MESHES: Final = [
"lantern",
"avocado",
"buggy",
"brain_stem",
# "buddha",
# "bunny",
# "dragon",
# "mori_knob",
]
# Maps mesh name to list of (remote_filename, local_filename) pairs.
MESH_FILES: Final = {
"avocado": [("avocado.glb", "avocado.glb")],
"brain_stem": [("brain_stem.glb", "brain_stem.glb")],
"buddha": [("buddha.obj", "buddha.obj")],
"buggy": [("buggy.glb", "buggy.glb")],
"bunny": [("bunny.obj", "bunny.obj")],
"dragon": [("dragon.obj", "dragon.obj")],
"lantern": [("lantern.glb", "lantern.glb")],
"mori_knob": [
("testObj.obj", "testObj.obj"),
("testObj.mtl", "testObj.mtl"),
],
}
DOWNLOADED_DIR: Final = Path(__file__).parent.parent / "dataset"
def ensure_mesh_downloaded(mesh_name: str) -> Path:
path = find_mesh_path_if_downloaded(mesh_name)
if path is not None:
return path
return download_mesh(mesh_name)
def find_mesh_path_if_downloaded(name: str) -> Path | None:
for mesh_format in ("obj", "glb"):
for path in DOWNLOADED_DIR.glob(f"{name}/**/*.{mesh_format}"):
return path
return None
def download_mesh(name: str) -> Path:
"""Downloads a mesh from the Rerun example datasets bucket and returns the path to the main mesh file."""
if name not in MESH_FILES:
raise RuntimeError(f"Unknown mesh named: {name}")
mesh_dir = DOWNLOADED_DIR / name
os.makedirs(mesh_dir, exist_ok=True)
main_path = None
for remote_name, local_name in MESH_FILES[name]:
local_path = mesh_dir / local_name
if not local_path.exists():
url = f"{DATASET_URL_BASE}/{name}/{remote_name}"
print(f"downloading {url}")
resp = requests.get(url)
resp.raise_for_status()
with open(local_path, "wb") as f:
f.write(resp.content)
# The main mesh file is the first one listed (obj or glb).
if main_path is None:
main_path = local_path
assert main_path is not None
return main_path