レールの上から見る視点を、タッチで電車からの視点に変えるiPhoneアプリのサンプルコードを描いてみます。
import UIKit
import SceneKit
class ViewController: UIViewController {
weak var sceneView : SCNView?
override func viewDidLoad() {
super.viewDidLoad()
setupScene()
createRailroad()
createTunnel()
createTrain()
createCamera()
createLight()
}
func setupScene() {
let sv = SCNView(frame: view.bounds)
sv.backgroundColor = UIColor(hue: 0.25, saturation: 0.2, brightness: 1, alpha: 1)
sv.scene = SCNScene()
view.addSubview(sv)
sceneView = sv
}
func createRailroad() {
let ground = SCNBox(width: 12, height: 12, length: 2, chamferRadius: 0)
ground.firstMaterial?.diffuse.contents = UIColor.brownColor()
let groundNode = SCNNode(geometry: ground)
groundNode.position = SCNVector3(x: 0, y: 0, z: –1.1)
sceneView?.scene?.rootNode.addChildNode(groundNode)
let path = UIBezierPath(roundedRect: CGRectMake(-5, –5, 10, 10), cornerRadius: 2)
[path .appendPath(UIBezierPath(roundedRect: CGRectMake(-4.6, –4.6, 9.2, 9.2), cornerRadius: 2))]
path.flatness = 0.01
let rail = SCNShape(path: path, extrusionDepth: 0.2)
rail.firstMaterial?.diffuse.contents = UIColor.darkGrayColor()
let railNode = SCNNode(geometry: rail)
sceneView?.scene?.rootNode.addChildNode(railNode)
}
func createTunnel() {
let t = SCNTube(innerRadius: 0.6, outerRadius: 0.7, height: 3)
t.firstMaterial?.diffuse.contents = UIColor.greenColor()
let tNode = SCNNode(geometry: t)
tNode.position = SCNVector3(x: 4.8, y: 0, z: 0)
sceneView?.scene?.rootNode.addChildNode(tNode)
}
func createTrain() {
let train = SCNBox(width: 1, height: 0.5, length: 0.5, chamferRadius: 0.1)
train.firstMaterial?.diffuse.contents = UIColor.redColor()
let trainNode = SCNNode(geometry: train)
trainNode.name = “train”
trainNode.position = SCNVector3(x: –3, y: –4.8, z: 0.3)
sceneView?.scene?.rootNode.addChildNode(trainNode)
trainNode.runAction(SCNAction.repeatActionForever(SCNAction.sequence([
SCNAction.moveTo(SCNVector3(x:3, y:-4.8, z:0.3), duration: 1.0),
SCNAction.group([
SCNAction.moveTo(SCNVector3(x:4.8, y:-3, z:0.3), duration: 0.5),
SCNAction.rotateToX(0, y: 0, z: CGFloat(M_PI) * 0.5, duration: 0.5 ,shortestUnitArc:true)
]),
SCNAction.moveTo(SCNVector3(x:4.8, y:3, z:0.3), duration: 1.0),
SCNAction.group([
SCNAction.moveTo(SCNVector3(x:3, y:4.8, z:0.3), duration: 0.5),
SCNAction.rotateToX(0, y: 0, z: CGFloat(M_PI), duration: 0.5)
]),
SCNAction.moveTo(SCNVector3(x:-3, y:4.8, z:0.3), duration: 1.0),
SCNAction.group([
SCNAction.moveTo(SCNVector3(x:-4.8, y:3, z:0.3), duration: 0.5),
SCNAction.rotateToX(0, y: 0, z: CGFloat(M_PI) * 1.5, duration: 0.5)
]),
SCNAction.moveTo(SCNVector3(x:-4.8, y:-3, z:0.3), duration: 1.0),
SCNAction.group([
SCNAction.moveTo(SCNVector3(x:-3, y:-4.8, z:0.3), duration: 0.5),
SCNAction.rotateToX(0, y: 0, z: CGFloat(M_PI) * 2.0, duration: 0.5)
])
])))
}
func createCamera() {
let camera = SCNNode()
camera.name = “camera”
camera.camera = SCNCamera()
camera.position = SCNVector3(x: 0, y: 0, z: 10)
sceneView?.scene?.rootNode.addChildNode(camera)
}
func createLight() {
let light = SCNLight()
light.type = SCNLightTypeDirectional
let lightNode = SCNNode()
lightNode.light = light
lightNode.position = SCNVector3(x: 0, y: 0, z: 20)
sceneView?.scene?.rootNode.addChildNode(lightNode)
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
if let camera = sceneView?.scene?.rootNode.childNodeWithName(“camera”, recursively: false) {
camera.pivot = SCNMatrix4MakeRotation(Float(M_PI) * 0.5, 0, 0, 1);
camera.position = SCNVector3(x: 0.6, y: 0, z: 0.25)
camera.rotation = SCNVector4(x: 0, y: 1, z: 0, w: –Float(M_PI) * 0.55)
camera.camera?.automaticallyAdjustsZRange = true
let train = sceneView?.scene?.rootNode.childNodeWithName(“train”, recursively: false)
train?.addChildNode(camera)
}
}
}