ModelIO 框架不工作

ModelIO Framework Not Working

我正在尝试导入 3D 模型文件并使用 ModelIOMetalKit(在 OS X 10.11 上)用 Metal 渲染它们,但是我的行为我从这些框架(特别是 ModelIO)中看到的并不像预期的那样。

我可以导入 .obj 文件并将它们转换为 MetalKit 网格而不会导致任何错误,但是网格(至少在渲染下)似乎只是三角形的忠实粉丝从一个点。下面截图中的模型应该是"Suzanne"猴头的细分版:

经检查,导入文件中 MDLSubmesh 的顶点索引没有任何意义。连续的索引集继续引用索引 0 处的顶点,有时在同一组索引中多次引用,这可以解释渲染过程中的外观。我已确认此 .obj 文件可以很好地导入其他应用程序。

我已经尝试导入其他 3D 文件格式(框架正式支持所有格式),但是 .obj 以外的任何格式都会导致 NSException 调用 MDLAsset' s init().

我正在使用 Xcode 7.2,目标是 OS X 10.11。

我也遇到过类似的问题,虽然我是 Metal 的菜鸟,但我想通了一些事情。

我试图导入 Melita 茶壶,但我也有一张 "explosion" 的脸,而不是标志性的泡茶设备。在阅读了 MDLVertexBufferLayout 的文档后,我找到了解决方案,其中写道:

A mesh may store vertex data in either a structure of arrays model, where data for each vertex attribute (such as vertex position or surface normal) lies in a separate vertex buffer, or in an array of structures model, where multiple vertex attributes share the same buffer.

  • In a structure of arrays, the mesh’s vertexBuffers array contains several MDLMeshBuffer objects, and the mesh’s vertexDescriptor object contains a separate MDLVertexBufferLayout object for each buffer.

  • In an array of structures, the mesh contains a single vertex buffer, and its descriptor contains a single vertex buffer layout object. To identify which bytes in the buffer refer to which vertices and vertex attributes, use the layout’s stride together with the format and offset properties of the descriptor’s vertex attributes.

通过查看 MDLVertexDescriptor 默认实现的 .layouts.attributes 属性,他们为每个属性类型创建一个缓冲区(如上面的引述,第一种情况),我想使用混合模式。

我用自己的数组手动设置了 .layouts.attributes,然后,瞧,我得到了……半个 melita 罐?

class func setup(meshWithDevice device: MTLDevice) -> MTKMesh
{
    // Allocator
    let allocator = MTKMeshBufferAllocator(device: device)

    // Vertex Descriptor, tells the MDLAsset how to layout the buffers
    let vertexDescriptor = MDLVertexDescriptor()

    // Vertex Buffer Layout, tells how many buffers will be used, and the stride of its structs
    // (the init(stide: Int) crashes in the Beta)
    let vertexLayout = MDLVertexBufferLayout()
    vertexLayout.stride = MemoryLayout<Vertex>.size

    // Apply the Layouts
    vertexDescriptor.layouts = [vertexLayout]

    // Apply the attributes, in my case, position and normal (float4 x2)
    vertexDescriptor.attributes =
    [
        MDLVertexAttribute(name: MDLVertexAttributePosition, format: MDLVertexFormat.float4, offset: 0, bufferIndex: 0),
        MDLVertexAttribute(name: MDLVertexAttributeNormal, format: MDLVertexFormat.float4, offset: MemoryLayout<float4>.size, bufferIndex: 0)
    ]

    var error : NSError? = nil

    // Load the teapot
    let asset = MDLAsset(url: Bundle.main.url(forResource: "teapot", withExtension: "obj")!, vertexDescriptor: vertexDescriptor, bufferAllocator: allocator, preserveTopology: true, error: &error)

    if let error = error
    {
        print(error)
    }

    // Obtain the teapot Mesh
    let teapotModel = asset.object(at: 0) as! MDLMesh

    // Convert into MetalKit Mesh, insted of ModelIO
    let teapot = try! MTKMesh(mesh: teapotModel, device: device)

    return teapot
}

(Swift 3.0 in XCode 8 Beta 6)

如果我设法渲染整个东西,我会更新我的 post。

编辑:现在可用

Whelp,错误在我这边,我的索引计数错了:

//// Buffers
renderPass.setVertexBuffer(mesh.vertexBuffers[0].buffer, offset: 0, at: 0)
renderPass.setVertexBuffer(uniformBuffer, at: 1)

let submesh   = mesh.submeshes[0]
let indexSize = submesh.indexType == .uInt32 ? 4 : 2

//// Draw Indices
renderPass.drawIndexedPrimitives(submesh.primitiveType,
                                 indexCount:  submesh.indexBuffer.length / indexSize,
                                 indexType:   submesh.indexType,
                                 indexBuffer: submesh.indexBuffer.buffer,
                                 indexBufferOffset: 0)

问题出在 let indexSize = submesh.indexType == .uInt32 ? 4 : 2,之前我在右侧执行 32 : 16,但是 .length 属性 以字节而不是位的形式出现,太愚蠢了。

无论如何,我设法用 Metal 加载了一个 Obj 文件,所以问题要么是:我上面提到的每个属性的单独缓冲问题,要么是您的代码中的一个完全不同的问题。