I have created a custom SCNGeometry object with some help from this question. However, when applying the geometry to a SCNNode, the pivot seems to not quite be in the correct location. When rotating the node, I want to rotate the node around the center of the geometry, but instead it rotates around another point. I can fix this problem by changing the node's pivot using node.pivot = SCNMatrix4MakeTranslation(ARROW_WIDTH / 2, 0, ARROW_LENGTH / 2)
, where the ARROW_WIDTH refers to the width of the geometry and the ARROW_LENGTH refers to the length of the geometry. This is however not ideal as every time I create a new node with the geometry, I have to manually fix the pivot of the node. Is there a way to define the "pivot" of a geometry somehow?
Current code that creates the custom SCNGeometry:
/**
Default constructor of an arrow geometry. This constructor takes in the needed parameters to construct the geometry at the specified size.
- parameters:
- length: The length of the arrow, which is the dimension that the arrow is pointing in.
- height: The height of the arrow, which is the thickness of the arrow.
- width: The width of the arrow, which defines the width of the arrow.
- indent: The indent of the arrow, which is the point and gap on the front and back of the arrow.
*/
init(length: Float, height: Float, width: Float, indent: Float) {
self.length = length
self.height = height
self.width = width
self.indent = indent > length ? length : indent
// Vertices
let v0 = SCNVector3(0, height / 2, 0)
let v1 = SCNVector3(width / 2, height / 2, indent)
... more vertices
let h4 = SCNVector3(width, -height / 2, indent)
let h5 = SCNVector3(width / 2, -height / 2, length - indent)
let vertices = [
// Top layer bottom triangles
v0, v1, h0,
v1, v2, h1,
... more vertices
v4, v10, v5,
v10, v11, v5
]
// Normals
let pX = SCNVector3(1, 0, 0)
... more normals
let topRight = calculateNormal(v1: v3, v2: v9, v3: v4)
let normals = [
// Top layer bottom triangles
pY, pY, pY,
... more normals
topLeft, topLeft, topLeft
]
// Indices
let indices: [Int32] = vertices.enumerated().map({ Int32($0.0) })
// Sources
let vertexSource = SCNGeometrySource(vertices: vertices)
let normalSource = SCNGeometrySource(vertices: normals)
// Create the geometry
let pointer = UnsafeRawPointer(indices)
let indexData = NSData(bytes: pointer, length: MemoryLayout<Int32>.size * indices.count)
let element = SCNGeometryElement(data: indexData as Data, primitiveType: .triangles, primitiveCount: indices.count / 3, bytesPerIndex: MemoryLayout<Int32>.size)
self._geometry = SCNGeometry(sources: [vertexSource, normalSource], elements: [element])
}
Without applying the manual pivot fix on the node, the arrow renders like this: (Note that the red point is the scene origin (0, 0, 0) and the arrow is positioned in the root node of the scene at that same position) no manual pivot fix
When applying the manual pivot fix on the node, the arrow renders like this: manual pivot fix