我正在尝试理解和使用 ARKit。但是有一件事我不能完全理解。
Apple 谈到 ARAnchor:
可用于在 AR 场景中放置对象的真实位置和方向。
但这还不够。所以我的问题是:
- 究竟是
ARAnchor
什么? - 锚点和特征点有什么区别?
- 只是
ARAnchor
特征点的一部分吗? - ARKit 如何确定它的锚点?
我正在尝试理解和使用 ARKit。但是有一件事我不能完全理解。
Apple 谈到 ARAnchor:
可用于在 AR 场景中放置对象的真实位置和方向。
但这还不够。所以我的问题是:
ARAnchor
什么? ARAnchor
特征点的一部分吗? 更新日期:2022 年 2 月 11 日。
ARAnchor
是一个不可见的空对象,可以在世界空间中的锚点位置保存 3D 模型。想想ARAnchor
它是一个transform node
带有局部轴的模型(您可以平移、旋转和缩放它)。每个 3D 模型都有一个枢轴点,对吧?所以这个枢轴点必须满足一个ARAnchor
.
如果您不在ARKit
/ RealityKit
app 中使用锚点,您的 3D 模型可能会偏离它们放置的位置,这将极大地影响您的应用程序的真实性和用户体验。因此,锚点是 AR 场景的关键元素。
根据 ARKit 文档 2017:
ARAnchor
是一个真实世界的位置和方向,可用于在 AR 场景中放置对象。在会话中添加锚点有助于 ARKit 优化该锚点周围区域的世界跟踪精度,以便虚拟对象相对于现实世界似乎保持在原位。如果虚拟对象移动,则从旧位置移除相应的锚点,并在新位置添加一个。
ARAnchor
是 ARKit 框架中存在的所有其他类型锚的父类,因此所有这些子类都继承自ARAnchor
类,但不能直接在代码中使用它。我也必须这么说,ARAnchor
没有Feature Points
任何共同点。Feature Points
而是用于成功跟踪和调试。
ARAnchor
不会自动跟踪现实世界的目标。如果您需要自动化,则必须使用renderer(...)
或session(...)
实例化方法,如果您符合协议ARSCNViewDelegate
或ARSessionDelegate
分别调用这些方法。
这是具有平面锚点视觉表示的图像。但请记住:默认情况下,您既看不到检测到的平面,也看不到其对应的ARPlaneAnchor
. 因此,如果您想在场景中看到任何锚点,您必须使用三个薄SCNCylinder
图元“可视化”它。
在 ARKit 中,您可以ARAnchors
使用不同的场景自动添加到场景中:
ARPlaneAnchor
planeDetection
实例属性为ON
,则 ARKit 能够将 ARPlaneAnchors 添加到当前会话。有时启用会planeDetection
大大增加场景理解阶段所需的时间。ARImageAnchor(符合ARTrackable
协议)
detectionImages
实例属性。在 ARKit 2.0 中,您最多可以跟踪 25 张图像,在 ARKit 3.0 和 ARKit 4.0 中,最多分别为 100 张图像。但是,在这两种情况下,同时不超过 4 张图像。有人承诺,在 ARKit 5.0 中,您一次可以检测和跟踪多达 100 张图像(但尚未实现)。ARBodyAnchor(符合ARTrackable
协议)
ARBodyTrackingConfiguration()
. 您将在Root Joint
CG Skeleton 或被跟踪角色的骨盆位置获得 ARBodyAnchor。ARFaceAnchor(符合ARTrackable
协议)
ARObjectAnchor
ARReferenceObject
的属性指定实例。detectionObjects
AREnvironmentProbeAnchor
AR参与者锚
true
值。isCollaborationEnabled
MultipeerConnectivity
ARMeshAnchor
50 anchors
甚至更多。这是因为每个分类对象(墙壁、椅子、门或桌子)都有自己的个人锚。每个 ARMeshAnchor 存储有关相应顶点的数据,八种分类案例之一,其面和顶点法线。ARGeoAnchor(符合ARTrackable
协议)
ARAppClipCodeAnchor(符合ARTrackable
协议)
还有其他常规方法可以在 AR 会话中创建锚点:
命中测试方法
ARHitTestResult
ARSCNView 和 ARSKView 的类及其对应的命中测试方法将在 iOS 14 中被弃用,因此您必须习惯 Ray-Casting。光线投射方法
特征点
ARCamera 的变换
任意世界位置
world anchor
版本AnchorEntity(.world(transform: mtx))
。此代码片段向您展示了如何在委托的方法中使用 ARPlaneAnchor renderer(_:didAdd:for:)
::
func renderer(_ renderer: SCNSceneRenderer,
didAdd node: SCNNode,
for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor
else { return }
let grid = Grid(anchor: planeAnchor)
node.addChildNode(grid)
}
AnchorEntity 是 RealityKit 中的 alpha 和 omega。根据 RealityKit 文档 2019:
AnchorEntity
是在 AR 会话中将虚拟内容与现实世界对象联系起来的锚点。
RealityKit框架和Reality Composer应用程序于 WWDC'19 发布。他们有一个名为AnchorEntity
. 您可以使用 AnchorEntity 作为任何实体层次结构的根点,并且必须将其添加到场景锚点集合中。AnchorEntity 自动跟踪现实世界的目标。在 RealityKit 和 Reality ComposerAnchorEntity
中,位于层次结构的顶部。这个锚可以容纳一百个模型,在这种情况下,它比为每个模型使用 100 个个人锚更稳定。
让我们看看它在代码中的样子:
func makeUIView(context: Context) -> ARView {
let arView = ARView(frame: .zero)
let modelAnchor = try! Experience.loadModel()
arView.scene.anchors.append(modelAnchor)
return arView
}
AnchorEntity
包含三个组成部分:
要找出两者之间的区别
ARAnchor
并AnchorEntity
查看THIS POST。
以下是适用于 iOS 的 RealityKit 2.0 中可用的九个 AnchorEntity 案例:
// Fixed position in the AR scene
AnchorEntity(.world(transform: mtx))
// For body tracking (a.k.a. Motion Capture)
AnchorEntity(.body)
// Pinned to the tracking camera
AnchorEntity(.camera)
// For face tracking (Selfie Camera config)
AnchorEntity(.face)
// For image tracking config
AnchorEntity(.image(group: "GroupName", name: "forModel"))
// For object tracking config
AnchorEntity(.object(group: "GroupName", name: "forObject"))
// For plane detection with surface classification
AnchorEntity(.plane([.any], classification: [.seat], minimumBounds: [1, 1]))
// When you use ray-casting
AnchorEntity(raycastResult: myRaycastResult)
// When you use ARAnchor with a given identifier
AnchorEntity(.anchor(identifier: uuid))
// Creates anchor entity on a basis of ARAnchor
AnchorEntity(anchor: arAnchor)
以下是适用于 macOS 的 RealityKit 2.0 中只有两个 AnchorEntity 的案例:
// Fixed world position in VR scene
AnchorEntity(.world(transform: mtx))
// Camera transform
AnchorEntity(.camera)
此外,您可以根据需要使用任何子类也不是多余
ARAnchor
的AnchorEntity
:
func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) {
guard let faceAnchor = anchors.first as? ARFaceAnchor
else { return }
arView.session.add(anchor: faceAnchor)
let anchor = AnchorEntity(anchor: faceAnchor)
anchor.addChild(model)
arView.scene.anchors.append(anchor)
}
目前(2022 年 2 月)Reality Composer 只有 4 种类型的 AnchorEntities:
// 1a
AnchorEntity(plane: .horizontal)
// 1b
AnchorEntity(plane: .vertical)
// 2
AnchorEntity(.image(group: "GroupName", name: "forModel"))
// 3
AnchorEntity(.face)
// 4
AnchorEntity(.object(group: "GroupName", name: "forObject"))
当然,关于初选主播,我应该说几句。对于那些喜欢为 USDZ 模型编写 Python 脚本的人,有 3 种初步锚定类型(2022 年 2 月)——它们是plane
和image
初步face
锚定。查看此代码片段以了解如何以 Python 方式实现模式。
def Cube "ImageAnchoredBox" (prepend apiSchemas = ["Preliminary_AnchoringAPI"])
{
uniform token preliminary:anchoring:type = "image"
rel preliminary: imageAnchoring:referenceImage = <ImageReference>
def Preliminary_ReferenceImage "ImageReference"
{
uniform asset image = @somePicture.jpg@
uniform double physicalWidth = 45
}
}
这是一个如何在 RealityKit(mac 版)中可视化锚点的示例。
import AppKit
import RealityKit
class ViewController: NSViewController {
@IBOutlet var arView: ARView!
var model = Entity()
let anchor = AnchorEntity()
fileprivate func visualAnchor() -> Entity {
let colors: [SimpleMaterial.Color] = [.red, .green, .blue]
for index in 0...2 {
let box: MeshResource = .generateBox(size: [0.20, 0.005, 0.005])
let material = UnlitMaterial(color: colors[index])
let entity = ModelEntity(mesh: box, materials: [material])
if index == 0 {
entity.position.x += 0.1
} else if index == 1 {
entity.transform = Transform(pitch: 0, yaw: 0, roll: .pi/2)
entity.position.y += 0.1
} else if index == 2 {
entity.transform = Transform(pitch: 0, yaw: -.pi/2, roll: 0)
entity.position.z += 0.1
}
model.scale *= 1.5
self.model.addChild(entity)
}
return self.model
}
override func awakeFromNib() {
anchor.addChild(self.visualAnchor())
arView.scene.addAnchor(anchor)
}
}