SceneKitで動的に線描画を更新できない。
swift4.2になります。
下記のコードSCNLineクラスのpathを更新して、更新したpathのものを描画したいのですが、viewController内で定義したSCNLineオブジェクトのgeometryを更新しても描画が更新されませんでした。一度ノードを消去してから改めて追加する方法で線描画を更新することができましたが、処理が重たくなってしまいます。何か良い方法をご教授いただきたいです。
import Foundation
import SceneKit
//ベジェ曲線計算部分
class SCNPath{
private var current: SCNVector3 = SCNVector3(0, 0, 0)
var points: [SCNVector3] = [] //曲線を構成する点の座標を保存する
/// 始点を設定します。pointsは上書きされます。デフォルトでは(0, 0, 0)です。
func start(from point: SCNVector3) -> SCNPath{
current = point
points = [point]
return self
}
func addLine(to point: SCNVector3) -> SCNPath{
var rtn = [SCNVector3]()
points.append(current)
rtn.append(current)
current = point
return self
}
func addQuadCurve(to point: SCNVector3, control: SCNVector3) -> SCNPath{
var rtn = [SCNVector3]()
let n = Int((control - current).length + (point - control).length) * 12 //この係数を変えると、カクカク度と計算量が反比例して変化する。
for i in 0..<n{
let t = CGFloat(i) / CGFloat(n)
let q1 = current + (control - current) * t
let q2 = control + (point - control) * t
let r = q1 + (q2 - q1) * t
rtn.append(r)
}
points += rtn
current = point
return self
}
func addCurve(to point: SCNVector3, control1: SCNVector3, control2: SCNVector3) -> SCNPath{
var rtn = [SCNVector3]()
let n = Int((control1 - current).length + (control2 - control1).length + (point - control2).length) * 12 //この係数を変えると、カクカク度と計算量が反比例して変化する。
for i in 0..<n{
let t = CGFloat(i) / CGFloat(n)
let q1 = current + (control1 - current) * t
let q2 = control1 + (control2 - control1) * t
let q3 = control2 + (point - control2) * t
let r1 = q1 + (q2 - q1) * t
let r2 = q2 + (q3 - q2) * t
let s = r1 + (r2 - r1) * t
rtn.append(s)
}
points += rtn
current = point
return self
}
func end(){
points.append(current)
}
func close() -> SCNPath{
_ = addLine(to: self.points[0])
if let last = points.last, last == current{}else{
points.append(current)
}
current = self.points[0]
return self
}
}
extension SCNVector3: Equatable{
public static func == (lhs: SCNVector3, rhs: SCNVector3) -> Bool{
return (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z)
}
}
//曲線のノード
class SCNLine: SCNNode{
var source:SCNGeometrySource!
var indices: [UInt32]!
override init(){
super.init()
}
// Pathを指定してBezier曲線を引く
init(path: SCNPath){
super.init()
source = SCNGeometrySource(vertices: path.points)
indices = {var rtn = [UInt32]();for i in 0..<path.points.count-1{rtn += [UInt32(i), UInt32(i+1)]};return rtn}()
let element = SCNGeometryElement(indices: indices, primitiveType: .line)
let geometry = SCNGeometry(sources: [source], elements: [element])
self.geometry = geometry
let material = SCNMaterial()
material.diffuse.contents = UIColor.white
self.geometry!.insertMaterial(material, at: 0)
}
// オマケ 直線を引く
init(from : SCNVector3, to : SCNVector3){
super.init()
let source = SCNGeometrySource.init(vertices: [from, to])
let indices : [UInt8] = [0, 1]
let data = Data.init(bytes: indices)
let element = SCNGeometryElement.init(data: data, primitiveType: .line, primitiveCount: 1, bytesPerIndex: 1)
let geometry = SCNGeometry.init(sources: [source], elements: [element])
// super.init(geometry: geometry)
self.geometry = geometry
let material = SCNMaterial.init()
material.diffuse.contents = UIColor.white
self.geometry!.insertMaterial(material, at: 0)
}
required init?(coder aDecoder: NSCoder) {
fatalError()
}
func updatePath(path:SCNPath){
source = SCNGeometrySource(vertices: path.points)
indices = {var rtn = [UInt32]();for i in 0..<path.points.count-1{rtn += [UInt32(i), UInt32(i+1)]};return rtn}()
let element = SCNGeometryElement(indices: indices, primitiveType: .line)
let geometry = SCNGeometry(sources: [source], elements: [element])
self.geometry = geometry
let material = SCNMaterial()
material.diffuse.contents = UIColor.white
self.geometry!.insertMaterial(material, at: 0)
}
}
//拡張実装
infix operator • // ⌥ + 8
infix operator × // かける[変換]
extension SCNVector3{
static func - (lhs: SCNVector3, rhs: SCNVector3) -> SCNVector3{
return SCNVector3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z)
}
static func + (lhs: SCNVector3, rhs: SCNVector3) -> SCNVector3{
return SCNVector3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z)
}
static func * (lhs: SCNVector3, rhs: CGFloat) -> SCNVector3{
return SCNVector3(lhs.x * Float(rhs), lhs.y * Float(rhs), lhs.z * Float(rhs))
}
static func / (lhs: SCNVector3, rhs: CGFloat) -> SCNVector3{
return SCNVector3(lhs.x / Float(rhs), lhs.y / Float(rhs), lhs.z / Float(rhs))
}
static func • (lhs: SCNVector3, rhs: SCNVector3) -> CGFloat{
return CGFloat((lhs.x * rhs.x) + (lhs.y * rhs.y) + (lhs.z * rhs.z))
}
static func × (lhs: SCNVector3, rhs: SCNVector3) -> SCNVector3{
return SCNVector3(
(lhs.y*rhs.z) - (lhs.z*rhs.y),
(lhs.z*rhs.x) - (lhs.x*rhs.z),
(lhs.x*rhs.y) - (lhs.y*rhs.x)
)
}
private var lengthSquared: CGFloat{
return CGFloat((x*x) + (y*y) + (z*z))
}
var length: CGFloat{
return lengthSquared.squareRoot()
}
var normalized: SCNVector3{
let length = self.length
return SCNVector3(x: x/Float(length), y: y/Float(length), z: z/Float(length))
}
}