SceneKit выборочно окрашивает лицо по определенному индексу

Моя цель: дать какой-то индекс i и немного UIColorc, сделайте лицо по этому указателю превратиться в этот цвет.

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)
Другие вопросы по тегам