我想混合使用virtual reality
和augmented reality
。
目标是我有一个立体相机(每只眼睛)。
我尝试在ARSCNView
中添加两个viewCotnroller
,但似乎ARKit同时只能启用一个ARWorldTrackingSessionConfiguration
。我怎样才能做到这一点?
我研究过将视图的图形表示复制到另一个视图但是无法找到。请帮我找到解决方案。
我找到了这个链接,也许可以照亮我们: ARKit with multiple users
以下是我的问题的一个示例:
https://www.youtube.com/watch?v=d6LOqNnYm5s
PS:不像我的帖子,评论为什么!
答案 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
实例属性。
答案 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;
});
}