How to get ARKit with Metal demo working in Portrait orientation?

I have built and run the example ARKit with Metal demo in XCode on iOS 11 beta 3 by choosing Augmented Reality and then Content Technology = Metal. It appears to run fine on my iPhone 7plus. Now I'd like to make one small change to it. The sample app is set to Device Orientation = LandscapeRight under Deployment Info. What I would like to do is switch it to run correctly in Portrait orientation but that doesn't seem to be a simple thing.


There are two references to landscapeRight orientation in the code within Renderer.swift as follows:


In updateSharedUniforms


    func updateSharedUniforms(frame: ARFrame) {
        /
      
        let uniforms = sharedUniformBufferAddress.assumingMemoryBound(to: SharedUniforms.self)
      
        uniforms.pointee.viewMatrix = simd_inverse(frame.camera.transform)
        uniforms.pointee.projectionMatrix = frame.camera.projectionMatrix(withViewportSize: viewportSize, orientation: .landscapeRight, zNear: 0.001, zFar: 1000)
     


and in updateImagePlane


    func updateImagePlane(frame: ARFrame) {
        /
        let displayToCameraTransform = frame.displayTransform(withViewportSize: viewportSize, orientation: .landscapeRight).inverted()


Changing these two enums from .landscapeRight to .portrait results in the app displaying the correct camera image in portrait mode but the anchor objects (as drawn by Metal) then don't stick to the right point in 3d space like they do in landscapeRight. Instead they start drifting off camera.

There must be some part of the code that is still assuming the viewport is 736x414 instead of 414x736 but it is not at all obvious where that is. Hoping somebody knows something or at least has an idea where the issue might be. Thanks!

Accepted Reply

This appears to have been fixed somewhere between 11 beta 5 and 7.


The previous viewport code in UpdateSharedUniforms in Renderer.swift:


        uniforms.pointee.viewMatrix = simd_inverse(frame.camera.transform)
        uniforms.pointee.projectionMatrix = frame.camera.projectionMatrix(withViewportSize: viewportSize, orientation: .portrait, zNear: 0.001, zFar: 1000)


The new code:


        uniforms.pointee.viewMatrix = frame.camera.viewMatrix(for: .portrait)
        uniforms.pointee.projectionMatrix = frame.camera.projectionMatrix(for: .portrait, viewportSize: viewportSize, zNear: 0.001, zFar: 1000)


Switching from .landscapeRight to .portrait now results in consistent behavior.

Replies

This appears to have been fixed somewhere between 11 beta 5 and 7.


The previous viewport code in UpdateSharedUniforms in Renderer.swift:


        uniforms.pointee.viewMatrix = simd_inverse(frame.camera.transform)
        uniforms.pointee.projectionMatrix = frame.camera.projectionMatrix(withViewportSize: viewportSize, orientation: .portrait, zNear: 0.001, zFar: 1000)


The new code:


        uniforms.pointee.viewMatrix = frame.camera.viewMatrix(for: .portrait)
        uniforms.pointee.projectionMatrix = frame.camera.projectionMatrix(for: .portrait, viewportSize: viewportSize, zNear: 0.001, zFar: 1000)


Switching from .landscapeRight to .portrait now results in consistent behavior.