【发布时间】:2017-04-05 14:36:03
【问题描述】:
我写了一个方法来解析一个包含顶点数据的数组。该方法的目标是根据该数据生成一个新的唯一顶点数组和一个新索引。
这是我用来在数组中存储顶点的结构。
struct Vertex: Hashable {
var x, y, z,
nx, ny, nz,
s, t: Float
var hashValue: Int {
return "\(self.x),\(self.y),\(self.z),\(self.nx),\(self.ny),\(self.nz),\(self.s),\(self.t),".hashValue
}
static func ==(lhs: Vertex, rhs: Vertex) -> Bool {
return lhs.hashValue == rhs.hashValue
}
}
这是我用来创建唯一顶点数组和新索引的方法。该方法的第一个参数采用一个数组,其中顶点数据已经按原始索引排序。
func makeVertexIndex(_ array: [Float]) -> ([Vertex], [Int]) {
var counter = 0
var indexCounter = 0
var holder = [Float]()
var vertices = [Vertex]()
var index = [Int]()
for i in array {
counter += 1
if counter == 8 {
counter = 0
holder.append(i)
let vertex = Vertex(x: holder[0], y: holder[1], z: holder[2],
nx: holder[3], ny: holder[4], nz: holder[5],
s: holder[6], t: holder[7])
if vertices.contains(vertex) {
guard let match = vertices.index(of: vertex) else { continue }
index.append(match)
} else {
vertices.append(vertex)
index.append(indexCounter)
indexCounter += 1
}
holder.removeAll()
} else {
holder.append(i)
}
}
return (vertices, index)
}
我能够成功解析三角形计数较低的网格,但是当我尝试在三角形计数较高的网格上运行时,它需要一个多小时才能运行。
我对编码很陌生,Swift 是我的第一语言,但我怀疑完成这项任务不应该花这么长时间,而且我可能只是写我的方法效率很低,或者也许有一种完全不同的方法我可以接近这个问题。
无论如何,如果我能得到任何帮助,我将不胜感激。感谢阅读。
更新 1: 我重新编写了创建顶点数组的方法,然后将其更改为一组以使值唯一并返回到数组,然后通过 vertexArray 循环运行它,以查找唯一顶点数组中的匹配项。此版本的方法将处理时间从我的测试网格上的 21 秒缩短到大约 12 秒。
func makeVertexIndex(_ array: [Float]) -> ([Vertex], [Int]) {
var counter = 0
var holder = [Float]()
var vertexArray = [Vertex]()
var vertices = [Vertex]()
var index = [Int]()
for i in array {
counter += 1
if counter == 8 {
counter = 0
holder.append(i)
let vertex = Vertex(x: holder[0], y: holder[1], z: holder[2],
nx: holder[3], ny: holder[4], nz: holder[5],
s: holder[6], t: holder[7])
vertexArray.append(vertex)
holder.removeAll()
} else {
holder.append(i)
}
}
let vertexSet = Set(vertexArray)
vertices = Array(vertexSet)
for v in vertexArray {
guard let match = vertices.index(of: v) else { continue }
index.append(match)
}
return (vertices, index)
}
更新 2:
这是我在实施一些推荐的解决方案后更新的结构和方法。
结构:
struct Vertex: Hashable {
var x, y, z,
nx, ny, nz,
s, t: Float
var hashValue: Int {
return "\(self.x),\(self.y),\(self.z),\(self.nx),\(self.ny),\(self.nz),\(self.s),\(self.t)".hashValue
}
static func ==(lhs: Vertex, rhs: Vertex) -> Bool {
return (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z) && (lhs.nx == rhs.nx) &&
(lhs.ny == rhs.ny) && (lhs.nz == rhs.nz) && (lhs.s == rhs.s) && (lhs.t == rhs.t)
}
}
方法:
func makeVertexIndex(_ array: [Float]) -> ([Vertex], [Int]) {
var vertexArray = [Vertex]()
vertexArray.reserveCapacity(array.count / 8)
var vertices = [Vertex]()
var index = [Int]()
// Creating an array of Vertex from an array containing
// position/normal/texcoord in correct order.
for i in stride(from: 0, to: array.count, by: 8) {
let vertex = Vertex(x: array[i], y: array[i + 1], z: array[i + 2],
nx: array[i + 3], ny: array[i + 4], nz: array[i + 5],
s: array[i + 6], t: array[i + 7])
vertexArray.append(vertex)
}
// Making the Vertex array unique by converting to set and back to array.
let vertexSet = Set(vertexArray)
vertices = Array(vertexSet)
// Making new index by finding the matching vertex in the
// unique vertex array and adding that array index to the new index
for v in vertexArray {
guard let match = vertices.index(of: v) else { continue }
index.append(match)
}
return (vertices, index)
}
在尝试了推荐解决方案的各个部分后,该方法能够在 13 分钟内处理一个包含 70K 三角形的模型,而之前需要一个半小时以上。
所以这是一个巨大的改进,感谢迄今为止的所有解决方案,将保持开放状态可能一两天,看看是否有其他建议。
【问题讨论】:
标签: arrays swift scenekit metal