【问题标题】:Stereo ARSCNview to make VR and AR mix立体 ARSCNview 使 VR 和 AR 混合
【发布时间】:2017-07-03 21:25:11
【问题描述】:

我想混合使用virtual realityaugmented reality。 目标是我有一个立体相机(每只眼睛)。

我尝试将两个ARSCNView 放入viewCotnroller,但似乎ARKit 只能同时启用一个ARWorldTrackingSessionConfiguration。我怎样才能做到这一点?

我研究了将视图的图形表示复制到另一个视图,但无法找到。请帮助我找到解决方案。

我找到了这个链接,也许它可以启发我们: ARKit with multiple users

这是我的问题的一个示例:

https://www.youtube.com/watch?v=d6LOqNnYm5s

PS:之前不像我的帖子,评论一下为什么!

【问题讨论】:

    标签: swift augmented-reality arkit virtual-reality arscnview


    【解决方案1】:

    下面的代码基本上就是Hal所说的。我之前在 github 上写了几行,或许可以帮助你入门。 (简单的代码,没有桶形失真,还没有调整窄 FOV)。

    本质上,我们将同一个场景连接到第二个 ARSCNView(所以两个 ARSCNView 看到的是同一个场景)。无需让 ARWorldTrackingSessionConfiguration 与 2 个 ARSCNViews 一起工作。然后,我们偏移它的 pointOfView,使其定位为第二只眼睛。

    https://github.com/hanleyweng/iOS-Stereoscopic-ARKit-Template

    【讨论】:

    • 天哪,这正是我正在搜索的内容!我对这种快速代码很陌生..非常感谢你的队友:-)
    【解决方案2】:

    ARSession documentation 表示ARSession 是一个共享对象。

    使用 ARKit 构建的每个 AR 体验都需要一个 ARSession 对象。如果你使用一个 ARSCN查看 要么 ARSK查看 对象以轻松构建您的 AR 体验的视觉部分,视图对象包含一个 ARSession 实例。如果您为 AR 内容构建自己的渲染器,则需要自己实例化和维护一个 ARSession 对象。

    所以最后一句话有一个线索。不要使用两个 ARSCNView 实例,而是使用 SCNView 并在它们之间共享一个 ARSession

    我预计这是一个常见的用例,因此值得提交 Radar 请求立体声支持。

    现在该怎么做?

    (单例)会话只有一个代表。您需要两个不同的委托实例,每个视图一个。您可以使用将委托消息发送到每个视图的对象来解决这个问题;可以解决,但需要做一些额外的工作。

    还有一个问题是需要两个稍微不同的摄像头位置,每只眼睛一个,用于立体视觉。 ARKit 使用一个摄像头,放置在 iOS 设备的位置,因此您必须对其进行模糊处理。

    然后你必须为每只眼睛处理不同的桶形失真。

    对我来说,这加起来就是编写我自己的自定义对象来拦截 ARKit 委托消息,将坐标转换为我从两个不同的相机看到的坐标,并管理两个不同的 SCNView(不是 ARSCNView)。或者也许使用一个 ARSCNView(一只眼睛),截取其帧更新,然后将这些帧传递给 SCNView(另一只眼睛)。

    归档雷达,发布号码,我会欺骗它。

    【讨论】:

    • 非常感谢您非常完整的回答!
    • 然而 ARSession 不参与 SCNView。我终于无法想象如何做到这一点。委托需要包含 ARSession 的所有数据,但这是不可能的,因为我们无法访问所有这些数据。或者我的知识有点差..
    • 使用 ARSessionDelegate 方法之一,可能是session(_ session: ARSession, didUpdate frame: ARFrame)。在此处捕获 AR 框架,将其传递给您的自定义调度程序,然后调度程序将其传递给每个 SCNView 以用作背景。就像我说的,很多工作。而且你仍然为每只眼睛使用相同的相机图像,所以我认为即使你让它工作,它也不会是令人满意的立体。
    • 好的,谢谢!真的很抱歉,我是这种编程的新手。现在我的立体声音响不会是立体声的。在 youtube 上,我们可以找到很多带有 2 张相同图片的视频。这是一个非常好的开始!
    【解决方案3】:

    为此,请使用以下代码:

    import UIKit
    import SceneKit
    import ARKit
    
    class ViewController: UIViewController, ARSCNViewDelegate {
    
        @IBOutlet weak var sceneView: ARSCNView!
        @IBOutlet weak var sceneView2: ARSCNView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            sceneView.delegate = self
            sceneView.showsStatistics = true
            let scene = SCNScene(named: "art.scnassets/ship.scn")!
            sceneView.scene = scene
            sceneView.isPlaying = true
    
            // SceneView2 Setup
            sceneView2.scene = scene
            sceneView2.showsStatistics = sceneView.showsStatistics
    
            // Now sceneView2 starts receiving updates
            sceneView2.isPlaying = true     
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            let configuration = ARWorldTrackingConfiguration()
            sceneView.session.run(configuration)
        }
        override func viewWillDisappear(_ animated: Bool) {
            super.viewWillDisappear(animated)
            sceneView.session.pause()
        }
    }
    

    不要忘记为ARSCNViews 激活.isPlaying 实例属性。

    【讨论】:

      【解决方案4】:

      Objective-C 版本 Han 的 github 代码,sceneViews 以编程方式创建,y + z 位置未更新 - 全部归功于 Han:

      -(void)setup{
      
          //left
          leftSceneView = [ARSCNView new];
          leftSceneView.frame = CGRectMake(0, 0, w, h/2);
          leftSceneView.delegate = self;
          leftSceneView.autoenablesDefaultLighting = true;
          [self.view addSubview:leftSceneView];
      
          //right
          rightSceneView = [ARSCNView new];
          rightSceneView.frame = CGRectMake(0, h/2, w, h/2);
          rightSceneView.playing = true;
          rightSceneView.autoenablesDefaultLighting = true;
          [self.view addSubview:rightSceneView];
      
          //scene
          SCNScene * scene = [SCNScene new];
          leftSceneView.scene = scene;
          rightSceneView.scene = scene;
      
          //tracking
          ARWorldTrackingConfiguration * configuration = [ARWorldTrackingConfiguration new];
          configuration.planeDetection = ARPlaneDetectionHorizontal;
          [leftSceneView.session runWithConfiguration:configuration];
      }
      
      -(void)renderer:(id<SCNSceneRenderer>)renderer updateAtTime:(NSTimeInterval)time {
      
          dispatch_async(dispatch_get_main_queue(), ^{
      
              //update right eye
              SCNNode * pov = self->leftSceneView.pointOfView.clone;
      
              SCNQuaternion orientation = pov.orientation;
              GLKQuaternion orientationQuaternion = GLKQuaternionMake(orientation.x, orientation.y, orientation.z, orientation.w);
              GLKVector3 eyePosition = GLKVector3Make(1, 0, 0);
              GLKVector3 rotatedEyePosition = GLKQuaternionRotateVector3(orientationQuaternion, eyePosition);
              SCNVector3 rotatedEyePositionSCNV = SCNVector3Make(rotatedEyePosition.x, rotatedEyePosition.y, rotatedEyePosition.z);
      
              float mag = 0.066f;
              float rotatedX = pov.position.x + rotatedEyePositionSCNV.x * mag;
              float rotatedY = pov.position.y;// + rotatedEyePositionSCNV.y * mag;
              float rotatedZ = pov.position.z;// + rotatedEyePositionSCNV.z * mag;
              [pov setPosition:SCNVector3Make(rotatedX, rotatedY, rotatedZ)];
      
              self->rightSceneView.pointOfView = pov;
          });
      
      }
      

      【讨论】:

        猜你喜欢
        • 2021-06-06
        • 1970-01-01
        • 2019-06-04
        • 1970-01-01
        • 1970-01-01
        • 2015-08-28
        • 1970-01-01
        • 2021-11-16
        • 2021-07-07
        相关资源
        最近更新 更多