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.

Replies

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.

Add a Comment

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.

  • Thanks, that could be it. But a link to some official documentation would be appreciated. The Swift documentation is empty: https://developer.apple.com/documentation/scenekit/scngeometryprimitivetype/polygon

  • This was linked above in the comments and is still applicable in Swift:

    https://developer.apple.com/documentation/scenekit/scngeometryprimitivetype/scngeometryprimitivetypepolygon

    Please file an enhancement request using Feedback Assistant to request that this information also be added to the Swift page.

    Thanks!

  • You have an Apple logo beside your username. I understand that you are from Apple. If this is the case, I would invite you to file an enhancement request yourself, or discuss it with your colleagues directly. I think it is more efficient than asking external developers to file enhancement requests. If you don't have enough motivation to fix such things without someone pushing you from the outside, then I don't think someone who reads an anonymous enhancement request would be more motivated than you. After the little attention I got after filing literally thousands of enhancement requests, I have stopped completely because it is not worth my time.

Add a Comment