首页 文章

立体声ARSCN视图使VR和AR混合

提问于
浏览
2

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

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

我研究过将视图的图形表示复制到另一个视图但不可能找到 . 请帮我找到解决方案 .

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

以下是我的问题示例:

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

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

4 回答

  • 4

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

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

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

  • 2

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

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

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

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

    现在该怎么办?

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

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

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

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

    提交雷达文件,发布号码,然后我就可以了 .

  • 4

    为此,请使用以下代码:

    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 实例属性 .

    enter image description here

  • 1

    Objective-C版本的Han的github代码,以编程方式创建的sceneViews,y z位置未更新 - 所有信用韩:

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

相关问题