home *** CD-ROM | disk | FTP | other *** search
/ Xentax forum attachments archive / xentax.7z / 6789 / fmt_folklore_bi5.7z / fmt_folklore_bi5.py
Encoding:
Python Source  |  2013-11-20  |  5.8 KB  |  166 lines

  1. from inc_noesis import *
  2.  
  3. def registerNoesisTypes():
  4.     handle = noesis.register("Folklore", ".bi5_")
  5.     noesis.setHandlerTypeCheck(handle, flCheckType)
  6.     noesis.setHandlerLoadModel(handle, flLoadModel)
  7.     #noesis.logPopup()
  8.     return 1
  9.  
  10.  
  11. def flCheckType(data):
  12.     bs = NoeBitStream(data)
  13.     return 1
  14.  
  15.  
  16. class folkloreFile: 
  17.          
  18.     def __init__(self, bs):
  19.         self.bs = bs
  20.         rapi.rpgSetOption(noesis.RPGOPT_BIGENDIAN, 1)
  21.         self.texList  = []
  22.         self.matList  = [] 
  23.         self.boneList = []
  24.         self.boneMap  = []
  25.         self.offsetList = []
  26.         self.meshOffsets = []
  27.  
  28.     def loadAll(self, bs):
  29.         fileSize, fileCount, tableOffset, nameOffset = bs.read(">" + 4 * "i")
  30.         bs.seek(tableOffset, NOESEEK_ABS)
  31.         bi5Off = bs.read(">" + (fileCount + 1) * "i")
  32.         bs.seek(nameOffset, NOESEEK_ABS)
  33.         for i in range(0, fileCount):
  34.             fileName = bs.readBytes(0x18).decode("ASCII").rstrip("\0")
  35.             if (bi5Off[i + 1] - bi5Off[i]) != 0:
  36.                 self.offsetList.append([fileName, bi5Off[i], (bi5Off[i + 1] - bi5Off[i])])
  37.         for i in range(0, len(self.offsetList)):
  38.             bs.seek(self.offsetList[i][1], NOESEEK_ABS)
  39.             chunkType = bs.readUInt()
  40.             if chunkType in flObjectLoaderDict:
  41.                 flObjectLoaderDict[chunkType](self, bs, i)
  42.             else:
  43.                 #print("NO :", chunkType)
  44.                 self.loadTXT(bs, self.offsetList[i])
  45.  
  46.     def loadAM2(self, bs, fname):
  47.         am2Header = bs.read(">" + "i2H5i")
  48.         bs.seek(am2Header[7] - 32, NOESEEK_REL)
  49.         boneParenting = []
  50.         for i in range(0, am2Header[1]):
  51.             null, id = bs.read(">" + 2 * "B")
  52.             bs.seek(0x16, NOESEEK_REL)
  53.             boneParenting.append(bs.read(">" + 2 * "h"))
  54.             bs.seek(4, NOESEEK_REL)
  55.             BonePos = NoeVec3.fromBytes(bs.readBytes(12), NOE_BIGENDIAN)
  56.             boneMtx = NoeQuat([0.0, 0.0, 0.0, 1.0]).toMat43()
  57.             boneMtx[3] = BonePos
  58.             bs.seek(0x24, NOESEEK_REL)
  59.             newBone = NoeBone(id, (self.offsetList[fname][0] + "_bone_" + str(id)), boneMtx, None, -1)
  60.             self.boneList.append(newBone)
  61.         for i in range(0, am2Header[1]):
  62.             p = self.boneList[i]
  63.             cidx = boneParenting[i][0]
  64.             while cidx != -1:
  65.                 b = self.boneList[cidx]
  66.                 b.parentIndex = p.index
  67.                 cidx = boneParenting[cidx][1]
  68.         self.boneList = rapi.multiplyBones(self.boneList)
  69.  
  70.     def loadCMD(self, bs, fname):
  71.         cmdHeader = bs.read(">" + "i2H5i")
  72.         meshInfo = []
  73.         for i in range(0, cmdHeader[1]):
  74.             bs.seek(0x7C, NOESEEK_REL)
  75.             meshInfo.append(bs.read(">" + "7i"))
  76.             bs.seek(0x18, NOESEEK_REL)
  77.         self.loadMaterial(bs, cmdHeader, meshInfo, fname)
  78.         self.loadBonePallet(bs, cmdHeader, meshInfo, fname)
  79.         self.loadMesh(bs, cmdHeader, meshInfo, fname)
  80.  
  81.     def loadBonePallet(self, bs, cmdHeader, meshInfo, fname):
  82.         for i in range(0, cmdHeader[1]):
  83.             #print(meshInfo[i])
  84.             bs.seek(self.offsetList[fname][1] + meshInfo[i][6], NOESEEK_ABS)
  85.             #print(bs.tell())
  86.             pallet = []
  87.             for a in range(0, 0x100):
  88.                 bid = bs.readUByte()
  89.                 if bid != 255:
  90.                     pallet.append(bid)
  91.             self.boneMap.append(pallet)
  92.  
  93.     def loadMesh(self, bs, cmdHeader, meshInfo, fname):
  94.         for i in range(0, cmdHeader[1]):
  95.             bs.seek(self.offsetList[fname][1] + meshInfo[i][3], NOESEEK_ABS)
  96.             faceBuff = bs.readBytes(4 * meshInfo[i][1])
  97.             bs.seek(self.offsetList[fname][1] + meshInfo[i][4], NOESEEK_ABS)
  98.             vertBuff = bs.readBytes(0x40 * meshInfo[i][2])
  99.             if meshInfo[i][0] == 0:
  100.                 pass
  101.             else:
  102.                 rapi.rpgSetBoneMap(self.boneMap[i])
  103.                 rapi.rpgSetMaterial(self.matList[i].name)
  104.                 rapi.rpgBindPositionBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 0x40, 0)
  105.                 rapi.rpgBindNormalBufferOfs(vertBuff, noesis.RPGEODATA_HALFFLOAT, 0x40, 12)
  106.                 #rapi.rpgBindColorBufferOfs(vertBuff, noesis.RPGEODATA_UBYTE, 0x40, 24, 4)
  107.                 rapi.rpgBindUV1BufferOfs(vertBuff, noesis.RPGEODATA_HALFFLOAT, 0x40, 32)
  108.                 rapi.rpgBindUV2BufferOfs(vertBuff, noesis.RPGEODATA_HALFFLOAT, 0x40, 36)
  109.                 rapi.rpgBindBoneWeightBufferOfs(vertBuff, noesis.RPGEODATA_HALFFLOAT, 0x40, 48, 4)
  110.                 rapi.rpgBindBoneIndexBufferOfs(vertBuff, noesis.RPGEODATA_HALFFLOAT, 0x40, 56, 4)
  111.                 rapi.rpgCommitTriangles(faceBuff, noesis.RPGEODATA_INT, meshInfo[i][1], noesis.RPGEO_TRIANGLE_STRIP, 1)
  112.     def loadMaterial(self, bs, cmdHeader, meshInfo, fname):
  113.         texNames = []
  114.         bs.seek(self.offsetList[fname][1] + cmdHeader[5], NOESEEK_ABS)
  115.         for i in range(0, cmdHeader[2]):
  116.             texNames.append(bs.readBytes(0x20).decode("ASCII").rstrip("\0"))
  117.         for i in range(0, cmdHeader[1]):
  118.             bs.seek(self.offsetList[fname][1] + meshInfo[i][5], NOESEEK_ABS)
  119.             matInfo = bs.read(">" + 3 * "h")
  120.             bs.seek(0x1E, NOESEEK_REL)
  121.             matInfo2 = bs.read(">" + 6 * "b")
  122.             bs.seek(6, NOESEEK_REL)
  123.             material = NoeMaterial("material_" + str(fname) + "_" + str(i), "")
  124.             if matInfo2[1] != -1:
  125.                 material.setTexture(texNames[matInfo2[1] - 1])
  126.             if matInfo2[2] != -1:
  127.                 material.setBumpTexture(texNames[matInfo2[2] - 1])
  128.             material.setFlags(0, 1)
  129.             self.matList.append(material)
  130.  
  131.     def loadTXT(self, bs, fname):
  132.         pass
  133.  
  134.     def loadDDS(self, bs, fname):
  135.         ddsHeader = bs.read(">" + "4i")
  136.         bs.seek(0x40, NOESEEK_REL)
  137.         type = bs.readUInt()
  138.         bs.seek(0x28, NOESEEK_REL)
  139.         texData = bs.readBytes(self.offsetList[fname][2] - 0x80)
  140.         texFmt = noesis.NOESISTEX_DXT1
  141.         if type == 0x31545844:
  142.             texFmt = noesis.NOESISTEX_DXT1
  143.         elif type == 0x33545844:
  144.             texFmt = noesis.NOESISTEX_DXT3
  145.         elif type == 0x35545844:
  146.             texFmt = noesis.NOESISTEX_DXT5
  147.         self.texList.append(NoeTexture(self.offsetList[fname][0], ddsHeader[3], ddsHeader[2], texData, texFmt))
  148.  
  149. flObjectLoaderDict = {
  150.     0x414D3200 : folkloreFile.loadAM2,
  151.     0x434D4400 : folkloreFile.loadCMD,
  152.     0x20534444 : folkloreFile.loadDDS,
  153. }
  154.  
  155. def flLoadModel(data, mdlList):
  156.     ctx = rapi.rpgCreateContext()
  157.     bi5 = folkloreFile(NoeBitStream(data, NOE_BIGENDIAN))
  158.     bi5.loadAll(bi5.bs)
  159.     rapi.rpgSmoothNormals()
  160.     try:
  161.         mdl = rapi.rpgConstructModel()
  162.     except:
  163.         mdl = NoeModel()
  164.     mdl.setModelMaterials(NoeModelMaterials(bi5.texList, bi5.matList))
  165.     mdlList.append(mdl); mdl.setBones(bi5.boneList)    
  166.     return 1