ARKit. |
WWDC 2017 Apple ARKit SDK . . .
Keynote, , , . , Apple ARKit, . , , . , - .
iPhone 6 . . ARKit 9 . Apple, , , .
(augmented reality, AR) , , . , , Boeing 1990 . . .
, 20 . . , .
AppStore? . , AR Apple:
ARKit , , , . , . , .
ARKit (World Tracking) . , . . . ARKit .
, . , .
ARKit ARSCNView
ARSKView
. live 3D 2D . , SCNView
SKView
. , ARKit - . 2D 3D , . . Apple , ARKit Unity Unreal Engine. , .
ARSCNView
ARSKView
ARKit ARSession
. . ARSession
.
AR, :
ARWorldTrackingSessionConfiguration
. . . .ARSessionConfiguration
. , . . ., :
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Create a session configuration
let configuration = ARWorldTrackingSessionConfiguration()
// Run the view's session
sceneView.session.run(configuration)
}
, ARKit . View , , session.pause()
.
. , ARKit , planeDetection
horizontal
. . , , .
, ARSCNView
, ARSKView
Metal
. , ARKit, ARAnchor
. , ARPlaneAnchor
. . . Metal . , ARSessionDelegate
ARSession
, . Apple , ARSCNViewDelegate
ARSKViewDelegate
.
. ARSession
. .
Pok'emon GO, . .
ARSCNView
3D . 2 . , . , .
, ViewController ARSCNView
IBOutlet. , SCNView
. . . .
override func viewDidLoad() {
super.viewDidLoad()
sceneView.scene.physicsWorld.contactDelegate = self
// Show statistics such as fps and timing information
sceneView.showsStatistics = true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Create a session configuration
let configuration = ARSessionConfiguration.isSupported ?
ARWorldTrackingSessionConfiguration() : ARSessionConfiguration()
// Run the view's session
sceneView.session.run(configuration)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Pause the view's session
sceneView.session.pause()
}
, . . , , .
ARKit , . , . SceneKit.
. , , .
: , , Touch Instinct. , , SCNNode
.
, :
.
class ARBullet: SCNNode {
override init() {
super.init()
let arKitBox = SCNSphere(radius: 0.025)
self.geometry = arKitBox
let shape = SCNPhysicsShape(geometry: arKitBox, options: nil)
self.physicsBody = SCNPhysicsBody(type: .dynamic, shape: shape)
self.physicsBody?.isAffectedByGravity = false
self.physicsBody?.categoryBitMask = CollisionCategory.arBullets.rawValue
self.physicsBody?.contactTestBitMask = CollisionCategory.logos.rawValue
// add texture
let material = SCNMaterial()
material.diffuse.contents = UIImage(named: "art.scnassets/ARKit_logo.png")
self.geometry?.materials = [material]
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class Logo: SCNNode {
override init() {
super.init()
let logo = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)
self.geometry = logo
let shape = SCNPhysicsShape(geometry: logo, options: nil)
self.physicsBody = SCNPhysicsBody(type: .dynamic, shape: shape)
self.physicsBody?.isAffectedByGravity = false
self.physicsBody?.categoryBitMask = CollisionCategory.logos.rawValue
self.physicsBody?.contactTestBitMask = CollisionCategory.arBullets.rawValue
// add texture
let material = SCNMaterial()
material.diffuse.contents = UIImage(named: "art.scnassets/logo-mobile.png")
self.geometry?.materials = Array(repeating: material, count: 6)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
CollisionCategory. .
struct CollisionCategory: OptionSet {
let rawValue: Int
static let arBullets = CollisionCategory(rawValue: 1 << 0)
static let logos = CollisionCategory(rawValue: 1 << 1)
}
. categoryBitMask
, contactTestBitMask
, .
, , . viewDidLoad
. .
extension ViewController: SCNPhysicsContactDelegate {
func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {
guard let nodeABitMask = contact.nodeA.physicsBody?.categoryBitMask,
let nodeBBitMask = contact.nodeB.physicsBody?.categoryBitMask,
nodeABitMask & nodeBBitMask == CollisionCategory.logos.rawValue & CollisionCategory.arBullets.rawValue else {
return
}
contact.nodeB.removeFromParentNode()
logoCount -= 1
if logoCount == 0 {
DispatchQueue.main.async {
self.stopGame()
}
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
contact.nodeA.removeFromParentNode()
})
}
}
, . . .
. .
. , . , .
private func addLogo() {
guard let currentFrame = sceneView.session.currentFrame else {
return
}
let logo = Logo()
sceneView.scene.rootNode.addChildNode(logo)
var translation = matrix_identity_float4x4
translation.columns.3.z = -1
logo.simdTransform = matrix_multiply(currentFrame.camera.transform, translation)
logoCount += 1
if logoCount == ViewController.logoMaxCount {
startGame()
}
}
. . , . , .
private func shoot() {
let arBullet = ARBullet()
let (direction, position) = cameraVector
arBullet.position = position
arBullet.physicsBody?.applyForce(direction, asImpulse: true)
sceneView.scene.rootNode.addChildNode(arBullet)
}
.
, Apple . ARKit , . . .
Xcode 9, , . . , Apple.