0

我在 SCNGeometry 扩展中使用下面的代码来获取顶点数据,以及用于 .normals 的类似代码,我的目标是从原始节点创建一个克隆网格来为每个顶点着色,但是当我尝试创建另一个节点时有了这些顶点和法线,生成的网格有一些三角形搞砸了,我有一个小网格要测试,这就是我得到的,你们中有人对我可能做错了什么有一些指导吗?

在这个例子中,这个函数给我一个 50 个顶点的数组,而网格实际上有 18 个面,因此结果应该是一个 54 个顶点的数组,对吗?

原始网格 克隆网格

扩大:

func extGetVertices() -> [SCNVector3]? {
    let sources = self.sources(for: .vertex)
    guard let source = sources.first else{return nil}
    let stride = source.dataStride / source.bytesPerComponent
    let offset = source.dataOffset / source.bytesPerComponent
    let vectorCount = source.vectorCount
    return source.data.withUnsafeBytes { (buffer : UnsafePointer<Float>) -> [SCNVector3] in
        var result = Array<SCNVector3>()
        for i in 0...vectorCount - 1 {
            let start = i * stride + offset
            result.append(SCNVector3(buffer[start], buffer[start+ 1], buffer[start+ 2]))
        }
        return result
    }
}

对象:

#
# object obj_12853878
#
v 1097 957 36
v 779.26361083984375 992 0
v 707.26361083984375 590.5828857421875 91
v 1076 334.41595458984375 0
v 748.26361083984375 326.41595458984375 0
v 732.01263427734375 22.33051872253417968 0
v 1110.4652099609375 639.2049560546875 0
v 335.71615600585937504 680.5828857421875 39
v 314.88912963867187504 369.207000732421875 9.023892608628001E-14
v 350.4644775390625 926.65570068359375 -33
v 36 358.41595458984375 0
v 0 0 -33
v 0 680.5828857421875 -27
v 0 957 19
v 335.71615600585937504 22 0
v 1076 0 30
# 16 vertices
vn -0.08388713002204895 0.23459480702877044 0.9684669375419616
vn 0 0 1
vn 0.24344816803932188 -0.28190669417381288 0.92804181575775152
vn -0.1642393171787262 -0.11176854372024536 0.98006796836853024
vn -0.11669350415468216 0.28533965349197388 0.9512959122657776
vn 0.00356122362427413 -0.0920381024479866 0.99574911594390864
vn -0.19254806637763976 0.06056648120284081 0.9794166088104248
vn 0.13100945949554444 -0.1627427488565445 0.97793215513229376
vn -0.0974447876214981 -0.0058451765216887 0.9952237606048584
vn -0.03258795291185379 -0.3300407826900482 0.9434040188789368
vn 0.23050078749656676 -0.09988142549991608 0.967932403087616
vn -0.07897967845201492 0.233848974108696 0.96905976533889776
vn 0.00482096569612622 -0.1245955303311348 0.99219590425491328
vn -0.18483471870422364 0.28617173433303832 0.940181851387024
vn -0.08079835772514343 0.08905769884586334 0.99274384975433344
vn 1.8364935581471252E-16 -2.4888339972415545E-16 1
# 16 vertex normals
g obj_12853878
s 1
f 1//1 2//1 3//1
f 4//2 5//2 6//2
f 7//3 3//3 5//3
f 3//4 8//4 9//4
f 2//5 10//5 8//5
f 9//6 11//6 12//6
f 8//7 13//7 11//7
f 10//8 14//8 13//8
f 15//9 9//9 12//9
f 5//10 3//10 9//10
f 7//11 1//11 3//11
f 2//12 8//12 3//12
f 8//13 11//13 9//13
f 10//14 13//14 8//14
f 4//15 6//15 16//15
f 7//2 5//2 4//2
f 5//2 15//2 6//2
f 5//16 9//16 15//16
#18 polygons

克隆代码:

guard let let vertices = node.geometry?.extGetVertices() else {return nil}
guard let let normals = node.geometry?.extGetNormals() else {return nil}
guard let let indices = (0..<vertices.count).indices.map {Int32($0)}

let vertexSource = SCNGeometrySource(vertices: vertices)
let indexElement = SCNGeometryElement(indices: indices, primitiveType: SCNGeometryPrimitiveType.triangles)
let normalSource = SCNGeometrySource(normals: normals)
let voxelGeometry = SCNGeometry(sources: [vertexSource, normalSource], elements: [indexElement])
let voxelMaterial = SCNMaterial()
voxelMaterial.diffuse.contents = UIColor.white
voxelGeometry.materials = [voxelMaterial]
let clonedNode = SCNNode(geometry: voxelGeometry)
4

