MDLAsset Export to USDC

En the following code, I create and export a triangle to USDC using the MDLAsset export function. The exported USDC file is correct, but I don't see the material component. It seems like the material is not being exported. Did I miss something?

    //new asset
    MDLAsset *asset = [[MDLAsset alloc] initWithBufferAllocator:nil];

    //------------------  vertex descriptor -------------------------------------------------------------------------
    
    MDLVertexAttribute *atrPos = [[MDLVertexAttribute alloc] initWithName:@"position" format:MDLVertexFormatFloat3 offset:0 bufferIndex:0];
    MDLVertexAttribute *atrNor = [[MDLVertexAttribute alloc] initWithName:@"normal" format:MDLVertexFormatFloat3 offset:12 bufferIndex:0];
    MDLVertexAttribute *atrCol = [[MDLVertexAttribute alloc] initWithName:@"color" format:MDLVertexFormatFloat4 offset:24 bufferIndex:0];
    
    //layout (12 + 12 + 16)
    MDLVertexBufferLayout *lay = [[MDLVertexBufferLayout alloc] initWithStride:40];
    
    //add descriptor and layaut
    MDLVertexDescriptor *vdc = [[MDLVertexDescriptor alloc] init];
    vdc.attributes = [NSMutableArray arrayWithObjects:atrPos, atrNor, atrCol, nil];
    vdc.layouts = [NSMutableArray arrayWithObjects:lay, nil];
  
    //--------------  material ---------------------------------------------------------------------------------------------------
    
    MDLScatteringFunction *scatteringFunction = [MDLPhysicallyPlausibleScatteringFunction new];
    MDLMaterial *material = [[MDLMaterial alloc] initWithName:@"matTest" scatteringFunction:scatteringFunction];

    //--------------------- mesh ------------------------------------------------------------------------------------------------
    
    //vertex (position, normal, and color RGBA)
    static const float triangleVertexData[] =
    {
          0.0,  0.5,  0.0,       0.0, 0.0, 1.0,         1.0, 1.0, 1.0, 1.0,
         -0.5, -0.5,  0.0,       0.0, 0.0, 1.0,         1.0, 1.0, 1.0, 1.0,
          0.5, -0.5,  0.0,       0.0, 0.0, 1.0,         1.0, 1.0, 1.0, 1.0
    };
    
    //vertex buffer
    int numVertices = 3;
    int lenBufferForVertices = sizeof(triangleVertexData);
    MTKMeshBuffer *mtkMeshBufferForVertices = (MTKMeshBuffer *)[[asset bufferAllocator] newBuffer:lenBufferForVertices type:MDLMeshBufferTypeVertex];
    NSData *nsData_vertex = [NSData dataWithBytes:triangleVertexData length:lenBufferForVertices];
    [mtkMeshBufferForVertices fillData:nsData_vertex offset:0];
    
    //index
    static uint16_t indices[] = {0,  1,  2};
    
    //index buffer
    int numIndices = 3;
    int lenBufferForIndices = numIndices * sizeof(uint16_t);
    MTKMeshBuffer *mtkMeshBufferForIndices = (MTKMeshBuffer *)[[asset bufferAllocator] newBuffer:lenBufferForIndices type:MDLMeshBufferTypeIndex];
    NSData *nsData_indices = [NSData dataWithBytes:indices length:lenBufferForIndices];
    [mtkMeshBufferForIndices fillData:nsData_indices offset:0];

    //submesh
    MDLSubmesh *submesh = [[MDLSubmesh alloc] initWithName:@"triangle"
                                              indexBuffer:mtkMeshBufferForIndices
                                              indexCount:numIndices
                                              indexType:MDLIndexBitDepthUInt16
                                              geometryType:MDLGeometryTypeTriangles
                                              material:material];
    
    //mesh
    MDLMesh *mdlMesh = [[MDLMesh alloc] initWithVertexBuffer:mtkMeshBufferForVertices
                                        vertexCount:numVertices
                                        descriptor:vdc
                                        submeshes:[NSArray arrayWithObjects:submesh, nil]];
    
    //add mesh object to asset
    [asset addObject:mdlMesh];
    
    //export to usdc
    BOOL res = [asset exportAssetToURL:[NSURL fileURLWithPath:filePath]];

Your code seems mostly correct for creating a simple MDLMesh with a material and exporting it to USDZ. However, there's a small issue in your code: the MDLScatteringFunction should be set on the material's property scatteringFunction rather than creating an MDLPhysicallyPlausibleScatteringFunction directly.

Here's the corrected part of your code:

MDLScatteringFunction *scatteringFunction = [MDLScatteringFunction new];
    
// Set the scattering function on the material
MDLMaterial *material = [[MDLMaterial alloc] initWithName:@"matTest"];
material.scatteringFunction = scatteringFunction;

Additionally, make sure that you have set up the Metal Kit renderer properly if you are intending to visualize this MDLMesh with a material in your app.

Here's a snippet that demonstrates how to set up the renderer and display the mesh:


MTKView *metalView = // Get your MTKView instance

// Create a MetalKit renderer
MDLMeshBufferAllocator *bufferAllocator = [[MTKMeshBufferAllocator alloc] initWithDevice:metalView.device];
MTKMesh *metalKitMesh = [[MTKMesh alloc] initWithMesh:mdlMesh device:metalView.device error:nil];

// Set the mesh on the MTKView's renderer
metalView.delegate = [[MyMTKViewDelegate alloc] initWithMesh:metalKitMesh];


Your code seems mostly correct for creating a simple MDLMesh with a material and exporting it to USDZ. However, there's a small issue in your code: the MDLScatteringFunction should be set on the material's property scatteringFunction rather than creating an MDLPhysicallyPlausibleScatteringFunction directly.

Here's the corrected part of your code:

objective
Copy code
// Create a scattering function
MDLScatteringFunction *scatteringFunction = [MDLScatteringFunction new];
    
// Set the scattering function on the material
MDLMaterial *material = [[MDLMaterial alloc] initWithName:@"matTest"];
material.scatteringFunction = scatteringFunction;
Additionally, make sure that you have set up the Metal Kit renderer properly if you are intending to visualize this MDLMesh with a material in your app.

Here's a snippet that demonstrates how to set up the renderer and display the mesh:

objective
Copy code
// Assuming you have a MTKView named 'metalView' in your storyboard or created programmatically

MTKView *metalView = // Get your MTKView instance

// Create a MetalKit renderer
MDLMeshBufferAllocator *bufferAllocator = [[MTKMeshBufferAllocator alloc] initWithDevice:metalView.device];
MTKMesh *metalKitMesh = [[MTKMesh alloc] initWithMesh:mdlMesh device:metalView.device error:nil];

// Set the mesh on the MTKView's renderer
metalView.delegate = [[MyMTKViewDelegate alloc] initWithMesh:metalKitMesh];
In this snippet, MyMTKViewDelegate should be a class that conforms to the MTKViewDelegate protocol, and you implement the drawInMTKView: method to render the mesh using Metal.

Remember to include the necessary MetalKit and Model I/O frameworks in your project and link against them. If you're still facing issues with material visibility after these changes, you might want to check the Metal and Model I/O documentation for any additional requirements or best practices.





Hello. The correction you suggest generates compilation errors. MDMaterial does not have that type of initialization, and the member scatteringFunction is readonly. But thank you very much for the response.

MDLAsset Export to USDC
 
 
Q