具有多边形作为primitiveType的SCNGeometry

时间:2017-07-05 09:25:30

标签: ios swift scenekit scnnode scnsphere

试图找出如何使用polygon作为primitiveType创建SCNGeometry, 我的目标是将多边形形状的节点添加为球体节点的子节点,并使其看起来像地图套件的MKPolygon like in this example

MKPolygon

我目前的代码是:

//Take an arbitrary array of vectors
let vertices: [SCNVector3] = [
SCNVector3Make(-0.1304485, 0.551937, 0.8236193),
SCNVector3Make(0.01393811, 0.601815, 0.7985139),
SCNVector3Make(0.2971005, 0.5591929, 0.7739732),
SCNVector3Make(0.4516893, 0.5150381, 0.7285002),
SCNVector3Make(0.4629132, 0.4383712, 0.7704169),
SCNVector3Make(0.1333823, 0.5224985, 0.8421428),
SCNVector3Make(-0.1684743, 0.4694716, 0.8667254)]

//Does polygon shape require indices?
let indices: [Int] = [0,1,2,3,4,5,6]

let vertexSource = SCNGeometrySource(vertices: vertices)
let indexData = Data(bytes: indices, count: indices.count * MemoryLayout<Int>.size)

//Note!!! I get compiler error if primitiveCount is greater than 0
let element = SCNGeometryElement(data: indexData, primitiveType: .polygon, primitiveCount: 0, bytesPerIndex: MemoryLayout<Int>.size)
let geometry = SCNGeometry(sources: [vertexSource], elements: [element])

let material = SCNMaterial()
material.diffuse.contents = UIColor.purple.withAlphaComponent(0.75)
material.isDoubleSided = true
geometry.firstMaterial = material

let node = SCNNode(geometry: geometry)

当像这样使用 SCNGeometryElement 时,我得到一个空节点。

1 个答案:

答案 0 :(得分:3)

你必须遇到问题:

  1. SceneKit(和Metal)仅支持32位整数作为索引(source)。 因此,indices数组的类型必须为[Int32]

  2. 对于多边形,SceneKit需要两条信息:多边形中的点数和顶点数组中的点的索引。 来自SCNGeometryPrimitiveTypePolygon上的Apples文档(仅存在于Objective-C中):

  3.   

    元素的data属性包含两个值序列。

         
        
    • 第一个序列的数值等于几何元素的值   primitiveCount值。此序列中的每个值都指定多边形基元中的顶点数。例如,如果第一个序列是[5,3],则几何元素包含五边形,后跟三角形。
    •   
    • 其余数据是一系列顶点索引。第一序列中的每个条目指定第二序列中的相应数量的条目。例如,如果第一个序列包含值[5,3],则第二个序列包括五边形的五个索引,然后是三角形的三个索引。
    •   

    您需要将索引数组更改为:

    let indices: [Int32] = [7, /* We have a polygon with seven points */,
                            0,1,2,3,4,5,6 /* The seven indices for our polygon */
                           ]
    

    然后你可以将primitiveCount设置为1(我们有一个要绘制的多边形)并且需要更改缓冲区的大小

    let indexData = Data(bytes: indices, 
                         count: indices.count * MemoryLayout<Int32>.size)
    
    // Now without runtime error
    let element = SCNGeometryElement(data: indexData, 
                                     primitiveType: .polygon,
                                     primitiveCount: 1, 
                                     bytesPerIndex: MemoryLayout<Int32>.size)