Skip to content

Commit

Permalink
Improve MeshletMesh::from_mesh performance further (#14038)
Browse files Browse the repository at this point in the history
This change updates meshopt-rs to 0.3 to take advantage of the newly
added sparse simplification mode: by default, simplifier assumes that
the entire mesh is simplified and runs a set of calculations that are
O(vertex count), but in our case we simplify many small mesh subsets
which is inefficient.

Sparse mode instead assumes that the simplified subset is only using a
portion of the vertex buffer, and optimizes accordingly. This changes
the meaning of the error (as it becomes relative to the subset, in our
case a meshlet group); to ensure consistent error selection, we also use
the ErrorAbsolute mode which allows us to operate in mesh coordinate
space.

Additionally, meshopt 0.3 runs optimizeMeshlet automatically as part of
`build_meshlets` so we no longer need to call it ourselves.

This reduces the time to build meshlet representation for Stanford Bunny
mesh from ~1.65s to ~0.45s (3.7x) in optimized builds.
  • Loading branch information
zeux authored and mockersf committed Jun 27, 2024
1 parent 4f0b0e0 commit 5d7da82
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 24 deletions.
2 changes: 1 addition & 1 deletion crates/bevy_pbr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ serde = { version = "1", features = ["derive", "rc"], optional = true }
bincode = { version = "1", optional = true }
thiserror = { version = "1", optional = true }
range-alloc = { version = "0.1", optional = true }
meshopt = { version = "0.2.1", optional = true }
meshopt = { version = "0.3.0", optional = true }
metis = { version = "0.2", optional = true }
itertools = { version = "0.13", optional = true }
# direct dependency required for derive macro
Expand Down
31 changes: 8 additions & 23 deletions crates/bevy_pbr/src/meshlet/from_mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ use bevy_render::{
use bevy_utils::HashMap;
use itertools::Itertools;
use meshopt::{
build_meshlets, compute_cluster_bounds, compute_meshlet_bounds,
ffi::{meshopt_Bounds, meshopt_optimizeMeshlet},
simplify, simplify_scale, Meshlets, SimplifyOptions, VertexDataAdapter,
build_meshlets, compute_cluster_bounds, compute_meshlet_bounds, ffi::meshopt_Bounds, simplify,
simplify_scale, Meshlets, SimplifyOptions, VertexDataAdapter,
};
use metis::Graph;
use smallvec::SmallVec;
Expand Down Expand Up @@ -178,22 +177,7 @@ fn validate_input_mesh(mesh: &Mesh) -> Result<Cow<'_, [u32]>, MeshToMeshletMeshC
}

fn compute_meshlets(indices: &[u32], vertices: &VertexDataAdapter) -> Meshlets {
let mut meshlets = build_meshlets(indices, vertices, 64, 64, 0.0);

for meshlet in &mut meshlets.meshlets {
#[allow(unsafe_code)]
#[allow(clippy::undocumented_unsafe_blocks)]
unsafe {
meshopt_optimizeMeshlet(
&mut meshlets.vertices[meshlet.vertex_offset as usize],
&mut meshlets.triangles[meshlet.triangle_offset as usize],
meshlet.triangle_count as usize,
meshlet.vertex_count as usize,
);
}
}

meshlets
build_meshlets(indices, vertices, 64, 64, 0.0)
}

fn find_connected_meshlets(
Expand Down Expand Up @@ -306,7 +290,8 @@ fn simplify_meshlet_groups(

// Allow more deformation for high LOD levels (1% at LOD 1, 10% at LOD 20+)
let t = (lod_level - 1) as f32 / 19.0;
let target_error = 0.1 * t + 0.01 * (1.0 - t);
let target_error_relative = 0.1 * t + 0.01 * (1.0 - t);
let target_error = target_error_relative * mesh_scale;

// Simplify the group to ~50% triangle count
// TODO: Use simplify_with_locks()
Expand All @@ -316,7 +301,7 @@ fn simplify_meshlet_groups(
vertices,
group_indices.len() / 2,
target_error,
SimplifyOptions::LockBorder,
SimplifyOptions::LockBorder | SimplifyOptions::Sparse | SimplifyOptions::ErrorAbsolute,
Some(&mut error),
);

Expand All @@ -325,8 +310,8 @@ fn simplify_meshlet_groups(
return None;
}

// Convert error to object-space and convert from diameter to radius
error *= mesh_scale * 0.5;
// Convert error from diameter to radius
error *= 0.5;

Some((simplified_group_indices, error))
}
Expand Down

0 comments on commit 5d7da82

Please sign in to comment.