|
let mut num_instances = 0; |
|
for ( |
|
instance_index, |
|
(half_size, world_from_instance, radius, &color, proc_mesh_key, fill_mode), |
|
) in itertools::izip!( |
|
half_sizes, |
|
world_from_instances, |
|
line_radii, |
|
colors.iter(), |
|
batch.meshes, |
|
batch.fill_modes |
|
) |
|
.enumerate() |
|
{ |
|
let instance = Instance::from(instance_index as u64); |
|
num_instances = instance_index + 1; |
|
|
|
let world_from_instance = world_from_instance |
|
* glam::Affine3A::from_scale(glam::Vec3::from(*half_size)) |
|
* constant_instance_transform; |
|
world_space_bounding_box = world_space_bounding_box.union( |
|
proc_mesh_key |
|
.simple_bounding_box() |
|
.transform_affine3(&world_from_instance), |
|
); |
|
|
|
match fill_mode { |
|
FillMode::MajorWireframe | FillMode::DenseWireframe => { |
|
let Some(wireframe_mesh) = query_context.store_ctx().caches.entry( |
|
|c: &mut proc_mesh::WireframeCache| c.entry(proc_mesh_key, self.render_ctx), |
|
) else { |
|
return Err(ViewSystemExecutionError::DrawDataCreationError( |
|
"Failed to allocate wireframe mesh".into(), |
|
)); |
|
}; |
|
|
|
for strip in &wireframe_mesh.line_strips { |
|
let strip_builder = line_batch |
|
.add_strip( |
|
strip |
|
.iter() |
|
.map(|&point| world_from_instance.transform_point3(point)), |
|
) |
|
.color(color) |
|
.radius(radius) |
|
.picking_instance_id(PickingLayerInstanceId(instance_index as _)) |
|
// Looped lines should be connected with rounded corners. |
|
.flags(LineStripFlags::FLAGS_OUTWARD_EXTENDING_ROUND_CAPS); |
|
|
|
if let Some(outline_mask_ids) = ent_context |
|
.highlight |
|
.instances |
|
.get(&Instance::from(instance_index as u64)) |
|
{ |
|
// Not using ent_context.highlight.index_outline_mask() because |
|
// that's already handled when the builder was created. |
|
strip_builder.outline_mask_ids(*outline_mask_ids); |
|
} |
|
} |
|
} |
|
FillMode::Solid => { |
|
let store_ctx = query_context.store_ctx(); |
|
let Some(solid_mesh) = |
|
store_ctx.caches.entry(|c: &mut proc_mesh::SolidCache| { |
|
c.entry(proc_mesh_key, self.render_ctx) |
|
}) |
|
else { |
|
return Err(ViewSystemExecutionError::DrawDataCreationError( |
|
"Failed to allocate solid mesh".into(), |
|
)); |
|
}; |
|
|
|
self.solid_instances.push(GpuMeshInstance { |
|
gpu_mesh: solid_mesh.gpu_mesh, |
|
world_from_mesh: world_from_instance, |
|
outline_mask_ids: ent_context.highlight.index_outline_mask(instance), |
|
picking_layer_id: re_view::picking_layer_id_from_instance_path_hash( |
|
InstancePathHash::instance(entity_path, instance), |
|
), |
|
additive_tint: color, |
|
}); |
|
} |
|
} |
|
} |
|
|
This code is way too slow when visualizing hundreds of thousands of meshes:
rerun/crates/viewer/re_view_spatial/src/visualizers/utilities/proc_mesh_vis.rs
Lines 152 to 236 in f7f0fc4
In constrast, spheres and points are ~100x faster in Rerun.
Optimizing boxes in particular would be nice because it is very useful for rendering voxel occupancy grids.
Approaches
Speed up instanced rendering
Provide a way of mapping transforms onto the GPU directly, speeding up rendering of all our primitives.
Write specific shaders for boxes
We could consider a fast-path for boxes, like we have for spheres, e.g. generating the vertex data in a shader.
Related
The way we solve this could maybe also speed up having millions of
Ellipsoids3D, which would unblock:Links