Skip to content

Commit 1449457

Browse files
committed
raw_mesh examples w/ procedural primitives (#1957)
Replaces GLTF file loading with procedurally generated geometric primitives (cube, pyramid, sphere, icosahedron, grid) to better demonstrate the Mesh3D archetype capabilities and clearly distinguish it from Asset3D.
1 parent d547758 commit 1449457

File tree

10 files changed

+758
-480
lines changed

10 files changed

+758
-480
lines changed

Cargo.lock

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8305,9 +8305,7 @@ name = "raw_mesh"
83058305
version = "0.27.0-alpha.8+dev"
83068306
dependencies = [
83078307
"anyhow",
8308-
"bytes",
83098308
"clap",
8310-
"gltf",
83118309
"rerun",
83128310
]
83138311

RAW_MESH_EXAMPLE_PLAN.md

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
# Raw Mesh Example Refactoring Plan
2+
3+
## Issue Summary
4+
5+
**GitHub Issue**: [#1957](https://github.com/rerun-io/rerun/issues/1957)
6+
**Title**: "raw_mesh example is misleading in that it loads gltf files"
7+
8+
### Problem Statement
9+
10+
The current `raw_mesh` examples (Python and Rust) are misleading because they:
11+
1. Load GLTF/GLB files to demonstrate mesh functionality
12+
2. GLTF/GLB files can already be loaded natively via Rerun's `Asset3D` archetype
13+
3. The examples don't actually demonstrate how to construct **raw mesh data** from scratch
14+
4. This creates confusion about the purpose and capabilities of the `Mesh3D` archetype vs `Asset3D`
15+
16+
Both README files already acknowledge this issue with a TODO comment:
17+
```html
18+
<!-- TODO(#1957): How about we load something elseto avoid confusion? -->
19+
```
20+
21+
### Current Affected Files
22+
23+
**Python Implementation:**
24+
- `examples/python/raw_mesh/raw_mesh/__main__.py`
25+
- `examples/python/raw_mesh/README.md`
26+
- `examples/python/raw_mesh/raw_mesh/download_dataset.py` (can be removed)
27+
28+
**Rust Implementation:**
29+
- `examples/rust/raw_mesh/src/main.rs`
30+
- `examples/rust/raw_mesh/README.md`
31+
32+
## Proposed Solution
33+
34+
Replace the GLTF file loading with **procedurally generated geometric primitives** that demonstrate:
35+
1. How to construct mesh vertices, normals, and indices from scratch
36+
2. How to apply colors and materials programmatically
37+
3. How to create a transform hierarchy without external dependencies
38+
4. The full capabilities of the `Mesh3D` archetype
39+
40+
## Implementation Details
41+
42+
### Geometric Primitives to Generate
43+
44+
Create a showcase of common 3D primitives, each demonstrating different `Mesh3D` features:
45+
46+
1. **Colored Cube**
47+
- Demonstrates: Basic vertex positions, triangle indices, per-vertex colors
48+
- 8 vertices, 12 triangles (6 faces × 2 triangles each)
49+
- Each face with a different color
50+
51+
2. **Textured Pyramid**
52+
- Demonstrates: UV texture coordinates, albedo texture
53+
- 5 vertices (4 base + 1 apex), 6 triangles
54+
- Procedurally generated checkerboard texture
55+
56+
3. **Smooth Sphere**
57+
- Demonstrates: Vertex normals for smooth shading, uniform albedo factor
58+
- UV sphere topology (latitude/longitude grid)
59+
- ~1000-2000 triangles for smooth appearance
60+
61+
4. **Flat-Shaded Icosahedron**
62+
- Demonstrates: Flat shading (no normals or face normals)
63+
- 12 vertices, 20 triangles
64+
- Simple platonic solid geometry
65+
66+
5. **Grid Mesh**
67+
- Demonstrates: Transform hierarchy (multiple instances at different positions)
68+
- Simple XZ plane grid
69+
- Multiple instances with different transforms
70+
71+
### Hierarchical Scene Structure
72+
73+
Create a hierarchical scene to demonstrate `Transform3D`:
74+
75+
```
76+
world/
77+
├── primitives/
78+
│ ├── cube (at origin)
79+
│ ├── pyramid (translated +X)
80+
│ ├── sphere (translated -X)
81+
│ ├── icosahedron (translated +Y)
82+
│ └── grid_instances/
83+
│ ├── grid_0 (translated +Z, rotated)
84+
│ ├── grid_1 (translated -Z, scaled)
85+
│ └── grid_2 (rotated differently)
86+
```
87+
88+
### Python Implementation Changes
89+
90+
**File: `examples/python/raw_mesh/raw_mesh/__main__.py`**
91+
92+
Changes needed:
93+
1. Remove `trimesh` dependency
94+
2. Remove GLTF loading logic
95+
3. Add geometric primitive generation functions:
96+
- `generate_cube()` → vertices, indices, colors
97+
- `generate_pyramid()` → vertices, indices, UV coords, texture
98+
- `generate_sphere(subdivisions)` → vertices, indices, normals
99+
- `generate_icosahedron()` → vertices, indices
100+
- `generate_grid()` → vertices, indices
101+
4. Add procedural texture generation (simple checkerboard pattern)
102+
5. Update scene logging to use generated meshes
103+
6. Update argument parser (remove scene selection, add options like `--subdivisions`)
104+
7. Update blueprint and description
105+
106+
**File: `examples/python/raw_mesh/pyproject.toml`**
107+
108+
Changes needed:
109+
1. Remove `trimesh` dependency
110+
2. Keep only `numpy` and `rerun-sdk`
111+
112+
**File: `examples/python/raw_mesh/README.md`**
113+
114+
Changes needed:
115+
1. Update description to emphasize procedural generation
116+
2. Remove references to GLTF files and scenes
117+
3. Update code examples to show primitive generation
118+
4. Remove the TODO comment
119+
5. Update run instructions (no more `--scene` option)
120+
121+
**File: `examples/python/raw_mesh/raw_mesh/download_dataset.py`**
122+
123+
Changes needed:
124+
1. Delete this file entirely (no longer needed)
125+
126+
### Rust Implementation Changes
127+
128+
**File: `examples/rust/raw_mesh/src/main.rs`**
129+
130+
Changes needed:
131+
1. Remove GLTF parsing code (lines 179-303)
132+
2. Remove `gltf` and `bytes` dependencies
133+
3. Add geometric primitive generation functions:
134+
- `generate_cube()``GltfPrimitive` struct (reuse for primitives)
135+
- `generate_pyramid()` → with texture
136+
- `generate_sphere(subdivisions)` → with normals
137+
- `generate_icosahedron()`
138+
- `generate_grid()`
139+
4. Rename `GltfPrimitive`, `GltfNode`, `GltfTransform` to generic names:
140+
- `GltfPrimitive``MeshPrimitive`
141+
- `GltfNode``MeshNode`
142+
- `GltfTransform``MeshTransform`
143+
5. Update `run()` function to create procedural scene
144+
6. Remove command-line scene selection
145+
7. Add procedural texture generation
146+
147+
**File: `examples/rust/raw_mesh/Cargo.toml`**
148+
149+
Changes needed:
150+
1. Remove `gltf` dependency
151+
2. Remove `bytes` dependency
152+
3. Keep `rerun` and basic dependencies
153+
154+
**File: `examples/rust/raw_mesh/README.md`**
155+
156+
Changes needed:
157+
1. Update description to emphasize procedural generation
158+
2. Remove references to GLTF files
159+
3. Remove the TODO comment
160+
4. Update run instructions
161+
162+
### Documentation Updates
163+
164+
Both implementations should include:
165+
1. Inline code comments explaining the math/geometry
166+
2. Comments showing how to calculate normals
167+
3. Comments about winding order (counter-clockwise for front faces)
168+
4. Examples of different color/material approaches
169+
5. Links to `Asset3D` for users who want to load mesh files
170+
171+
### Testing Considerations
172+
173+
1. Visual regression tests may need updating (screenshots will change)
174+
2. Example metadata in README frontmatter should be updated
175+
3. Thumbnails will need regeneration
176+
177+
## Benefits of This Approach
178+
179+
1. **Educational**: Shows users exactly how to construct mesh data from scratch
180+
2. **Self-contained**: No external file dependencies or downloads
181+
3. **Clear purpose**: Distinguishes `Mesh3D` (programmatic) from `Asset3D` (file-based)
182+
4. **Comprehensive**: Demonstrates all `Mesh3D` features in one example
183+
5. **Fast**: No file I/O, runs instantly
184+
6. **Platform-independent**: Pure math, no file path issues
185+
186+
## Backward Compatibility
187+
188+
Since these are examples (not API), backward compatibility is not a concern. However:
189+
1. Users who reference this example in documentation should be notified
190+
2. The old thumbnails/screenshots should be replaced
191+
3. Any tutorials referencing the GLTF scenes should be updated
192+
193+
## Implementation Steps
194+
195+
1. **Python implementation first** (easier to prototype)
196+
- Implement geometric primitive generators
197+
- Test each primitive individually
198+
- Create hierarchical scene
199+
- Update documentation
200+
201+
2. **Rust implementation** (based on Python approach)
202+
- Port geometric algorithms to Rust
203+
- Maintain same visual output as Python version
204+
- Update documentation
205+
206+
3. **Documentation & assets**
207+
- Generate new screenshots/thumbnails
208+
- Update README files
209+
- Remove dataset download logic
210+
211+
4. **Testing**
212+
- Visual verification of all primitives
213+
- Verify both Python and Rust produce similar output
214+
- Test on different platforms
215+
216+
## Open Questions
217+
218+
1. **Texture generation**: Should we generate actual image textures or use solid colors?
219+
- Recommendation: Simple procedural checkerboard (demonstrates UV mapping without image files)
220+
221+
2. **Complexity**: How detailed should the sphere be?
222+
- Recommendation: Make it configurable, default ~32 latitude × 16 longitude segments
223+
224+
3. **Additional features**: Should we demonstrate:
225+
- Multiple materials per mesh? (No - keep it simple)
226+
- Texture arrays? (No - too advanced)
227+
- Line rendering? (No - different archetype)
228+
229+
## Success Criteria
230+
231+
- [ ] No external file dependencies (GLTF, images, etc.)
232+
- [ ] Demonstrates all `Mesh3D` archetype features
233+
- [ ] Clear, well-commented code showing geometric construction
234+
- [ ] Both Python and Rust implementations produce similar visual output
235+
- [ ] Documentation clearly explains the difference between `Mesh3D` and `Asset3D`
236+
- [ ] Examples run instantly without downloads
237+
- [ ] Issue #1957 can be closed
238+
239+
## Estimated Effort
240+
241+
- Python implementation: 4-6 hours
242+
- Rust implementation: 4-6 hours
243+
- Documentation & testing: 2-3 hours
244+
- **Total**: 10-15 hours
245+
246+
## References
247+
248+
- Issue: https://github.com/rerun-io/rerun/issues/1957
249+
- `Mesh3D` docs: https://rerun.io/docs/reference/types/archetypes/mesh3d
250+
- `Asset3D` docs: https://rerun.io/docs/reference/types/archetypes/asset3d
251+
- PR #10249 (partial fix): Linked to `Asset3D` in documentation

examples/python/raw_mesh/README.md

Lines changed: 66 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@ thumbnail_dimensions = [480, 480]
66
channel = "release"
77
-->
88

9-
Demonstrates logging of raw 3D mesh data (so-called "triangle soups") with simple material properties and their transform hierarchy.
9+
Demonstrates how to construct and log raw 3D mesh data (so-called "triangle soups") programmatically from scratch.
1010

11-
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
12-
directly via [`Asset3D`](https://rerun.io/docs/reference/types/archetypes/asset3d).
11+
This example shows how to create mesh geometry by manually defining vertices, normals, colors, and texture coordinates, then demonstrating different material properties of the [`Mesh3D`](https://rerun.io/docs/reference/types/archetypes/mesh3d) archetype by reusing the same base geometry.
1312

14-
<!-- TODO(#1957): How about we load something elseto avoid confusion? -->
13+
If you want to log existing mesh files (like GLTF, OBJ, STL, etc.), use the [`Asset3D`](https://rerun.io/docs/reference/types/archetypes/asset3d) archetype instead.
1514

1615
<picture data-inline-viewer="examples/raw_mesh">
1716
<img src="https://static.rerun.io/raw_mesh/d5d008b9f1b53753a86efe2580443a9265070b77/full.png" alt="">
@@ -25,43 +24,85 @@ directly via [`Asset3D`](https://rerun.io/docs/reference/types/archetypes/asset3
2524
[`Transform3D`](https://www.rerun.io/docs/reference/types/archetypes/transform3d), [`Mesh3D`](https://www.rerun.io/docs/reference/types/archetypes/mesh3d)
2625

2726
## Background
28-
Raw 3D mesh data refers to the basic geometric representation of a three-dimensional object, typically composed of interconnected triangles.
29-
These triangles collectively form the surface of the object, defining its shape and structure in a digital environment.
30-
Rerun was employed to visualize and manage this raw mesh data, along with its associated simple material properties and transform hierarchy.
27+
Raw 3D mesh data refers to the basic geometric representation of a three-dimensional object, typically composed of interconnected triangles (vertices, edges, and faces). This example demonstrates how to construct such data programmatically without loading external files.
3128

29+
## Mesh Material Properties
30+
31+
The example generates a single sphere geometry and reuses it with different material parameters to showcase various features of the `Mesh3D` archetype:
32+
33+
### Vertex Colors
34+
The base sphere with per-vertex colors that create a gradient based on vertex position.
35+
36+
### Albedo Factor
37+
A solid color applied to the entire mesh using the `albedo_factor` parameter (pink in this example).
38+
39+
### Albedo Texture
40+
UV texture coordinates with a procedurally generated checkerboard texture demonstrating how to apply images to meshes.
41+
42+
### Vertex Normals
43+
Vertex normals for smooth shading, showing how surface orientation affects lighting.
3244

3345
## Logging and visualizing with Rerun
3446

3547
The visualizations in this example were created with the following Rerun code:
3648

37-
### 3D mesh data
38-
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.
49+
### Vertex colors
50+
Raw 3D mesh data is logged as [`Mesh3D`](https://www.rerun.io/docs/reference/types/archetypes/mesh3d) objects with per-vertex colors:
3951

4052
```python
4153
rr.log(
42-
path,
54+
"world/sphere/vertex_colors",
4355
rr.Mesh3D(
44-
vertex_positions=mesh.vertices,
45-
vertex_colors=vertex_colors,
46-
vertex_normals=mesh.vertex_normals,
47-
vertex_texcoords=vertex_texcoords,
48-
albedo_texture=albedo_texture,
49-
triangle_indices=mesh.faces,
50-
albedo_factor=albedo_factor,
56+
vertex_positions=sphere_data["vertex_positions"],
57+
vertex_colors=sphere_data["vertex_colors"],
58+
triangle_indices=sphere_data["triangle_indices"],
5159
),
5260
)
5361
```
54-
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.
62+
63+
### Albedo factor
64+
Apply a solid color to the entire mesh:
65+
5566
```python
5667
rr.log(
57-
path,
58-
rr.Transform3D(
59-
translation=trimesh.transformations.translation_from_matrix(world_from_mesh),
60-
mat3x3=world_from_mesh[0:3, 0:3],
68+
"world/sphere/albedo_factor",
69+
rr.Mesh3D(
70+
vertex_positions=sphere_data["vertex_positions"],
71+
albedo_factor=np.array([255, 100, 150, 255], dtype=np.uint8),
72+
triangle_indices=sphere_data["triangle_indices"],
6173
),
6274
)
6375
```
6476

77+
### Textured meshes
78+
For meshes with textures, provide UV coordinates and a texture:
79+
80+
```python
81+
rr.log(
82+
"world/sphere/albedo_texture",
83+
rr.Mesh3D(
84+
vertex_positions=sphere_data["vertex_positions"],
85+
vertex_texcoords=sphere_data["vertex_texcoords"],
86+
albedo_texture=texture,
87+
triangle_indices=sphere_data["triangle_indices"],
88+
),
89+
)
90+
```
91+
92+
### Smooth shading with normals
93+
For smooth shading, provide vertex normals:
94+
95+
```python
96+
rr.log(
97+
"world/sphere/vertex_normals",
98+
rr.Mesh3D(
99+
vertex_positions=sphere_data["vertex_positions"],
100+
vertex_normals=sphere_data["vertex_normals"],
101+
albedo_factor=np.array([100, 150, 255, 255], dtype=np.uint8),
102+
triangle_indices=sphere_data["triangle_indices"],
103+
),
104+
)
105+
```
65106

66107
## Run the code
67108
To run this example, make sure you have the Rerun repository checked out and the latest SDK installed:
@@ -79,11 +120,11 @@ To experiment with the provided example, simply execute the main Python script:
79120
```bash
80121
python -m raw_mesh # run the example
81122
```
82-
You can specify scene:
123+
You can customize the sphere subdivisions for more or less detail:
83124
```bash
84-
python -m raw_mesh --scene {lantern,avocado,buggy,brain_stem}
125+
python -m raw_mesh --sphere-subdivisions 64
85126
```
86-
If you wish to customize it, explore additional features, or save it use the CLI with the `--help` option for guidance:
127+
If you wish to explore additional features or save it, use the CLI with the `--help` option for guidance:
87128
```bash
88129
python -m raw_mesh --help
89130
```

0 commit comments

Comments
 (0)