2

I don't understand what's wrong with the following code:

class Terrain {

    private class func createGeometry () -> SCNGeometry {

        let sources = [
            SCNGeometrySource(vertices:[
                SCNVector3(x: -1.0, y: -1.0, z:  0.0),
                SCNVector3(x: -1.0, y:  1.0, z:  0.0),
                SCNVector3(x:  1.0, y:  1.0, z:  0.0),
                SCNVector3(x:  1.0, y: -1.0, z:  0.0)], count:4),
            SCNGeometrySource(normals:[
                SCNVector3(x:  0.0, y:  0.0, z: -1.0),
                SCNVector3(x:  0.0, y:  0.0, z: -1.0),
                SCNVector3(x:  0.0, y:  0.0, z: -1.0),
                SCNVector3(x:  0.0, y:  0.0, z: -1.0)], count:4),
            SCNGeometrySource(textureCoordinates:[
                CGPoint(x: 0.0, y: 0.0),
                CGPoint(x: 0.0, y: 1.0),
                CGPoint(x: 1.0, y: 1.0),
                CGPoint(x: 1.0, y: 0.0)], count:4)
        ]

        let elements = [
            SCNGeometryElement(indices: [0, 2, 3, 0, 1, 2], primitiveType: .Triangles)
        ]

        let geo = SCNGeometry(sources:sources, elements:elements)

        let mat = SCNMaterial()
        mat.diffuse.contents = UIColor.redColor()
        mat.doubleSided = true
        geo.materials = [mat, mat]


        return geo
    }

    class func createNode () -> SCNNode {

        let node = SCNNode(geometry: createGeometry())
        node.name = "Terrain"
        node.position = SCNVector3()
        return node
    }
}

I use it as follows:

   let terrain = Terrain.createNode()
   sceneView.scene?.rootNode.addChildNode(terrain)

But get:

2016-01-19 22:21:17.600 SceneKit: error, C3DRendererContextSetupResidentMeshSourceAtLocation - double not supported
2016-01-19 22:21:17.601 SceneKit: error, C3DSourceAccessorToVertexFormat - invalid vertex format
/BuildRoot/Library/Caches/com.apple.xbs/Sources/Metal/Metal-55.2.6.1/Framework/MTLVertexDescriptor.mm:761: failed assertion `Unused buffer at index 18.'
rickster
  • 124,678
  • 26
  • 272
  • 326
Stéphane de Luca
  • 12,745
  • 9
  • 57
  • 95

1 Answers1

2

The issue is that the geometry is expecting float components but you’re giving it doubles—CGPoint’s components are CGFloat values, which are typedef’d to double on 64-bit systems. Unfortunately, the SCNGeometrySource …textureCoordinates: initializer insists on CGPoints, so you can’t use that; the workaround I found was to create an NSData wrapping an array of SIMD float vectors, then use the much longer data:semantic:etc: initializer to consume the data. Something like this should do the trick:

let coordinates = [float2(0, 0), float2(0, 1), float2(1, 1), float2(1, 0)]
let coordinateData = NSData(bytes:coordinates, length:4 * sizeof(float2))
let coordinateSource = SCNGeometrySource(data: coordinateData,
                                     semantic: SCNGeometrySourceSemanticTexcoord,
                                  vectorCount: 4,
                              floatComponents: true,
                          componentsPerVector: 2,
                            bytesPerComponent: sizeof(Float),
                                   dataOffset: 0,
                                   dataStride: sizeof(float2))
Noah Witherspoon
  • 57,021
  • 16
  • 130
  • 131
  • 1
    By using the way you set the texture coord (or by removing texturecoord in the elements) my code does not break anymore. Good. But it draws nothing on screen. I asked this specific question here: http://stackoverflow.com/questions/34897040/scenekit-custom-geometry-does-not-show-up – Stéphane de Luca Jan 20 '16 at 10:08