iPhone針が幅広な時計

針が幅広な時計を表示するiPhoneアプリのサンプルコードを描いてみます。

import UIKit

import SceneKit

class ViewController: UIViewController, SCNSceneRendererDelegate {

    weak var sceneView : SCNView?

    var lasttime : NSTimeInterval = 0

    var stop = true

    

    override func viewDidLoad() {

        super.viewDidLoad()

        setupScene()

        createCase()

        createHands()

        createCamera()

    }

    

    func setupScene() {

        let sv = SCNView(frame: view.bounds)

        sv.delegate = self

        sv.backgroundColor = UIColor(hue: 0.1, saturation: 0.1, brightness: 1, alpha: 1)

        sv.scene = SCNScene()

        sv.allowsCameraControl = true

        view.addSubview(sv)

        sceneView = sv

    }

    

    func createCase() {

        let c = SCNCylinder(radius: 10, height: 0.5)

        c.firstMaterial?.diffuse.contents = UIColor(hue: 0.2, saturation: 0.5, brightness: 1, alpha: 1)

        let cNode = SCNNode(geometry: c)

        sceneView?.scene?.rootNode.addChildNode(cNode)

        

        [Int](0..<12).each { i in

            let dot = SCNBox(width: 0.8, height: 0.1, length: 0.3, chamferRadius: 0.05)

            dot.firstMaterial?.diffuse.contents = UIColor(hue: 0.5, saturation: 0.7, brightness: 0.2, alpha: 1)

            let dotNode = SCNNode(geometry: dot)

            let w = Float(i) * Float(M_PI) / 6.0

            let x = 9.5 * Float(cos(w))

            let z = 9.5 * Float(sin(w))

            dotNode.position = SCNVector3(x: x, y: 0.3, z: z)

            dotNode.rotation = SCNVector4(x: 0, y: 1, z: 0, w: -w)

            cNode.addChildNode(dotNode)

        }

    }

    

    func createHands() {

        let handA = SCNBox(width: 0.2, height: 10, length: 8.4, chamferRadius: 0)

        handA.firstMaterial?.diffuse.contents = UIColor(hue: 0.6, saturation: 0.2, brightness: 1, alpha: 0.7)

        let handANode = SCNNode(geometry: handA)

        handANode.pivot = SCNMatrix4Translate(handANode.transform, 0, –5, –4.2)

        sceneView?.scene?.rootNode.addChildNode(handANode)

        

        let handB = SCNBox(width: 0.4, height: 5, length: 4.2, chamferRadius: 0)

        handB.firstMaterial?.diffuse.contents = UIColor(hue: 0, saturation: 0.2, brightness: 1, alpha: 0.7)

        let handBNode = SCNNode(geometry: handB)

        handBNode.pivot = SCNMatrix4Translate(handBNode.transform, 0, –2.5, –2.1)

        sceneView?.scene?.rootNode.addChildNode(handBNode)

        

        handANode.name = “hand a”

        handBNode.name = “hand b”

    }

    

    func createCamera() {

        let camera = SCNNode()

        camera.camera = SCNCamera()

        camera.position = SCNVector3(x: 0, y: 10, z: 50)

        camera.rotation = SCNVector4(x: 1, y: 0, z: 0, w: –0.2)

        sceneView?.scene?.rootNode.addChildNode(camera)

    }

    

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {

        stop = !stop

        sceneView?.playing = true

    }

    func renderer(aRenderer: SCNSceneRenderer, didApplyAnimationsAtTime time: NSTimeInterval) {

        if stop {

            return

        }

        

        let handA = sceneView?.scene?.rootNode.childNodeWithName(“hand a”, recursively: false)

        let handB = sceneView?.scene?.rootNode.childNodeWithName(“hand b”, recursively: false)

        

        let d = Float(time – lasttime) > 0.1 ? 0 : Float(time – lasttime)

        handA?.rotation = SCNVector4(x: 0, y: 1, z: 0, w: handA!.rotation.w – d * 10)

        handB?.rotation = SCNVector4(x: 0, y: 1, z: 0, w: handB!.rotation.w – d * (10.0 / 12.0))

        

        lasttime = time;

    }

}

extension Array {

    func each(doit:T -> Void) {for i in self { doit(i); }}

}