立体声ARSCN视图制作VR和AR混音

时间:2017-07-03 21:25:12

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

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

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

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

我找到了这个链接,也许可以照亮我们: ARKit with multiple users

以下是我的问题的一个示例:

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

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

4 个答案:

答案 0 :(得分:4)

ARSession documentation表示ARSession是共享对象。

  

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

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

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

现在该怎么做?

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

还存在需要两个稍微不同的相机位置的问题,每个眼睛一个,用于立体视觉。 ARKit使用一个放置在iOS设备位置的摄像头,所以你不得不模糊。

然后你必须处理每只眼睛不同的桶形扭曲。

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

归档雷达,发布号码,然后我会把它丢掉。

答案 1 :(得分:4)

以下代码基本上就是哈尔所说的。我之前在github上写了几行,可能会帮助你入门。 (简单的代码,没有桶形失真,没有调整窄视场 - 但)。

基本上,我们将同一场景连接到第二个ARSCNView(因此两个ARSCNViews都看到相同的场景)。无需让ARWorldTrackingSessionConfiguration与2个ARSCNViews一起使用。然后,我们将其pointOfView偏移,使其定位为第二只眼睛。

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

答案 2 :(得分: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实例属性。

enter image description here

答案 3 :(得分: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;
    });

}