Upgrade to Pro — share decks privately, control downloads, hide ads and more …

栗まんじゅう問題を体感するアプリを作って入門した ARKit + SceneKit

栗まんじゅう問題を体感するアプリを作って入門した ARKit + SceneKit

Sosuke Okubo

November 19, 2018
Tweet

More Decks by Sosuke Okubo

Other Decks in Programming

Transcript

  1. "3,JU w J04ͷ"VHNFOUFE3FBMJUZ'SBNFXPSL w J04Ͱ௥Ճ"3,JU w J04"3,JU w J04"3,JU w

    J1IPOFTҎ߱ͷ୺຤Ͱར༻Մೳ w 5SVF%FQUIΧϝϥ͕ඞཁͳػೳ͕͋ΔͷͰ୺຤͝ͱʹ͞Βʹࡉ ੍͔͍ݶ༗Γ
  2. 6OJUZWT4DFOF,JU GPS"3,JU w 4DFOF,JU w 6*,JUͱ૊Έ߹Θͤ΍͍͢ w ৘ใ͕গͳ͍ w "3,JUͷ࠷৽ػೳ͕͙͢࢖͑Δ

    w ʢ6OJUZͱൺֱͯ͠ʣϏϧυָ͕ w 6OJUZ w 6OJUZͷεΩϧɾࢿ࢈͕ར༻Ͱ͖Δ w ৘ใ͕ଟ͍ w "3,JUͷ࠷৽ͷػೳΛར༻͢Δʹ͸ʢجຊతʹ͸ʣ6OJUZ"3,JUQMVHJOͷରԠ͕ඞཁ w Ϗϧυ͕େม
  3. ฏ໘Λݕग़͢Δ w DPOpHVSBUJPO͸ɺଞʹ"30SJFOUBUJPO5SBDLJOH$POpHVSBUJPO "3'BDF5SBDLJOH$POpHVSBUJPO  "3*NBHF5SBDLJOH$POpHVSBUJPO "30CKFDU4DBOOJOH$POpHVSBUJPOͳͲͷछྨ͕͋Δ w DPOpHVSBUJPOΑͬͯɺಘΒΕΔ"3"OLFSͷΫϥε͕มΘΔ w

    "31MBOF"DIPSͷ৔߹͸ɺฏ໘ͷҐஔ΍େ͖͞ͷ৘ใؚ͕·Ε͍ͯΔ w "3'BDF5SBDLJOH$POpHVSBUJPOͷ৔߹͸ɺ"3'BDF"ODIPSͱͳΓإͷ޲͖΍ύʔπʹؔ͢Δ৘ใؚ͕·Ε͍ͯΔ let configuration = ARWorldTrackingConfiguration() configuration.planeDetection = [.horizontal, .vertical] sceneView.session.run(configuration) // MARK: - ARSCNViewDelegate func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) { guard let planeAnchor = anchor as? ARPlaneAnchor else { fatalError() } import UIKit import SceneKit import ARKit class ViewController: UIViewController, ARSCNViewDelegate { @IBOutlet var sceneView: ARSCNView!
  4. λοϓͨ͠ฏ໘ʹϞσϧΛஔ͘ w λοϓͷݕग़ʹ͸ී௨ʹ6*,JUͷΫϥε͕ར༻Ͱ͖Δ w "34$/7JFX͕IJU5FTUϝιου͓࣋ͬͯΓɺฦΓ஋Ͱ͋Δ"3)JU5FTU3FTVMUΫϥε͕4DFOF಺ͷ࠲ඪΛಘΒΕΔ w IJU5FTUϝιουͷUZQFTҾ਺͸ɺ"3)JU5FTU3FTVMU3FTVMU5ZQFͱͳ͓ͬͯΓฏ໘Ͱ͸ͳ͘ಛ௃఺ͱIJU͢Δ ͔ͳͲΛ΋֬ೝͰ͖Δ w ࠓճ͸܀·Μ͡Ύ͏Λޙ΄Ͳ૿৩ͤ͞ΔͨΊʹɺ༻ҙ͓͍ͯͨ͠܀·Μ͡Ύ͏ϊʔυΛΫϩʔϯͯ͠௥Ճ͢Δ

    let gesture = UITapGestureRecognizer(target: self, action: #selector(onTapSceneView)) sceneView.addGestureRecognizer(gesture) @objc func onTapSceneView(sender: UITapGestureRecognizer) { let location = sender.location(in: sceneView) let hitTestResult = sceneView.hitTest(location, types: .existingPlaneUsingExtent) if let result = hitTestResult.first { let node = kuriNode.clone() node.position = SCNVector3( result.worldTransform.columns.3.x, result.worldTransform.columns.3.y, result.worldTransform.columns.3.z ) sceneView.scene.rootNode.addChildNode(node) } }
  5. ෺ཧԋࢉΛద༻ͤ͞Δ w 4$//PEFͷQIZTJDT#PEZϓϩύςΟʹ4$/1IZTJDT#PEZ ΠϯελϯεΛ௥Ճ͢Δ w 4DFOF಺ͷΦϒδΣΫτ͸ɺΠϯεϖΫλ͔Β΋ઃఆՄೳ w 1IZTJDT#PEZͷUZQFʹ͸ɺTUBUJD EZOBNJD LJOFNBUJD

    ͕͋Δ w ࠓճͷ৔߹͸ɺ܀·Μ͡Ύ͏͕EZOBNJDͰɺ·Μ͡Ύ ͏͕ஔ͔ΕΔฏ໘͕TUBUJDͱ͢Δ let shape = SCNPhysicsShape(geometry: planeNode.geometry!, options: nil) planeNode.physicsBody = SCNPhysicsBody(type: .static, shape: shape) planeNode.physicsBody?.categoryBitMask = 2
  6. ࣌ؒܦաͰϊʔυΛ૿৩͢Δ w 4DFOF,JUͰ5JNFSͷΑ͏ͳఆظ࣮ߦΛߦ͏ʹ͸4$/"DUJPOSFQFBU'PSFWFSΛ࢖༻͢Δ w 4$/"DUJPO͸ɺ4$/"DUJPOTFRVFODFͳͲΛ࢖͏͜ͱͰෳ਺ͷ4$/"DUJPOΛ૊Έ߹ΘͤΔ͜ͱ͕Ͱ͖Δ w 4$/"DUJPO͸4$//PEFͷSVO"DUJPOͰ࣮ߦͰ͖Δ w ࠓճͷ৔߹͸ɺඵ͝ͱʹݱࡏͷ܀·Μ͡Ύ͏Λͷ਺͚ͩ͞ΒʹϊʔυΛ௥Ճ͍ͯ͠Δ w

    ࣮ࡍͷόΠόΠϯ͸෼͝ͱ let position = SCNVector3(result.worldTransform.columns.3.x, result.worldTransform.columns.3.y + 0.05, result.worldTransform.columns.3.z) let wait = SCNAction.wait(duration: 5) let add = SCNAction.run { (node) in if self.count > 0 { for _ in 0..<self.count { self.addKuriNode(parentNode: node, position: position) } self.count += self.count } else { self.addKuriNode(parentNode: node, position: position) self.count += 1 } } let repeatForever = SCNAction.repeatForever(SCNAction.sequence([add, wait])) sceneView.scene.rootNode.runAction(repeatForever)