2

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

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

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

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

这是我的问题的示例:

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

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

4

4 回答 4

5

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

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

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

于 2017-07-08T10:29:44.923 回答
4

ARSession文档说这是ARSession一个共享对象。

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

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

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

现在该怎么做?

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

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

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

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

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

于 2017-07-04T00:25:48.517 回答
2

为此,请使用以下代码:

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()
    }
}

并且不要忘记.isPlaying为两者激活实例属性ARSCNViews

在此处输入图像描述

于 2018-09-01T09:19:26.860 回答
1

Han 的 github 代码的 Objective-C 版本,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;
    });

}
于 2018-07-27T14:06:24.720 回答