Creating SCNGeometryElement with SCNGeometryPrimitiveType.polygon always causes error

I'm using this code to create a rectangle (that will eventually be a more complex shape):

let vertices = [simd_float3(x: 1, y: 1, z: 0), simd_float3(x: 1, y: -1, z: 0), simd_float3(x: -1, y: -1, z: 0), simd_float3(x: -1, y: 1, z: 0)]
let vertexSource = SCNGeometrySource(data: Data(bytes: vertices, count: MemoryLayout<simd_float3>.size * vertices.count), semantic: .vertex, vectorCount: vertices.count, usesFloatComponents: true, componentsPerVector: 3, bytesPerComponent: MemoryLayout<Float>.size, dataOffset: 0, dataStride: MemoryLayout<simd_float3>.stride)
let indices: [Int32] = Array(0..<Int32(vertices.count))
let element = SCNGeometryElement(data: Data(bytes: indices, count: MemoryLayout<Int32>.size * indices.count), primitiveType: .polygon, primitiveCount: 1, bytesPerIndex: MemoryLayout<Int32>.size)
let geometry = SCNGeometry(sources: [vertexSource], elements: [element])

which logs this error in the Xcode console:

[SceneKit] Error: SCNGeometryElement initialization - Invalid polygon edge count (0)

There also doesn't seem to be any documentation about how to use this .polygon mode. When using .triangleStrip with a primitiveCount of 2, no error is logged.

I once got this working and never touched it afterwards. I agree the documentation by Apple is really bad in this topic. I'd suggest to read about the data structures of OpenGL which are mostly the same. With .triangleStrip every new vertex at the end of the array adds another triangle and everything is connected. I think with .polygon mode you have to define the three vertices for every triangle. So the first three vertices are one triangle and then the next three vertices are another triangle, separate from the first one. Only a number of 3 is valid. So in your code you have to add two more vertices or remove one.

The issue in your code is that you have not provided the polygon vertex counts for each polygon in your indices buffer (in this case you only have one polygon, but you still need to provide this count).

SceneKit is interpreting the first vertex index as the count of vertices in your polygon, zero, and because there cannot be a polygon with zero vertices, SceneKit is logging the following:

[SceneKit] Error: SCNGeometryElement initialization - Invalid polygon edge count (0)

To fix that, you could do something like this:

let indices: [Int32] = Array(0..<Int32(vertices.count))
let polygonVertexCounts: [Int32] = [4]

let polygonVertexCountsData = Data(bytes: polygonVertexCounts, count: MemoryLayout<Int32>.stride * polygonVertexCounts.count)

let indicesData = Data(bytes: indices, count: MemoryLayout<Int32>.stride * indices.count)

// Join the two Data's together to pass to the SCNGeometryElement.  Order matters here, the polygonVertexCounts have to come first.
let data = polygonVertexCountsData + indicesData

let element = SCNGeometryElement(data: data, primitiveType: .polygon, primitiveCount: 1, bytesPerIndex: MemoryLayout<Int32>.stride)

In the snippet above, [4] is used to say that your index array is comprised of a single polygon that has 4 vertices. If you add more polygons to your index array, then you should add an entry for each new polygon to the polygonVertexCounts array.

Creating SCNGeometryElement with SCNGeometryPrimitiveType.polygon always causes error
 
 
Q