iPhoneカットで観覧車

円をカットして観覧車が周っているように見せるiPhoneアプリのサンプルコード

import UIKit

import SceneKit

class ViewController: UIViewController {

    weak var sceneView : SCNView?

    

    override func viewDidLoad() {

        super.viewDidLoad()

        setupScene()

        

        [SCNVector3(x: 0, y: 0, z: 0), SCNVector3(x: –5, y: 5, z: 0), SCNVector3(x: 5, y: –5, z: 0)].each{ position in

            self.createWheel(position)

        }

        

        createCamera()

    }

    func setupScene() {

        let sv = SCNView(frame: view.bounds)

        sv.scene = SCNScene()

        sv.allowsCameraControl = true

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

        view.addSubview(sv)

        

        sceneView = sv

    }

    func createWheel(p : SCNVector3) {

        let wheel = SCNNode()

        wheel.name = “wheel”

        wheel.position = p

        self.sceneView?.scene?.rootNode.addChildNode(wheel)

        

        let stand = SCNBox (width: 1, height: 2, length: 1.2, chamferRadius: 0)

        stand.firstMaterial?.diffuse.contents = UIColor(hue: 0.3, saturation: 0.6, brightness: 1, alpha: 1)

        let standNode = SCNNode(geometry: stand)

        standNode.position = SCNVector3(x: p.x, y: p.y1.4, z: p.z)

        self.sceneView?.scene?.rootNode.addChildNode(standNode)

        

        let w = M_PI / 4.0

        let arcpath = UIBezierPath(arcCenter: CGPointZero, radius: 2, startAngle: 0, endAngle: CGFloat(w), clockwise: true)

        arcpath.addLineToPoint(CGPointZero)

        arcpath.closePath()

        arcpath.flatness = 0.01

        [Int](07).each {i in

            let piece = SCNShape(path: arcpath, extrusionDepth: 0.2)

            piece.firstMaterial?.diffuse.contents = UIColor(hue: 0.03, saturation: 0.6, brightness: 1, alpha: 1)

            let pieceNode = SCNNode(geometry: piece)

            pieceNode.name = “piece”

            pieceNode.rotation = SCNVector4(x: 0, y: 0, z: 1, w: Float(w) * Float(i))

            wheel.addChildNode(pieceNode)

        }

    }

    

    func createCamera() {

        let camera = SCNNode()

        camera.camera = SCNCamera()

        camera.position = SCNVector3(x: –13, y: 0, z: 30)

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

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

    }

    

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

        self.sceneView?.scene?.rootNode.childNodes

            .filter { ($0 as SCNNode).name == “wheel” }

            .each{ wheel in

                wheel.childNodes

                    .filter {($0 as SCNNode).name == “piece” }

                    .each {piece in

                        let x = 0.3 * CGFloat(cos(piece.rotation.w + Float(M_PI/8.0)))

                        let y = 0.3 * CGFloat(sin(piece.rotation.w + Float(M_PI/8.0)))

                        piece.runAction(SCNAction.sequence([SCNAction.moveByX(x, y: y, z: 0, duration: 0.5), SCNAction.waitForDuration(2.5)]), completionHandler: {

                            piece.runAction(SCNAction.moveTo(SCNVector3Zero, duration: 0.25))

                            return;

                        })

                    }

                wheel.runAction(SCNAction.rotateByAngle(CGFloat(M_PI), aroundAxis: SCNVector3(x: 0, y: 0, z: 1), duration: 3.0))

            }

    }

}

extension Array {

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

}