'''Noesis import plugin. Written by Tsukihime''' from inc_noesis import * import noesis import rapi def registerNoesisTypes(): '''Register the plugin. Just change the Game name and extension.''' handle = noesis.register("Fatal Action Zero", ".lmd2") noesis.setHandlerTypeCheck(handle, noepyCheckType) noesis.setHandlerLoadModel(handle, noepyLoadModel) return 1 def noepyCheckType(data): '''Verify that the format is supported by this plugin. Default yes''' bs = NoeBitStream(data) idstring = bs.readUInt() if idstring == 0x17: return 1 return 0 def noepyLoadModel(data, mdlList): '''Build the model, set materials, bones, and animations. You do not need all of them as long as they are empty lists (they are by default)''' ctx = rapi.rpgCreateContext() parser = SanaeParser(data) parser.parse_file() mdl = rapi.rpgConstructModel() mdl.setModelMaterials(NoeModelMaterials(parser.texList, parser.matList)) mdl.setBones(parser.boneList) mdl.setAnims(parser.animList) mdlList.append(mdl) return 1 class Mesh(object): def __init__(self): self.name = "" self.numIdx = 0 self.numVerts = 0 self.vertSize = 0 self.idxBuff = bytes() self.vertBuff = bytes() class SanaeParser(object): def __init__(self, data): '''Initialize some data. Refer to Sanae.py to see what is already initialized''' self.inFile = NoeBitStream(data) self.animList = [] self.texList = [] self.matList = [] self.boneList = [] self.meshList = [] def build_meshes(self): for mesh in self.meshList: if mesh.vertType == 3: rapi.rpgBindPositionBufferOfs(mesh.vertBuff, noesis.RPGEODATA_FLOAT, 48, 0) elif mesh.vertType == 9: rapi.rpgBindPositionBufferOfs(mesh.vertBuff, noesis.RPGEODATA_FLOAT, 72, 0) rapi.rpgBindNormalBufferOfs(mesh.vertBuff, noesis.RPGEODATA_FLOAT, 72, 52) rapi.rpgBindUV1BufferOfs(mesh.vertBuff, noesis.RPGEODATA_FLOAT, 72, 40) for numIdx, idxBuff, matName in mesh.faceGroups: rapi.rpgSetMaterial(matName) rapi.rpgCommitTriangles(idxBuff, noesis.RPGEODATA_USHORT, numIdx, noesis.RPGEO_TRIANGLE, 1) def read_name(self): string = self.inFile.readBytes(self.inFile.readShort()) return noeStrFromBytes(string) def parse_materials(self, numMat): for i in range(numMat): self.inFile.read('17f') matName = self.read_name() self.inFile.readUInt() numTex = self.inFile.readUInt() texNames = [] for j in range(numTex): texName = self.read_name() self.inFile.readUInt() texNames.append(texName) material = NoeMaterial(matName, "") if texNames: material.setTexture(texNames[0]) self.matList.append(material) def parse_textures(self, numTex): for i in range(numTex): texName = self.read_name() texSize = self.inFile.readUInt() texData = self.inFile.readBytes(texSize) tex = rapi.loadTexByHandler(texData, ".dds") if tex: tex.name = texName self.texList.append(tex) def parse_vertices(self, numVerts, vertType): if vertType == 9: return self.inFile.readBytes(numVerts * 72) elif vertType == 3: return self.inFile.readBytes(numVerts * 48) def parse_faces(self, numIdx): return self.inFile.readBytes(numIdx * 2) def parse_face_groups(self, numGroups): faceGroups = [] for i in range(numGroups): numIdx = self.inFile.readUInt() idxBuff = self.parse_faces(numIdx) self.inFile.readUInt() matName = self.read_name() faceGroups.append([numIdx, idxBuff, matName]) return faceGroups def parse_meshes(self, numMesh): for i in range(numMesh): print(self.inFile.tell()) mesh = Mesh() self.inFile.readUInt() mesh.meshName = self.read_name() self.inFile.read('16f') mesh.vertType = self.inFile.readUInt() mesh.numVerts = self.inFile.readUInt() self.inFile.readByte() #delim? mesh.vertBuff = self.parse_vertices(mesh.numVerts, mesh.vertType) # face groups self.inFile.readUInt() # zero numGroups = self.inFile.readUInt() # face groups mesh.faceGroups = self.parse_face_groups(numGroups) count = self.inFile.readUInt() self.inFile.readBytes(count*4) self.inFile.readUInt() self.inFile.readByte() self.meshList.append(mesh) def parse_bones(self, numBones): pass def parse_file(self): '''Main parser method''' idstring = self.inFile.readUInt() base = self.read_name() self.inFile.readUInt() self.inFile.readUInt() numMesh = self.inFile.readUInt() self.parse_meshes(numMesh) self.inFile.read('2L') self.read_name() numMat = self.inFile.readUInt() self.parse_materials(numMat) numTex = self.inFile.readUInt() self.parse_textures(numTex) self.build_meshes()