SceneKit 通过某个索引选择性地为人脸着色
SceneKit selectively color a face by a certain index
我的objective:给定一些索引i
和一些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 正试图在顶点周围着色,而不是这些顶点形成的面。我怎样才能强制它只为那些顶点创建的 face/polygon 着色?
这里发生的事情最好用一个简单的例子来解释。
这是一个由两个三角形组成的平面:
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)
这导致:
red-white 渐变存在是因为颜色是在顶点之间插值的。现在具有红色的顶点也属于第二个面,该面也具有白色的顶点。如果你想达到这样的效果:
然后您必须复制面之间共享的顶点:
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)
我的objective:给定一些索引i
和一些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 正试图在顶点周围着色,而不是这些顶点形成的面。我怎样才能强制它只为那些顶点创建的 face/polygon 着色?
这里发生的事情最好用一个简单的例子来解释。 这是一个由两个三角形组成的平面:
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)
这导致:
red-white 渐变存在是因为颜色是在顶点之间插值的。现在具有红色的顶点也属于第二个面,该面也具有白色的顶点。如果你想达到这样的效果:
然后您必须复制面之间共享的顶点:
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)