from inc_noesis import * import noesis import rapi import os def registerNoesisTypes(): '''Register the plugin''' handle = noesis.register("Wolf", ".ltb") noesis.setHandlerTypeCheck(handle, noepyCheckType) noesis.setHandlerLoadModel(handle, noepyLoadModel) #see also noepyLoadModelRPG return 1 def noepyCheckType(data): '''Verify that the format is supported by this plugin.''' if len(data) < 9: return 0 try: bs = NoeBitStream(data) ver1 = bs.readShort() ver2 = bs.readShort() if ver1 != 1 or ver2 != 9: return 0 return 1 except: return 0 def noepyLoadModel(data, mdlList): '''Load the model''' ctx = rapi.rpgCreateContext() parser = ZuOnline_LTB(data) parser.parse_file() mdl = rapi.rpgConstructModel() mdlList.append(mdl) mdl.setModelMaterials(NoeModelMaterials(parser.texList, parser.matList)) mdlList.append(mdl) return 1 class ZuOnline_LTB(object): def __init__(self, data): self.inFile = NoeBitStream(data) self.animList = [] self.texList = [] self.matList = [] self.boneList = [] self.dirpath = rapi.getDirForFilePath(rapi.getInputName()) self.texpath = self.dirpath def basename(self): '''Returns the filename without extension''' filename = rapi.getLocalFileName(rapi.getInputName()) basename, ext = os.path.splitext(filename) return basename def read_name(self): string = self.inFile.readBytes(self.inFile.readUShort()) try: return noeStrFromBytes(string) except: return string def parse_vertices(self, numVerts, meshType): if meshType == 1: vertBuff = self.inFile.readBytes(numVerts * 32) rapi.rpgBindPositionBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 32, 0) rapi.rpgBindNormalBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 32, 12) rapi.rpgBindUV1BufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 32, 24) elif meshType == 2: vertBuff = self.inFile.readBytes(numVerts * 36) rapi.rpgBindPositionBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 36, 0) rapi.rpgBindNormalBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 36, 16) rapi.rpgBindUV1BufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 36, 28) elif meshType == 3: vertBuff = self.inFile.readBytes(numVerts * 40) rapi.rpgBindPositionBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 40, 0) rapi.rpgBindNormalBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 40, 20) rapi.rpgBindUV1BufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 40, 32) elif meshType == 4: vertBuff = self.inFile.readBytes(numVerts * 44) rapi.rpgBindPositionBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 44, 0) rapi.rpgBindNormalBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 44, 24) rapi.rpgBindUV1BufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 44, 36) else: print("unknown meshType: %d" %meshType) def parse_faces(self, numIdx): return self.inFile.readBytes(numIdx * 2) def parse_unk(self): count = self.inFile.readUInt() self.inFile.seek(count*12, 1) def create_material(self, matNum, meshName): matName = "material[%d]" %matNum texName = self.texpath + meshName + ".dtx" material = NoeMaterial(matName, texName) self.matList.append(material) return matName def parse_submesh(self, numSubmesh, meshName): for i in range(numSubmesh): self.inFile.readUInt() matNum = self.inFile.readUInt() self.inFile.read('4L') self.inFile.readByte() unk1 = self.inFile.readUInt() sectionSize = self.inFile.readUInt() #sectionSize could be 0 if sectionSize: start = self.inFile.tell() numVerts = self.inFile.readUInt() numIdx = self.inFile.readUInt() * 3 meshType = self.inFile.readUInt() self.inFile.read('5L') if unk1 == 4: self.inFile.readUInt() elif unk1 == 5: self.inFile.readUShort() self.parse_vertices(numVerts, meshType) idxBuff = self.parse_faces(numIdx) #just seeking past unknowns rather than parse the unknown curr = self.inFile.tell() - start remain = sectionSize - curr self.inFile.seek(remain, 1) unk2 = self.inFile.readByte() self.inFile.seek(unk2, 1) print(meshName) matName = self.create_material(matNum, meshName) rapi.rpgSetMaterial(matName) rapi.rpgCommitTriangles(idxBuff, noesis.RPGEODATA_USHORT, numIdx, noesis.RPGEO_TRIANGLE, 1) def parse_mesh(self, numMesh): for i in range(numMesh): meshName = self.read_name() numSubmesh = self.inFile.readUInt() for j in range(numSubmesh): self.inFile.readFloat() self.inFile.read('2L') self.parse_submesh(numSubmesh, meshName) def parse_unk1(self, unk1): for i in range(unk1): self.inFile.read("15f") self.inFile.readInt() self.inFile.readFloat() def parse_file(self): self.inFile.read('2H') self.inFile.read('4L') # zeroes version = self.inFile.readUInt() self.inFile.readUInt() self.inFile.readUInt() numBones = self.inFile.readUInt() self.inFile.read('11L') self.inFile.read('H') #large number self.inFile.readUInt() self.inFile.readFloat() unk1 = self.inFile.readInt() self.parse_unk1(unk1) numMesh = self.inFile.readInt() self.parse_mesh(numMesh)