Corona Renderer for Blender 3.0 alpha: Hair Export problem

Hi there. As you know guys, I’m working on porting and re-coding Corona renderer exporter for Blender 3.x. (Here you can see: Corona Renderer). The problem is aimed on exporting ParticlesSytsem, exactly Hair particles.

def cgeo_write_mesh(me, vertfw, normfw, uvsfw, trisfw, globalNormals,
    combined, mtl_dict, mtl_rev_dict, obmaterial_names,
    uvlayer_buff, layers, ob, depsgraph):
    global __MATINDEX__, lock

    pack = struct.pack
    #Export UVs
    facecol = len(me.vertex_colors) > 0 and ob.corona.export_vcol
    faceuv = len(me.uv_layers) > 0 and not facecol
    # debug('Color or uv', facecol, faceuv)
    if facecol:
        vertex_color = me.vertex_colors.active.data[:]
    if faceuv:
        uv_texture = me.uv_layers.active.data[:]
        #uv_layer = me.uv_layers.active.data[:]

    me_verts = me.vertices[:]

    # Make our own list so it can be sorted to reduce context switching
    face_index_pairs = [(face, index) for index, face in enumerate(me.polygons)]

    if not (len(face_index_pairs) + len(me.vertices)):  # Make sure there is somthing to write

        # clean up
        bpy.data.meshes.remove(me)

        return  # dont bother with this mesh.

    #Default to exporting normals for Corona, so test for face_index_pairs only
    #if face_index_pairs:
    me.calc_normals()

    materials = me.materials[:]
    material_names = [m.name if m else None for m in materials]

    # avoid bad index errors
    if not materials:
        materials = [None]
        material_names = [name_compat(None)]

    # Sort by Material, then images
    # so we dont over context switch in the obj file.
    if facecol:
        face_index_pairs.sort(key=lambda a: a[0].use_smooth)
    elif faceuv:
        face_index_pairs.sort(key=lambda a: (a[0].material_index, a[0].use_smooth))
    elif len(materials) > 1:
        face_index_pairs.sort(key=lambda a: (a[0].material_index, a[0].use_smooth))
    else:
        # no materials
        face_index_pairs.sort(key=lambda a: a[0].use_smooth)

    # Set the default mat to no material and no image.
    contextMat = 0, 0  # Can never be this, so we will label a new material the first chance we get.
    contextSmooth = None  # Will either be true or false,  set bad to force initialization switch.


    with lock:
        totno = combined["totno"]
        totverts = combined["totverts"]
        totuvco = combined["totuvco"]
        # NORMAL, Smooth/Non smoothed.
        for f, f_index in face_index_pairs:
            if f.use_smooth:
                for v_idx in f.vertices:
                    v = me_verts[v_idx]
                    noKey = veckey3d(v.normal)
                    if noKey not in globalNormals:
                        globalNormals[noKey] = totno
                        totno += 1
                        #Write vertex normals
                        normfw(pack('<fff', noKey[0], noKey[1], noKey[2]))

            else:
                # Hard, 1 normal from the face.
                noKey = veckey3d(f.normal)
                if noKey not in globalNormals:
                    globalNormals[noKey] = totno
                    totno += 1
                    normfw(pack('<fff', noKey[0], noKey[1], noKey[2]))

        # Write counts
        combined["combinedverts"] += len(me_verts)
        combined["combinednormals"] += totno-1
        # combineduvs += 1 if faceuv else 0
        combined["combinedtris"] += len(face_index_pairs)

        totno = 1

        # Write verts
        for v in me_verts:
            vertfw(pack('<fff', v.co[0], v.co[1], v.co[2]))

        # UV
        uv_unique_count = 0
        if faceuv or facecol:
            # debug('uv layers', len( me.uv_layers))
            # in case removing some of these dont get defined.
            uv = uvkey = uv_dict = f_index = uv_index = uv_ls = uv_k = None

            if faceuv:
                uv_layer_face_maps = [None] * len(me.uv_layers)
                for uvlayer in me.uv_layers:
                    layers.append(uvlayer.name)
            else:
                uv_layer_face_maps = [None]
                layers.append('facecol')


            layercount = 0
            for uvlayer in layers:
                debug("Starting uv layer", layercount, uvlayer)
                if faceuv:
                    uvlayerdata = me.uv_layers[uvlayer].data
                try:
                    bytesbuf = uvlayer_buff[uvlayer]['bytesbuf']
                    uv_dict = uvlayer_buff[uvlayer]['uv_dict']
                    uv_counter = uvlayer_buff[uvlayer]['uv_counter']
                except:
                    uvlayer_buff[uvlayer] = {}
                    bytesbuf = uvlayer_buff[uvlayer]['bytesbuf'] = io.BytesIO()
                    uv_counter = uvlayer_buff[uvlayer]['uv_counter'] = 0
                    uv_dict = uvlayer_buff[uvlayer]['uv_dict'] = {}
                # uv_dict = {}  # could use a set() here
                uv_layer_face_maps[layercount] = uv_face_mapping = [None] * len(face_index_pairs)
                # bytesbuf = io.BytesIO()
                for f, f_index in face_index_pairs:
                    uv_ls = uv_face_mapping[f_index] = []
                    for uv_index, l_index in enumerate(f.loop_indices):
                        if faceuv:
                            uv = uvlayerdata[l_index].uv
                            uvkey = uv[0], uv[1]
                        else:
                            uv = vertex_color[l_index].color
                            uvkey = uv[0], uv[1], uv[2]

                        try:
                            uv_k = uv_dict[uvkey]
                        except:
                            uv_k = uv_dict[uvkey] = len(uv_dict)
                            uv_counter += 1
                            if faceuv:
                                bytesbuf.write(pack('<fff', uv[0], uv[1], 0))
                            else:
                                bytesbuf.write(pack('<fff', uv[0], uv[1], uv[2]))
                        # uv_k = uv_counter
                        # uv_counter += 1

                        uv_ls.append(uv_k)

                uvlayer_buff[uvlayer]['uv_counter'] = uv_counter
                # debug("primary uv ", uv_counter)
                layercount += 1

            del uv, uvkey, uv_dict, f_index, uv_index
            # Only need uv_unique_count and uv_face_mapping


        else:
            f_image = None
            uv_unique_count = 0
            # uvsfw(pack('<I', 1))
            # uvsfw(pack('<fff', 0, 0, 0))

        if facecol:
            f_image = None

        for f, f_index in face_index_pairs:
            f_smooth = f.use_smooth
            f_mat = min(f.material_index, len(materials) - 1)

            if faceuv:
                tface = me.uv_layers[f_index] 
                #print('Texture face', type(tface), dir(tface)) 
                f_image = tface.image

            # MAKE KEY
            if faceuv and f_image:  # Object is always true.
                key = material_names[f_mat], f_image.name
            else:
                key = material_names[f_mat], None  # No image, use None instead.

            matid = 0

            mat_data = mtl_dict.get(key)
            if not mat_data:

                # First add to global dict so we can export to mtl
                # Then write mtl

                # Make a new names from the mat and image name,
                # converting any spaces to underscores with name_compat.

                # If none image dont bother adding it to the name
                # Try to avoid as much as possible adding texname (or other things)
                # to the mtl name (see [#32102])...
                mtl_name = key[0] #"%s" % name_compat(key[0])
                mtl_id = __MATINDEX__
                __MATINDEX__ += 1
                mat_data = mtl_dict[key] = mtl_name, materials[f_mat], f_image, mtl_id
                mtl_rev_dict[mtl_name] = key

            try:
                matid = obmaterial_names.index(mat_data[0])
            except ValueError as e:
                if depsgraph.corona.material_override:
                    matid = 0
                else:
                    return 'Object "%s" is missing a material' % ob.name

            f_v = [(vi, me_verts[v_idx]) for vi, v_idx in enumerate(f.vertices)]

            # Write faces
            if faceuv or facecol:
                ccvx = []
                ccvt = []
                ccvn = []
                # Need to index faces from 0, not from 1
                # So subtract 1 from each value before writing
                if f_smooth:  # Smoothed, use vertex normals
                    for vi, v in f_v:
                        ccvx.append(v.index + totverts - 1)
                        # ccvt.append(totuvco + uv_face_mapping[f_index][vi] - 1)
                        ccvn.append(globalNormals[veckey3d(v.normal)] - 1)

                else:  # No smoothing, face normals
                    no = globalNormals[veckey3d(f.normal)]
                    for vi, v in f_v:
                        ccvx.append(v.index + totverts - 1)
                        # ccvt.append(totuvco + uv_face_mapping[f_index][vi] - 1)
                        ccvn.append(no - 1)

                for uv_face_mapping in uv_layer_face_maps:
                    for vi, v in f_v:
                        ccvt.append(uv_face_mapping[f_index][vi])
                # Tri
                # Vertex Segment Count - 1
                trisfw(pack('<I', 0))
                # Vertex Indexes
                trisfw(pack('<III', ccvx[0], ccvx[1], ccvx[2]))
                # Normal Segment Count - 1
                trisfw(pack('<I', 0))
                trisfw(pack('<III', ccvn[0], ccvn[1], ccvn[2]))
                # Map Coordinates Indicies
                # for mapchannel in range(0, combineduvs):
                #     trisfw(pack('<III', ccvt[0], ccvt[1], ccvt[2]))
                for vt in ccvt:
                    trisfw(pack('<I', vt))
                # Material ID
                trisfw(pack('<H', matid))
                # Edge visibility
                trisfw(pack('<c', b'\x07'))

            else:
                ccvx = []
                ccvn = []
                # No UV's
                if f_smooth:  # Smoothed, use vertex normals
                    for vi, v in f_v:
                        ccvx.append(v.index + totverts - 1)
                        ccvn.append(globalNormals[veckey3d(v.normal)] - 1)
                else:  # No smoothing, face normals
                    no = globalNormals[veckey3d(f.normal)]
                    for vi, v in f_v:
                        ccvx.append(v.index + totverts - 1)
                        ccvn.append(no - 1)
                # Tri
                # Vertex Segment Count - 1
                trisfw(pack('<I', 0))
                # Vertex Indexes
                trisfw(pack('<III', ccvx[0], ccvx[1], ccvx[2]))
                # Normal Segment Count - 1
                trisfw(pack('<I', 0))
                trisfw(pack('<III', ccvn[0], ccvn[1], ccvn[2]))
                # Map Coordinates Indicies hard coded 1 map channels
                trisfw(pack('<III', 0, 0, 0))
                # Material ID
                trisfw(pack('<H', matid))
                # Edge visibility
                trisfw(pack('<c', b'\x07'))

        # Make the indices global rather then per mesh
        totverts += len(me_verts)
        if faceuv:
            totuvco += uv_unique_count

        # clean up
        bpy.data.meshes.remove(me)

        combined["totno"] = totno
        combined["totverts"] = totverts
        combined["totuvco"] = uv_unique_count
        combined["faceuv"] = faceuv
        combined["facecol"] = facecol

In this line I’ve got the problem:

            if faceuv:
                tface = me.uv_layers[f_index] 
                #print('Texture face', type(tface), dir(tface)) 
                f_image = tface.image

It gives me:
AttributeError: MeshUVLoops has no attribute ‘image’

1 Like