cycles adding texture to face via python / import script I am writing an importer for a custom file format. So far I have created my object:

 me = bpy.data.meshes.new(ModelName)
 ob = bpy.data.objects.new(ModelName,me)
 scn = bpy.context.scene
 scn.objects.link(ob)
 scn.objects.active = ob
 ob.select = True


And then I create the vertex, face, and materials:

    myvertex = []
    myfaces = []
    MyTextureNames = []

    for textures in range(0, MtlCount):
        StrLen = struct.unpack('i',fdata.read(4))[0]
        mtlname = fdata.read(StrLen).decode()
        MyTextureNames.append(mtlname)

        new_mat=bpy.data.materials.new(mtlname)
        new_mat.use_nodes = True

        bpy.ops.object.material_slot_add()
        context.object.active_material = new_mat

    for points in range(0, VertexCount):
        # read three coordinates
        p1 = struct.unpack('f',fdata.read(4))[0]
        p3 = struct.unpack('f',fdata.read(4))[0]
        p2 = struct.unpack('f',fdata.read(4))[0]

        #print ("x: " + str(p1) + " y: " + str(p2) + " z: " + str(p3))

        myvertex.append((p1,p2,p3))

    for points in range(0,FaceCount):
        # read three coordinates
        p1 = struct.unpack('i',fdata.read(4))[0]
        p3 = struct.unpack('i',fdata.read(4))[0]
        p2 = struct.unpack('i',fdata.read(4))[0]

        #print ("x: " + str(p1) + " y: " + str(p2) + " z: " + str(p3))

        myfaces.append((p1,p2,p3))


    # Add verts and faces with the following line
    me.from_pydata(myvertex, [], myfaces)

    me.update()


When I run this script I get my object, with vertices and faces intact, and when I look in the materials all my materials are listed and already set to use nodes and Diffuse BSDF. Great.

My question is: How do I now assign the material to the correct faces? (I do have an array containing the information mapping the face to the material, I just do not know how to tell blender "For this face use this material". 

I also am unclear as to how I set the UV coordinates which I also have stashed in an array for access. 

And not to over complicate this "question" but other things I am trying to figure out how to do are reading the image information which is packed in my file, getting it into memory and then telling blender to use that memory location for the image information to use for the diffuse.
For materials, this is simple: each polygon (face) as a "material_index" property which corresponds to the object's "material_slots" property.

For the UVs, that can be more complex. Here is how Blender stores all that:

UV layers are in "obj.data.uv_layers". 

But to create uv layers, you need to go to "uv_textures" and add one via "obj.data.uv_textures.new( 'name' )".

You can now access to "obj.data.uv_layers['name']" and to "obj.data.uv_layers['name'].data". This last data is an array that contains information for each vertex in the mean of uv layer vertex (not 3D vertex, because a 3D vertex can be represented many times in the UV map).

What is unifying all these is the concept of 'loop'. 'loop' is a per face information.

You have a 'main loop' which is into "obj.data.loops" and contains the 3D per face information for each vertex. Say we take "loop_info = obj.data.loops[0]", it contains "loop_info.vertex_index" (the index to find the 3D vertex in "obj.data.vertices"), and other information like vertex "normal".

Now an uv layers is also a per face information (a loop). "obj.data.uv_layers['name'].data" is a loop (organized with the same index order as the main loop).

If we take "uv_info = obj.data.uv_layers['name'].data[0]", "uv_info.uv" is the 2D coordinate in this UV map.

Last thing you need to know (I think), the correspondence between a polygon and the loops: this is stored in the polygon itself. If you get "polygon = obj.data.polygons[0]", then you can get the loop projection of its vertices in "polygon.loop_indices". 

For instance, "obj.data.uv_layers['name'].data[polygon.loop_indices[0]]" is valid.

I think the other aspects are relative to your file format.

Concerning images. You can start with "img = bpy.data.images.new(name, width, height)". Color information is in "img.pixels" organized from bottom left to upper right (UV like). "img.pixels" is a 4*width*height float array containing R,G,B,A values (black is 0, white is 1).

Following the comments... I cannot imagine what your file format is.

So I can only, give some advices and a little help...

Warning this code is untested (as I have no data), so surely, there will be some bugs here. But I hope that will help for the principles of how it works:

Materials part: just for the comment at the end

modelName = "xxxx"
mesh = bpy.data.meshes.new( modelName )
obj = bpy.data.objects.new( modelName, mesh )

for textures in range(0, MtlCount):
    StrLen = struct.unpack('i',fdata.read(4))[0]

    mtlname = fdata.read(StrLen).decode()

    MyTextureNames.append( mtlname )

    new_mat = bpy.data.materials.new( mtlname )
    new_mat.use_nodes = True

    #I do prefer using .data instead of .ops because ops often need a context and/or a mode
    obj.data.materials.append( new_mat )


Creating the mesh, with some guess about unpack (as I've never used it).
But that should work and be faster than a for loop.

def ToTuples( aList, tupleSize ):
    return [tuple(aList[x:x+tupleSize]) for x in range(0, len(aList), tupleSize)]

#Shorter... probably much faster than loops
myVertices = ToTuples( struct.unpack( 'f', fdata.read( 4 * 3 * VertexCount ) ), 3 )
myFaces = ToTuples( struct.unpack( 'i', fdata.read( 4 * 3 * FaceCount ) ), 3 )

mesh.from_pydata( myVertices, [], myfaces )
mesh.update()


Face material attribution: 2 examples

#If face/material is describe as face index to material index in your file
for fIndex, mIndex in ToTuples( struct.unpack( 'i', fdata.read( 4 * 2 * FaceCount ) ), 2 ):
    mesh.polygons[fIndex].materialIndex = mIndex

#If face/material is describe just as a sequence of material index in the same order as the faces
for fIndex, mIndex in enumerate( struct.unpack( 'i', fdata.read( 4 * FaceCount ) ) ):
    mesh.polygons[fIndex].materialIndex = mIndex


UV map:

#Assuming you have one UV map and all polygons are tris
#=&gt; you have 3 * FaceCount uv definitions in Blender, so this is the size of the 'loop(s)'
#But I do not know how your file is...
#So, I guess it is defined as the following, assuming the vertex order of the face is the same as above:
# faceIndex, vertex1co, vertex2co, vertex3co
# All these is 7 * 4 bytes * FaceCount

uvTex = mesh.uv_textures.new()
uvMap = mesh.uv_layers[uvTex.name]

for fi, v1x, v1y, v2x, v2y, v3x, v3y in ToTuples( struct.unpack( 'i f f f f f f', fdata.read( 7 * 4 * FaceCount ) ), 7 ):
    #Find the polygon
    polygon = mesh.polygons[fi]
    #In the uv map, get the corresponding vertex using the polygon loop index (for first, second and third) and set its uv coordinates
    uvMap.data[polygon.loop_indices[0]].uv = (v1x, v1y)
    uvMap.data[polygon.loop_indices[1]].uv = (v2x, v2y)
    uvMap.data[polygon.loop_indices[2]].uv = (v3x, v3y)


I don't think this is the place to do more... and doing more needs to know the specifications of your file format...

Hope it helps!