@@ -392,6 +392,9 @@ impl TransformForest {
392
392
}
393
393
} ;
394
394
395
+ // Query type of target's root for later.
396
+ let target_root_info = self . roots . get ( & target. root ) ;
397
+
395
398
itertools:: Either :: Right ( sources. map ( move |source| {
396
399
let Some ( root_from_source) = self . root_from_entity . get ( & source) else {
397
400
return (
@@ -413,6 +416,11 @@ impl TransformForest {
413
416
let target_from_source = root_from_source. left_multiply ( target. target_from_root ) ;
414
417
Ok ( target_from_source)
415
418
}
419
+ // There might be a connection via a pinhole making this 3D in 2D.
420
+ else if let Some ( TransformTreeRootInfo :: Pinhole ( pinhole_tree_root) ) = target_root_info
421
+ {
422
+ from_3d_source_to_2d_target ( & target, & source, pinhole_tree_root)
423
+ }
416
424
// There might be a connection via a pinhole making this 2D in 3D.
417
425
else if let Some ( TransformTreeRootInfo :: Pinhole ( pinhole_tree_root) ) =
418
426
self . roots . get ( & source. root )
@@ -439,36 +447,81 @@ impl TransformForest {
439
447
fn from_2d_source_to_3d_target (
440
448
target : & TargetInfo ,
441
449
source : & SourceInfo < ' _ > ,
442
- pinhole_tree_root : & PinholeTreeRoot ,
450
+ source_pinhole_tree_root : & PinholeTreeRoot ,
443
451
lookup_image_plane_distance : & dyn Fn ( EntityPathHash ) -> f32 ,
444
452
) -> Result < TransformInfo , TransformFromToError > {
445
453
let PinholeTreeRoot {
446
454
parent_tree_root,
447
455
pinhole_projection,
448
456
parent_root_from_pinhole_root : root_from_pinhole3d,
449
- } = pinhole_tree_root ;
457
+ } = source_pinhole_tree_root ;
450
458
459
+ // `root` here is the target's root!
460
+ // We call the source's root `pinhole3d` to distinguish it.
451
461
if * parent_tree_root != target. root {
452
462
return Err ( TransformFromToError :: no_path_between_target_and_source (
453
463
target, source,
454
464
) ) ;
455
465
}
456
466
457
467
// Rename for clarification:
458
- let pinhole2d_from_source = source. root_from_source ;
468
+ let image_plane_from_source = source. root_from_source ;
459
469
460
470
// There's a connection via a pinhole making this 2D in 3D.
461
471
// We can transform into the target space!
462
472
let pinhole_image_plane_distance = lookup_image_plane_distance ( source. root ) ;
463
473
464
474
// TODO: Locally cache pinhole transform?
465
- let pinhole3d_from_pinhole2d =
466
- pinhole2d_image_plane_from_pinhole3d ( pinhole_projection, pinhole_image_plane_distance) ;
467
- let target_from_pinhole2d =
468
- target. target_from_root * root_from_pinhole3d * pinhole3d_from_pinhole2d ;
475
+ let pinhole3d_from_image_plane =
476
+ pinhole3d_from_image_plane ( pinhole_projection, pinhole_image_plane_distance) ;
477
+ let target_from_image_plane =
478
+ target. target_from_root * root_from_pinhole3d * pinhole3d_from_image_plane ;
469
479
470
- // target_from_source = target_from_pinhole2d * pinhole2d_from_source
471
- Ok ( pinhole2d_from_source. left_multiply ( target_from_pinhole2d) )
480
+ // target_from_source = target_from_image_plane * image_plane_from_source
481
+ Ok ( image_plane_from_source. left_multiply ( target_from_image_plane) )
482
+ }
483
+
484
+ fn from_3d_source_to_2d_target (
485
+ target : & TargetInfo ,
486
+ source : & SourceInfo < ' _ > ,
487
+ target_pinhole_tree_root : & PinholeTreeRoot ,
488
+ ) -> Result < TransformInfo , TransformFromToError > {
489
+ let PinholeTreeRoot {
490
+ parent_tree_root,
491
+ pinhole_projection,
492
+ parent_root_from_pinhole_root : root_from_pinhole3d,
493
+ } = target_pinhole_tree_root;
494
+
495
+ // `root` here is the source's root!
496
+ // We call the target's root `pinhole3d` to distinguish it.
497
+ if * parent_tree_root != source. root {
498
+ return Err ( TransformFromToError :: no_path_between_target_and_source (
499
+ target, source,
500
+ ) ) ;
501
+ }
502
+
503
+ // Rename for clarification:
504
+ let target_from_image_plane = target. target_from_root ;
505
+
506
+ // TODO(#1025):
507
+ // There's no meaningful image plane distance for 3D->2D views.
508
+ let pinhole_image_plane_distance = 500.0 ;
509
+ // Currently our 2D views require us to invert the `pinhole2d_image_plane_from_pinhole3d` matrix.
510
+ // This builds a relationship between the 2D plane and the 3D world, when actually the 2D plane
511
+ // should have infinite depth!
512
+ // The inverse of this matrix *is* working for this, but quickly runs into precision issues.
513
+ // See also `ui_2d.rs#setup_target_config`
514
+
515
+ // TODO: Locally cache pinhole transform?
516
+ let pinhole3d_from_image_plane =
517
+ pinhole3d_from_image_plane ( pinhole_projection, pinhole_image_plane_distance) ;
518
+ let image_plane_from_pinhole3d = pinhole3d_from_image_plane. inverse ( ) ;
519
+ let pinhole3d_from_root = root_from_pinhole3d. inverse ( ) ;
520
+ let target_from_root =
521
+ target_from_image_plane * image_plane_from_pinhole3d * pinhole3d_from_root;
522
+
523
+ // target_from_source = target_from_root * root_from_source
524
+ Ok ( source. root_from_source . left_multiply ( target_from_root) )
472
525
}
473
526
474
527
fn left_multiply_smallvec1_of_transforms (
@@ -531,7 +584,7 @@ fn compute_root_from_archetype(
531
584
. unwrap_or_default ( )
532
585
}
533
586
534
- fn pinhole2d_image_plane_from_pinhole3d (
587
+ fn pinhole3d_from_image_plane (
535
588
resolved_pinhole_projection : & ResolvedPinholeProjection ,
536
589
pinhole_image_plane_distance : f32 ,
537
590
) -> glam:: Affine3A {
@@ -567,14 +620,6 @@ fn pinhole2d_image_plane_from_pinhole3d(
567
620
568
621
// Above calculation is nice for a certain kind of visualizing a projected image plane,
569
622
// but the image plane distance is arbitrary and there might be other, better visualizations!
570
-
571
- // TODO(#1025):
572
- // As such we don't ever want to invert this matrix!
573
- // However, currently our 2D views require us to do exactly that since we're forced to
574
- // build a relationship between the 2D plane and the 3D world, when actually the 2D plane
575
- // should have infinite depth!
576
- // The inverse of this matrix *is* working for this, but quickly runs into precision issues.
577
- // See also `ui_2d.rs#setup_target_config`
578
623
}
579
624
580
625
/// Resolved transforms at an entity.
0 commit comments