#By Minmode from inc_noesis import * import noesis import rapi import math #Write vmd file vmd = False pmxScale = 1.15 def registerNoesisTypes(): handle = noesis.register("The iDOLM@STER Model", ".nud") noesis.setHandlerTypeCheck(handle, nudCheckType) noesis.setHandlerLoadModel(handle, nudLoadModel) handle = noesis.register("The iDOLM@STER Model", ".xmb") noesis.setHandlerTypeCheck(handle, nudCheckType) noesis.setHandlerLoadModel(handle, nudLoadModel) handle = noesis.register("The iDOLM@STER Texture", ".nut") noesis.setHandlerTypeCheck(handle, nutCheckType) noesis.setHandlerLoadRGBA(handle, nutLoadRGBA) handle = noesis.register("The iDOLM@STER Animation", ".num") noesis.setHandlerTypeCheck(handle, numCheckType) noesis.setHandlerLoadModel(handle, numLoadModel) handle = noesis.register("The iDOLM@STER Animation", ".nnum") noesis.setHandlerTypeCheck(handle, numCheckType) noesis.setHandlerLoadModel(handle, numLoadModel) handle = noesis.register("The iDOLM@STER Animation Pack", ".mpk") noesis.setHandlerTypeCheck(handle, mpkCheckType) noesis.setHandlerLoadModel(handle, mpkLoadModel) return 1 def nudCheckType(data): bs = NoeBitStream(data) if len(data) < 1: return 0 magic = bs.readBytes(4).decode("ASCII") if magic != "NUP3" and magic != "NDP3" and magic != "XMB ": return 0 return 1 def nutCheckType(data): bs = NoeBitStream(data) if len(data) < 4: return 0 magic = bs.readBytes(4).decode("ASCII") if magic != "NNUM" and magic != "NTP3": return 0 return 1 def numCheckType(data): bs = NoeBitStream(data) if len(data) < 1: return 0 magic = bs.readBytes(4).decode("ASCII") if magic != "NUMO" and magic != "NNUM": return 0 return 1 def mpkCheckType(data): bs = NoeBitStream(data) if len(data) < 1: return 0 magic = bs.readBytes(3).decode("ASCII") if magic != "MPK": return 0 return 1 def nudLoadModel(data, mdlList): ctx = rapi.rpgCreateContext() rapi.rpgSetOption(noesis.RPGOPT_BIGENDIAN, 1) #rapi.rpgSetOption(noesis.RPGOPT_TRIWINDBACKWARD, 1) fileName = rapi.getExtensionlessName(rapi.getLocalFileName(rapi.getLastCheckedName())) filePath = rapi.getDirForFilePath(rapi.getLastCheckedName()) nud = nudFile(NoeBitStream(data, 1), fileName, filePath) try: mdl = rapi.rpgConstructModel() except: mdl = NoeModel() mdl.setModelMaterials(NoeModelMaterials(nud.texList, nud.matList)) try: nud.boneList = rapi.multiplyBones(nud.boneList) except: pass mdlList.append(mdl); mdl.setBones(nud.boneList) return 1 def nutLoadRGBA(data, texList): bs = NoeBitStream(data, 1) magic = bs.readBytes(4).decode("ASCII") version = bs.readUShort() texCount = bs.readUShort() bs.seek(0x10, NOESEEK_ABS) for i in range(texCount): offset = bs.tell() chunkSize = bs.readUInt() unk = bs.readUInt() texSize = bs.readUInt() headerSize = bs.readUShort() bs.seek(0x4, NOESEEK_REL) texType = bs.readUShort() width = bs.readUShort() height = bs.readUShort() bs.seek(0x8, NOESEEK_REL) texOffset = bs.readUInt() bs.seek(offset + headerSize - 0x08, NOESEEK_ABS) texID = bs.readUInt() bs.seek(0x4, NOESEEK_REL) if version == 0x200: bs.seek(offset + texOffset, NOESEEK_ABS) texData = bs.readBytes(texSize) if magic == "NTXR": texData = rapi.swapEndianArray(texData, 2) if texType == 0: texFmt = noesis.NOESISTEX_DXT1 elif texType == 1: texFmt = noesis.NOESISTEX_DXT3 elif texType == 2: texFmt = noesis.NOESISTEX_DXT5 else: if magic == "NTXR": texData = rapi.swapEndianArray(texData, 2) texData = rapi.imageDecodeRaw(texData, width, height, "a8r8g8b8") texFmt = noesis.NOESISTEX_RGBA32 fileName = rapi.getExtensionlessName(rapi.getLocalFileName(rapi.getInputName())) if fileName.endswith("_comp"): fileName = fileName[:-5] if fileName.endswith("_slender") or fileName.endswith("_glamour"): fileName = fileName[:-8] tex1 = NoeTexture(fileName+"_"+str(i), width, height, texData, texFmt) texList.append(tex1) if version == 0x200: bs.seek(offset + headerSize, NOESEEK_ABS) else: bs.seek(offset + chunkSize, NOESEEK_ABS) return 1 def numLoadModel(data, mdlList): ctx = rapi.rpgCreateContext() rapi.rpgSetOption(noesis.RPGOPT_BIGENDIAN, 1) #rapi.rpgSetOption(noesis.RPGOPT_TRIWINDBACKWARD, 1) test = rapi.getExtensionlessName(rapi.getLocalFileName(rapi.getLastCheckedName())) if test.startswith("cam_") or test.startswith("dan_tvc"): boneList = [] boneMtx = NoeMat43() boneList.append(NoeBone(0, "Camera", boneMtx, None, -1)) boneList.append(NoeBone(1, "Camera_Interest", boneMtx, None, -1)) boneList.append(NoeBone(2, "Camera_upv", boneMtx, None, -1)) boneList.append(NoeBone(3, "Camera_fov", boneMtx, None, -1)) scaleList = [[1.0, 1.0, 1.0] for x in range(4)] fileName = rapi.getExtensionlessName(rapi.getLocalFileName(rapi.getLastCheckedName())) filePath = rapi.getDirForFilePath(rapi.getLastCheckedName()) num = numFile(NoeBitStream(data, 1), data, scaleList, [], fileName) try: mdl = rapi.rpgConstructModel() except: mdl = NoeModel() mdlList.append(mdl); mdl.setBones(boneList) animList = [NoeKeyFramedAnim(fileName, boneList, num.kfBones, 1.0)] else: modelPath = noesis.userPrompt(noesis.NOEUSERVAL_FILEPATH, "Open Model File", "Select a nud/xmb file to open.", noesis.getSelectedFile(), None) if isinstance(modelPath, str): fileName = rapi.getExtensionlessName(rapi.getLocalFileName(modelPath)) filePath = rapi.getDirForFilePath(modelPath) valid = nudCheckType(rapi.loadIntoByteArray(modelPath)) if valid == 0: noesis.messagePrompt("Invalid model file.") mdlList.append(NoeModel()) return 1 nud = nudFile(NoeBitStream(rapi.loadIntoByteArray(modelPath), 1), fileName, filePath) else: noesis.messagePrompt("Invalid model file.") mdlList.append(NoeModel()) return 1 try: mdl = rapi.rpgConstructModel() except: mdl = NoeModel() mdl.setModelMaterials(NoeModelMaterials(nud.texList, nud.matList)) try: nud.boneList = rapi.multiplyBones(nud.boneList) except: pass mdlList.append(mdl); mdl.setBones(nud.boneList) fileName = rapi.getExtensionlessName(rapi.getLocalFileName(rapi.getLastCheckedName())) filePath = rapi.getDirForFilePath(rapi.getLastCheckedName()) num = numFile(NoeBitStream(data, 1), data, nud.scaleList, [], fileName) if not fileName.endswith("HANDL") and not fileName.endswith("HANDR"): if rapi.checkFileExists(filePath + fileName + "_HANDL.num"): dataL = rapi.loadIntoByteArray(filePath + fileName + "_HANDL.num") num = numFile(NoeBitStream(dataL, 1), dataL, nud.scaleList, num.kfBones, fileName + "_HANDL") if rapi.checkFileExists(filePath + fileName + "_HANDL.nnum"): dataL = rapi.loadIntoByteArray(filePath + fileName + "_HANDL.nnum") num = numFile(NoeBitStream(dataL, 1), dataL, nud.scaleList, num.kfBones, fileName + "_HANDL") if rapi.checkFileExists(filePath + fileName + "_HANDR.num"): dataR = rapi.loadIntoByteArray(filePath + fileName + "_HANDR.num") num = numFile(NoeBitStream(dataR, 1), dataR, nud.scaleList, num.kfBones, fileName + "_HANDR") if rapi.checkFileExists(filePath + fileName + "_HANDR.nnum"): dataR = rapi.loadIntoByteArray(filePath + fileName + "_HANDR.nnum") num = numFile(NoeBitStream(dataR, 1), dataR, nud.scaleList, num.kfBones, fileName + "_HANDR") animList = [NoeKeyFramedAnim(fileName, nud.boneList, num.kfBones, 1.0)] mdl.setAnims(animList) rapi.setPreviewOption("setAnimSpeed", "60") if vmd: writeVMD(animList[0], num.frameCount) return 1 def mpkLoadModel(data, mdlList): ctx = rapi.rpgCreateContext() rapi.rpgSetOption(noesis.RPGOPT_BIGENDIAN, 1) #rapi.rpgSetOption(noesis.RPGOPT_TRIWINDBACKWARD, 1) modelPath = noesis.userPrompt(noesis.NOEUSERVAL_FILEPATH, "Open Model File", "Select a nud/xmb file to open.", noesis.getSelectedFile(), None) if isinstance(modelPath, str): fileName = rapi.getExtensionlessName(rapi.getLocalFileName(modelPath)) filePath = rapi.getDirForFilePath(modelPath) valid = nudCheckType(rapi.loadIntoByteArray(modelPath)) if valid == 0: noesis.messagePrompt("Invalid model file.") mdlList.append(NoeModel()) return 1 nud = nudFile(NoeBitStream(rapi.loadIntoByteArray(modelPath), 1), fileName, filePath) else: noesis.messagePrompt("Invalid model file.") mdlList.append(NoeModel()) return 1 try: mdl = rapi.rpgConstructModel() except: mdl = NoeModel() mdl.setModelMaterials(NoeModelMaterials(nud.texList, nud.matList)) try: nud.boneList = rapi.multiplyBones(nud.boneList) except: pass mdlList.append(mdl); mdl.setBones(nud.boneList) fileName = rapi.getExtensionlessName(rapi.getLocalFileName(rapi.getLastCheckedName())) filePath = rapi.getDirForFilePath(rapi.getLastCheckedName()) bs = NoeBitStream(data, 1) magic = bs.readBytes(4).decode("ASCII").rstrip("\0") fileCount = bs.readUInt() - 1 unkID = bs.readUInt() unkOff = bs.readUInt() animList = [] frameCount = [] if "_facial" in fileName: for i in range(int(fileCount/3)): kfBones = [] for a in range(3): numID = bs.readInt() numOff = bs.readUInt() if numID != -1: numData = data[numOff:] if a == 0: if i == 0: num = numFile(NoeBitStream(numData, 1), numData, nud.scaleList, kfBones, fileName + "_face") elif i == 1: num = numFile(NoeBitStream(numData, 1), numData, nud.scaleList, kfBones, fileName + "_eye") elif i == 2: num = numFile(NoeBitStream(numData, 1), numData, nud.scaleList, kfBones, fileName + "_mouth") kfBones = num.kfBones if i == 0: animList.append(NoeKeyFramedAnim(fileName + "_face", nud.boneList, kfBones, 1.0)) frameCount.append(num.frameCount) elif i == 1: animList.append(NoeKeyFramedAnim(fileName + "_eye", nud.boneList, kfBones, 1.0)) frameCount.append(num.frameCount) elif i == 2: animList.append(NoeKeyFramedAnim(fileName + "_mouth", nud.boneList, kfBones, 1.0)) frameCount.append(num.frameCount) else: for i in range(int(fileCount/3)): kfBones = [] for a in range(3): numID = bs.readInt() numOff = bs.readUInt() if numID != -1: numData = data[numOff:] if a == 0: num = numFile(NoeBitStream(numData, 1), numData, nud.scaleList, kfBones, fileName) elif a == 1: num = numFile(NoeBitStream(numData, 1), numData, nud.scaleList, kfBones, fileName + "_HANDL") elif a == 2: num = numFile(NoeBitStream(numData, 1), numData, nud.scaleList, kfBones, fileName + "_HANDR") kfBones = num.kfBones animList.append(NoeKeyFramedAnim(fileName + "_" + str(i), nud.boneList, kfBones, 1.0)) frameCount.append(num.frameCount) mdl.setAnims(animList) rapi.setPreviewOption("setAnimSpeed", "60") if vmd: for i in range(len(animList)): writeVMD(animList[i], frameCount[i]) return 1 class nudFile: def __init__(self, bs, fileName, filePath): self.texList = [] self.matList = [] self.matDict = {} self.boneList = [] self.boneMap = [] self.boneDict = {} self.scaleList = [] self.texID = [] self.fileName = fileName self.filePath = filePath self.loadAll(bs) def loadAll(self, bs): magic = bs.readBytes(4).decode("ASCII") if magic == "NUP3": nutData = rapi.loadIntoByteArray(self.filePath + self.fileName + ".nut") sklData = rapi.loadIntoByteArray(self.filePath + self.fileName + ".skl") numData = rapi.loadIntoByteArray(self.filePath + self.fileName + ".num") self.readNut(nutData, self.fileName) self.readSkl(sklData) self.readNum(numData) self.readNUP3(bs) elif magic == "NDP3": nut2Data = None if rapi.checkFileExists(self.filePath + self.fileName[:-8] + "_slender_comp.nut"): self.fileName = self.fileName[:-8] nutData = rapi.loadIntoByteArray(self.filePath + self.fileName + "_slender_comp.nut") self.readNut(nutData, self.fileName) elif rapi.checkFileExists(self.filePath + self.fileName + "_comp.nut"): nutData = rapi.loadIntoByteArray(self.filePath + self.fileName + "_comp.nut") self.readNut(nutData, self.fileName) elif rapi.checkFileExists(self.filePath + self.fileName + ".nut"): nutData = rapi.loadIntoByteArray(self.filePath + self.fileName + ".nut") self.readNut(nutData, self.fileName) if rapi.checkFileExists(self.filePath + self.fileName + "_head.nut"): nut2Data = rapi.loadIntoByteArray(self.filePath + self.fileName + "_head.nut") self.readNut(nut2Data, self.fileName + "_head") if rapi.checkFileExists(self.filePath + self.fileName + ".skl"): sklData = rapi.loadIntoByteArray(self.filePath + self.fileName + ".skl") self.readSkl(sklData) elif rapi.checkFileExists(self.filePath + self.fileName[:-1] + "a.skl"): sklData = rapi.loadIntoByteArray(self.filePath + self.fileName[:-1] + "a.skl") self.readSkl(sklData) if rapi.checkFileExists(self.filePath + self.fileName + ".num"): numData = rapi.loadIntoByteArray(self.filePath + self.fileName + ".num") self.readNum(numData) elif rapi.checkFileExists(self.filePath + self.fileName[:-1] + "a.num"): numData = rapi.loadIntoByteArray(self.filePath + self.fileName[:-1] + "a.num") self.readNum(numData) elif rapi.checkFileExists(self.filePath + self.fileName + ".nnum"): nnumData = rapi.loadIntoByteArray(self.filePath + self.fileName + ".nnum") self.readNnum(nnumData) elif rapi.checkFileExists(self.filePath + self.fileName[:-1] + "a.nnum"): nnumData = rapi.loadIntoByteArray(self.filePath + self.fileName[:-1] + "a.nnum") self.readNnum(nnumData) self.readNDP3(bs, None) elif magic == "XMB ": self.readXMB(bs) def readNut(self, data, fileName): bs = NoeBitStream(data, 1) magic = bs.readBytes(4).decode("ASCII") version = bs.readUShort() texCount = bs.readUShort() bs.seek(0x10, NOESEEK_ABS) for i in range(texCount): offset = bs.tell() chunkSize = bs.readUInt() unk = bs.readUInt() texSize = bs.readUInt() headerSize = bs.readUShort() bs.seek(0x4, NOESEEK_REL) texType = bs.readUShort() width = bs.readUShort() height = bs.readUShort() bs.seek(0x8, NOESEEK_REL) texOffset = bs.readUInt() bs.seek(offset + headerSize - 0x08, NOESEEK_ABS) self.texID.append(bs.readUInt()) bs.seek(0x4, NOESEEK_REL) if version == 0x200: bs.seek(offset + texOffset, NOESEEK_ABS) texData = bs.readBytes(texSize) if magic == "NTXR": texData = rapi.swapEndianArray(texData, 2) if texType == 0: texFmt = noesis.NOESISTEX_DXT1 elif texType == 1: texFmt = noesis.NOESISTEX_DXT3 elif texType == 2: texFmt = noesis.NOESISTEX_DXT5 else: if magic == "NTXR": texData = rapi.swapEndianArray(texData, 2) texData = rapi.imageDecodeRaw(texData, width, height, "a8r8g8b8") texFmt = noesis.NOESISTEX_RGBA32 tex1 = NoeTexture(fileName+"_"+str(i), width, height, texData, texFmt) self.texList.append(tex1) if version == 0x200: bs.seek(offset + headerSize, NOESEEK_ABS) else: bs.seek(offset + chunkSize, NOESEEK_ABS) def readNUP3(self, bs): fileSize = bs.readUInt() unk = bs.readUShort() meshCount = bs.readUShort() unk = bs.readUShort() unk = bs.readUShort() bs.seek(0x10, NOESEEK_REL) for i in range(meshCount): bs.seek(0x8, NOESEEK_REL) matCount = bs.readUInt() bs.seek(0x14, NOESEEK_REL) for a in range(matCount): faceOff = bs.readUInt() vertOff = bs.readUInt() unkOff = bs.readUInt() unk = bs.readUInt() unk = bs.readUInt() texCount = bs.readUInt() unk = bs.readUInt() alphaBlend = bs.readUInt() material = NoeMaterial("Material_" + str(i) + "_" + str(a), "") material.setDefaultBlend(alphaBlend) for b in range(texCount): texID = bs.readUInt() bs.seek(0x1c, NOESEEK_REL) if b == 0: material.setTexture(self.texList[self.texID.index(texID)].name) #elif b == 1: #material.setTexture(self.texList[self.texID.index(texID)].name) elif b == 2: material.setEnvTexture(self.texList[self.texID.index(texID)].name) self.matList.append(material) tablePos = bs.tell() bs.seek(faceOff, NOESEEK_ABS) faceCount = bs.readUShort() bs.seek(0x6, NOESEEK_REL) faceBuff = bs.readBytes(faceCount * 2) bs.seek(vertOff, NOESEEK_ABS) vertCount = bs.readUShort() vertInfo = bs.readUByte() bs.seek(0x5, NOESEEK_REL) if vertInfo == 0x81: vertBuff = bs.readBytes(vertCount * 0x20) 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 vertInfo == 0x83: vertBuff = bs.readBytes(vertCount * 0x24) rapi.rpgBindPositionBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 36, 0) rapi.rpgBindNormalBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 36, 12) rapi.rpgBindUV1BufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 36, 28) elif vertInfo == 0xc1: vertBuff = bs.readBytes(vertCount * 0x34) rapi.rpgBindPositionBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 52, 0) rapi.rpgBindNormalBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 52, 12) rapi.rpgBindUV1BufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 52, 24) rapi.rpgBindBoneIndexBufferOfs(vertBuff, noesis.RPGEODATA_UBYTE, 52, 32, 4) rapi.rpgBindBoneWeightBufferOfs(vertBuff, noesis.RPGEODATA_FLOAT, 52, 36, 4) rapi.rpgSetName("Mesh_" + str(i) + "_" + str(a)) rapi.rpgSetMaterial("Material_" + str(i) + "_" + str(a)) rapi.rpgCommitTriangles(faceBuff, noesis.RPGEODATA_USHORT, faceCount, noesis.RPGEO_TRIANGLE_STRIP, 1) bs.seek(tablePos, NOESEEK_ABS) def readNDP3(self, bs, morphData): fileSize = bs.readUInt() unk = bs.readUShort() meshCount = bs.readUShort() unk = bs.readUShort() unk = bs.readUShort() dataOff = bs.readUInt() + 0x30 faceOff = dataOff faceSize = bs.readUInt() buff1Off = faceOff + faceSize buff1Size = bs.readUInt() buff2Off = buff1Off + buff1Size buff2Size = bs.readUInt() nameOff = buff2Off + buff2Size vec4 = bs.read(">4f") meshTable = [] for i in range(meshCount): vec4 = bs.read(">4f") vec4 = bs.read(">4f") meshNameOff = bs.readUInt() + nameOff unk = bs.readUInt() bind = bs.readShort() matCount = bs.readUShort() unk = bs.readUInt() meshTable.append([meshNameOff, matCount, bind]) matTable = [] for i in range(meshCount): subTable = [] for a in range(meshTable[i][1]): faceStart = bs.readUInt() + faceOff buff1Start = bs.readUInt() + buff1Off buff2Start = bs.readUInt() + buff2Off vertCount = bs.readUShort() buff2Flag = bs.readUByte() buff1Flag = bs.readUByte() matInfo1Off = bs.readUInt() matInfo2Off = bs.readUInt() matInfo3Off = bs.readUInt() matInfo4Off = bs.readUInt() faceCount = bs.readUShort() faceFlag = bs.readUByte() unk = bs.readUByte() bs.seek(0x0C, NOESEEK_REL) subTable.append([faceStart, buff1Start, buff2Start, vertCount, buff1Flag, buff2Flag, matInfo1Off, faceCount]) matTable.append(subTable) nameCheck = [] for i in range(meshCount): bs.seek(meshTable[i][0], NOESEEK_ABS) meshName = bs.readString() if meshName in nameCheck: meshName += "_" + str(i) else: nameCheck.append(meshName) for a in range(meshTable[i][1]): bs.seek(matTable[i][a][6], NOESEEK_ABS) material = NoeMaterial(meshName + "_" + str(a), "") unk = bs.readUShort() matType = bs.readUByte() matFlag = bs.readUByte() #print(a) #print("0x%02X"%(matType & 0xFF)) #print("0x%02X"%(matFlag & 0xFF)) unk = bs.readUInt() alphaBlend = bs.readUShort() texCount = bs.readUShort() bs.seek(0x14, NOESEEK_REL) material.setDefaultBlend(alphaBlend) texID = [] for b in range(texCount): texID.append(bs.readUInt()) #print(self.texList[self.texID.index(texID[b])].name) bs.seek(0x14, NOESEEK_REL) material.setTexture(self.texList[self.texID.index(texID[0])].name) if matType == 0x04: material.setOcclTexture(self.texList[self.texID.index(texID[1])].name) if texCount == 3: if matFlag & 0x05: material.setNormalTexture(self.texList[self.texID.index(texID[-1])].name) else: material.setEnvTexture(self.texList[self.texID.index(texID[-1])].name) elif matType == 0x08: if texCount > 1: material.setOcclTexture(self.texList[self.texID.index(texID[1])].name) if matFlag & 0x04: material.setEnvTexture(self.texList[self.texID.index(texID[-1])].name) elif matType == 0xF4: if texCount > 1: material.setOcclTexture(self.texList[self.texID.index(texID[1])].name) else: if matFlag & 0x08 or matFlag & 0x04: material.setEnvTexture(self.texList[self.texID.index(texID[-1])].name) if matFlag & 0x40: material.setTexture(self.texList[self.texID.index(texID[1])].name) material.setOcclTexture(self.texList[self.texID.index(texID[0])].name) material.setFlags2(material.flags2 | noesis.NMATFLAG2_OCCL_UV1 | noesis.NMATFLAG2_OCCL_ISLM) self.matList.append(material) rapi.rpgSetName(meshName + "_" + str(a)) rapi.rpgSetMaterial(meshName + "_" + str(a)) bs.seek(matTable[i][a][0], NOESEEK_ABS) faceBuff = bs.readBytes(matTable[i][a][7] * 2) bs.seek(matTable[i][a][1], NOESEEK_ABS) if matTable[i][a][5] == 0x06 and matTable[i][a][4] == 0x10: buff1 = bs.readBytes(0x18 * matTable[i][a][3]) rapi.rpgBindPositionBufferOfs(buff1, noesis.RPGEODATA_FLOAT, 0x18, 0) rapi.rpgBindNormalBufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x18, 12) rapi.rpgBindUV1BufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x18, 20) if morphData != None: rapi.rpgFeedMorphTargetPositionsOfs(morphData[i][a], noesis.RPGEODATA_FLOAT, 0x18, 0) rapi.rpgFeedMorphTargetNormalsOfs(morphData[i][a], noesis.RPGEODATA_HALFFLOAT, 0x18, 12) rapi.rpgCommitMorphFrame(matTable[i][a][3]) rapi.rpgCommitMorphFrameSet() elif matTable[i][a][5] == 0x06 and matTable[i][a][4] == 0x12: buff1 = bs.readBytes(0x1C * matTable[i][a][3]) rapi.rpgBindPositionBufferOfs(buff1, noesis.RPGEODATA_FLOAT, 0x1C, 0) rapi.rpgBindNormalBufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x1C, 12) rapi.rpgBindUV1BufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x1C, 24) if morphData != None: rapi.rpgFeedMorphTargetPositionsOfs(morphData[i][a], noesis.RPGEODATA_FLOAT, 0x1C, 0) rapi.rpgFeedMorphTargetNormalsOfs(morphData[i][a], noesis.RPGEODATA_HALFFLOAT, 0x1C, 12) rapi.rpgCommitMorphFrame(matTable[i][a][3]) rapi.rpgCommitMorphFrameSet() elif matTable[i][a][5] == 0x06 and matTable[i][a][4] == 0x14: buff1 = bs.readBytes(0x20 * matTable[i][a][3]) rapi.rpgBindPositionBufferOfs(buff1, noesis.RPGEODATA_FLOAT, 0x20, 0) rapi.rpgBindNormalBufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x20, 12) rapi.rpgBindUV1BufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x20, 28) if morphData != None: rapi.rpgFeedMorphTargetPositionsOfs(morphData[i][a], noesis.RPGEODATA_FLOAT, 0x1C, 0) rapi.rpgFeedMorphTargetNormalsOfs(morphData[i][a], noesis.RPGEODATA_HALFFLOAT, 0x1C, 12) rapi.rpgCommitMorphFrame(matTable[i][a][3]) rapi.rpgCommitMorphFrameSet() elif matTable[i][a][5] == 0x06 and matTable[i][a][4] == 0x20: buff1 = bs.readBytes(0x1C * matTable[i][a][3]) rapi.rpgBindPositionBufferOfs(buff1, noesis.RPGEODATA_FLOAT, 0x1C, 0) rapi.rpgBindNormalBufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x1C, 12) if self.fileName.startswith("bg3d_"): rapi.rpgBindUV1BufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x1C, 24) rapi.rpgBindUV2BufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x1C, 20) else: rapi.rpgBindUV1BufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x1C, 20) rapi.rpgBindUV2BufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x1C, 24) if morphData != None: rapi.rpgFeedMorphTargetPositionsOfs(morphData[i][a], noesis.RPGEODATA_FLOAT, 0x1C, 0) rapi.rpgFeedMorphTargetNormalsOfs(morphData[i][a], noesis.RPGEODATA_HALFFLOAT, 0x1C, 12) rapi.rpgCommitMorphFrame(matTable[i][a][3]) rapi.rpgCommitMorphFrameSet() elif matTable[i][a][5] == 0x06 and matTable[i][a][4] == 0x22: buff1 = bs.readBytes(0x20 * matTable[i][a][3]) rapi.rpgBindPositionBufferOfs(buff1, noesis.RPGEODATA_FLOAT, 0x20, 0) rapi.rpgBindNormalBufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x20, 12) if self.fileName.startswith("bg3d_"): rapi.rpgBindUV1BufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x20, 28) rapi.rpgBindUV2BufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x20, 24) else: rapi.rpgBindUV1BufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x20, 24) rapi.rpgBindUV2BufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x20, 28) if morphData != None: rapi.rpgFeedMorphTargetPositionsOfs(morphData[i][a], noesis.RPGEODATA_FLOAT, 0x20, 0) rapi.rpgFeedMorphTargetNormalsOfs(morphData[i][a], noesis.RPGEODATA_HALFFLOAT, 0x20, 12) rapi.rpgCommitMorphFrame(matTable[i][a][3]) rapi.rpgCommitMorphFrameSet() else: if matTable[i][a][4] == 0x10: buff1 = bs.readBytes(0x04 * matTable[i][a][3]) rapi.rpgBindUV1BufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x04, 0) elif matTable[i][a][4] == 0x12: buff1 = bs.readBytes(0x08 * matTable[i][a][3]) #rapi.rpgBindColorBufferOfs(buff1, noesis.RPGEODATA_UBYTE, 0x08, 0, 4) rapi.rpgBindUV1BufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x08, 4) elif matTable[i][a][4] == 0x20: buff1 = bs.readBytes(0x08 * matTable[i][a][3]) rapi.rpgBindUV1BufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x08, 0) rapi.rpgBindUV2BufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x08, 4) elif matTable[i][a][4] == 0x22: buff1 = bs.readBytes(0x0C * matTable[i][a][3]) #rapi.rpgBindColorBufferOfs(buff1, noesis.RPGEODATA_UBYTE, 0x0C, 0, 4) rapi.rpgBindUV1BufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x0C, 4) rapi.rpgBindUV2BufferOfs(buff1, noesis.RPGEODATA_HALFFLOAT, 0x0C, 8) else: print("Unkown buff1 flag " + str(matTable[i][a][4])) if matTable[i][a][5] == 0x11: bs.seek(matTable[i][a][2], NOESEEK_ABS) buff2 = bs.readBytes(0x40 * matTable[i][a][3]) rapi.rpgBindPositionBufferOfs(buff2, noesis.RPGEODATA_FLOAT, 0x40, 0) rapi.rpgBindNormalBufferOfs(buff2, noesis.RPGEODATA_FLOAT, 0x40, 16) rapi.rpgBindBoneIndexBufferOfs(buff2, noesis.RPGEODATA_INT, 0x40, 32, 4) rapi.rpgBindBoneWeightBufferOfs(buff2, noesis.RPGEODATA_FLOAT, 0x40, 48, 4) if morphData != None: rapi.rpgFeedMorphTargetPositionsOfs(morphData[i][a], noesis.RPGEODATA_FLOAT, 0x40, 0) rapi.rpgFeedMorphTargetNormalsOfs(morphData[i][a], noesis.RPGEODATA_FLOAT, 0x40, 16) rapi.rpgCommitMorphFrame(matTable[i][a][3]) rapi.rpgCommitMorphFrameSet() elif matTable[i][a][5] == 0x13: bs.seek(matTable[i][a][2], NOESEEK_ABS) buff2 = bs.readBytes(0x60 * matTable[i][a][3]) rapi.rpgBindPositionBufferOfs(buff2, noesis.RPGEODATA_FLOAT, 0x60, 0) rapi.rpgBindNormalBufferOfs(buff2, noesis.RPGEODATA_FLOAT, 0x60, 16) rapi.rpgBindBoneIndexBufferOfs(buff2, noesis.RPGEODATA_INT, 0x60, 64, 4) rapi.rpgBindBoneWeightBufferOfs(buff2, noesis.RPGEODATA_FLOAT, 0x60, 80, 4) if morphData != None: rapi.rpgFeedMorphTargetPositionsOfs(morphData[i][a], noesis.RPGEODATA_FLOAT, 0x60, 0) rapi.rpgFeedMorphTargetNormalsOfs(morphData[i][a], noesis.RPGEODATA_FLOAT, 0x60, 16) rapi.rpgCommitMorphFrame(matTable[i][a][3]) rapi.rpgCommitMorphFrameSet() else: print("Unkown buff2 flag " + str(matTable[i][a][5])) rapi.rpgCommitTriangles(faceBuff, noesis.RPGEODATA_USHORT, matTable[i][a][7], noesis.RPGEO_TRIANGLE_STRIP, 1) rapi.rpgClearBufferBinds() def readNud2(self, data): bs = NoeBitStream(data, 1) magic = bs.readBytes(4).decode("ASCII") fileSize = bs.readUInt() unk = bs.readUShort() meshCount = bs.readUShort() unk = bs.readUShort() unk = bs.readUShort() dataOff = bs.readUInt() + 0x30 faceOff = dataOff faceSize = bs.readUInt() buff1Off = faceOff + faceSize buff1Size = bs.readUInt() buff2Off = buff1Off + buff1Size buff2Size = bs.readUInt() nameOff = buff2Off + buff2Size vec4 = bs.read(">4f") meshTable = [] for i in range(meshCount): vec4 = bs.read(">4f") vec4 = bs.read(">4f") meshNameOff = bs.readUInt() + nameOff unk = bs.readUInt() bind = bs.readShort() matCount = bs.readUShort() unk = bs.readUInt() meshTable.append([meshNameOff, matCount, bind]) matTable = [] for i in range(meshCount): subTable = [] for a in range(meshTable[i][1]): faceStart = bs.readUInt() + faceOff buff1Start = bs.readUInt() + buff1Off buff2Start = bs.readUInt() + buff2Off vertCount = bs.readUShort() buff2Flag = bs.readUByte() buff1Flag = bs.readUByte() matInfo1Off = bs.readUInt() matInfo2Off = bs.readUInt() matInfo3Off = bs.readUInt() matInfo4Off = bs.readUInt() faceCount = bs.readUShort() faceFlag = bs.readUByte() unk = bs.readUByte() bs.seek(0x0C, NOESEEK_REL) subTable.append([faceStart, buff1Start, buff2Start, vertCount, buff1Flag, buff2Flag, matInfo1Off, faceCount]) matTable.append(subTable) morphData = [] for i in range(meshCount): md = [] for a in range(meshTable[i][1]): bs.seek(matTable[i][a][1], NOESEEK_ABS) if matTable[i][a][5] == 0x06 and matTable[i][a][4] == 0x10: buff1 = bs.readBytes(0x18 * matTable[i][a][3]) md.append(buff1) elif matTable[i][a][5] == 0x06 and matTable[i][a][4] == 0x12: buff1 = bs.readBytes(0x1C * matTable[i][a][3]) md.append(buff1) elif matTable[i][a][5] == 0x06 and matTable[i][a][4] == 0x14: buff1 = bs.readBytes(0x20 * matTable[i][a][3]) md.append(buff1) elif matTable[i][a][5] == 0x06 and matTable[i][a][4] == 0x20: buff1 = bs.readBytes(0x1C * matTable[i][a][3]) md.append(buff1) elif matTable[i][a][5] == 0x06 and matTable[i][a][4] == 0x22: buff1 = bs.readBytes(0x20 * matTable[i][a][3]) md.append(buff1) else: if matTable[i][a][5] == 0x11: bs.seek(matTable[i][a][2], NOESEEK_ABS) buff2 = bs.readBytes(0x40 * matTable[i][a][3]) md.append(buff2) elif matTable[i][a][5] == 0x13: bs.seek(matTable[i][a][2], NOESEEK_ABS) buff2 = bs.readBytes(0x60 * matTable[i][a][3]) md.append(buff2) else: print("Unkown buff2 flag " + str(matTable[i][a][5])) morphData.append(md) return morphData def readXMB(self, bs): tableCount = bs.readUInt() bs.seek(0x10, NOESEEK_REL) tableOff = bs.readUInt() tableDataOff = bs.readUInt() unkOff = bs.readUInt() typeOff = bs.readUInt() dataOff = bs.readUInt() bs.seek(tableOff, NOESEEK_ABS) tableInfo = [] for i in range(tableCount): bs.seek(0x04, NOESEEK_REL) tableInfo.append(bs.readUShort()) bs.seek(0x0A, NOESEEK_REL) bs.seek(tableDataOff, NOESEEK_ABS) tableData = [] for i in range(tableCount): td = [] for a in range(tableInfo[i]): typeStart = bs.readUInt() dataStart = bs.readUInt() td.append([typeStart, dataStart]) tableData.append(td) xmbData = [] for i in range(tableCount): print("_________________________________________________") kind = None name = None for a in range(tableInfo[i]): bs.seek(typeOff + tableData[i][a][0], NOESEEK_ABS) dataType = bs.readString() bs.seek(dataOff + tableData[i][a][1], NOESEEK_ABS) data = bs.readString() if dataType == "kind": kind = data elif dataType == "name": name = data print(dataType) print(data) xmbData.append([kind, name]) morphData = None for i in range(tableCount): if xmbData[i][0] == "bg3d_nut": nutData = rapi.loadIntoByteArray(self.filePath + xmbData[i][1]) self.readNut(nutData, xmbData[i][1][:-4]) break elif xmbData[i][0] == "nut": nutData = rapi.loadIntoByteArray(self.filePath + xmbData[i][1]) if xmbData[i][1][:-4].endswith("_comp"): self.readNut(nutData, xmbData[i][1][:-9]) else: self.readNut(nutData, xmbData[i][1][:-4]) break for i in range(tableCount): if xmbData[i][0] == "nut2": nutData = rapi.loadIntoByteArray(self.filePath + xmbData[i][1]) self.readNut(nutData, xmbData[i][1][:-4]) break for i in range(tableCount): if xmbData[i][0] == "nut_uvs0": nutData = rapi.loadIntoByteArray(self.filePath + xmbData[i][1]) self.readNut(nutData, xmbData[i][1][:-4]) break for i in range(tableCount): if xmbData[i][0] == "nut_uvs1": nutData = rapi.loadIntoByteArray(self.filePath + xmbData[i][1]) self.readNut(nutData, xmbData[i][1][:-4]) break for i in range(tableCount): if xmbData[i][0] == "nut_uvs2": nutData = rapi.loadIntoByteArray(self.filePath + xmbData[i][1]) self.readNut(nutData, xmbData[i][1][:-4]) break for i in range(tableCount): if xmbData[i][0] == "skl": sklData = rapi.loadIntoByteArray(self.filePath + xmbData[i][1]) self.readSkl(sklData) break for i in range(tableCount): if xmbData[i][0] == "num": nnumData = rapi.loadIntoByteArray(self.filePath + xmbData[i][1]) self.readNnum(nnumData) break for i in range(tableCount): if xmbData[i][0] == "nud2": nudData = rapi.loadIntoByteArray(self.filePath + xmbData[i][1]) morphData = self.readNud2(nudData) break for i in range(tableCount): if xmbData[i][0] == "bg3d_nud": nudData = rapi.loadIntoByteArray(self.filePath + xmbData[i][1]) nudBs = NoeBitStream(nudData, 1) magic = nudBs.readBytes(4).decode("ASCII") self.readNDP3(nudBs, morphData) break elif xmbData[i][0] == "nud": nudData = rapi.loadIntoByteArray(self.filePath + xmbData[i][1]) nudBs = NoeBitStream(nudData, 1) magic = nudBs.readBytes(4).decode("ASCII") self.readNDP3(nudBs, morphData) break for i in range(tableCount): if xmbData[i][0] == "nud_uvs0": nudData = rapi.loadIntoByteArray(self.filePath + xmbData[i][1]) nudBs = NoeBitStream(nudData, 1) magic = nudBs.readBytes(4).decode("ASCII") self.readNDP3(nudBs, morphData) break for i in range(tableCount): if xmbData[i][0] == "nud_uvs1": nudData = rapi.loadIntoByteArray(self.filePath + xmbData[i][1]) nudBs = NoeBitStream(nudData, 1) magic = nudBs.readBytes(4).decode("ASCII") self.readNDP3(nudBs, morphData) break for i in range(tableCount): if xmbData[i][0] == "nud_uvs2": nudData = rapi.loadIntoByteArray(self.filePath + xmbData[i][1]) nudBs = NoeBitStream(nudData, 1) magic = nudBs.readBytes(4).decode("ASCII") self.readNDP3(nudBs, morphData) break def readSkl(self, data): bs = NoeBitStream(data, 1) magic = bs.readBytes(4).decode("ASCII") boneCount = bs.readUInt() version = bs.readFloat() physicsSize = bs.readUInt() unk = bs.readUInt() self.boneParents = [] for i in range(boneCount): parent = bs.readInt() unk = bs.readUInt() unk = bs.readUInt() tx, ty, tz = bs.read(">3f") rx, ry, rz = bs.read(">3f") sx, sy, sz = bs.read(">3f") self.boneParents.append(parent) def readNnum(self, data): bs = NoeBitStream(data, 1) magic = bs.readBytes(4).decode("ASCII") unk = bs.readUInt() unk = bs.readUInt() unk = bs.readUInt() unk = bs.readFloat() boneCount = bs.readUInt() unk = bs.readFloat() unk = bs.readFloat() for i in range(boneCount): animMap = bs.readUByte() offFix = bs.tell() while offFix%4 != 0: bs.seek(0x01, NOESEEK_REL) offFix = bs.tell() self.readNum(data[bs.tell():]) def readNum(self, data): bs = NoeBitStream(data, 1) magic = bs.readBytes(8).decode("ASCII").rstrip("\0") unk = bs.readUInt() fileSize = bs.readUInt() bs.seek(0x20, NOESEEK_REL) dataSize = bs.readUInt() bs.seek(0x1c, NOESEEK_REL) frameCount = bs.readUShort() channelCount = bs.readUShort() boneNames = self.initBoneNames() for i in range(int(channelCount/3)): tx, ty, tz = bs.read(">3h") rx, ry, rz = bs.read(">3h") sx, sy, sz = bs.read(">3h") rot = NoeAngles(((rx/32768.0)*math.pi*noesis.g_flRadToDeg, (ry/32768.0)*math.pi*noesis.g_flRadToDeg, (rz/32768.0)*math.pi*noesis.g_flRadToDeg)) boneMtx = rot.toMat43_XYZ() boneMtx[0] *= (sx/32768.0)*2.0 boneMtx[1] *= (sy/32768.0)*2.0 boneMtx[2] *= (sz/32768.0)*2.0 boneMtx[3] = NoeVec3((tx/1000.0, ty/1000.0, tz/1000.0)) if i < len(boneNames): newBone = NoeBone(i, boneNames[i], boneMtx, None, self.boneParents[i]) else: newBone = NoeBone(i, "Bone_" + str(i), boneMtx, None, self.boneParents[i]) self.boneList.append(newBone) self.scaleList.append([(sx/32768.0)*2.0, (sy/32768.0)*2.0, (sz/32768.0)*2.0]) def initBoneNames(self): names = ["POSITION", "MUKI", "BASE", "MUNE1", "MUNE2", "KUBI", "ATAMA", "SAKOTSU_R", "KATA_R", "UDE_R", "TE_R", "SAKOTSU_L", "KATA_L", "UDE_L", "TE_L", "KOSHI", "MOMO_R", "HIZA_R", "ASHI_R", "MOMO_L", "HIZA_L", "ASHI_L", "TSUMASAKI_R", "TSUMASAKI_L", "OYA3_R", "OYA2_R", "OYA1_R", "HITO3_R", "HITO2_R", "HITO1_R", "NAKA3_R", "NAKA2_R", "NAKA1_R", "KUSU3_R", "KUSU2_R", "KUSU1_R", "KO3_R", "KO2_R", "KO1_R", "OYA3_L", "OYA2_L", "OYA1_L", "HITO3_L", "HITO2_L", "HITO1_L", "NAKA3_L", "NAKA2_L", "NAKA1_L", "KUSU3_L", "KUSU2_L", "KUSU1_L", "KO3_L", "KO2_L", "KO1_L", "KUBI_RT", "MUNE_R", "MUNE_L", "SAKOTSU_RT_R", "WAKI_R", "KATA_RT_R", "KATA_MD_R", "HIJI_R", "UDE_MD_R", "TEKUBI_R", "SAKOTSU_RT_L", "WAKI_L", "KATA_RT_L", "KATA_MD_L", "HIJI_L", "UDE_MD_L", "TEKUBI_L", "SHIRI_R", "SHIRI_L", "COMANECI_R", "MOMO_RT_R", "MOMO_MD_R", "HIZAKOZO_R", "ASHIKUBI_R", "COMANECI_L", "MOMO_RT_L", "MOMO_MD_L", "HIZAKOZO_L", "ASHIKUBI_L", "ATAMA_OFF", "mayuge_L01", "mayuge_L02", "mayuge_L03", "mayuge_L04", "mayuge_L05", "mayuge_L06", "mayuge_R01", "mayuge_R02", "mayuge_R03", "mayuge_R04", "mayuge_R05", "mayuge_R06", "eye_L", "kurome_L", "eye_R", "kurome_R", "mabuta_L_U01", "mabuta_L_U02", "mabuta_L_U03", "mabuta_L_U04", "mabuta_L_U05", "mabuta_L_U06", "mabuta_L_D01", "mabuta_L_D02", "mabuta_L_D03", "mabuta_L_D04", "mabuta_L_D05", "mabuta_R_U01", "mabuta_R_U02", "mabuta_R_U03", "mabuta_R_U04", "mabuta_R_U05", "mabuta_R_U06", "mabuta_R_D01", "mabuta_R_D02", "mabuta_R_D03", "mabuta_R_D04", "mabuta_R_D05", "kuchi_UC", "kuchi_UL1", "kuchi_UL2", "kuchi_UL3", "kuchi_UR1", "kuchi_UR2", "kuchi_UR3", "kuchi_DC", "kuchi_DL1", "kuchi_DL2", "kuchi_DR1", "kuchi_DR2", "ha_U", "ha_D"] return names class numFile: def __init__(self, bs, data, scaleList, kfBones ,fileName): self.scaleList = scaleList self.kfBones = kfBones self.frameCount = 0 self.data = data self.fileName = fileName self.loadAll(bs) def loadAll(self, bs): magic = bs.readBytes(4).decode("ASCII") if magic == "NUMO": self.readNum(bs, None) elif magic == "NNUM": self.readNnum(bs) def readNnum(self, bs): unk = bs.readUInt() unk = bs.readUInt() unk = bs.readUInt() unk = bs.readFloat() boneCount = bs.readUInt() unk = bs.readFloat() unk = bs.readFloat() animMap = [] for i in range(boneCount): animMap.append(bs.readUByte()) offFix = bs.tell() while offFix%4 != 0: bs.seek(0x01, NOESEEK_REL) offFix = bs.tell() self.readNum(NoeBitStream(self.data[bs.tell() + 4:], 1), animMap) def readNum(self, bs, animMap): unk = bs.readUInt() unk = bs.readUInt() fileSize = bs.readUInt() bs.seek(0x20, NOESEEK_REL) dataSize = bs.readUInt() bs.seek(0x1c, NOESEEK_REL) frameCount = bs.readUShort() channelCount = bs.readUShort() self.frameCount = frameCount boneIndex = 0 if self.fileName.endswith("HANDR"): boneIndex = 24 if animMap == None: animMap = [0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02] elif self.fileName.endswith("HANDL"): boneIndex = 39 if animMap == None: animMap = [0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02] elif self.fileName.endswith("face"): boneIndex = 83 if animMap == None: animMap = [0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x13, 0x03,0x13,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03, 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03, 0x03,0x03,0x03,0x03] elif self.fileName.endswith("eye"): boneIndex = 100 if animMap == None: animMap = [0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03, 0x03,0x03,0x03,0x03,0x03,0x03,0x03] elif self.fileName.endswith("mouth"): boneIndex = 122 if animMap == None: animMap = [0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03] elif self.fileName.startswith("cam_") or self.fileName.startswith("dan_tvc"): if animMap == None: animMap = [0x01,0x01,0x10,0x20] if animMap == None: animMap = [0x01,0x08,0x03,0x02,0x02,0x02,0x02,0x02,0x02,0x04,0x02,0x02,0x02,0x04,0x02,0x02,0x02,0x04,0x02,0x02,0x04,0x02,0x02,0x02] animBone = [] animData = [] frameData = [] boneCount = len(animMap) for i in range(0, boneCount): animBone.append(NoeKeyFramedBone(i + boneIndex)) animData.append([[],[],[]]) frameData.append([[],[],[]]) for i in range(frameCount): for a in range(boneCount): if animMap[a] & 0x01 or animMap[a] & 0x08: #tran tx, ty, tz = bs.read(">3h") if self.fileName.startswith("cam_") or self.fileName.startswith("dan_tvc"): animData[a][0].append([tx/1000.0*10.0, ty/1000.0*10.0, tz/1000.0*10.0]) elif boneIndex == 0: animData[a][0].append([tx/1000.0*2.0, ty/1000.0*2.0, tz/1000.0*2.0]) else: animData[a][0].append([tx/1000.0, ty/1000.0, tz/1000.0]) if animMap[a] & 0x02 or animMap[a] & 0x04: #rot rx, ry, rz = bs.read(">3h") animData[a][1].append([(rx/32768.0)*math.pi, (ry/32768.0)*math.pi, (rz/32768.0)*math.pi]) if animMap[a] & 0x10: #sca sx, sy, sz = bs.read(">3h") animData[a][2].append([(sx/32768.0)*2.0*self.scaleList[a+boneIndex][0], (sy/32768.0)*2.0*self.scaleList[a+boneIndex][1], (sz/32768.0)*2.0*self.scaleList[a+boneIndex][2]]) if animMap[a] & 0x20: #fov fx, fy, fz = bs.read(">3h") animData[a][1].append([(fx/32768.0)*math.pi, fy, fz]) for i in range(frameCount): for a in range(boneCount): if animMap[a] & 0x01 or animMap[a] & 0x08: #tran if i == 0 or i == frameCount - 1: frameData[a][0].append(NoeKeyFramedValue(i, animData[a][0][i])) if i == frameCount - 1: frameData[a][0].append(NoeKeyFramedValue(i + 1, animData[a][0][i])) else: if animData[a][0][i] == animData[a][0][i-1] and animData[a][0][i] == animData[a][0][i+1]: pass else: frameData[a][0].append(NoeKeyFramedValue(i, animData[a][0][i])) if animMap[a] & 0x02 or animMap[a] & 0x04: #rot if i == 0 or i == frameCount - 1: rot = NoeAngles((animData[a][1][i][0]*noesis.g_flRadToDeg, animData[a][1][i][1]*noesis.g_flRadToDeg, animData[a][1][i][2]*noesis.g_flRadToDeg)) quat = rot.toMat43_XYZ().toQuat() frameData[a][1].append(NoeKeyFramedValue(i, quat)) if i == frameCount - 1: frameData[a][1].append(NoeKeyFramedValue(i + 1, quat)) else: if animData[a][1][i] == animData[a][1][i-1] and animData[a][1][i] == animData[a][1][i+1]: pass else: rot = NoeAngles((animData[a][1][i][0]*noesis.g_flRadToDeg, animData[a][1][i][1]*noesis.g_flRadToDeg, animData[a][1][i][2]*noesis.g_flRadToDeg)) quat = rot.toMat43_XYZ().toQuat() frameData[a][1].append(NoeKeyFramedValue(i, quat)) if animMap[a] & 0x10: #sca if i == 0 or i == frameCount - 1: frameData[a][2].append(NoeKeyFramedValue(i, animData[a][2][i])) if i == frameCount - 1: frameData[a][2].append(NoeKeyFramedValue(i + 1, animData[a][2][i])) else: if animData[a][2][i] == animData[a][2][i-1] and animData[a][2][i] == animData[a][2][i+1]: pass else: frameData[a][2].append(NoeKeyFramedValue(i, animData[a][2][i])) elif self.scaleList[a + boneIndex] != [1.0, 1.0, 1.0] and i == 0: frameData[a][2].append(NoeKeyFramedValue(i, self.scaleList[a + boneIndex])) if animMap[a] & 0x20: #fov if i == 0 or i == frameCount - 1: rot = NoeAngles((animData[a][1][i][0]*noesis.g_flRadToDeg, 0, 0)) quat = rot.toQuat() frameData[a][1].append(NoeKeyFramedValue(i, quat)) if i == frameCount - 1: frameData[a][1].append(NoeKeyFramedValue(i + 1, quat)) else: if animData[a][1][i] == animData[a][1][i-1] and animData[a][1][i] == animData[a][1][i+1]: pass else: rot = NoeAngles((animData[a][1][i][0]*noesis.g_flRadToDeg, 0, 0)) quat = rot.toQuat() frameData[a][1].append(NoeKeyFramedValue(i, quat)) for i in range(boneCount): if animMap[i] & 0x01 or animMap[i] & 0x08: animBone[i].setTranslation(frameData[i][0], noesis.NOEKF_TRANSLATION_VECTOR_3, noesis.NOEKF_INTERPOLATE_LINEAR) if animMap[i] & 0x02 or animMap[i] & 0x04 or animMap[i] & 0x20: animBone[i].setRotation(frameData[i][1], noesis.NOEKF_ROTATION_QUATERNION_4, noesis.NOEKF_INTERPOLATE_LINEAR) if animMap[i] & 0x10 or self.scaleList[i + boneIndex] != [1.0, 1.0, 1.0]: animBone[i].setScale(frameData[i][2], noesis.NOEKF_SCALE_VECTOR_3, noesis.NOEKF_INTERPOLATE_LINEAR) self.kfBones.append(animBone[i]) def writeVMD(anim, frameCount): fileName = rapi.getExtensionlessName(rapi.getLocalFileName(rapi.getLastCheckedName())) writeName = rapi.getDirForFilePath(rapi.getOutputName()) + anim.name + ".vmd" f = open(writeName, "wb") print(anim.name) f.write("Vocaloid Motion Data 0002".ljust(30, chr(0)).encode("shift_jis"))#magic f.write(fileName.ljust(20, chr(0))[:20].encode("shift_jis"))#model name animData = [[], [], []] worldScale = {} for i in range(len(anim.kfBones)): worldScale[anim.kfBones[i].boneIndex] = [] posFrames = anim.kfBones[i].translationKeys rotFrames = anim.kfBones[i].rotationKeys if rotFrames == []: rot = NoeAngles((0.0, 0.0, 0.0)) quat = rot.toMat43().toQuat() rotFrames = [NoeKeyFramedValue(0, quat), NoeKeyFramedValue(frameCount, quat)] sclFrames = anim.kfBones[i].scaleKeys if sclFrames == []: sclFrames = [NoeKeyFramedValue(0, [1.0, 1.0, 1.0]), NoeKeyFramedValue(frameCount, [1.0, 1.0, 1.0])] posCount = 0 rotCount = 0 sclCount = 0 prevPosCount = -1 prevRotCount = -1 prevSclCount = -1 if posFrames == []: posX = 0.0 posY = 0.0 posZ = 0.0 prevPosCount = 0 oldPosX = None oldPosY = None oldPosZ = None oldSclX = None oldSclY = None oldSclZ = None oldQuat = None for a in range(frameCount): posTest = False rotTest = False sclTest = False wSclTest = False if posCount != prevPosCount: posTest = True if rotCount != prevRotCount: rotTest = True if sclCount != prevSclCount: sclTest = True if anim.bones[anim.kfBones[i].boneIndex].parentIndex != -1: if anim.bones[anim.kfBones[i].boneIndex].parentIndex in worldScale: wSclX = worldScale[anim.bones[anim.kfBones[i].boneIndex].parentIndex][a][0] wSclY = worldScale[anim.bones[anim.kfBones[i].boneIndex].parentIndex][a][1] wSclZ = worldScale[anim.bones[anim.kfBones[i].boneIndex].parentIndex][a][2] if worldScale[anim.bones[anim.kfBones[i].boneIndex].parentIndex][a] != worldScale[anim.bones[anim.kfBones[i].boneIndex].parentIndex][a - 1]: wSclTest = True else: wSclX, wSclY, wSclZ = 1.0, 1.0, 1.0 prevPosCount = posCount prevRotCount = rotCount prevSclCount = sclCount if posTest or rotTest or sclTest or wSclTest: if posTest or sclTest or wSclTest: if sclTest: sclX = sclFrames[sclCount].value[0] sclY = sclFrames[sclCount].value[1] sclZ = sclFrames[sclCount].value[2] else: sclX = oldSclX sclY = oldSclY sclZ = oldSclZ if posTest: if anim.bones[anim.kfBones[i].boneIndex].parentIndex != -1: pMatrix = anim.bones[anim.bones[anim.kfBones[i].boneIndex].parentIndex]._matrix matrix = anim.bones[anim.kfBones[i].boneIndex]._matrix bm = pMatrix.toQuat().toMat43().inverse() bms = math.sqrt((matrix[0][0] * matrix[0][0]) + (matrix[1][0] * matrix[1][0]) + (matrix[2][0] * matrix[2][0])) bm[3][0] = posFrames[posCount].value[0] bm[3][1] = posFrames[posCount].value[1] bm[3][2] = posFrames[posCount].value[2] bm = bm.inverse() posX = (bm[3][0] * -1 * bms * wSclX) - (matrix[3][0] - pMatrix[3][0]) posY = (bm[3][1] * -1 * bms * wSclY) - (matrix[3][1] - pMatrix[3][1]) posZ = (bm[3][2] * -1 * bms * wSclZ) - (matrix[3][2] - pMatrix[3][2]) else: posX = posFrames[posCount].value[0] posY = posFrames[posCount].value[1] posZ = posFrames[posCount].value[2] elif wSclTest: if anim.bones[anim.kfBones[i].boneIndex].parentIndex != -1: pMatrix = anim.bones[anim.bones[anim.kfBones[i].boneIndex].parentIndex]._matrix matrix = anim.bones[anim.kfBones[i].boneIndex]._matrix bm = pMatrix.toQuat().toMat43().inverse() bms = math.sqrt((pMatrix[0][0] * pMatrix[0][0]) + (pMatrix[1][0] * pMatrix[1][0]) + (pMatrix[2][0] * pMatrix[2][0])) bm[3][0] = posFrames[posCount].value[0] bm[3][1] = posFrames[posCount].value[1] bm[3][2] = posFrames[posCount].value[2] bm = bm.inverse() posX = (bm[3][0] * -1 * bms * wSclX) - (matrix[3][0] - pMatrix[3][0]) posY = (bm[3][1] * -1 * bms * wSclY) - (matrix[3][1] - pMatrix[3][1]) posZ = (bm[3][2] * -1 * bms * wSclZ) - (matrix[3][2] - pMatrix[3][2]) else: posX = posFrames[posCount].value[0] * wSclX posY = posFrames[posCount].value[1] * wSclY posZ = posFrames[posCount].value[2] * wSclZ if anim.bones[anim.kfBones[i].boneIndex].parentIndex != -1: worldScale[anim.kfBones[i].boneIndex].append([sclX * wSclX, sclY * wSclY, sclZ * wSclZ]) else: worldScale[anim.kfBones[i].boneIndex].append([sclX, sclY, sclZ]) oldSclX = sclX oldSclY = sclY oldSclZ = sclZ oldPosX = posX oldPosY = posY oldPosZ = posZ else: if anim.bones[anim.kfBones[i].boneIndex].parentIndex != -1: worldScale[anim.kfBones[i].boneIndex].append([sclX * wSclX, sclY * wSclY, sclZ * wSclZ]) else: worldScale[anim.kfBones[i].boneIndex].append([sclX, sclY, sclZ]) posX = oldPosX posY = oldPosY posZ = oldPosZ if rotTest: bm = anim.bones[anim.kfBones[i].boneIndex]._matrix.toQuat() if anim.bones[anim.kfBones[i].boneIndex].parentIndex != -1: pbm = anim.bones[anim.bones[anim.kfBones[i].boneIndex].parentIndex]._matrix quat = rotFrames[rotCount].value * pbm.toQuat() else: quat = rotFrames[rotCount].value bm[0] *= -1 bm[1] *= -1 bm[3] *= -1 quat[0] *= -1 quat[1] *= -1 quat[3] *= -1 quat = (quat.toMat43() * bm.toMat43().inverse()).toQuat() oldQuat = quat else: quat = oldQuat animData[0].append(anim.bones[anim.kfBones[i].boneIndex].name) animData[1].append(a) animData[2].append([posX, posY, posZ, quat]) else: if anim.bones[anim.kfBones[i].boneIndex].parentIndex != -1: worldScale[anim.kfBones[i].boneIndex].append([sclX * wSclX, sclY * wSclY, sclZ * wSclZ]) else: worldScale[anim.kfBones[i].boneIndex].append([sclX, sclY, sclZ]) if len(posFrames) > 1 and posFrames[posCount + 1].time == a + 1: posCount += 1 if len(rotFrames) > 1 and rotFrames[rotCount + 1].time == a + 1: rotCount += 1 if len(sclFrames) > 1 and sclFrames[sclCount + 1].time == a + 1: sclCount += 1 f.write(struct.pack('i',len(animData[0]))) for i in range(len(animData[0])): f.write(animData[0][i][:14].ljust(15, chr(0)).encode("shift_jis")) f.write(struct.pack('i',animData[1][i])) if not animData[0][i].endswith("_scl") and not animData[0][i].endswith("_vis") and not animData[0][i].endswith("_cov") and not animData[0][i].endswith("_trf") and not animData[0][i].endswith("_rpt") and not animData[0][i].endswith("_off"): f.write(struct.pack('f',animData[2][i][0] * pmxScale)) f.write(struct.pack('f',animData[2][i][1] * pmxScale)) f.write(struct.pack('f',animData[2][i][2] * -1 * pmxScale)) else: f.write(struct.pack('f',animData[2][i][0])) f.write(struct.pack('f',animData[2][i][1])) f.write(struct.pack('f',animData[2][i][2])) f.write(animData[2][i][3].toBytes()) f.write(bytearray.fromhex("14 14 00 00 14 14 14 14 6B 6B 6B 6B 6B 6B 6B 6B 14 14 14 14 14 14 14 6B 6B 6B 6B 6B 6B 6B 6B 00 14 14 14 14 14 14 6B 6B 6B 6B 6B 6B 6B 6B 00 00 14 14 14 14 14 6B 6B 6B 6B 6B 6B 6B 6B 00 00 00")) f.write(struct.pack('5i',0,0,0,0,0)) f.close()