ARKit是苹果公司在2017年推出的增强现实框架,它旨在简化AR应用的创建。ARKit允许用户将2D/3D数字对象和信息与现实世界融合,将应用程序从屏幕中解放出来,并通过全新的方式与周围环境互动。随着iOS 11.3的最新更新,应用程序现在可以在垂直表面上识别和放置虚拟对象。这些特性使得ARKit在许多行业,特别是游戏、商业、建筑和教育等领域的应用变得真正无限。,Perfectial团队,正在尝试VR/AR,并乐于分享经验。
可能最知名的使用ARKit框架的应用之一是“IKEA Place”,用户可以选择并虚拟地将宜家产品放置在周围区域。想展示它是如何开发的。
让从基础开始——为ARKit制作3D模型。首先,需要一个可以使用的实际3D模型。幸运的是,它可以很容易地用Blender或其他3D建模软件渲染。只要确保它支持.DAE扩展名。(可以使用一个小提示:2D图形由SpriteKit支持,3D由SceneKit支持)。
因此,需要.SCN SceneKit文件和3D模型。.DAE文件应该在Xcode中转换为.SCN格式。要执行此操作,请选择编辑器菜单,然后点击转换为SceneKit场景文件格式(.scn)。
下一步是确定要放置3D对象的水平平面。需要为ARSCNView确定一个委托:增强现实将被渲染的视图。然后实现委托方法didAdd、didUpdate和didRemove。下面是一个didAdd方法的示例:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else {
return
}
node.addChildNode(horizontalSurface(planeAnchor: planeAnchor))
}
需要确保已经添加了一个平面锚点,而不是另一个锚点(使用guard语句)。现在,让看看上面代码中使用的horizontalSurface方法:
func horizontalSurface(planeAnchor: ARPlaneAnchor) -> SCNNode {
let horizontalSurface = SCNNode(geometry: SCNPlane(
width: CGFloat(planeAnchor.extent.x),
height: CGFloat(planeAnchor.extent.z)))
horizontalSurface.geometry?.firstMaterial?.diffuse.contents = UIColor.blue.withAlphaComponent(0.4)
horizontalSurface.geometry?.firstMaterial?.isDoubleSided = true
horizontalSurface.position = SCNVector3(
planeAnchor.center.x,
planeAnchor.center.y,
planeAnchor.center.z)
horizontalSurface.eulerAngles = SCNVector3(
90.0.degreesToRadians,
0,
0)
return horizontalSurface
}
由于蓝色的“漫反射”,可以在现实生活中看到平面(如果颜色未定义,它们将是透明的)。当用户点击AR视图时,新对象应该出现。现在,对于实现,需要处理用户的触摸并在ARSCNView上添加手势识别器。这是处理点击的方法:
@objc func handleTap(sender: UITapGestureRecognizer) {
if let tappedSceneView = sender.view as? ARSCNView {
let tapLocationInView = sender.location(in: tappedSceneView)
let planeHitTest = tappedSceneView.hitTest(tapLocationInView, types: .existingPlaneUsingExtent)
if !planeHitTest.isEmpty {
addFurniture(hitTest: planeHitTest)
}
}
}
在addFurniture方法中,家具将被添加,代码如下:
if let furnitureNode = SCNScene(named: "art.scnassets/\(currentFurniture).scn")?.rootNode {
let position = hitTest.first!.worldTransform.columns.3
furnitureNode.position = SCNVector3(position.x, position.y, position.z)
sceneView.scene.rootNode.addChildNode(furnitureNode)
}
现在,每次点击屏幕,用户都可以在水平表面上放置一个对象。
ARKit还有另一个创意用途——3D绘画。可以在空中绘画并放置这些对象。第一步是每当触摸屏幕时,就在空气中挂一个小点。最简单最快的方法是使用willRenderScene(ARSCNViewDelegate方法之一):
let dotNode = SCNNode(geometry: SCNSphere(radius: this.dotRadius))
dotNode.position = currentPositionOfCamera
dotNode.geometry?.firstMaterial?.diffuse.contents = this.selectedColor()
this.sceneView.scene.rootNode.addChildNode(dotNode)
以下是如何识别相机当前位置的方法:
if let pointOfView = sceneView.pointOfView {
let orientation = SCNVector3(
-pointOfView.transform.m31,
-pointOfView.transform.m32,
-pointOfView.transform.m33)
let location = SCNVector3(
pointOfView.transform.m41,
pointOfView.transform.m42,
pointOfView.transform.m43)
return orientation + location
}
甚至可以创建现实生活中的3D涂鸦。想,艺术家们应该会喜欢这个功能!
所以,已经知道如何在平面上放置不同的对象,现在是时候学习如何移动对象了。在这个实验中,将使用太阳系,其中八个行星围绕太阳和它们的轴旋转,月亮围绕地球旋转。
首先,需要使对象(行星)围绕其轴旋转:
earth.runAction(rotation(time: earthRotationAroundItselfTime))
下面是rotation方法的内容:
func rotation(time: TimeInterval, degrees: CGFloat = 360.0) -> SCNAction {
let onceRotation = SCNAction.rotateBy(
x: 0,
y: degreesToRadians(degrees),
z: 0,
duration: time)
return SCNAction.repeatForever(onceRotation)
}
marsParent.position = sunPosition
mars.position = marsPosition
marsParent.addChildNode(mars)