if (heapSize < 200000) then
        heapSize = 2000000 -- allow ~ 40 MB instead of just 7.5 MB. Prevents "Runtime Error: Out of scripter memory"
fname = getOpenFileName \
caption:"Open .mesh from Mesh folder" \
types:"Shadow of Mordor Models (*.mesh)|*.mesh" \
historyCategory:"LOTR_SOMObjectPresets"
f = fopen fname "rb"

clearlistener()

fn ReadHalfFloat fstream = 
	(
	hf=readshort fstream
	sign = bit.get hf 16
	exponent = (bit.shift (bit.and hf (bit.hexasint "7C00")) -10) as integer - 16
	fraction = bit.and hf (bit.hexasint "03FF")
	if sign==true then sign = 1 else sign = 0
	exponentF = exponent + 127
	outputAsFloat = bit.or (bit.or (bit.shift fraction 13) \
	(bit.shift exponentF 23)) (bit.shift sign 31)
	return bit.intasfloat outputasfloat*2
)

fn readFixedString bstream fixedLen = (
local str = ""
for i = 1 to fixedLen do (
str += bit.intAsChar (ReadByte bstream #unsigned))
str
)
struct weight_data
(
	boneids,weights
)
struct Mesh_Info_Struct
(
VertexCount, FaceCount, VertexId,UsedBones, VertexEnd,Vsize
)		
clearlistener()


fseek f 0xC #seek_set
MshCount=readlong f
SData=readlong f
Unk00=readlong f
MeshOff=readlong f
SizeBoneId=readlong f
Count00=readlong f
Count01=readlong f
BoneCount=readlong f
DataCountId=readlong f
CountShort=readlong f
Count20=readlong f
Count12=readlong f
UnkCount00=readlong f
UnkCount01=readlong f
UnkCount02=readlong f

for a = 1 to Count00 do (
getPos = ftell f + 4
fseek f getPos #seek_set			
)	
for a = 1 to Count01 do (
getPos = ftell f + 4
fseek f getPos #seek_set			
)	
for a = 1 to DataCountId do (
BoneId=readbyte f#unsigned	
)
for a = 1 to CountShort do (
BoneId=readshort f#unsigned	
)	
for a = 1 to Count20 do (
getPos = ftell f + 20
fseek f getPos #seek_set			
)	
for a = 1 to Count12 do (
getPos = ftell f + 12
fseek f getPos #seek_set			
)	

Print ("Start @ 0x"+((bit.intAsHex(ftell f))as string))

fseek f (SizeBoneId) #seek_cur
MeshCount00=readlong f
fseek f (0x8) #seek_cur

Print ("End @ 0x"+((bit.intAsHex(ftell f))as string))	
	
MeshStartPos=ftell f

fseek f (MeshOff) #seek_cur
	
MeshPos00=ftell f	
CheckSHRT=readshort f
if CheckSHRT==0 then fseek f (MeshPos00-2) #seek_set
if CheckSHRT!=0 then fseek f (MeshPos00) #seek_set
	
SDataCount=readlong f
for a = 1 to SDataCount do (
getPos = ftell f + 36
fseek f getPos #seek_set			
)	
	
MeshCount=readlong f
Mesh_Info = #()

for a = 1 to MeshCount do (
getPos = ftell f + 40	
Null= readlong f
VertexCount = readlong f
UnkOff01 = readlong f
UnkOff02 = readlong f	
FaceCount = readlong f	
MShdId= readlong f
UsedBones=readlong f	
Unk=readlong f	
VertexId = readlong f	
VertexEnd = readlong f	

VSize=0	
	
if UnkCount02==1 then (	
if VertexId==1 then VSize=60	
if VertexId==0 then VSize=64	
)
if UnkCount02!=1 then (	
if VertexId==1 then VSize=64	
if VertexId==0 then VSize=60	
)

fseek f getPos #seek_set
append Mesh_Info (Mesh_Info_Struct VertexCount:VertexCount FaceCount:FaceCount VertexId:VertexId UsedBones:UsedBones VertexEnd:VertexEnd Vsize:Vsize )				
)

UnkShort=readshort f

for i=1 to MeshCount do (
getPos = ftell f + 8
fseek f getPos #seek_set			
)	

CheckSHRT=readshort f
if CheckSHRT==0 then fseek f 0x8 #seek_cur
if CheckSHRT!=0 then fseek f 0x4 #seek_cur
	
BNArr=#()

for i = 1 to BoneCount do(
	
	Unk=readfloat f;
    BoneParent=readshort f; ChildCount=readshort f
	c21=readfloat f;c22=readfloat f;c23=readfloat f
	c11=readfloat f;c12=readfloat f;c13=readfloat f;c14=readfloat f
	ScaleFloat=readfloat f
	
    tfm = (quat c11 c12 c13 c14) as matrix3
    tfm.row4 = [c21,c22,c23]
     
    newBone = bonesys.createbone    \
                                      tfm.row4      \
                                      (tfm.row4 + 0.01 * (normalize tfm.row1)) \
                                      (normalize tfm.row3)
                            newBone.width  = 0.01
                            newBone.height = 0.01
							newBone.name = i as string			  
                            newBone.transform = tfm
                            newBone.setBoneEnable false 0
                            newBone.wirecolor = yellow
                            newbone.showlinks = true
                            newBone.pos.controller      = TCB_position ()
                            newBone.rotation.controller = TCB_rotation ()  
	if BoneParent!=-1 then
    newBone.parent=BNArr[(BoneParent+1)]		
    append BNArr newBone   
)

rootRT = dummy name:"Main_Root" boxsize:[.1,.1,.1]
for b in BNArr where b.parent==undefined do b.parent = rootRT
rootRT.transform = (matrix3 [1,0,0] [0,0,1] [0,-1,0] [0,0,0])	

print Mesh_Info

fseek f MeshStartPos #seek_set
	
for i = 1 to MeshCount do (
					
for x = 1 to Mesh_Info[i].VertexCount do (
getPos = ftell f + Mesh_Info[i].VSize
fseek f getPos #seek_set
)		

VEndPos00=ftell f
LongCheck00=readlong f
if LongCheck00!=0 then fseek f VEndPos00 #seek_set
if LongCheck00==0 then (
VEndPos01=ftell f
fseek f 0xC #seek_cur
LongCheck01=readlong f
if Mesh_Info[i].VSize==64 then (
VEndPos02=ftell f
LongCheck02=readlong f
if LongCheck02==0 then fseek f 0x10 #seek_cur
if LongCheck02!=0 then fseek f VEndPos02 #seek_set
)	
if Mesh_Info[i].VSize==60 then (
VEndPos02=ftell f
LongCheck02=readlong f
if LongCheck02==0 then fseek f 0x10 #seek_cur
if LongCheck02!=0 then fseek f VEndPos02 #seek_set
)	
if LongCheck01!=0 then fseek f VEndPos01 #seek_set	
)
)

FaceStart=ftell f

Print ("Face Start @ 0x"+((bit.intAsHex(ftell f))as string))

fseek f MeshStartPos #seek_set

for i = 1 to MeshCount do (
	
vertArray = #()
Facearray = #()	
UV_array = #()
Weight_array=#()
	
VertexSize=0	
			
if Mesh_Info[i].VSize==64 then 	
for x = 1 to Mesh_Info[i].VertexCount do (
getPos = ftell f + Mesh_Info[i].VSize
vx = ReadHalfFloat f
vy = ReadHalfFloat f
vz = ReadHalfFloat f
	
Null=readshort f	
		
tu=Readfloat f	
tv=Readfloat f	*-1	

fseek f 0x28 #seek_cur

weight3 = readbyte f #unsigned	
weight2 = readbyte f #unsigned	
weight1 = readbyte f #unsigned	
weight4 = readbyte f #unsigned		
	
bone1 = readbyte f #unsigned	
bone2 = readbyte f #unsigned	
bone3 = readbyte f #unsigned	
bone4 = readbyte f #unsigned

w = (weight_data boneids:#() weights:#())
maxweight = 0
if(weight1 != 0) then
   maxweight = maxweight + weight1
if(weight2 != 0) then
   maxweight = maxweight + weight2
if(weight3 != 0) then
   maxweight = maxweight + weight3
if(weight4 != 0) then
   maxweight = maxweight + weight4


if(maxweight != 0) then (
      if(weight1 != 0) then (
         w1 = weight1 as float
         append w.boneids (bone1 + 1)
         append w.weights (w1/255.0)
      )
      if(weight2 != 0) then (
         w2 = weight2 as float
         append w.boneids (bone2 + 1)
         append w.weights (w2/255.0)
      )
      if(weight3 != 0) then (
         w3 = weight3 as float
         append w.boneids (bone3 + 1)
         append w.weights (w3/255.0)
      )
      if(weight4 != 0) then (
         w4 = weight4 as float
         append w.boneids (bone4 + 1)
        append w.weights (w4/255.0)
      )      
   )
append Weight_array w	
fseek f getPos #seek_set
append vertArray [vx,-vz,vy]
append UV_array [tu,tv,0]	
)		

	
if Mesh_Info[i].VSize==60 then 	
for x = 1 to Mesh_Info[i].VertexCount do (
getPos = ftell f + Mesh_Info[i].VSize
vx = ReadHalfFloat f
vy = ReadHalfFloat f
vz = ReadHalfFloat f
	
Null=readshort f	
		
tu=Readshort f	
tv=Readshort f*-1	
		
fseek f 0x28 #seek_cur

weight3 = readbyte f #unsigned	
weight2 = readbyte f #unsigned	
weight1 = readbyte f #unsigned	
weight4 = readbyte f #unsigned			
	
bone1 = readbyte f #unsigned	
bone2 = readbyte f #unsigned	
bone3 = readbyte f #unsigned	
bone4 = readbyte f #unsigned
	
w = (weight_data boneids:#() weights:#())
maxweight = 0
if(weight1 != 0) then
   maxweight = maxweight + weight1
if(weight2 != 0) then
   maxweight = maxweight + weight2
if(weight3 != 0) then
   maxweight = maxweight + weight3
if(weight4 != 0) then
   maxweight = maxweight + weight4


if(maxweight != 0) then (
      if(weight1 != 0) then (
         w1 = weight1 as float
         append w.boneids (bone1 + 1)
         append w.weights (w1/255.0)
      )
      if(weight2 != 0) then (
         w2 = weight2 as float
         append w.boneids (bone2 + 1)
         append w.weights (w2/255.0)
      )
      if(weight3 != 0) then (
         w3 = weight3 as float
         append w.boneids (bone3 + 1)
         append w.weights (w3/255.0)
      )
      if(weight4 != 0) then (
         w4 = weight4 as float
         append w.boneids (bone4 + 1)
        append w.weights (w4/255.0)
      )      
   )
append Weight_array w	
fseek f getPos #seek_set
append vertArray [vx,-vz,vy]
append UV_array ([tu,tv,0]/32767)	
)	

VEndPos00=ftell f
LongCheck00=readlong f
if LongCheck00!=0 then fseek f VEndPos00 #seek_set
if LongCheck00==0 then (
VEndPos01=ftell f
fseek f 0xC #seek_cur
LongCheck01=readlong f
if Mesh_Info[i].VSize==64 then (
VEndPos02=ftell f
LongCheck02=readlong f
if LongCheck02==0 then fseek f 0x10 #seek_cur
if LongCheck02!=0 then fseek f VEndPos02 #seek_set
)	
if Mesh_Info[i].VSize==60 then (
VEndPos02=ftell f
LongCheck02=readlong f
if LongCheck02==0 then fseek f 0x10 #seek_cur
if LongCheck02!=0 then fseek f VEndPos02 #seek_set
)	
if LongCheck01!=0 then fseek f VEndPos01 #seek_set	
)

MshEnd=ftell f
	
Print ("Mesh End @ 0x"+((bit.intAsHex(ftell f))as string))
	
FaceOff=FaceStart	
	
fseek f FaceOff #seek_set
	
Print ("Face Start @ 0x"+((bit.intAsHex(ftell f))as string))		
	
for x=1 to 	(Mesh_Info[i].FaceCount)do (	
fa=readshort f #unsigned +1
fb=readshort f #unsigned +1
fc=readshort f #unsigned +1
append faceArray [fa,fb,fc]	
)	
	
FaceStart+=(Mesh_Info[i].FaceCount*6) 	
	
Print ("Face End @ 0x"+((bit.intAsHex(ftell f))as string))	

fseek f MshEnd #seek_set	
	
-- try(
msh = mesh vertices:vertArray faces:faceArray
msh.numTVerts = UV_array.count
buildTVFaces msh
for j = 1 to UV_array.count do setTVert msh j UV_array[j]
for j = 1 to faceArray.count do setTVFace msh j faceArray[j]
msh.displayByLayer = false
msh.backfacecull = false
msh.wirecolor = (color 230 200 210)

max modify mode
select msh
skinMod = skin ()
addModifier msh skinMod
for i = 1 to Mesh_Info[i].UsedBones do
(  
	maxbone = BNArr[i]
-- 	maxbone = BNArr[BoneMapArray[i]]
	if i != BoneCount then 
		skinOps.addBone skinMod maxbone 0
	else
		skinOps.addBone skinMod maxbone 1
)
modPanel.setCurrentObject skinMod
for i = 1 to (Mesh_Info[i].VertexCount) do (
   w = Weight_array[i]
   bi = #() --bone index array
   wv = #() --weight value array
   
   for j = 1 to w.boneids.count do
   (
      boneid = w.boneids[j]
      weight = w.weights[j]
      append bi boneid
      append wv weight
   )   
   
   skinOps.ReplaceVertexWeights skinMod i bi wv
   
)
-- )catch(format "failed!!\n")
)

fclose f 