I am trying to create a SCNNode whose geometry is created using an array of x, y, and z positions. I am using the following code; however, this is not showing up. Does anyone know what's wrong?
class CustomShapeNode: SCNNode {
init(positions: [(Double, Double, Double)]) {
super.init()
// Create an array of SCNVector3 from the positions array
var scnPositions = [SCNVector3]()
for position in positions {
scnPositions.append(SCNVector3(Float(position.0), Float(position.1), Float(position.2)))
}
// Create a geometry from the positions array
let geometry = SCNGeometry(sources: [SCNGeometrySource(vertices: scnPositions)], elements: [SCNGeometryElement(indices: Array(0..<scnPositions.count), primitiveType: .triangles)])
// Set the geometry to the node
self.geometry = geometry
// Set the color of the node geometry
self.geometry?.firstMaterial?.diffuse.contents = UIColor.red
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
CodePudding user response:
Use the following code:
import SceneKit
class ViewController: UIViewController {
var sceneView: SCNView? = nil
let node = CustomShapeNode([SCNVector3( 0,0,0), // CCW
SCNVector3( 1,1,0),
SCNVector3(-1,1,0)])
override func viewDidLoad() {
super.viewDidLoad()
sceneView = self.view as? SCNView
sceneView?.scene = SCNScene()
sceneView?.backgroundColor = .darkGray
sceneView?.allowsCameraControl = true
sceneView?.scene?.rootNode.addChildNode(node)
}
}
class CustomShapeNode: SCNNode {
init(_ positions: [SCNVector3]) {
super.init()
let normalsPerFace = 1
let indices: [Int32] = [0, 1, 2]
let source = SCNGeometrySource(vertices: [positions[0],
positions[1],
positions[2]])
let normals = [positions[0],positions[1],positions[2]].map {
[SCNVector3](repeating: $0, count: normalsPerFace)
}.flatMap { $0 }
let normalSource = SCNGeometrySource(normals: normals)
let data = Data(bytes: indices,
count: indices.count * MemoryLayout<Int32>.size)
let element = SCNGeometryElement(data: data,
primitiveType: .triangles,
primitiveCount: 1,
bytesPerIndex: MemoryLayout<Int32>.size)
let p1 = CGPoint(x: CGFloat(positions[0].x),
y: CGFloat(positions[0].y))
let p2 = CGPoint(x: CGFloat(positions[1].x),
y: CGFloat(positions[1].y))
let p3 = CGPoint(x: CGFloat(positions[2].x),
y: CGFloat(positions[2].y))
let texCoord = SCNGeometrySource(textureCoordinates: [p1, p2, p3])
self.geometry = SCNGeometry(sources: [source, normalSource, texCoord],
elements: [element])
self.geometry?.firstMaterial?.diffuse.contents = UIColor.systemOrange
self.geometry?.firstMaterial?.lightingModel = .constant
self.geometry?.firstMaterial?.isDoubleSided = true
}
required init?(coder: NSCoder) {
fatalError("Hasn't been implemented yet")
}
}