Loading a .obj asset

it seemed to me that the procedure described in chapter 2 for loading an asset required that I know some things about the asset that I might not: namely the vertex descriptor.

On investigation I found that a different asset initialiser MDLAsset(url:) loads the asset and creates a MTLVertexDescriptor.

It seems (though I don’t know why!) that I still need to allocate a mesh buffer, so I then reloaded the asset using the code below, thus avoiding the 10 lines of code in the text needed to construct the vertex descriptor.

It works!! Am I missing something important here?

var mesh: MTKMesh!

func loadMesh() {
    guard let assetURL = Bundle.main.url(forResource: "train",
                                       withExtension: "obj")
    else { fatalError() }
  
    // make an asset to obtain its Model I/O vertex descriptor
    var asset = MDLAsset(url: assetURL)
    // remake it with a buffer allocator and the now known vertex descriptor 
    asset = MDLAsset(url: assetURL,
                     vertexDescriptor: asset.vertexDescriptor!,
                     bufferAllocator: MTKMeshBufferAllocator(device: Renderer.device))
    let mdlMesh = asset.childObjects(of: MDLMesh.self).first as! MDLMesh
    mesh = try MTKMesh(mesh: mdlMesh, device: Renderer.device)
}

Certainly you can do that.

However, when rendering, if you are dependent upon a certain format of vertex descriptor, then you should make sure that the model loads in that format.

In chapter 15, for example, the VertexIn structure is defined:

struct VertexIn {
  float4 position [[attribute(Position)]];
  float3 normal [[attribute(Normal)]];
  float2 uv [[attribute(UV)]];
  float3 color [[attribute(Color)]];
  float3 tangent [[attribute(Tangent)]];
  float3 bitangent [[attribute(Bitangent)]];
};

The vertex shader is defined:

vertex VertexOut vertex_main(
  const VertexIn in [[stage_in]],
  constant Uniforms &uniforms [[buffer(UniformsBuffer)]])

The stage_in attribute expects that the buffer layouts are defined in the pipeline’s vertex descriptor. If you load the model with its built-in vertex descriptor, it will be missing some of these attributes, and the vertex shader won’t be able to run.

Thank you. That’s good to know.
It is curious that I need to instantiate twice to set up the buffer.

Warren has written a great article that explains the mesh allocator:

Thank you Caroline.
As always, the most helpful advice.

1 Like