等高線グラフっぽいのを表示するiPhoneアプリのサンプルコードを描いてみます。
import UIKit
import SceneKit
import SpriteKit
class ViewController: UIViewController {
weak var sceneView : SCNView?
var values = Array<Int>()
struct Float3 {
var x, y, z: GLfloat
}
struct Float2 {
var s, t: GLfloat
}
struct Vertex {
var position: Float3
var normal: Float3
var tcoord: Float2
}
var vertices: [Float3] = {
var arr = [Float3]()
for i in 0..<40 {
let col = Float(i % 8)
let row = Float(i / 8)
arr.append(Float3(x: col * 5, y: 0, z: row * 5))
}
return arr
}()
var normals: [Float3] = {
var arr = [Float3]()
for i in 0..<40 {
arr.append(Float3(x: 0, y: 0.5, z: 0.5))
}
return arr
}()
var indices: [GLint] = {
var arr = [GLint]()
for i in 0..<40 {
if (i % 8) == 7 { continue }
if (i / 8) == 4 { continue }
let n = GLint(i)
arr.append(n + 1)
arr.append(n)
arr.append(n + 9)
arr.append(n + 8)
arr.append(n + 9)
arr.append(n)
}
return arr
}()
override func viewDidLoad() {
super.viewDidLoad()
setupScene()
updateSurfaceChart()
createCamera()
createLight()
}
func setupScene() {
let w = CGRectGetMaxX(self.view.bounds)
let h = CGRectGetMaxY(self.view.bounds)
let sv = SCNView(frame: CGRectMake(0, 0, w, h))
sv.scene = SCNScene()
sv.backgroundColor = UIColor(hue: 0.3, saturation: 0.05, brightness: 1, alpha: 1)
sv.allowsCameraControl = true
self.view.addSubview(sv)
self.sceneView = sv
sv.overlaySKScene = SKScene(size: CGSize(width: w, height: h))
let n = SKSpriteNode(color: UIColor.darkGrayColor(), size: CGSize(width: w, height: h * 0.5))
n.position = CGPoint(x: w * 0.5, y: h * 0.25)
sv.overlaySKScene.addChild(n)
let d = CGRectGetMaxX(self.view.bounds) / 8.0
for i in 0..<40 {
let x = CGFloat(i % 8) * d + d * 0.5
let y = CGFloat(i / 8) * d + 80
let n = SKSpriteNode(color: UIColor(hue: 0, saturation: 0.3, brightness: 1, alpha: 1), size: CGSize(width: 30, height: 30))
n.position = CGPoint(x: x, y: y)
n.name = “marker\(i)“
n.zRotation = CGFloat(M_PI)/4.0
sv.overlaySKScene.addChild(n)
let label = SKLabelNode(text: “\(vertices[i].y)“)
label.fontName = UIFont.boldSystemFontOfSize(0).fontName
label.fontSize = 15
label.name = “label”
n.addChild(label)
values.append(i)
}
}
func updateSurfaceChart() {
self.sceneView?.scene?.rootNode.childNodeWithName(“surface”, recursively: false)?.removeFromParentNode()
let vdata = NSData(bytes: vertices, length: vertices.count * sizeof(Float3))
let vertexSource = SCNGeometrySource(data: vdata, semantic: SCNGeometrySourceSemanticVertex, vectorCount: vertices.count, floatComponents: true, componentsPerVector: 3, bytesPerComponent: sizeof(GLfloat), dataOffset: 0, dataStride: sizeof(Float3))
let ndata = NSData(bytes: normals, length: normals.count * sizeof(Float3))
let normalSource = SCNGeometrySource(data: ndata, semantic: SCNGeometrySourceSemanticNormal, vectorCount: normals.count, floatComponents: true, componentsPerVector: 3, bytesPerComponent: sizeof(GLfloat), dataOffset: 0, dataStride: sizeof(Float3))
let indexData = NSData(bytes:indices, length:indices.count * sizeof(GLint))
let element = SCNGeometryElement(data: indexData, primitiveType: .Triangles, primitiveCount: indices.count, bytesPerIndex: sizeof(GLint))
let surface = SCNGeometry(sources: [vertexSource, normalSource], elements: [element])
surface.firstMaterial?.diffuse.contents = UIColor.redColor()
let sn = SCNNode(geometry: surface)
sn.name = “surface”
self.sceneView?.scene?.rootNode.addChildNode(sn)
}
func createCamera() {
let camera = SCNNode()
camera.camera = SCNCamera()
camera.position = SCNVector3(x: 15, y: 20, z: 50)
camera.rotation = SCNVector4(x: 1, y: 0, z: 0, w: –0.6)
self.sceneView?.scene?.rootNode.addChildNode(camera)
}
func createLight() {
let light = SCNLight()
light.type = SCNLightTypeSpot
let lightNode = SCNNode()
lightNode.light = light
lightNode.position = SCNVector3(x: 15, y: 5, z: 90)
lightNode.rotation = SCNVector4(x: 1, y: 0, z: 0, w: –0.3)
self.sceneView?.scene?.rootNode.addChildNode(lightNode)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
if let p = touches.anyObject()?.locationInNode(self.sceneView?.overlaySKScene) {
let hit = self.sceneView!.overlaySKScene.nodeAtPoint(p)
if (hit.name?.hasPrefix(“marker”) != nil) {
let idx = (hit.name! as NSString).substringFromIndex(6).toInt()!
vertices[idx].y += 2.0
updateSurfaceChart()
let label = hit.childNodeWithName(“label”) as SKLabelNode
label.text = “\((label.text as NSString).floatValue + 2.0)“
}
}
}
}