1

我的目标:给定一些 indexi和 some UIColor c,使该索引处的脸变成该颜色。

let vertices = // all of my vertices in the format of SCNVector3

let vertexSource = SCNGeometrySource(data: verticesData,
                                    semantic: .vertex,
                                    vectorCount: vertices.count,
                                    usesFloatComponents: true,
                                    componentsPerVector: 3,
                                    bytesPerComponent: MemoryLayout<Float>.size,
                                    dataOffset: 0,
                                    dataStride: MemoryLayout<SCNVector3>.size)


var colors: [SCNVector3] = vertices.map { SCNVector3(1, 1, 1) } // Make it all white color at first
colors[10] = SCNVector3(1, 0, 0)                                // Pick one at random and make it red
let colorSource = SCNGeometrySource(data: NSData(bytes: colors, length: MemoryLayout<SCNVector3>.size * colors.count) as Data,
                                    semantic: .color,
                                    vectorCount: colors.count,
                                    usesFloatComponents: true,
                                    componentsPerVector: 3,
                                    bytesPerComponent: MemoryLayout<Float>.size,
                                    dataOffset: 0,
                                    dataStride: MemoryLayout<SCNVector3>.size)

let elements = SCNGeometryElement(data: NSData(bytes: indices, length: MemoryLayout<Int32>.size * indices.count) as Data,
                                primitiveType: .polygon,
                                primitiveCount: indices.count / 4,
                                bytesPerIndex: MemoryLayout<Int32>.size)

let g = SCNGeometry(sources: [vertexSource, colorSource], elements: [element])

我的 3D 对象渲染正确。正如预期的那样,它全是白色。然而,那张红脸并没有出现。我看到一丝红色,但看起来 SceneKit 正在尝试在顶点周围着色,而不是那些顶点形成的面。如何强制它只为这些顶点创建的面/多边形着色?

4

1 回答 1

2

这里发生的事情最好用一个简单的例子来解释。这是一个由两个三角形组成的平面:

let vertices: [SCNVector3] = [
    SCNVector3(-1, 1, 0),
    SCNVector3( 1, 1, 0),
    SCNVector3( 1, -1, 0),
    SCNVector3(-1, -1, 0)
]
let indices: [UInt16] = [
    0, 3, 1,
    1, 3, 2
]
var colors: [SCNVector3] = vertices.map { _ in SCNVector3(1, 1, 1) }

现在,当您将红色分配给colors数组中的一个条目时,您会得到以下结果:

在此处输入图像描述

这是有道理的,因为您将颜色分配给单个顶点,而不是整个面。需要为面部的每个索引分配红色,(0, 3, 1)以确保整个面部都是红色的:

colors[0] = SCNVector3(1, 0, 0)
colors[3] = SCNVector3(1, 0, 0)
colors[1] = SCNVector3(1, 0, 0)

结果是:

在此处输入图像描述

红白渐变在那里是因为颜色是在顶点之间插值的。现在具有红色的顶点也属于第二个面,该面也具有白色的顶点。如果你想达到这个结果:

在此处输入图像描述

然后你必须复制面之间共享的顶点:

let vertices: [SCNVector3] = [
    SCNVector3(-1, 1, 0),
    SCNVector3(-1, -1, 0),
    SCNVector3( 1, 1, 0),

    SCNVector3( 1, 1, 0),
    SCNVector3(-1, -1, 0),
    SCNVector3( 1, -1, 0)
    ]

let indices: [UInt16] = [
    0, 1, 2,
    3, 4, 5
]

colors[0] = SCNVector3(1, 0, 0)
colors[1] = SCNVector3(1, 0, 0)
colors[2] = SCNVector3(1, 0, 0)
于 2019-05-22T12:21:06.337 回答