unprojectPoint(_:) broken in iOS 14

[I've already submitted this via Feedback Assistant, issue FB8904434. Providing a brief summary here for other affected developers to discover.]

The behavior of unprojectPoint(_:) has changed in iOS 14, for both
ARSCNView and SCNView.

The unprojected point should be most distant for a z-value of 1.0.
But in iOS 14, it is actually most distant for a z-value of 0.5.

Background
When you unproject a screen coordinate, you provide a z value between 0.0 and 1.0 to specify the depth. 0.0 corresponds to the near clipping plane, 1.0 to the far clipping plane, and intermediate values map in between.

Expected/documented behavior:
Distance from the unprojected point to the camera should increase monotonically (though not necessarily linearly) with z.

Observed behavior:
  • iOS 13: distance increases monotonically with z. Takes a huge jump between z = 0.9 and z = 1.0.

  • iOS 14: distance increases for z 0.0 to 0.5, then decreases. Takes a huge jump on either side of z = 0.5.

Note
I am surprised by just how non-linear the mapping is, under either version of iOS. For example, under iOS 13 as z varies from 0.0 to 0.9, the distance changes from 0.5 mm to 5 mm. Then at 1.0 the distance jumps to over 1000 meters.

Replies

Hello,

Please see this post which contains an answer for this issue: https://developer.apple.com/forums/thread/664755

(In short, the usesReverseZ property is now being respected by unprojectPoint method in iOS 14)

Thanks!
Thanks, gchiste!

I wasn't previously aware of usesReverseZ. Now that I've read about that property (though not, unfortunately, in Apple's SceneKit documentation), I understand why my results were so non-linear.

I will do some experiments with usesReverseZ in a bit. But I'm not seeing why that would change my observation that a z value of 0.5 is apparently mapping to the far clipping plane. Wouldn't usesReverseZ simply control whether z == 0 vs. z == 1 maps to the far clipping plane?
The good news: Yes, if I set usesReverseZ to false, then the behavior of unprojectPoint() returns to the pre-iOS 14 behavior.

The bad news: This doesn’t explain why when usesReverseZ == true, a z-value of 0.5 maps to the far clipping plane. For reverse-z, presumably 0.0 should do so? Also, the other mappings look just as non-linear as in pre-iOS 14 — that’s not what is supposed to happen with reverse-z.

So it seems to me that unprojectPoint() is working incorrectly when usesReverseZ == true. (Defaulting it to true in iOS 14 seems a bit questionable.)

Hello Dave,

I see what you mean! Please continue to follow up with your bug report. In the meantime, please continue to disable reverseZ as a workaround. (I do recommend that you switch it back on once the issue is resolved)