[add] 2d label support - #12847
Conversation
There was a problem hiding this comment.
Hi! Thanks for opening this pull request.
Because this is your first time contributing to this repository, make sure you've read our Contributor Guide and Code of Conduct.
There was a problem hiding this comment.
Pull request overview
Adds support for rendering 3D-positioned labels in 2D spatial views by projecting 3D label targets into the 2D view’s UI coordinate system, aligning label placement with the renderer’s camera/projection setup.
Changes:
- Refactors label creation to accept a precomputed
ui_from_worldmatrix instead of anEye. - Enables
UiLabelTarget::Position3Dlabels to be projected and shown in 2D views (previously skipped). - Exposes re_renderer’s
Projection::projection_from_viewso 2D view code can reuse the renderer’s projection math when computingui_from_world.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| crates/viewer/re_view_spatial/src/ui.rs | Updates label pipeline to take an explicit ui_from_world matrix and removes the 2D skip for 3D label targets. |
| crates/viewer/re_view_spatial/src/ui_3d.rs | Updates 3D view callsite to pass eye.ui_from_world(...) into label creation. |
| crates/viewer/re_view_spatial/src/ui_2d.rs | Computes a renderer-consistent ui_from_world matrix for 2D views and passes it into label creation. |
| crates/viewer/re_renderer/src/view_builder.rs | Makes Projection::projection_from_view public (so other crates can build consistent transforms). |
Comments suppressed due to low confidence (1)
crates/viewer/re_view_spatial/src/ui.rs:389
- Label depth sorting uses the projected NDC z (
project_point3(...).z) as the sort key. This worked with the 3D view’s regular projection, but the 2D view now uses re_renderer’s reverse‑Z projection, which flips the z ordering and can cause farther labels to be drawn on top of nearer ones in 2D views. Use a projection-invariant depth key (e.g. clip-spacew, which is proportional to view-space distance for perspective projections and unaffected by reverse‑Z) forUiLabelTarget::Position3Dsorting.
UiLabelTarget::Position3D(pos) => {
let pos_in_ui = *ui_from_world_3d * pos.extend(1.0);
if pos_in_ui.w <= 0.0 {
continue; // behind camera
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| fn ui2d_from_world(config: &TargetConfiguration, space2d_rect: Rect) -> glam::Mat4 { | ||
| let projection_from_view = config | ||
| .projection_from_view | ||
| .projection_from_view(config.resolution_in_pixel); | ||
| let ndc_scale_and_translation = config | ||
| .viewport_transformation | ||
| .to_ndc_scale_and_translation(); | ||
| let projection_from_view = ndc_scale_and_translation * projection_from_view; | ||
|
|
||
| glam::Mat4::from_translation(glam::vec3( | ||
| space2d_rect.center().x, | ||
| space2d_rect.center().y, | ||
| 0.0, | ||
| )) * glam::Mat4::from_scale(0.5 * glam::vec3(space2d_rect.width(), -space2d_rect.height(), 1.0)) | ||
| * projection_from_view | ||
| * config.view_from_world.to_mat4() | ||
| } |
| impl Projection { | ||
| fn projection_from_view(self, resolution_in_pixel: [u32; 2]) -> glam::Mat4 { | ||
| pub fn projection_from_view(self, resolution_in_pixel: [u32; 2]) -> glam::Mat4 { |
|
It's awesome to see this implemented, thank you for the contribution 🚀! Before we merge this, could you please address the comments form the Copilot review? They look reasonable to me. It would also be awesome to have a dedicated snapshot test in |
|
Thanks for your reply. I'll take a look at the review next weekend. |
Related
What