import io import ntpath from . import ascii_ops from . import xps_const from . import xps_types from mathutils import Vector def readUvVert(file): line = ascii_ops.readline(file) values = ascii_ops.splitValues(line) x = (ascii_ops.getFloat(values[0])) # X pos y = (ascii_ops.getFloat(values[1])) # Y pos coords = [x, y] return coords def readXYZ(file): line = ascii_ops.readline(file) values = ascii_ops.splitValues(line) x = (ascii_ops.getFloat(values[0])) # X pos y = (ascii_ops.getFloat(values[1])) # Y pos z = (ascii_ops.getFloat(values[2])) # Z pos coords = [x, y, z] return coords def fillArray(array, minLen, value): # Complete the array with selected value filled = array + [value] * (minLen - len(array)) return filled def read4Float(file): line = ascii_ops.readline(file) values = ascii_ops.splitValues(line) values = fillArray(values, 4, 0) x = (ascii_ops.getFloat(values[0])) y = (ascii_ops.getFloat(values[1])) z = (ascii_ops.getFloat(values[2])) w = (ascii_ops.getFloat(values[3])) coords = [x, y, z, w] return coords def readBoneWeight(file): line = ascii_ops.readline(file) values = ascii_ops.splitValues(line) values = fillArray(values, 4, 0) weights = [ascii_ops.getFloat(val) for val in values] return weights def readBoneId(file): line = ascii_ops.readline(file) values = ascii_ops.splitValues(line) values = fillArray(values, 4, 0) ids = [ascii_ops.getInt(val) for val in values] return ids def read4Int(file): line = ascii_ops.readline(file) values = ascii_ops.splitValues(line) values = fillArray(values, 4, 0) r = ascii_ops.getInt(values[0]) g = ascii_ops.getInt(values[1]) b = ascii_ops.getInt(values[2]) a = ascii_ops.getInt(values[3]) vertexColor = [r, g, b, a] return vertexColor def readTriIdxs(file): line = ascii_ops.readline(file) values = ascii_ops.splitValues(line) face1 = ascii_ops.getInt(values[0]) face2 = ascii_ops.getInt(values[1]) face3 = ascii_ops.getInt(values[2]) faceLoop = [face1, face2, face3] return faceLoop def readBones(file): bones = [] # Bone Count boneCount = ascii_ops.readInt(file) for boneId in range(boneCount): boneName = ascii_ops.readString(file) parentId = ascii_ops.readInt(file) coords = readXYZ(file) xpsBone = xps_types.XpsBone(boneId, boneName, coords, parentId) bones.append(xpsBone) return bones def readMeshes(file, hasBones): meshes = [] meshCount = ascii_ops.readInt(file) for meshId in range(meshCount): # Name meshName = ascii_ops.readString(file) if not meshName: meshName = 'xxx' # print('Mesh Name:', meshName) # uv Count uvLayerCount = ascii_ops.readInt(file) # Textures textures = [] textureCount = ascii_ops.readInt(file) for texId in range(textureCount): textureFile = ntpath.basename(ascii_ops.readString(file)) # print('Texture file', textureFile) uvLayerId = ascii_ops.readInt(file) xpsTexture = xps_types.XpsTexture(texId, textureFile, uvLayerId) textures.append(xpsTexture) # Vertices vertex = [] vertexCount = ascii_ops.readInt(file) for vertexId in range(vertexCount): coord = readXYZ(file) normal = readXYZ(file) vertexColor = read4Int(file) uvs = [] for uvLayerId in range(uvLayerCount): uvVert = readUvVert(file) uvs.append(uvVert) # if ???? # tangent???? # tangent = read4float(file) boneWeights = [] if hasBones: # if cero bones dont have weights to read boneIdx = readBoneId(file) boneWeight = readBoneWeight(file) for idx in range(len(boneIdx)): boneWeights.append( xps_types.BoneWeight(boneIdx[idx], boneWeight[idx])) xpsVertex = xps_types.XpsVertex( vertexId, coord, normal, vertexColor, uvs, boneWeights) vertex.append(xpsVertex) # Faces faces = [] triCount = ascii_ops.readInt(file) for i in range(triCount): triIdxs = readTriIdxs(file) faces.append(triIdxs) xpsMesh = xps_types.XpsMesh( meshName, textures, vertex, faces, uvLayerCount) meshes.append(xpsMesh) return meshes def readPoseFile(file): return file.read() def poseData(string): poseData = {} poseList = string.split('\n') for bonePose in poseList: if bonePose: pose = bonePose.split(':') boneName = pose[0] dataList = fillArray(pose[1].split(), 9, 1) rotDelta = Vector(( ascii_ops.getFloat(dataList[0]), ascii_ops.getFloat(dataList[1]), ascii_ops.getFloat(dataList[2]))) coordDelta = Vector(( ascii_ops.getFloat(dataList[3]), ascii_ops.getFloat(dataList[4]), ascii_ops.getFloat(dataList[5]))) scale = Vector(( ascii_ops.getFloat(dataList[6]), ascii_ops.getFloat(dataList[7]), ascii_ops.getFloat(dataList[8]))) bonePose = xps_types.XpsBonePose( boneName, coordDelta, rotDelta, scale) poseData[boneName] = bonePose return poseData def boneDictData(string): boneDictRename = {} boneDictRestore = {} poseList = string.split('\n') for bonePose in poseList: if bonePose: pose = bonePose.split(';') if len(pose) == 2: oldName, newName = pose boneDictRename[oldName] = newName boneDictRestore[newName] = oldName return boneDictRename, boneDictRestore def readIoStream(filename): with open(filename, "r", encoding=xps_const.ENCODING_READ) as a_file: ioStream = io.StringIO(a_file.read()) return ioStream def readXpsModel(filename): ioStream = readIoStream(filename) # print('Reading Header') # xpsHeader = readHeader(ioStream) print('Reading Bones') bones = readBones(ioStream) hasBones = bool(bones) print('Reading Meshes') meshes = readMeshes(ioStream, hasBones) xpsModelData = xps_types.XpsData(bones=bones, meshes=meshes) return xpsModelData def readXpsPose(filename): ioStream = readIoStream(filename) # print('Import Pose') poseString = readPoseFile(ioStream) bonesPose = poseData(poseString) return bonesPose def readBoneDict(filename): ioStream = readIoStream(filename) boneDictString = readPoseFile(ioStream) boneDictRename, boneDictRestore = boneDictData(boneDictString) return boneDictRename, boneDictRestore if __name__ == "__main__": readModelfilename = r'G:\3DModeling\XNALara\XNALara_XPS\data\TESTING2\Tekken\Tekken - Lili Bride\generic_item.mesh.ascii' readPosefilename = r'G:\3DModeling\XNALara\XNALara_XPS\data\TESTING2\Tekken\Tekken - Lili Bride\Lili 1.pose' print('----READ START----') xpsData = readXpsModel(readModelfilename) xpsData = readXpsPose(readPosefilename) print('----READ END----')