
バーベルをロボがヒョイっと持ち上げるiPhoneアプリのサンプルコードを描いてみます。
import UIKit
import SceneKit
class ViewController: UIViewController, SCNSceneRendererDelegate {
weak var sceneView : SCNView?
override func viewDidLoad() {
super.viewDidLoad()
setupScene()
createGround()
createLifter()
createWeight()
createCamera()
}
func setupScene() {
let sv = SCNView(frame: view.bounds)
sv.backgroundColor = UIColor(hue: 0.3, saturation: 0.1, brightness: 1, alpha: 1)
sv.scene = SCNScene()
sv.allowsCameraControl = true
sv.autoenablesDefaultLighting = true
sv.delegate = self
view.addSubview(sv)
sceneView = sv
}
func createGround() {
let box = SCNBox(width: 5, height: 0.2, length: 5, chamferRadius: 0)
box.firstMaterial?.diffuse.contents = UIColor(hue: 0.25, saturation: 0.7, brightness: 1, alpha: 1)
let boxNode = SCNNode(geometry: box)
boxNode.position = SCNVector3(x: 0, y: –1, z: 0)
sceneView?.scene?.rootNode.addChildNode(boxNode)
}
func createLifter() {
let lifter = SCNNode()
lifter.name = “lifter”
let color = UIColor.lightGrayColor()
let head = SCNCone(topRadius: 1, bottomRadius: 0.9, height: 1)
head.firstMaterial?.diffuse.contents = color
let headNode = SCNNode(geometry: head)
headNode.position = SCNVector3(x: 0, y: 1, z: 0)
lifter.addChildNode(headNode)
let body = SCNCylinder(radius: 0.5, height: 1.5)
body.firstMaterial?.diffuse.contents = color
let bodyNode = SCNNode(geometry: body)
bodyNode.position = SCNVector3(x: 0, y: –0.25, z: 0)
lifter.addChildNode(bodyNode)
for i in 0…1 {
let hand = SCNCylinder(radius: 0.2, height: 1.4)
hand.firstMaterial?.diffuse.contents = color
let handNode = SCNNode(geometry: hand)
handNode.name = “hand”
handNode.pivot = SCNMatrix4MakeTranslation(0, 0.7, 0)
handNode.position = SCNVector3(x: i==0 ? –1 : 1, y: 0.3, z: 0)
handNode.rotation = SCNVector4(x: 1, y: 0, z: 0, w: –0.7)
lifter.addChildNode(handNode)
let eye = SCNSphere(radius: 0.1)
eye.firstMaterial?.diffuse.contents = UIColor.blackColor()
let eyeNode = SCNNode(geometry: eye)
eyeNode.position = SCNVector3(x: i==0 ? –0.5 : 0.5, y: 1.0, z: 0.8)
lifter.addChildNode(eyeNode)
}
sceneView?.scene?.rootNode.addChildNode(lifter)
}
func createWeight() {
let weight = SCNNode()
weight.name = “weight”
let bar = SCNCylinder(radius: 0.1, height: 6)
bar.firstMaterial?.diffuse.contents = UIColor.darkGrayColor()
let barNode = SCNNode(geometry: bar)
barNode.rotation = SCNVector4(x: 0, y: 0, z: 1, w: Float(M_PI * 0.5))
weight.addChildNode(barNode)
for i in 0…1 {
let disk = SCNCylinder(radius: 1, height: 0.2)
disk.firstMaterial?.diffuse.contents = UIColor(white: 0.05, alpha: 1)
let diskNode = SCNNode(geometry: disk)
diskNode.position = SCNVector3(x: i==0 ? –3 : 3, y: 0, z: 0)
diskNode.rotation = SCNVector4(x: 0, y: 0, z: 1, w: Float(M_PI * 0.5))
weight.addChildNode(diskNode)
}
weight.position = SCNVector3(x: 0, y: –0.6, z: 1.1)
sceneView?.scene?.rootNode.addChildNode(weight)
}
func createCamera() {
let camera = SCNNode()
camera.camera = SCNCamera()
camera.position = SCNVector3(x: 0, y: 3, z: 13)
camera.rotation = SCNVector4(x: 1, y: 0, z: 0, w: –0.3)
sceneView?.scene?.rootNode.addChildNode(camera)
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
let lifter = sceneView?.scene?.rootNode.childNodes
.filter { ($0 as! SCNNode).name == “lifter” }.first as! SCNNode
lifter.childNodes
.filter { ($0 as! SCNNode).name == “hand” }
.each { n -> Void in
n.runAction(SCNAction.rotateByAngle(CGFloat(M_PI) * 0.6, aroundAxis: SCNVector3(x: 1, y: 0, z: 0), duration: 1.0))
}
}
func renderer(aRenderer: SCNSceneRenderer, updateAtTime time: NSTimeInterval) {
if let hand = sceneView?.scene?.rootNode.childNodeWithName(“hand”, recursively: true) {
if let weight = sceneView?.scene?.rootNode.childNodeWithName(“weight”, recursively: false) {
let p = hand.presentationNode().convertPosition(SCNVector3(x: 0, y: –0.8, z: 0), toNode: self.sceneView?.scene?.rootNode)
weight.position = SCNVector3(x: 0, y: p.y, z: p.z)
}
}
}
}
extension Array {
func each(doit:T -> Void) { for i in self { doit(i) }}
}