pythongltftrimesh

How do I apply a material to a .glb/.gltf mesh?


I have a model in .glb format with nothing edit(but a mesh) in the scene. How do I apply a material of a glb/gltf mesh using Python? I am using Pygltflib and Trimesh although I can use other libraries.


Solution

  • I can only give a genereal answer, because you did not provide any code, but you would do it like this in principal:

    material = Material() # Create a material
    pbr = PbrMetallicRoughness() # Use PbrMetallicRoughness
    pbr.baseColorFactor = [1.0, 0.0, 0.0, 1.0] # solid red
    material.pbrMetallicRoughness = pbr
    

    after that supply the material to your primitive like that

    primitive.material = 0
    

    and do not forget to add it to the gltf. As always if you use more materials, the order will be important of course:

    gltf.materials.append(material)
    

    For completeness here is how to add a double sided red metallicRoughnessMaterial with "MASK" alphaMode to the triangle example and save it as .glb:

    from pygltflib import *
    
    # create gltf objects for a scene with a primitive triangle with indexed geometry
    gltf = GLTF2()
    scene = Scene()
    mesh = Mesh()
    material = Material()
    primitive = Primitive()
    node = Node()
    buffer = Buffer()
    bufferView1 = BufferView()
    bufferView2 = BufferView()
    accessor1 = Accessor()
    accessor2 = Accessor()
    
    # add data
    buffer.uri = "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA="
    buffer.byteLength = 44
    
    bufferView1.buffer = 0
    bufferView1.byteOffset = 0
    bufferView1.byteLength = 6
    bufferView1.target = ELEMENT_ARRAY_BUFFER
    
    bufferView2.buffer = 0
    bufferView2.byteOffset = 8
    bufferView2.byteLength = 36
    bufferView2.target = ARRAY_BUFFER
    
    accessor1.bufferView = 0
    accessor1.byteOffset = 0
    accessor1.componentType = UNSIGNED_SHORT
    accessor1.count = 3
    accessor1.type = SCALAR
    accessor1.max = [2]
    accessor1.min = [0]
    
    accessor2.bufferView = 1
    accessor2.byteOffset = 0
    accessor2.componentType = FLOAT
    accessor2.count = 3
    accessor2.type = VEC3
    accessor2.max = [1.0, 1.0, 0.0]
    accessor2.min = [0.0, 0.0, 0.0]
    
    pbr = PbrMetallicRoughness() # Use PbrMetallicRoughness
    pbr.baseColorFactor = [1.0, 0.0, 0.0, 1.0] # solid red
    material.pbrMetallicRoughness = pbr
    material.doubleSided = True # make material double sided
    material.alphaMode = MASK   # to get around 'MATERIAL_ALPHA_CUTOFF_INVALID_MODE' warning
    
    primitive.attributes.POSITION = 1
    primitive.material = 0
    node.mesh = 0
    scene.nodes = [0]
    
    # assemble into a gltf structure
    gltf.scenes.append(scene)
    gltf.meshes.append(mesh)
    gltf.materials.append(material)
    gltf.meshes[0].primitives.append(primitive)
    gltf.nodes.append(node)
    gltf.buffers.append(buffer)
    gltf.bufferViews.append(bufferView1)
    gltf.bufferViews.append(bufferView2)
    gltf.accessors.append(accessor1)
    gltf.accessors.append(accessor2)
    
    gltf.convert_buffers(BufferFormat.BINARYBLOB) # Convert buffers to allow saving as .glb
    
    # save to a .glb file
    gltf.save("triangle.glb")