2 回答 2

0

好的,我发现了我原来的问题,我将索引数组创建为一系列连续的数字,但它们也可以从原始网格中获得

func extGetIndices() -> [Int32]? {
    guard let dataCount = self.elements.first?.data.count else { return nil }
    let faces = self.elements.first?.data.withUnsafeBytes {(ptr: UnsafeRawBufferPointer) -> [Int32] in
        guard let boundPtr = ptr.baseAddress?.assumingMemoryBound(to: Int32.self) else {return []}
        let buffer = UnsafeBufferPointer(start: boundPtr, count: dataCount / 4)
        return Array<Int32>(buffer)
    }
    return faces
}

所以,克隆节点的更新代码是:

guard let let vertices = node.geometry?.extGetVertices() else {return nil}
guard let let normals = node.geometry?.extGetNormals() else {return nil}
guard let let indices = node.geometry?.extGetIndices() else {return nil}

let vertexSource = SCNGeometrySource(vertices: vertices)
let indexElement = SCNGeometryElement(indices: indices, primitiveType: SCNGeometryPrimitiveType.triangles)
let normalSource = SCNGeometrySource(normals: normals)
let voxelGeometry = SCNGeometry(sources: [vertexSource, normalSource], elements: [indexElement])
let voxelMaterial = SCNMaterial()
voxelMaterial.diffuse.contents = UIColor.white
voxelGeometry.materials = [voxelMaterial]
let clonedNode = SCNNode(geometry: voxelGeometry)

此外,节点可以被着色为具有颜色类型的 SCNGeometrySource 并为每个顶点添加颜色:

let colors = getRandomColors(vertices.count)
let colorData = NSData(bytes: colors , length: MemoryLayout<SCNVector3>.stride * colors.count)
let colorSource = SCNGeometrySource(data: colorData as Data, semantic: .color, vectorCount: colors.count, usesFloatComponents: true, componentsPerVector: 3, bytesPerComponent: MemoryLayout<Float>.size, dataOffset: 0, dataStride: MemoryLayout<SCNVector3>.stride)
let voxelGeometry = SCNGeometry(sources: [vertexSource, normalSource, colorSource ], elements: [indexElement])


//random colors function
func getRandomColors(count: Int) -> [SCNVector3] {
    var colors: [SCNVector3] = []
    for _ in 0..<count {
        let red = Double.random(in: 0...1)
        let green = Double.random(in: 0...1)
        let blue = Double.random(in: 0...1)
        colors.append(SCNVector3(red, green, blue))
    }
    return colors
}
于 2022-02-21T16:10:02.480 回答
0

这里有一个例子:

func cloneNode(node: SCNNode) -> SCNNode? {
    guard let vertices = node.geometry?.extGetVertices() else {return nil}
    guard let normals = node.geometry?.extGetNormals() else {return nil}
    let indices = (0..<vertices.count).indices.map {Int32($0)}

    // initialise color source
    struct RGBColor {
        let r,g,b : Float
    }

    var colors : [RGBColor] = []
    
    // to have contiguous memory space
    colors.reserveCapacity(vertices.count)

    // convert to color geometry source
    let colorsAsData = NSData(bytes: colors, length: MemoryLayout<RGBColor>.size * colors.count) as Data
    // fill colors arrays
    let colorSource = SCNGeometrySource(data: colorsAsData,
                                        semantic: .color,
                                        vectorCount: colors.count,
                                        usesFloatComponents: true,
                                        componentsPerVector: 3,
                                        bytesPerComponent: MemoryLayout<Float>.size,
                                        dataOffset: MemoryLayout.offset(of: \RGBColor.r)!,
                                        dataStride: MemoryLayout<RGBColor>.stride)

    
    let vertexSource = SCNGeometrySource(vertices: vertices)
    let indexElement = SCNGeometryElement(indices: indices, primitiveType: SCNGeometryPrimitiveType.triangles)
    let normalSource = SCNGeometrySource(normals: normals)
    // Add the colors source in the list
    let voxelGeometry = SCNGeometry(sources: [vertexSource, normalSource, colorSource], elements: [indexElement])
    let voxelMaterial = SCNMaterial()
    voxelMaterial.diffuse.contents = UIColor.white
    voxelGeometry.materials = [voxelMaterial]
    let clonedNode = SCNNode(geometry: voxelGeometry)
    
    return clonedNode
    
}
于 2022-02-21T16:15:50.770 回答