Newbie trying to loop through files, process and export as FBX

Hello, can anyone give me some pointers with my script.

I’m kinda new to python and I’m stuck with a script and I don’t know enough to google for the answer, I’m lacking some fundamental understanding I think.

So I’m pretty competent with VBA and have reasonable understanding of C#, but this is the first time I’ve looked at Python. I’ve got a script that takes some models from an old game that are in a serialised binary file. It works great but I’ve been trying to adapt the code so I can just feed it a array of file names to loop through, and dump them out into a folder as fbx’s.

It works kind of… if the models only have 1 object its fine, if the models have multiple objects (like wheels and turrets) it will only export the last object in the file. My understating of this behaviour is that it loops through the file and extracts each object one at a time but the export is happening on every object thus over writing any existing files with the same name.

I think I need to put a loop in somewhere between feeding the file name in and the end of the last object being read. But I just cant figure this out :tired_face:

Any help would be massively appreciated!!

import struct, os
import numpy as np
import bpy, bmesh, mathutils
import logging


folder = "D:\\Projects\\mngpack\\MovieBin"
folder = "D:\\Projects\mngpack\\ObjectBin"
    
SelNameArr = ["ALIENGROUNDPROD.bin_n","ALIENLARGEPROD.bin_n","Apache.bin_n","Barrier.bin_n","windmill.bin_n","windmill_r.bin_n","yacht.bin_n"]


scale_divider = 80.0


#read a string
def read_string_all(file):
    read_done = False
    read_str = ""
    
    while read_done == False:
      v = struct.unpack('B', file.read(1))[0]
      if v == 0:
        read_done = True
      else:
        read_str += chr(v)

    return read_str

#read chars with a given number
def read_string(file, numchrs=1):
    read_str = ""
    for i in range(numchrs):
        v = struct.unpack('B', file.read(1))[0]
        read_str +=chr(v)
    return read_str

#read Triangular faces
def readTris(numTris, TrisHolder):
    for i in range(numTris):
        face = {}
        #44 Bytes in total
        face['p1'], face['p2'], face['p3'], face['p4'] = struct.unpack("HHHH", file.read(8))
        face['u1'], face['v1'] = struct.unpack("ff", file.read(8))
        face['u2'], face['v2'] = struct.unpack("ff", file.read(8))
        face['u3'], face['v3'] = struct.unpack("ff", file.read(8))
        face['para1'] = struct.unpack("L", file.read(4))
        face['para2'] = struct.unpack("f", file.read(4))
        face['para3'] = struct.unpack("L", file.read(4))
        TrisHolder.append(face)

#read Quadrangular faces
def readQuads(numQuads, QuadsHolder):
    for i in range(numQuads):
        face = {}
    
        #52 Bytes in total
        face['p1'], face['p2'], face['p3'], face['p4'] = struct.unpack("HHHH", file.read(8))
        face['u1'], face['v1'] = struct.unpack("ff", file.read(8))
        face['u2'], face['v2'] = struct.unpack("ff", file.read(8))
        face['u3'], face['v3'] = struct.unpack("ff", file.read(8)) 
        face['u4'], face['v4'] = struct.unpack("ff", file.read(8))
    
        face['para1'] = struct.unpack("L", file.read(4))
        face['para2'] = struct.unpack("f", file.read(4))
        face['para3'] = struct.unpack("L", file.read(4))
        QuadsHolder.append(face)





