@@ -154,6 +154,31 @@ pub enum TransformFromToError {
154
154
} ,
155
155
}
156
156
157
+ impl TransformFromToError {
158
+ fn no_path_between_target_and_source ( target : & TargetInfo , source : & SourceInfo < ' _ > ) -> Self {
159
+ Self :: NoPathBetweenFrames {
160
+ target : target. id ,
161
+ src : source. id ,
162
+ target_root : target. root ,
163
+ source_root : source. root ,
164
+ }
165
+ }
166
+ }
167
+
168
+ /// Private utility struct for working with a target frame.
169
+ struct TargetInfo {
170
+ id : EntityPathHash ,
171
+ root : EntityPathHash ,
172
+ target_from_root : glam:: Affine3A ,
173
+ }
174
+
175
+ /// Private utility struct for working with a source frame.
176
+ struct SourceInfo < ' a > {
177
+ id : EntityPathHash ,
178
+ root : EntityPathHash ,
179
+ root_from_source : & ' a TransformInfo ,
180
+ }
181
+
157
182
/// Properties of a pinhole transform tree root.
158
183
///
159
184
/// Each pinhole forms its own subtree which may be embedded into a 3D space.
@@ -204,7 +229,7 @@ pub struct TransformForest {
204
229
roots : IntMap < EntityPathHash , TransformTreeRootInfo > ,
205
230
206
231
/// All entities reachable from one of the tree roots.
207
- transform_per_entity : IntMap < EntityPathHash , TransformInfo > ,
232
+ root_from_entity : IntMap < EntityPathHash , TransformInfo > ,
208
233
}
209
234
210
235
impl TransformForest {
@@ -226,7 +251,7 @@ impl TransformForest {
226
251
let mut tree = Self {
227
252
roots : std:: iter:: once ( ( EntityPath :: root ( ) . hash ( ) , TransformTreeRootInfo :: EntityRoot ) )
228
253
. collect ( ) ,
229
- transform_per_entity : Default :: default ( ) ,
254
+ root_from_entity : Default :: default ( ) ,
230
255
} ;
231
256
tree. gather_descendants_transforms (
232
257
entity_tree,
@@ -254,7 +279,7 @@ impl TransformForest {
254
279
let root_from_parent = transform_root_from_parent. target_from_entity ;
255
280
256
281
let previous_transform = self
257
- . transform_per_entity
282
+ . root_from_entity
258
283
. insert ( subtree. path . hash ( ) , transform_root_from_parent) ;
259
284
debug_assert ! ( previous_transform. is_none( ) , "Root was added already" ) ; // TODO(andreas): Build out into cycle detection (cycles can't _yet_ happen)
260
285
@@ -337,10 +362,10 @@ impl TransformForest {
337
362
sources : impl Iterator < Item = EntityPathHash > ,
338
363
lookup_image_plane_distance : & dyn Fn ( EntityPathHash ) -> f32 ,
339
364
) -> impl Iterator < Item = ( EntityPathHash , Result < TransformInfo , TransformFromToError > ) > {
340
- // We're looking for common root between source and target.
365
+ // We're looking for a common root between source and target.
341
366
// We start by looking up the target's tree root.
342
367
343
- let Some ( root_from_target) = self . transform_per_entity . get ( & target) else {
368
+ let Some ( root_from_target) = self . root_from_entity . get ( & target) else {
344
369
return itertools:: Either :: Left ( sources. map ( move |source| {
345
370
(
346
371
source,
@@ -349,8 +374,8 @@ impl TransformForest {
349
374
} ) ) ;
350
375
} ;
351
376
352
- // Invert `root_from_target` to get `target_from_root `.
353
- let ( target_root , target_from_root ) = {
377
+ // Invert `root_from_target` to get `target.from_root `.
378
+ let target = {
354
379
let TransformInfo {
355
380
root : target_root,
356
381
target_from_entity : root_from_entity,
@@ -360,83 +385,92 @@ impl TransformForest {
360
385
target_from_archetype : _,
361
386
} = & root_from_target;
362
387
363
- ( * target_root, root_from_entity. inverse ( ) )
388
+ TargetInfo {
389
+ id : target,
390
+ root : * target_root,
391
+ target_from_root : root_from_entity. inverse ( ) ,
392
+ }
364
393
} ;
365
394
366
395
itertools:: Either :: Right ( sources. map ( move |source| {
367
- let Some ( root_from_source) = self . transform_per_entity . get ( & source) else {
396
+ let Some ( root_from_source) = self . root_from_entity . get ( & source) else {
368
397
return (
369
398
source,
370
399
Err ( TransformFromToError :: UnknownSourceFrame ( source) ) ,
371
400
) ;
372
401
} ;
373
402
374
- let source_root = root_from_source. root ;
403
+ let source = SourceInfo {
404
+ id : source,
405
+ root : root_from_source. root ,
406
+ root_from_source,
407
+ } ;
375
408
376
409
// Common case: both source & target share the same root.
377
- if source_root == target_root {
410
+ let result = if source . root == target . root {
378
411
// TODO: fast track for root being target.
379
412
// target_from_source = target_from_reference * root_from_source
380
- let target_from_source = root_from_source. left_multiply ( target_from_root) ;
381
- ( source , Ok ( target_from_source) )
413
+ let target_from_source = root_from_source. left_multiply ( target . target_from_root ) ;
414
+ Ok ( target_from_source)
382
415
}
383
416
// There might be a connection via a pinhole making this 2D in 3D.
384
417
else if let Some ( TransformTreeRootInfo :: Pinhole ( pinhole_tree_root) ) =
385
- self . roots . get ( & source_root )
418
+ self . roots . get ( & source . root )
386
419
{
387
- let PinholeTreeRoot {
388
- parent_tree_root,
389
- pinhole_projection,
390
- parent_root_from_pinhole_root : root_from_pinhole3d,
391
- } = pinhole_tree_root;
392
-
393
- if * parent_tree_root != target_root {
394
- return (
395
- source,
396
- Err ( TransformFromToError :: NoPathBetweenFrames {
397
- target,
398
- src : source,
399
- target_root,
400
- source_root,
401
- } ) ,
402
- ) ;
403
- }
404
-
405
- // Rename for clarification:
406
- let pinhole2d_from_source = root_from_source;
407
-
408
- // There's a connection via a pinhole making this 2D in 3D.
409
- // We can transform into the target space!
410
- let pinhole_image_plane_distance = lookup_image_plane_distance ( source_root) ;
411
-
412
- // TODO: Locally cache pinhole transform?
413
- let pinhole3d_from_pinhole2d = pinhole2d_image_plane_from_pinhole3d (
414
- pinhole_projection,
415
- pinhole_image_plane_distance,
416
- ) ;
417
- let target_from_pinhole2d =
418
- target_from_root * root_from_pinhole3d * pinhole3d_from_pinhole2d;
419
-
420
- // target_from_source = target_from_pinhole2d * pinhole2d_from_source
421
- let target_from_source = pinhole2d_from_source. left_multiply ( target_from_pinhole2d) ;
422
- ( source, Ok ( target_from_source) )
420
+ from_2d_source_to_3d_target (
421
+ & target,
422
+ & source,
423
+ pinhole_tree_root,
424
+ lookup_image_plane_distance,
425
+ )
423
426
}
424
427
// Disconnected, we can't transform into the target space.
425
428
else {
426
- (
427
- source,
428
- Err ( TransformFromToError :: NoPathBetweenFrames {
429
- target,
430
- src : source,
431
- target_root,
432
- source_root,
433
- } ) ,
434
- )
435
- }
429
+ Err ( TransformFromToError :: no_path_between_target_and_source (
430
+ & target, & source,
431
+ ) )
432
+ } ;
433
+
434
+ ( source. id , result)
436
435
} ) )
437
436
}
438
437
}
439
438
439
+ fn from_2d_source_to_3d_target (
440
+ target : & TargetInfo ,
441
+ source : & SourceInfo < ' _ > ,
442
+ pinhole_tree_root : & PinholeTreeRoot ,
443
+ lookup_image_plane_distance : & dyn Fn ( EntityPathHash ) -> f32 ,
444
+ ) -> Result < TransformInfo , TransformFromToError > {
445
+ let PinholeTreeRoot {
446
+ parent_tree_root,
447
+ pinhole_projection,
448
+ parent_root_from_pinhole_root : root_from_pinhole3d,
449
+ } = pinhole_tree_root;
450
+
451
+ if * parent_tree_root != target. root {
452
+ return Err ( TransformFromToError :: no_path_between_target_and_source (
453
+ target, source,
454
+ ) ) ;
455
+ }
456
+
457
+ // Rename for clarification:
458
+ let pinhole2d_from_source = source. root_from_source ;
459
+
460
+ // There's a connection via a pinhole making this 2D in 3D.
461
+ // We can transform into the target space!
462
+ let pinhole_image_plane_distance = lookup_image_plane_distance ( source. root ) ;
463
+
464
+ // 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;
469
+
470
+ // target_from_source = target_from_pinhole2d * pinhole2d_from_source
471
+ Ok ( pinhole2d_from_source. left_multiply ( target_from_pinhole2d) )
472
+ }
473
+
440
474
fn left_multiply_smallvec1_of_transforms (
441
475
target_from_reference : glam:: Affine3A ,
442
476
reference_from_source : & SmallVec1 < [ glam:: Affine3A ; 1 ] > ,
0 commit comments