SceneKit выборочно окрашивает лицо по определенному индексу
Моя цель: дать какой-то индекс 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 пытается закрасить вершины, а не грани, которые образуют эти вершины. Как я могу заставить его просто раскрасить лицо / многоугольник, созданный этими вершинами?
1 ответ
То, что здесь происходит, лучше всего объяснить на простом примере. Вот плоскость, состоящая из двух треугольников:
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
array вы получите такой результат:
Это имеет смысл, потому что вы назначаете цвет одной вершине, а не всему лицу. Красный цвет нужно присвоить каждому индексу лица.(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)