当前位置 : 主页 > 手机开发 > 其它 >

swift – ModelIO框架不起作用

来源:互联网 收集:自由互联 发布时间:2021-06-11
我正在尝试导入3D模型文件并使用MetalIO使用ModelIO和MetalKit(在OS X 10.11上)渲染它们,但我从这些框架(特别是ModelIO)看到的行为并不像预期的那样. 我可以导入.obj文件并将它们转换为MetalKit网
我正在尝试导入3D模型文件并使用MetalIO使用ModelIO和MetalKit(在OS X 10.11上)渲染它们,但我从这些框架(特别是ModelIO)看到的行为并不像预期的那样.

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

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

我尝试导入其他3D文件格式(所有正式支持的框架),但除了.obj之外的任何格式都会在调用MDLAsset的init()时导致未捕获的NSException.

我正在使用Xcode 7.2并以OS X 10.11为目标.

我也遇到过类似的问题,虽然我是Metal的新秀,但我想出了一些问题.

我试图进口Melita茶壶,但我也有一个“爆炸”的面孔,而不是标志性的茶叶冲泡设备.在阅读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然后,我得到了……半个梅丽塔锅?

Half-baked implementation... get it!?

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
}

(XCode 8 Beta 6中的Swift 3.0)

如果我设法渲染整个内容,我会更新我的帖子.

编辑:立即工作

Holy shi---

Whelp,这个bug就在我的最后,我在索引计数中错了:

//// 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)

问题是让indexSize = submesh.indexType == .uInt32? 4:2,在我做右边32:16之前,但.length属性以字节而不是位,所以很笨.

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

网友评论