iPhone回転ポール

長い棒のまわりを短い棒が周るiPhoneアプリのサンプルコードを描いてみます。

import UIKit

import SceneKit

class ViewController: UIViewController, SCNPhysicsContactDelegate {

    weak var sceneView : SCNView?

    

    override func viewDidLoad() {

        super.viewDidLoad()

        setupScene()

        createPole()

        createCamera()

        createBar()

    }

    func setupScene() {

        let sv = SCNView(frame: view.bounds)

        sv.scene = SCNScene()

        sv.scene?.physicsWorld.contactDelegate = self

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

        sv.allowsCameraControl = true

        self.view.addSubview(sv)

        self.sceneView = sv

    }

    

    func createPole() {

        let cy = SCNCylinder(radius: 0.5, height: 20)

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

        let cyNode = SCNNode(geometry: cy)

        cyNode.physicsBody = SCNPhysicsBody.staticBody()

        cyNode.physicsBody?.restitution = 0

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

    }

    

    func createCamera() {

        let camera = SCNNode()

        camera.camera = SCNCamera()

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

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

    }

    

    func createBar() {

        let bar = SCNCylinder(radius: 0.3, height: 6)

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

        let barNode = SCNNode(geometry: bar)

        barNode.name = “bar”

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

        barNode.rotation = SCNVector4Make(1, 0, 0, Float(M_PI)/2.0)

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

        

        barNode.runAction(SCNAction.repeatActionForever(SCNAction.sequence([SCNAction.moveTo(SCNVector3(x: –30, y: 10, z: 2), duration: 0.5), SCNAction.moveTo(SCNVector3(x: –30, y: –10, z: 2), duration: 0.5)])))

        barNode.physicsBody?.restitution = 0

    }

    

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

        if let bar = self.sceneView?.scene?.rootNode.childNodeWithName(“bar”, recursively: false) {

            bar.removeAllActions()

            bar.physicsBody = SCNPhysicsBody.dynamicBody()

            bar.physicsBody?.applyForce(SCNVector3(x: 40, y: 0, z: 0), atPosition: SCNVector3(x: 0, y: 0, z: 0), impulse: true)

            

            

        }

    }

    

    func physicsWorld(world: SCNPhysicsWorld, didBeginContact contact: SCNPhysicsContact) {

        let bar = [contact.nodeA, contact.nodeB].filter { ($0 as SCNNode).name == “bar” }.first

        if bar == nil { return }

        

        let ring = SCNTube(innerRadius: 1.5, outerRadius: 1.5, height: 0.1)

        ring.firstMaterial?.diffuse.contents = UIColor.clearColor()

        let ringNode = SCNNode(geometry: ring)

        ringNode.position = bar!.presentationNode().convertPosition(contact.contactPoint, fromNode:self.sceneView?.scene?.rootNode)

        ringNode.rotation = SCNVector4(x: 1, y: 0, z: 0, w: Float(M_PI)/2.0)

        bar?.addChildNode(ringNode)

        let v = bar?.physicsBody?.velocity

        let w = bar?.physicsBody?.angularVelocity

        bar?.physicsBody = SCNPhysicsBody.dynamicBody()

        bar?.physicsBody?.physicsShape = SCNPhysicsShape(node: bar!, options: [SCNPhysicsShapeTypeKey: SCNPhysicsShapeTypeConcavePolyhedron])

        bar?.physicsBody?.velocity = v!

        bar?.physicsBody?.angularVelocity = w!

        bar?.name = “”

        

        self.createBar()

    }

}