SCNGeometry 与多边形作为primitiveType

Posted

技术标签:

【中文标题】SCNGeometry 与多边形作为primitiveType【英文标题】:SCNGeometry with polygon as primitiveType 【发布时间】:2017-12-08 21:10:44 【问题描述】:

试图弄清楚我如何创建一个以多边形为primitiveType的SCNGeometry, 我的目标是将多边形节点添加为球体节点的子节点,并使其看起来像地图套件的 MKPolygon,like in this example。

我当前的代码是:

//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】:

你有两个问题:

    SceneKit(和 Metal)仅支持 32 位整数作为索引 (source)。 所以你的索引数组的类型需要是[Int32]

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

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

第一个序列有多个值等于几何元素的 原始计数值。此序列中的每个值都指定多边形图元中的顶点数。例如,如果第一个序列是 [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)

【讨论】:

谢谢,这解决了我在操场上的大部分问题,尽管当我分配primitiveCount: 1 时出现错误:The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation. 这是否意味着我无法在操场上创建以多边形作为原始类型的 SCNGeometryElement? 我已经在 Xcode Playgrounds 中测试了我的代码(尽管在 Xcode 9b2 中)。尝试重新启动 Xcode 或将代码复制粘贴到新的代码中,这可能只是 Xcode 中的一个错误。 重启帮助,Tnx 绘制了一些多边形,但有些多边形显示“无法创建零长度缓冲区。” 我也遇到了@khunshan 所描述的情况,当使用许多顶点时似乎更频繁地崩溃。我就这个问题发布了我自己的问题here

以上是关于SCNGeometry 与多边形作为primitiveType的主要内容,如果未能解决你的问题,请参考以下文章

自定义 SCNGeometry 节点上基于物理的照明

如何从 SCNVector3 在 SceneKit 中生成凹面或凸面多边形平面

在 SceneKit 中镜像 SCNGeometry

iOS开发之SceneKit框架--SCNGeometry.h

为啥自定义 SCNGeometry 中的黑色比 SCNSphere 中的浅

SceneKit:使用 dae 动画更新 SCNGeometry