'''Noesis import plugin. Written by HimeWorks''' from inc_noesis import * import noesis import rapi import os '''Loading configuration 0 = load only selected model 1 = load all models in the selected model's folder You should only load all models if a model is separated into different files ''' MODE = 0 def registerNoesisTypes(): '''Register the plugin. Just change the Game name and extension.''' handle = noesis.register("Rumble Roses", ".yobj") 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) id = noeStrFromBytes(bs.readBytes(4)) return id == "YOBJ" def load_all_models(mdlList): '''Load all models''' #carry over from previous models matList = [] texList = [] dirPath = rapi.getDirForFilePath(rapi.getInputName()) fileList = [file for file in os.listdir(dirPath) if file.lower().endswith(".r3cm")] for file in fileList: filename, ext = os.path.splitext(file) f = open(dirPath + file, 'rb') data2 = f.read() parser = SanaeParser(data2) parser.parse_file(filename) matList.extend(parser.matList) texList.extend(parser.texList) mdl = rapi.rpgConstructModel() mdl.setBones(parser.boneList) mdl.setModelMaterials(NoeModelMaterials(texList, matList)) mdlList.append(mdl) def load_single_model(data, mdlList): '''Loads a single model. For testing purposes''' filename, ext = os.path.splitext(rapi.getLocalFileName(rapi.getInputName())) parser = SanaeParser(data) parser.parse_file(filename) mdl = rapi.rpgConstructModel() mdl.setBones(parser.boneList) mdl.setModelMaterials(NoeModelMaterials(parser.texList, parser.matList)) # panims = [ # NoeProceduralAnim("arm left shoulder 1", 15.0, 2, 0.1), # NoeProceduralAnim("arm right shoulder 1", -15.0, 2, 0.1), # NoeProceduralAnim("pelvis", -15.0, 1, 0.1), # NoeProceduralAnim("spine upper", -5.0, 1, 0.1), # NoeProceduralAnim("spine lower", -5.0, 1, 0.1) # ] # anims = rapi.createProceduralAnim(parser.boneList, panims, 100) # mdl.setAnims(anims) mdlList.append(mdl) def noepyLoadModel(data, mdlList): '''Load the model''' ctx = rapi.rpgCreateContext() rapi.rpgSetOption(noesis.RPGOPT_TRIWINDBACKWARD, 1) if MODE == 1: load_all_models(mdlList) else: load_single_model(data, mdlList) return 1 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.vertSize = 76 def read_name(self): length = self.inFile.readByte() string = self.inFile.readBytes(length) return noeStrFromBytes(string) def parse_materials(self, numMat): pass def parse_textures(self, name, numTex): mat = NoeMaterial(name, "") if numTex == 1: texName = rapi.getLocalFileName(self.read_name()) mat.setTexture(texName) layerIndex = self.inFile.readInt() elif numTex == 3: # Diffuse Map texName = rapi.getLocalFileName(self.read_name()) mat.setTexture(texName) layerIndex = self.inFile.readInt() # ??? light map? self.read_name() layerIndex = self.inFile.readInt() # normal map self.read_name() mat.setNormalTexture(texName) layerIndex = self.inFile.readInt() elif numTex == 4: # Diffuse Map texName = rapi.getLocalFileName(self.read_name()) mat.setTexture(texName) layerIndex = self.inFile.readInt() # ??? light map? self.read_name() layerIndex = self.inFile.readInt() # normal map self.read_name() mat.setNormalTexture(texName) layerIndex = self.inFile.readInt() # specular map self.read_name() mat.setSpecularTexture(texName) layerIndex = self.inFile.readInt() else: print("unknown textures: %d" %numTex) self.matList.append(mat) rapi.rpgSetMaterial(mat.name) def parse_vertices(self, numVerts): return self.inFile.readBytes(numVerts*self.vertSize) def parse_faces(self, numIdx): return self.inFile.readBytes(numIdx*4) def parse_meshes(self, numMesh): for i in range(numMesh): meshName = self.read_name() rapi.rpgSetName(meshName) numUVLayers = self.inFile.readInt() numTextures = self.inFile.readInt() self.parse_textures(meshName, numTextures) numVerts = self.inFile.readInt() vertBuff = self.parse_vertices(numVerts) numIdx = self.inFile.readInt() * 3 idxBuff = self.parse_faces(numIdx) print(self.vertSize) if self.vertSize == 60: rapi.rpgBindPositionBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 60, 0) rapi.rpgBindNormalBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 60, 12) rapi.rpgBindColorBufferOfs(vertBuff, noesis.RPGEODATA_BYTE, 60, 24, 4) rapi.rpgBindUV1BufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 60, 28) rapi.rpgBindBoneIndexBufferOfs(vertBuff, noesis.RPGEODATA_USHORT, 60, 36, 4) rapi.rpgBindBoneWeightBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 60, 44, 4) elif self.vertSize == 76: rapi.rpgBindPositionBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 76, 0) rapi.rpgBindNormalBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 76, 12) rapi.rpgBindColorBufferOfs(vertBuff, noesis.RPGEODATA_BYTE, 76, 24, 4) rapi.rpgBindUV1BufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 76, 28) rapi.rpgBindBoneIndexBufferOfs(vertBuff, noesis.RPGEODATA_USHORT, 76, 52, 4) rapi.rpgBindBoneWeightBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 76, 60, 4) rapi.rpgCommitTriangles(idxBuff, noesis.RPGEODATA_UINT, numIdx, noesis.RPGEO_TRIANGLE, 1) def parse_bones(self, numBones): for i in range(numBones): boneIndex = i boneName = self.read_name() parentIndex = self.inFile.readShort() boneCoords = NoeVec3.fromBytes(self.inFile.readBytes(12)) boneMat = NoeMat43() boneMat[3] = boneCoords bone = NoeBone(boneIndex, boneName, boneMat, None, parentIndex) self.boneList.append(bone) def parse_unk1(self, count): for i in range(count): self.inFile.readBytes(64) def parse_unk2(self, count): for i in range(count): self.inFile.readBytes(32) def parse_file(self, filename): '''Main parser method''' id = self.inFile.readBytes(4) self.inFile.readInt() # offset self.inFile.readInt() count1 = self.inFile.readInt() # offset self.inFile.readInt() self.inFile.readInt() self.inFile.readInt() # count 1 self.inFile.readInt() # count 2 self.inFile.readInt() # count 3 self.inFile.readInt() # count 4 self.inFile.readInt() # bone offset self.inFile.readInt() # ? offset self.inFile.readInt() # ? offset self.inFile.readInt() # count self.inFile.read("4L") self.parse_unk1(count1) count2 = self.inFile.readInt() self.parse_unk2(count2)