`PlaneDragGizmo` drifts with set snap-distance when moving pointer fast

Hello Babylon.js!

I am using a PlaneDragGizmo. If I set a snapDistance and drag the gizmo fast, the position of the gizmo starts to “drift” away from the pointer’s position. I.e. the gizmo is not at the same position as the pointer after moving the pointer fast.

This playground illustrates the “drift”.

Drift when setting a snapDistance:
gizmo-drifts-with-snap

No drift when setting NO snapDistance:
gizmo-no-drift-without-snap

Thanks a lot!

cc @Cedric

I am wondering if there is a precision issue when looking at the “steps” & “remain” calculation.

const dragSteps = Math.floor(Math.abs(currentSnapDragDistance) / this.snapDistance);
currentSnapDragDistance = currentSnapDragDistance % this.snapDistance;

Let’s assume

  • currentSnapDragDistance = 1 and
  • this.snapDistance = 0.3

then

  • dragSteps = Math.floor(Math.abs(currentSnapDragDistance) / this.snapDistance) = 3 :white_check_mark:
  • currentSnapDragDistance % this.snapDistance = 1 % 0.3 = 0.10000000000000003 != 0.1
    • or other way put: 1 % 0.3 === 0.1 // false :thinking:

Could these type of tiny precision errors accumulate?

P.s.: is the check if (this.dragBehavior.validateDrag(TmpVectors.Vector3[0])) { ... } necessary, if validateDrag() always returns true?

I just observed, that

  1. the drift also happens when I drag slowly
  2. it is most prominent when dragging to the “left upper corner”. I.e. dragging in other directions seem to have less influence :thinking:
    Update: actually, I’m not sure how big the influence of the direction is :man_facepalming:

gizmo-drifts-with-snap-slow

I need to take a closer look but my guess is distance is snapped everyframe and not accumulated then snapped. So error accumulates and you get that big difference after some frames.

Snap is not computed per X or Y value of the drag. It’s computed on the distance, whatever the direction is:

Which means if direction changes frequently, you’ll end up with a quite random position but the distance with the previous position will be a multiple of snapDistance.

But it does what is says: it snaps the distance. I’m doing the change to do an axis separation.

@Philippe I’ve open this PR : Back from vacation fixes by CedricGuillemet · Pull Request #17097 · BabylonJS/Babylon.js · GitHub

Let me know if it fixes your problem.

Hey @Cedric

Back from holidays, I checked the change and can confirm that the change works.

Thank you.

1 Like