def ImportMdl():
#--- header ---
#(don't touch unless you know what you're doing)
from COMMON import (Switch,switch,Case,case,
u8,u16,u24,u32,u64,s8,s16,s24,s32,s64,f32,f64,h8,h16,h24,h32,h64,u_,s_,f_,h_,
bu8,bu16,bu24,bu32,bu64,bs8,bs16,bs24,bs32,bs64,bf32,bf64,bh8,bh16,bh24,bh32,bh64,bu_,bs_,bf_,bh_,
Skip,skip,pad,Jump,jump,BF,Mtx,SqMtxInv,StructArr,String,string,
SetScene,SetObject,SetBone,SetPrimitive,SetFacepoint,SetWeight,
IncreaseRangeFor,DecreaseRangeFor,IWLD,ResetIWLD,IFLD,ResetIFLD)
#--- /header ---
def str_off(offset):
STRING=(hex(offset).replace('0x','')).upper()
return '0'*(8-len(STRING))+STRING
def Bone_DAT(offset): #jobj
#print 'bone: '+str_off(offset)
p=Jump(offset)
unk1 = bu32()
Flags = bu32()
skip(12) #map data
R = [bf32(),bf32(),bf32()]
S = [bf32(),bf32(),bf32()]
L = [bf32(),bf32(),bf32()]
inverse = bu32()+32
unk2 = bu32()
if inverse>32: Jump(inverse)
mtx=[
bf32(),bf32(),bf32(),bf32(),
bf32(),bf32(),bf32(),bf32(),
bf32(),bf32(),bf32(),bf32(),
0,0,0,1]
Jump(p)
return SqMtxInv(4,mtx),L+R+S,Flags
def Object_DAT(offset): #pobj
#print 'obj: '+str_off(offset)
Jump(offset)
name='obj'+str_off(offset)
unk = bu32()
Next = bu32()+32
attrs = bu32()+32
flags = bu16()
DL_size = bu16()*32
DL_data = bu32()+32
weights = bu32()+32
SetObject( name, ParentName='joint_obj') #create a new object
def getWeights(WOs):
def Format(MW): Jump(MWO[0],32); return [Bone_DAT(MW[0]+32)[0],MW[1]]
Jump(WOs); return [[Format(MW) for MW in StructArr(['bu32','bf32'])] for MWO in StructArr(['bu32'])]
def getAttrs(AO): Jump(AO); return StructArr(['bu32','bu32','bu32','bu32','bu8','bu8','bu16','bu32'],[255,'*','*','*','*','*','*','*'])
#[ [[Mtx,Wght],[Mtx,Wght]] ,[...],[...]] #TODO: [Name,Mtx,Wght] <- for setting the vert-weight values per facepoint
weights_list=(getWeights(weights) if weights>32 else [])
#[[CPL_idx,CPL_Type,has_bnd,dtype,exponent,unk,stride,offset],[...],[...]]
Attributes=getAttrs(attrs)
def geometry(Attributes=Attributes): #global Attributes -> (Traceback: global name 'Attributes' not defined)
global length;length=0
def CPT(i): #face-point index/value formats
global length; length+=[0,1,1,2][i]
if i == 0: return '' #null
if i == 1: return bu8() #direct data
if i == 2: return bu8() #8bit index
if i == 3: return bu16() #16bit index
def vector(D_Type, exponent, offset, IS3D):
def DataType(DT):
if DT==0: return bu8()/pow(2.0,exponent) #8bit unsigned pseudo-float
if DT==1: return bs8()/pow(2.0,exponent) #8bit signed pseudo-float
if DT==2: return bu16()/pow(2.0,exponent) #16bit unsigned pseudo-float
if DT==3: return bs16()/pow(2.0,exponent) #16bit signed pseudo-float
if DT==4: return bf32() #32bit float
j=Jump(offset,32); return [DataType(D_Type),DataType(D_Type)]+([DataType(D_Type)] if IS3D else [])
Jump(j)
def transform(V,MWs):
tx,ty,tz = 0,0,0
for MW in MWs: #[Matrix,Weight]
tx += ((V[0]*MW[0][0]) + (V[1]*MW[0][1]) + (V[2]*MW[0][2]) + MW[0][3])
ty += ((V[0]*MW[0][4]) + (V[1]*MW[0][5]) + (V[2]*MW[0][6]) + MW[0][7])
tz += ((V[0]*MW[0][8]) + (V[1]*MW[0][9]) + (V[2]*MW[0][10]) + MW[0][11])
return [tx-V[0],ty-V[1],tz-V[2]] #[X,Y,Z]
count=bu16()
while count>0:
mtcs = []; V,N,C,U='','',['',''],['','','','','','','','']
for attr in Attributes:
def Get(IS3D): return vector(attr[3], attr[4], attr[7]+(CPT(attr[1])*attr[6]), IS3D)
Switch(attr[0])
if Case( 0): mtcs = weights_list[CPT(attr[1])/3] #vert/nor_mtx (random invalid index)
elif Case( 1): CPT(attr[1]) #uv[0]_mtx (unknown processing)
elif Case( 2): CPT(attr[1]) #uv[1]_mtx
elif Case( 3): CPT(attr[1]) #uv[2]_mtx
elif Case( 4): CPT(attr[1]) #uv[3]_mtx
elif Case( 5): CPT(attr[1]) #uv[4]_mtx
elif Case( 6): CPT(attr[1]) #uv[5]_mtx
elif Case( 7): CPT(attr[1]) #uv[6]_mtx
elif Case( 8): CPT(attr[1]) #uv[7]_mtx
elif Case( 9): V=('' if CPT(attr[1])=='' else transform(Get(1),mtcs)) #vert
elif Case(10): N=('' if CPT(attr[1])=='' else transform(Get(1),mtcs)) #normal
elif Case(11): CPT(attr[1]) #color[0] #vertex colors
elif Case(12): CPT(attr[1]) #color[1]
elif Case(13): U[0]=('' if CPT(attr[1])=='' else Get(0)) #UV0
elif Case(14): U[1]=('' if CPT(attr[1])=='' else Get(0)) #UV1
elif Case(15): U[2]=('' if CPT(attr[1])=='' else Get(0)) #UV2
elif Case(16): U[3]=('' if CPT(attr[1])=='' else Get(0)) #UV3
elif Case(17): U[4]=('' if CPT(attr[1])=='' else Get(0)) #UV4
elif Case(18): U[5]=('' if CPT(attr[1])=='' else Get(0)) #UV5
elif Case(19): U[6]=('' if CPT(attr[1])=='' else Get(0)) #UV6
elif Case(20): U[7]=('' if CPT(attr[1])=='' else Get(0)) #UV7
elif Case(21): CPT(attr[1]) #vert_mtx_arr
elif Case(22): CPT(attr[1]) #normal_mtx_arr
elif Case(23): CPT(attr[1]) #uv_mtx_arr
elif Case(24): CPT(attr[1]) #light_mtx_array
elif Case(25): CPT(attr[1]) #NBT (NX,NY,NZ, BX,BY,BZ, TX,TY,TZ)
elif Case(25): pass #CP_NULL
count-=1
SetFacepoint(V,N,tuple(C),tuple(U))
#SetWeight(Bone,Weight) #TODO (use in FOR loop)
return length+3
Jump(DL_data)
while DL_size>0:
Switch(bh8()) #primitive ID
if Case('80'): t='quads'
elif Case('88'): t='quadstrip' #possible support based on pattern (hasn't actually been seen)
elif Case('90'): t='triangles'
elif Case('98'): t='trianglestrip'
elif Case('A0'): t='trianglefan'
elif Case('A8'): t='lines'
elif Case('B0'): t='linestrip'
elif Case('B8'): t='points'
SetPrimitive(t)
DL_size-=geometry()
if Next>32: Object_DAT(Next)
def Data_MAP(offset): #dobj
Jump(offset)
unk = bu32()
Next = bu32()+32
Material = bu32()+32
Object = bu32()+32
if Next>32: Data_MAP(Next)
#if Material>32: Material_MAP(Material)
if Object>32: Object_DAT(Object)
def Bone_MAP(offset, parent=''): #jobj
Jump(offset)
name='bn'+str_off(offset)
skip(8) #bone data 1
Child = bu32()+32
Next = bu32()+32
Data = bu32()+32
skip(44) #bone data 2
MTX,LRS,Flags = Bone_DAT(offset)
SetObject('joint_obj') #active object being the rig object
SetBone(name,0,LRS,MTX,parent)
if Child>32: Bone_MAP(Child,name)
if Next>32: Bone_MAP(Next,parent)
if Data>32: Data_MAP(Data)
#main header:
block_size = bu32()
offset_tbl = bu32()+32
num_offsets = bu32()
num_bases = bu32()
num_refs = bu32()
tmp1 = bu32() #001B?
unk1 = bu32()
unk2 = bu32()
#get the base offsets:
bases = []
current_base = 0
Jump(offset_tbl+(num_offsets*4)+(current_base*8))
def base_name(offset):
last=Jump(offset_tbl+(num_offsets*4)+((num_bases+num_refs)*8)+offset); return String()
jump(last)
while IWLD(current_base) < num_bases:
bases.append([bu32(),base_name(bu32())])
current_base += 1
ResetIWLD()
for base in bases:
if (base[1]).split('_')[2] == 'joint': SetObject('joint_obj',24); Bone_MAP(base[0]+32)