SceneKit 自定义几何体产生“double not supported”/“invalid vertex format”运行时错误
SceneKit custom geometry produces “double not supported” / “invalid vertex format” runtime error
我不明白以下代码有什么问题:
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
}
}
我是这样使用的:
let terrain = Terrain.createNode()
sceneView.scene?.rootNode.addChildNode(terrain)
但是得到:
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.'
问题是几何需要 float
个分量,但你给了它 double
s——CGPoint 的分量是 CGFloat 值,它被类型定义为 double
64 位系统。不幸的是,SCNGeometrySource …textureCoordinates:
初始化器坚持使用 CGPoints,所以你不能使用它;我发现的解决方法是创建一个 NSData 包装一个 SIMD float vectors, then use the much longer data:semantic:etc:
初始化程序数组来使用数据。这样的事情应该可以解决问题:
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))
我不明白以下代码有什么问题:
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
}
}
我是这样使用的:
let terrain = Terrain.createNode()
sceneView.scene?.rootNode.addChildNode(terrain)
但是得到:
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.'
问题是几何需要 float
个分量,但你给了它 double
s——CGPoint 的分量是 CGFloat 值,它被类型定义为 double
64 位系统。不幸的是,SCNGeometrySource …textureCoordinates:
初始化器坚持使用 CGPoints,所以你不能使用它;我发现的解决方法是创建一个 NSData 包装一个 SIMD float vectors, then use the much longer data:semantic:etc:
初始化程序数组来使用数据。这样的事情应该可以解决问题:
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))