ARKit文档翻译之ARSCNView类
ARSCNView
用于显示使用3DSceneKit内容增强相机视图的AR体验的视图。
概述
ARSCNView类提供了将虚拟3D内容与现实世界的设备相机视图混合的增强现实体验的最简单的方法。当运行视图提供的ARSession对象时:
- 视图会自动将来自设备摄像头的实时视频渲染为场景背景。
- 视图的SceneKit场景的世界坐标系直接响应由会话配置建立的AR世界坐标系。
- 视图会自动移动其SceneKit摄像头,使其与设备的真实移动相匹配。
因为ARKit会自动将SceneKit空间与现实世界相匹配,所以放置一个虚拟对象,使其看起来维持在现实世界中的位置,这需要适当地设置该对象的SceneKit位置。(参阅使用SceneKit提供3D虚拟内容。)
不一定需要使用ARAnchor类来追踪添加到场景中的对象的位置,但是通过实现ARSCNViewDelegate代理方法,可以将SceneKit内容添加到ARKit自动检测到的任何锚点。
API
第一步
- 使用SceneKit提供3D虚拟内容
使用SceneKit为AR体验添加逼真的三维对象。
概述
因为ARKit会自动将SceneKit空间与现实世界相匹配,所以放置一个虚拟对象,使其看起来维持在现实世界中的位置,这需要适当地设置该对象的SceneKit位置。例如,在默认配置中,以下代码将边长10厘米的立方体放置在相机初始位置前方20厘米处:
let cubeNode = SCNNode(geometry: SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0))
cubeNode.position = SCNVector3(0, 0, -0.2) // SceneKit/AR coordinates are in meters
sceneView.scene.rootNode.addChildNode(cubeNode)
上述代码直接在视图的SceneKit场景中放置一个对象。因为ARKit将SceneKit空间与显示世界空间相匹配,该对象自动出现在追踪现实世界的位置上。
或者,通过自己创建锚点并将其添加到会话中或通过观察ARKit自动创建的锚点,可以使用ARAnchor类来追踪现实世界的位置。例如,当启用平面检测时,ARKit会为每个检测到的平面添加并更新锚点。实现ARSCNViewDelegate方法添加这些锚点的可使内容,如下所示:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
// This visualization covers only detected planes.
guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
// Create a SceneKit plane to visualize the node using its position and extent.
let plane = SCNPlane(width: CGFloat(planeAnchor.extent.x), height: CGFloat(planeAnchor.extent.z))
let planeNode = SCNNode(geometry: plane)
planeNode.position = SCNVector3Make(planeAnchor.center.x, 0, planeAnchor.center.z)
// SCNPlanes are vertically oriented in their local coordinate space.
// Rotate it to match the horizontal orientation of the ARPlaneAnchor.
planeNode.transform = SCNMatrix4MakeRotation(-Float.pi / 2, 1, 0, 0)
// ARKit owns the node corresponding to the anchor, so make the plane a child node.
node.addChildNode(planeNode)
}
遵循设计3D资源的最佳实践
- 使用SceneKit基于物理材料的照明模型,以获得更逼真的外观。(参阅SCNMaterial类和Badger:SceneKit高级渲染示例代码项目。)
- 烘焙环境遮挡阴影(Bake ambient occlusion shading),使物体在各种场景照明条件下光照适宜。
- 如果你创建一个想要放置在AR真实平面上的虚拟对象,请在3D资源的对象下方包含一个具有柔和阴影纹理的透明平面。
- var session: ARSession
管理视频内容的运动追踪和摄像机图像处理的AR会话。
讨论
视图创建自己的会话对象;使用此属性访问和配置视图会话。
- var scene: SCNScene
要在视图中显示的SceneKit场景
注意
与父类SCNView不同,ARSCNView对象要求显示的场景为非nil值。
响应AR更新
- var delegate: ARSCNViewDelegate?
你提供的一个用于调整视图的AR场景信息与SceneKit内容同步的对象。
- protocol ARSCNViewDelegate
可以实现的来调整SceneKit内容与AR会话的自动同步的方法。
概述
实现此协议以提供与视图的AR会话追踪的ARAnchor对象相对应的SceneKit内容或管理视图对这些内容的自动更新。
此协议扩展了ARSessionObserver协议,因此你的会话代理也可以实现这些方法来响应会话状态的更改。
func renderer(SCNSceneRenderer, nodeFor: ARAnchor)
请求代理对象提供一个对应于新添加的锚点的SceneKit节点。
参数
renderer:渲染场景的ARSCNView对象
anchor:需要节点的一个锚点
返回值
一个ARKit将添加到场景中并更新以追踪其对应AR锚点的新的SceneKit节点。
讨论
根据会话配置,ARkit可以自动向会话添加锚点。ARKit还会调用此方法为使用会话的add(anchor:)方法手动添加的任何ARAnchor对象提供可视化内容。
你可以实现此方法来提供一个新的SCNNode对象(或SCNNode子类的实例),其中包含计划用作锚点的可视化表示形式的任何附件。注意,ARKit控制节点的可见性及其transform属性,因此你可能会发现添加子节点或调整节点的pivot属性以维持对所做位置或方向的任何更改。
如果此方法返回nil,则不会将任何节点添加到场景中。
或者,如果不实现此方法,ARKit将创建一个空节点,你可以实现renderer(_:didAdd:for:)方法以提供将其添加到该节点来提供可视化内容。
func renderer(SCNSceneRenderer, nodeFor: ARAnchor)
告诉代理对象一个与新的AR锚点相对应的SceneKit节点已添加到场景中。
参数
renderer:渲染场景的ARSCNView对象
node:新添加的SceneKit节点
anchor:需要节点的一个锚点
讨论
根据会话配置,ARkit可以自动向会话添加锚点。该视图为每个新锚点调用此方法一次。ARKit还会调用此方法为使用会话的add(anchor:)方法手动添加的任何ARAnchor对象提供可视化内容。
可以通过将几何体(或其他SceneKit功能)添加到此节点或添加子节点来为锚点添加可视化内容。
或者,可以实现renderer(_:nodeFor:)方法给锚点创建自己的节点(或SCNNode子类的实例)。
func renderer(SCNSceneRenderer, willUpdate: SCNNode, for: ARAnchor)
告诉代理对象SceneKit节点的属性将被更新以匹配其相应锚点的当前状态。
参数
renderer:渲染场景的ARSCNView对象
node:更新的SceneKit节点
anchor:对应于该节点的AR锚点
讨论
根据会话配置,ARKit可能会自动更新会话中的锚点。该视图为每个更新的锚点调用此方法一次。
func renderer(SCNSceneRenderer, didUpdate: SCNNode, for: ARAnchor)
告诉代理对象一个SceneKit节点的属性已被更新以匹配其相应锚点的当前状态。
参数
renderer:渲染场景的ARSCNView对象
node:已更新的SceneKit节点
anchor:对应于该节点的AR锚点
讨论
根据会话配置,ARKit可能会自动更新会话中的锚点。该视图为每个已更新的锚点调用此方法一次。
func renderer(SCNSceneRenderer, didRemove: SCNNode, for: ARAnchor)
告诉代理对象已将删除的AR锚点对应的Scene节点从场景中删除。
参数
renderer:渲染场景的ARSCNView对象
node:已删除的SceneKit节点
anchor:对应于该节点的AR锚点
讨论
根据会话配置,ARKit可以自动从会话中删除锚点。该视图为每个已删除的锚点调用此方法一次。
真实世界表面的碰撞测试
- func hitTest(CGPoint, types: ARHitTestResult.ResultType)
搜索对应于SceneKit视图中某个点捕获的摄像机图像中的真实物体或AR锚点。
参数
point:在2D坐标系中视图的一个点
types:要搜索的碰撞测试的结果类型
返回值
从近到远(距相机的距离)排序的结果列表
讨论
碰撞测试通过相机图像的AR会话处理检测到的真实世界物体或表面。视图坐标系中的2D点可以指3D设备上从设备摄像头开始的任何点,并沿着由设备方位和相机投影确定的方向延伸。该方法搜索该行,返回与相机的距离的顺序相交的所有对象。
注意
此方法搜索通过AR会话检测到的AR锚点和真实世界对象,而不是在视图中显示SceneKit内容。要搜索SceneKit对象,请该用视图的hitTest(_:options:)方法。
将内容映射到现实世界的位置
- func anchor(for: SCNNode)
返回与指定的SceneKit节点相关联的AR锚点(如果有)。
参数
node:视图场景中的SceneKit节点
返回值
追踪该节点的ARAnchor对象,如果该节点在视图的场景中不与锚点相关联,则返回nil。
- func node(for: ARAnchor)
返回与指定AR锚点相关联的SceneKit节点(如果有)。
参数
anchor:视图的AR会话中的一个锚点。
返回值
锚点追踪AR场景中的位置的节点,如果锚点没有关联的节点,或者不在视图的AR会话中,则返回nil。
管理场景照明
- var automaticallyUpdatesLighting: Bool
一个指定ARKit是否在视图场景中创建和更新SceneKit照明的布尔值。
讨论
如果此该值为true(默认值),视图将自动创建一个或多个SCNLight对象,将其添加到场景中,并更新其属性以反映来自摄像机场景的预计照明信息。如果要直接控制SceneKit场景中的所有照明,请将此值设置为false。
调试AR显示
- struct ARSCNDebugOptions
用于绘制覆盖内容以帮助在SceneKit视图中调试AR追踪的选项。
概述
要使用这些调试覆盖物,将它们添加到视图的debugOptions属性中设置的选项(继承自SCNView类)。
static let showWorldOrigin: SCNDebugOptions
显示指定AR世界坐标系的位置和方向的坐标轴可视化。
讨论
此可视化可用于所有会话配置和会话alignment选项,但对ARWorldTrackingSessionConfiguration会话最有用。例如,如果在启用此选项时开始运行会话,那么后退一步,AR世界坐标系追踪的现实世界位置应在设备屏幕上显示。
static let showFeaturePoints: SCNDebugOptions
显示一个表明ARKit用于追踪设备位置的场景分析的中间结果的点云。
讨论
此选项仅在运行ARWorldTrackingSessionConfiguration会话时可用。