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
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()