
紙を折って階段っぽくするiPhoneアプリのサンプルコードを描いてみます。
import UIKit
import SceneKit
class ViewController: UIViewController {
weak var sceneView : SCNView?
var count = 0
override func viewDidLoad() {
super.viewDidLoad()
setupScene()
createPaper()
createCamera()
}
func setupScene() {
sceneView = {
let sv = SCNView(frame: self.view.bounds)
sv.scene = SCNScene()
sv.backgroundColor = UIColor(hue: 0.4, saturation: 0.1, brightness: 1, alpha: 1)
self.view.addSubview(sv)
return sv
}()
}
func createPaper() {
[Int](0…9).foreach { i in
let paper = SCNBox(width: 5, height: 5, length: 0.2 – CGFloat(i) * 0.01, chamferRadius: 0)
paper.firstMaterial?.diffuse.contents = UIColor(hue: CGFloat(i) * 0.1, saturation: 0.7, brightness: 1, alpha: 1)
let paperNode = SCNNode(geometry: paper)
paperNode.name = “paper \(9-i)“
paperNode.position = SCNVector3(x: 0, y: 0, z:0)
paperNode.pivot = SCNMatrix4MakeTranslation(0, 2.5, 0)
self.sceneView?.scene?.rootNode.addChildNode(paperNode)
}
}
func createCamera() {
let camera = SCNNode()
camera.name = “camera”
camera.camera = SCNCamera()
camera.position = SCNVector3(x: 0, y: 0, z: 20)
self.sceneView?.scene?.rootNode.addChildNode(camera)
let target = SCNNode()
self.sceneView?.scene?.rootNode.addChildNode(target)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
let paperArr = self.sceneView?.scene?.rootNode.childNodes
.filter { ($0 as SCNNode).name?.componentsSeparatedByString(” “)[0] == “paper” }
.filter { ($0 as SCNNode).name?.componentsSeparatedByString(” “)[1].toInt() > self.count } as [SCNNode]
let camera = self.sceneView?.scene?.rootNode.childNodeWithName(“camera”, recursively: false)
switch(self.count) {
case 0:
camera?.runAction(
SCNAction.group([
SCNAction.moveTo(SCNVector3(x: 0, y: 4, z: 18), duration: 0.5),
SCNAction.rotateByX(CGFloat(-0.1), y: 0, z: 0, duration: 0.5)
]))
paperArr.foreach {i in
i.runAction(SCNAction.rotateByAngle(1.5 * CGFloat(M_PI), aroundAxis: SCNVector3(x: 1, y: 0, z: 0), duration: 0.5))
}
break
case 1:
camera?.runAction(SCNAction.moveTo(SCNVector3(x: 0, y: 8, z: 28), duration: 0.5))
paperArr.foreach {i in
i.pivot = SCNMatrix4MakeTranslation(2.5, 0, 0)
i.transform = SCNMatrix4Translate(i.transform, 2.5, 0, –2.5)
i.runAction(SCNAction.rotateByX(0, y: 0, z: –CGFloat(M_PI), duration: 1.0))
}
break
case 2:
camera?.runAction(SCNAction.moveTo(SCNVector3(x: 0, y: 8, z: 32), duration: 0.5))
paperArr.foreach {i in
i.pivot = SCNMatrix4MakeTranslation(0, –2.5, 0)
i.transform = SCNMatrix4Translate(i.transform, 2.5, 0, –2.5)
i.runAction(SCNAction.rotateByX(0.5 * CGFloat(M_PI), y: 0, z: 0, duration: 0.5))
}
break
case 3:
camera?.runAction(SCNAction.moveTo(SCNVector3(x: 4, y: 11, z: 34), duration: 0.5))
paperArr.foreach {i in
i.pivot = SCNMatrix4MakeTranslation(0, 2.5, 0)
i.transform = SCNMatrix4Translate(i.transform, 0, 5, 0)
i.runAction(SCNAction.rotateByX(1.5 * CGFloat(M_PI), y: 0, z: 0, duration: 0.5))
}
break
case 4:
camera?.runAction(SCNAction.moveTo(SCNVector3(x: 5, y: 11, z: 35), duration: 0.5))
paperArr.foreach {i in
i.pivot = SCNMatrix4MakeTranslation(-2.5, 0, 0)
i.transform = SCNMatrix4Translate(i.transform, 2.5, 0, –2.5)
i.runAction(SCNAction.rotateByX(0, y: 0, z: –CGFloat(M_PI), duration: 0.5))
}
break
case 5:
camera?.runAction(SCNAction.moveTo(SCNVector3(x: 7, y: 13, z: 38), duration: 0.5))
paperArr.foreach {i in
i.pivot = SCNMatrix4MakeTranslation(0, –2.5, 0)
i.transform = SCNMatrix4Translate(i.transform, 2.5, 0, –2.5)
i.runAction(SCNAction.rotateByX(–0.5 * CGFloat(M_PI), y: 0, z: 0, duration: 0.5))
}
break
case 6:
camera?.runAction(
SCNAction.group([
SCNAction.moveTo(SCNVector3(x: 7, y: 28, z: 32), duration: 0.5),
SCNAction.rotateByX(CGFloat(-0.4), y: 0, z: 0, duration: 0.5)
]))
paperArr.foreach {i in
i.pivot = SCNMatrix4MakeTranslation(0, 2.5, 0)
i.transform = SCNMatrix4Translate(i.transform, 0, 5, 0)
i.runAction(SCNAction.rotateByX(–1.5 * CGFloat(M_PI), y: 0, z: 0, duration: 0.5))
}
break
default:
break
}
++self.count
}
}
extension Array {
func foreach(doit:(T) -> Void) {for i in self {doit(i)}}
}