for i in range(len(SelNameArr)):
    print(i)
    
    fileName = SelNameArr[i]
    file = open(folder+"\\"+fileName, 'rb')
    headString = read_string(file, 4)
    print(headString)
    num0, num1 = struct.unpack("LL", file.read(8))
    print(str(num0)+","+str(num1))
    somepath = read_string_all(file)
    print(somepath)
    num2 = struct.unpack("L", file.read(4))[0]
    print("Positions : "+str(num2))
    #num2 is the number of vertices

    verts = []
    verts_attr1 = []
    for i in range(num2):
        x1, x2, x3 = struct.unpack("fff", file.read(12))
        verts.append([x1/scale_divider, x3/scale_divider, x2/scale_divider])#this is right
        attr = struct.unpack("L", file.read(4))[0]
        verts_attr1.append(attr)
    #print(verts)
    #print(verts_attr1)

    num3, num4, num5 = struct.unpack("LLL", file.read(12))
    print(str(num3)+","+str(num4)+","+str(num5))

    points1 = []
    attrs1 = []
    vertsseq = []
    for i in range(num3):
        x1, x2, x3 = struct.unpack("fff", file.read(12))
        points1.append([x1, x2, x3])
        attr1, attr2 = struct.unpack("LL", file.read(8))
        attrs1.append([attr1, attr2])
        vertsseq.append(attr2)
    #print(points1)
    #print(attrs1)
    print(vertsseq)
    numparts = struct.unpack("L", file.read(4))[0]
    print("Parts : "+str(numparts))
    imagetimes = struct.unpack("L", file.read(4))[0]
    #file.read(516)
    file.read(512)

    file.read(120)
    f1, f2, f3 = struct.unpack("LLL",file.read(12))

    facesTri = []
    facesQuad = []
    parts = []
    attrbefore = []
    attrafter = []
    print(f1)
    print(f2)
    print(f3)

    if (f1 == 0) & (f2 == 1) & (f3 == 0):
        mode = 0
        print("mode simple")
        skiptime = struct.unpack("L", file.read(4))[0]
        numQuad1, numQuad2, numTri1, numTri2 = struct.unpack("LLLL", file.read(16))
        for i in range(skiptime):
            attrafter.append(struct.unpack("LLLL", file.read(16)))
        print("Quads : "+str(numQuad1))
        #print(numQuad2)
        print("Tris : "+str(numTri1))
        #print(numTri2)


        readTris(numTri1, facesTri)
        readQuads(numQuad1, facesQuad)

        for i in range(numparts):
            file.read(4)
            tifname = read_string_all(file)
            tiftime = struct.unpack("L", file.read(4))[0]
            for j in range(tiftime):
                file.read(28)
            #file.read(32)
        
        for i in range(numparts):
            part = {}
        
            part['attr0'] = struct.unpack("L", file.read(4))[0]
            part['partname'] = read_string_all(file)
        
            #96 Bytes in total
            part['indexpart'] = struct.unpack("L", file.read(4))[0]
            # file.read(72)
            #these transinfo have a total length of 72 Bytes
            part['transinfo1'] = struct.unpack("fff",file.read(12))
            part['transinfo2'] = struct.unpack("L",file.read(4))
            part['transinfo3'] = struct.unpack("fff",file.read(12))
            part['transinfo4'] = struct.unpack("L",file.read(4))
            part['transinfo5'] = struct.unpack("fff",file.read(12))
            part['transinfo6'] = struct.unpack("L",file.read(4))
            part['transinfo7'] = struct.unpack("fff",file.read(12))
            part['transinfo8'] = struct.unpack("L",file.read(4))
            part['transinfo9'] = struct.unpack("L",file.read(4))
            part['transinfo10'] = struct.unpack("f",file.read(4))
            #file.read(96)
            part['attr1'], part['attr2'], part['attr3'], part['attr4'] = struct.unpack("LLLL", file.read(16))
            #it is not index of tif file
            #just a name I give it
            part['indextif'] = struct.unpack("L", file.read(4))[0]
        
            part['tifname'] = read_string_all(file)
            part['tifattr1'] = struct.unpack("L", file.read(4))[0]
            if part['tifattr1'] == 1:
                file.read(68*imagetimes + 4)
            if part['tifattr1'] == 0:
                part['tifattr2'] = struct.unpack("L", file.read(4))[0]
                if part['tifattr2'] > 0:
                    for j in range(part['tifattr2']):
                        file.read(72)
        
            #print(part)
            parts.append(part)
        for part in parts:
            attrbefore.append([part['attr1'], part['attr2'], part['attr3'], part['attr4']])


    if (f1 == 0) & (f2 == 0) & (f3 == 0):

        mode = 1
        print("mode complex")
        
        for i in range(numparts):
            part = {}
        
            part['attr0'] = struct.unpack("L", file.read(4))[0]
            part['partname'] = read_string_all(file)
        
            #96 Bytes in total
            part['indexpart'] = struct.unpack("L", file.read(4))[0]
            # file.read(72)
            #these transinfo have a total length of 72 Bytes
            part['transinfo1'] = struct.unpack("fff",file.read(12))
            part['transinfo2'] = struct.unpack("L",file.read(4))
            part['transinfo3'] = struct.unpack("fff",file.read(12))
            part['transinfo4'] = struct.unpack("L",file.read(4))
            part['transinfo5'] = struct.unpack("fff",file.read(12))
            part['transinfo6'] = struct.unpack("L",file.read(4))
            part['transinfo7'] = struct.unpack("fff",file.read(12))
            part['transinfo8'] = struct.unpack("L",file.read(4))
            part['transinfo9'] = struct.unpack("L",file.read(4))
            part['transinfo10'] = struct.unpack("f",file.read(4))
            #file.read(96)
            part['attr1'], part['attr2'], part['attr3'], part['attr4'] = struct.unpack("LLLL", file.read(16))
            #it is not index of tif file
            #just a name I give it
            part['indextif'] = struct.unpack("L", file.read(4))[0]
        
            part['tifname'] = read_string_all(file)
            part['tifattr1'] = struct.unpack("L", file.read(4))[0]
            if part['tifattr1'] == 1:
                file.read(68*imagetimes + 4)
            if part['tifattr1'] == 0:
                part['tifattr2'] = struct.unpack("L", file.read(4))[0]
                if part['tifattr2'] > 0:
                    for j in range(part['tifattr2']):
                        file.read(72)
        
            #print(part)
            parts.append(part)
        file.read(8)
        for i in range(numparts):
            attrbefore.append(struct.unpack("LLLL", file.read(16)))
        
        file.read(12)
        skiptime = struct.unpack("L", file.read(4))[0]
        numQuad1, numQuad2, numTri1, numTri2 = struct.unpack("LLLL", file.read(16))
        for i in range(skiptime):
            attrafter.append(struct.unpack("LLLL", file.read(16)))
        print("Quads : "+str(numQuad1))
        #print(numQuad2)
        print("Tris : "+str(numTri1))
        #print(numTri2)
        
        readTris(numTri1, facesTri)
        readQuads(numQuad1, facesQuad)

    file.close()
    
    if (mode == 1)|(mode == 0):
        offsetZero = np.array([parts[0]['transinfo7'][0], parts[0]['transinfo7'][2], parts[0]['transinfo7'][1]])
        for part in parts:
            object_name = part['partname']
            me = bpy.data.meshes.new(object_name + "Mesh")
            ob = bpy.data.objects.new(object_name, me)

            bm = bmesh.new()
            bm.from_mesh(me)
            uv_layer = bm.loops.layers.uv.new()

            bpy.context.collection.objects.link(ob)
            
            bpy.context.view_layer.objects.active = ob

            offsetpos = np.array([part['transinfo7'][0], part['transinfo7'][2], part['transinfo7'][1]])
            offsetpos = (offsetpos - offsetZero)/scale_divider

            bpy.ops.object.mode_set(mode='EDIT', toggle=False)

            for i in range(attrbefore[part['indexpart']][3]):
                vtx = bm.verts.new(np.array(verts[vertsseq[attrbefore[part['indexpart']][2] + i]]) + offsetpos)
            bm.verts.ensure_lookup_table()

            for i in range(len(facesQuad)):
                if (i >= attrafter[part['indexpart']][0])&(i < (attrafter[part['indexpart']][0]+attrafter[part['indexpart']][1])):
                    try:
                        face = bm.faces.new((bm.verts[facesQuad[i]['p1']], bm.verts[facesQuad[i]['p2']], bm.verts[facesQuad[i]['p4']], bm.verts[facesQuad[i]['p3']]))
                        face.smooth = False
                        
                        tempTable = [1, 2, 4, 3]

                        for uv_set_loop in range(4):
                            face.loops[uv_set_loop][uv_layer].uv = [facesQuad[i]['u'+str(tempTable[uv_set_loop])], facesQuad[i]['v'+str(tempTable[uv_set_loop])]]
                    except Exception as e:
                        print(str(e))

            for i in range(len(facesTri)):
                if (i >= attrafter[part['indexpart']][2])&(i < (attrafter[part['indexpart']][2]+attrafter[part['indexpart']][3])):
                    try:
                        face = bm.faces.new((bm.verts[facesTri[i]['p1']], bm.verts[facesTri[i]['p2']], bm.verts[facesTri[i]['p3']]))
                        face.smooth = False

                        for uv_set_loop in [1, 2, 3]:
                            face.loops[uv_set_loop - 1][uv_layer].uv = [facesTri[i]['u'+str(uv_set_loop)], facesTri[i]['v'+str(uv_set_loop)]]
                    except Exception as e:
                        print(str(e))

            bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
            bm.to_mesh(me)
            bm.free()
            
            ob.select_set(state=True)
            saved_location = bpy.context.scene.cursor.location
            bpy.context.scene.cursor.location = offsetpos
            bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
            #print(bpy.context.scene.cursor_location)
            bpy.context.scene.cursor.location = saved_location
            
            bpy.ops.object.select_all(action='DESELECT')
            bpy.ops.export_scene.fbx(filepath='S:\\HWModels\\'+fileName+'.fbx', axis_forward='-Z', axis_up='Y')

            bpy.ops.object.select_all(action='SELECT')
            
            bpy.ops.object.delete()