I'm trying to get data from a Metal Mesh Vertex array to a Swift struct.
I know that Swift structs and C struct may not be equal. I also know I could do this with a c briding header but that introduces some other issues.
How do I do this with explicit serialization from the metal data to an array of Swift structs?
It would be helpful to also see the deserialization of the same data.
import PlaygroundSupport
import MetalKit
import simd
struct Vertex {
var position: vector_float3
var normal: vector_float3
var texture: vector_float2
init() {
position = float3(repeating: 0.0)
normal = float3(repeating: 0.0)
texture = float2(repeating: 0.0)
}
init(pos: vector_float3, nor: vector_float3, text: vector_float2) {
position = pos
normal = nor
texture = text
}
}
guard let device = MTLCreateSystemDefaultDevice() else {
fatalError("GPU is not supported")
}
let allocator = MTKMeshBufferAllocator(device: device)
let mesh = MDLMesh.init(boxWithExtent: [0.75, 0.75, 0.75], segments: [1, 1, 1], inwardNormals: false, geometryType: .quads, allocator: allocator)
// Details about the vertex
print("Details about the vertex")
print( mesh.vertexDescriptor )
// Look at the vertex detail
// This doesn't work because, I think, of the way Swift pads the memory in structs.
print("Number of vertex: ", mesh.vertexCount)
let buff = mesh.vertexBuffers[0]
// This gives the wrong result but is nice code
let count = buff.length / MemoryLayout.stride
print("Wrong result!")
print("Space in buffer for vertex: ", count)
let wrongResult = buff.map().bytes.bindMemory(to: Vertex.self, capacity: count)
for i in 0 ..< count {
print( "Vertex: ", i, wrongResult[i])
}
// This gives the correct result but is really ugly code
print("Correct result!")
let tempResult = buff.map().bytes.bindMemory(to: Float.self, capacity: mesh.vertexCount*8)
var result = Array(repeating: Vertex(), count: mesh.vertexCount)
for i in 0 ..< mesh.vertexCount {
result[i].position.x = tempResult[i*8 + 0]
result[i].position.y = tempResult[i*8 + 1]
result[i].position.z = tempResult[i*8 + 2]
result[i].normal.x = tempResult[i*8 + 3]
result[i].normal.y = tempResult[i*8 + 4]
result[i].normal.z = tempResult[i*8 + 5]
result[i].texture.x = tempResult[i*8 + 6]
result[i].texture.y = tempResult[i*8 + 7]
}
for i in 0 ..< mesh.vertexCount {
print( "Vertex: ", i, result[i])
}