Skip to content

Commit b20d107

Browse files
kpreidemilk
andauthored
Add FillMode::MajorWireframe for more significant ellipsoid wireframes. (#7044)
### What * Add `FillMode::MajorWireframe`. For ellipsoids, this causes them to be drawn as three axis-aligned ellipses. It has no other effects. This implements the main part of #6962. * The previous `FillMode::Wireframe` has also been been renamed to `DenseWireframe` to reflect its relative role. * Updated `hexasphere` to 14.1.0 and removed the bug workaround code. I'm not sure if adding another `FillMode` is the best way to expose this rendering functionality, but it works out tidily enough for now. This does not modify any examples, but if we applied `MajorWireframe` to the `ellipsoid3d_batch` snippet, we'd get: ![Screenshot 2024-08-02 at 14 23 09](https://github.com/user-attachments/assets/e25a3244-d0b8-4e49-a4bf-388c6d7e9d33) ### Checklist * [X] I have read and agree to [Contributor Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and the [Code of Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md) * [X] I've included a screenshot or gif (if applicable) * [ ] I have tested the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7044?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7044?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [X] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [X] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! * [X] If have noted any breaking changes to the log API in `CHANGELOG.md` and the migration guide - [PR Build Summary](https://build.rerun.io/pr/7044) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`. --------- Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
1 parent 9fe28a4 commit b20d107

File tree

13 files changed

+157
-76
lines changed

13 files changed

+157
-76
lines changed

Cargo.lock

+2-2
Original file line numberDiff line numberDiff line change
@@ -2505,9 +2505,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
25052505

25062506
[[package]]
25072507
name = "hexasphere"
2508-
version = "14.0.0"
2508+
version = "14.1.0"
25092509
source = "registry+https://github.com/rust-lang/crates.io-index"
2510-
checksum = "6c64d70ed6295005e2bc5a6f624300cfd6d49908da76b3654c4cbdb1d4222705"
2510+
checksum = "344d5bf5d6b6da1020fcfd4014d44e0cc695356c603db9c774b30bd6d385ad2b"
25112511
dependencies = [
25122512
"constgebra",
25132513
"glam",

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ glam = "0.28"
171171
glob = "0.3"
172172
gltf = "1.1"
173173
half = "2.3.1"
174-
hexasphere = "14.0.0"
174+
hexasphere = "14.1.0"
175175
image = { version = "0.25", default-features = false }
176176
indent = "0.1"
177177
indexmap = "2.1" # Version chosen to align with other dependencies

crates/store/re_types/definitions/rerun/components/fill_mode.fbs

+23-5
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,31 @@ enum FillMode: ubyte(
77
/// Invalid value. Won't show up in generated types.
88
Invalid = 0,
99

10-
/// Lines are drawn around the edges of the shape.
10+
// Design note: This entire enum is an temporary mechanism which should be replaced by
11+
// allowing entities to simultaneously have fill and stroke colors.
12+
// Doing that is blocked on tagged components:
13+
// <https://github.com/rerun-io/rerun/issues/6889>.
14+
// Once those colors exist, visualizers should be updated to simply render whichever combination
15+
// of these features have non-(0, 0, 0, 0) colors set.
16+
17+
/// Lines are drawn around the parts of the shape which directly correspond to the logged data.
18+
///
19+
/// Examples of what this means:
1120
///
12-
/// The interior (2D) or surface (3D) are not drawn.
13-
Wireframe (default),
21+
/// * An [archetypes.Ellipsoids3D] will draw three axis-aligned ellipses that are cross-sections
22+
/// of each ellipsoid, each of which displays two out of three of the sizes of the ellipsoid.
23+
/// * For [archetypes.Boxes3D], it is the edges of the box, identical to `DenseWireframe`.
24+
MajorWireframe (default),
1425

15-
/// The interior (2D) or surface (3D) is filled with a single color.
26+
/// Many lines are drawn to represent the surface of the shape in a see-through fashion.
1627
///
17-
/// Lines are not drawn.
28+
/// Examples of what this means:
29+
///
30+
/// * An [archetypes.Ellipsoids3D] will draw a wireframe triangle mesh that approximates each
31+
/// ellipsoid.
32+
/// * For [archetypes.Boxes3D], it is the edges of the box, identical to `MajorWireframe`.
33+
DenseWireframe,
34+
35+
/// The surface of the shape is filled in with a solid color. No lines are drawn.
1836
Solid,
1937
}

crates/store/re_types/src/components/fill_mode.rs

+29-13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/viewer/re_space_view_spatial/src/proc_mesh.rs

+34-33
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
55
use std::sync::Arc;
66

7-
use ahash::HashSet;
87
use glam::{uvec3, vec3, Vec3, Vec3A};
8+
use hexasphere::BaseShape;
99
use itertools::Itertools as _;
1010
use smallvec::smallvec;
1111

@@ -28,15 +28,25 @@ pub enum ProcMeshKey {
2828
///
2929
/// The resulting mesh may be scaled to represent spheres and ellipsoids
3030
/// of other sizes.
31-
Sphere { subdivisions: usize },
31+
Sphere {
32+
/// Number of triangle subdivisions to perform to create a finer, rounder mesh.
33+
subdivisions: usize,
34+
35+
/// If true, then when a wireframe mesh is generated, it includes only
36+
/// the 3 axis-aligned “equatorial” circles, and not the full triangle mesh.
37+
axes_only: bool,
38+
},
3239
}
3340

3441
impl ProcMeshKey {
3542
/// Returns the bounding box which can be computed from the mathematical shape,
3643
/// without regard for its exact approximation as a mesh.
3744
pub fn simple_bounding_box(&self) -> re_math::BoundingBox {
3845
match self {
39-
Self::Sphere { subdivisions: _ } => {
46+
Self::Sphere {
47+
subdivisions: _,
48+
axes_only: _,
49+
} => {
4050
// sphere’s radius is 1, so its size is 2
4151
re_math::BoundingBox::from_center_size(Vec3::splat(0.0), Vec3::splat(2.0))
4252
}
@@ -166,21 +176,19 @@ fn generate_wireframe(key: &ProcMeshKey, render_ctx: &RenderContext) -> Wirefram
166176
line_strips,
167177
}
168178
}
169-
ProcMeshKey::Sphere { subdivisions } => {
179+
ProcMeshKey::Sphere {
180+
subdivisions,
181+
axes_only,
182+
} => {
170183
let subdiv: hexasphere::Subdivided<(), OctahedronBase> =
171184
hexasphere::Subdivided::new(subdivisions, |_| ());
172185

173186
let sphere_points = subdiv.raw_points();
174187

175-
// TODO(kpreid): There is a bug in `hexasphere` where it fails to return lines which
176-
// reach the original corners of the shape. This will be fixed as part of
177-
// <https://github.com/OptimisticPeach/hexasphere/issues/19>,
178-
// which is merged but not yet published on crates.io.
179-
// When hexasphere 15.0 or 14.0.1 is available, update, then keep the first branch
180-
// of this `if` only.
181-
let line_strips: Vec<Vec<Vec3>> = if false {
182-
subdiv
183-
.get_all_line_indices(1, |v| v.push(0))
188+
let line_strips: Vec<Vec<Vec3>> = if axes_only {
189+
let mut buffer: Vec<u32> = Vec::new();
190+
subdiv.get_major_edges_line_indices(&mut buffer, 1, |v| v.push(0));
191+
buffer
184192
.split(|&i| i == 0)
185193
.map(|strip| -> Vec<Vec3> {
186194
strip
@@ -190,24 +198,14 @@ fn generate_wireframe(key: &ProcMeshKey, render_ctx: &RenderContext) -> Wirefram
190198
})
191199
.collect()
192200
} else {
193-
// Gather edges from the triangles, deduplicating.
194-
let lines: HashSet<(u32, u32)> = subdiv
195-
.get_all_indices()
196-
.chunks(3)
197-
.flat_map(|triangle| {
198-
let [i1, i2, i3] = <[u32; 3]>::try_from(triangle).unwrap();
199-
[(i1, i2), (i2, i3), (i3, i1)]
200-
})
201-
.map(|(i1, i2)| if i1 > i2 { (i2, i1) } else { (i1, i2) })
202-
.collect();
203-
204-
lines
205-
.into_iter()
206-
.map(|(i1, i2)| {
207-
vec![
208-
sphere_points[i1 as usize].into(),
209-
sphere_points[i2 as usize].into(),
210-
]
201+
subdiv
202+
.get_all_line_indices(1, |v| v.push(0))
203+
.split(|&i| i == 0)
204+
.map(|strip| -> Vec<Vec3> {
205+
strip
206+
.iter()
207+
.map(|&i| sphere_points[i as usize - 1].into())
208+
.collect()
211209
})
212210
.collect()
213211
};
@@ -296,7 +294,10 @@ fn generate_solid(
296294
vertex_texcoords: vec![glam::Vec2::ZERO; num_vertices],
297295
}
298296
}
299-
ProcMeshKey::Sphere { subdivisions } => {
297+
ProcMeshKey::Sphere {
298+
subdivisions,
299+
axes_only: _, // no effect on solid mesh
300+
} => {
300301
let subdiv: hexasphere::Subdivided<(), OctahedronBase> =
301302
hexasphere::Subdivided::new(subdivisions, |_| ());
302303

@@ -374,7 +375,7 @@ fn materials_for_uncolored_mesh(
374375
#[derive(Clone, Copy, Debug, Default)]
375376
struct OctahedronBase;
376377

377-
impl hexasphere::BaseShape for OctahedronBase {
378+
impl BaseShape for OctahedronBase {
378379
fn initial_points(&self) -> Vec<Vec3A> {
379380
vec![
380381
Vec3A::NEG_X,

crates/viewer/re_space_view_spatial/src/visualizers/boxes3d.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ impl Boxes3DVisualizer {
111111
);
112112

113113
match data.fill_mode {
114-
FillMode::Wireframe => {
114+
FillMode::DenseWireframe | FillMode::MajorWireframe => {
115115
let box3d = line_batch
116116
.add_box_outline_from_transform(world_from_instance)
117117
.color(color)
@@ -283,7 +283,7 @@ impl VisualizerSystem for Boxes3DVisualizer {
283283
.unwrap_or_default();
284284

285285
match fill_mode {
286-
FillMode::Wireframe => {
286+
FillMode::DenseWireframe | FillMode::MajorWireframe => {
287287
// Each box consists of 12 independent lines with 2 vertices each.
288288
line_builder.reserve_strips(num_boxes * 12)?;
289289
line_builder.reserve_vertices(num_boxes * 12 * 2)?;

crates/viewer/re_space_view_spatial/src/visualizers/ellipsoids.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,18 @@ impl Ellipsoids3DVisualizer {
107107

108108
// TODO(kpreid): subdivisions should be configurable, and possibly dynamic based on
109109
// either world size or screen size (depending on application).
110-
let subdivisions = 2;
111-
let proc_mesh_key = proc_mesh::ProcMeshKey::Sphere { subdivisions };
110+
let subdivisions = match data.fill_mode {
111+
FillMode::DenseWireframe => 2, // Don't make it too crowded - let the user see inside the mesh.
112+
FillMode::Solid => 6, // Smooth, but not too CPU/GPU intensive
113+
FillMode::MajorWireframe => 12, // Three smooth ellipses
114+
};
115+
let proc_mesh_key = proc_mesh::ProcMeshKey::Sphere {
116+
subdivisions,
117+
axes_only: match data.fill_mode {
118+
FillMode::MajorWireframe => true,
119+
FillMode::DenseWireframe | FillMode::Solid => false,
120+
},
121+
};
112122

113123
// No need to take half_size times 2 since the mesh we're using is already scaled accordingly.
114124
let world_from_instance =
@@ -120,7 +130,7 @@ impl Ellipsoids3DVisualizer {
120130
);
121131

122132
match data.fill_mode {
123-
FillMode::Wireframe => {
133+
FillMode::MajorWireframe | FillMode::DenseWireframe => {
124134
let Some(wireframe_mesh) =
125135
ctx.viewer_ctx
126136
.cache

docs/content/reference/types/components/fill_mode.md

+2-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rerun_cpp/src/rerun/components/fill_mode.hpp

+17-6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rerun_py/rerun_sdk/rerun/components/fill_mode.py

+20-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)