iPhone重量挙げ

バーベルをロボがヒョイっと持ち上げる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 01 {

            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 01 {

            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) }}

}