From 55bb2e423b6f246a26a583e452e38605f59d81ff Mon Sep 17 00:00:00 2001 From: Hipstercat Date: Tue, 23 Feb 2021 19:04:32 +0100 Subject: [PATCH] skn + anm --- anm.py | 267 ++++++++++++++++++++++++++++++++++++++++ skn.py | 377 ++++++++++++++++++++++++++++++++------------------------- 2 files changed, 480 insertions(+), 164 deletions(-) create mode 100644 anm.py diff --git a/anm.py b/anm.py new file mode 100644 index 0000000..e9067bb --- /dev/null +++ b/anm.py @@ -0,0 +1,267 @@ +from lib.fileutils import * +import logging +import sys + + +class MConsoleHandler(logging.StreamHandler): + special_code = '[!n]' + + def emit(self, record) -> None: + record.msg = str(record.msg) + if self.special_code in record.msg: + record.msg = record.msg.replace(self.special_code, '') + self.terminator = '' + else: + self.terminator = '\n' + return super().emit(record) + + +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) +cs = MConsoleHandler(sys.stdout) +fmt = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s") +fmt = logging.Formatter("%(message)s") +cs.setFormatter(fmt) +logger.addHandler(cs) + +NAM_FlagHasHandles = (1 << 0) +NAM_FlagCaseInsensitive = (1 << 1) +ANM_NODE_FLAG_POS_ANIMATED = (1 << 0) +ANM_NODE_FLAG_ROT_ANIMATED = (1 << 1) +ANM_NODE_FLAG_ROL_ANIMATED = (1 << 2) +ANM_NODE_FLAG_SCL_ANIMATED = (1 << 3) +ANM_NODE_FLAG_AFF_ANIMATED = (1 << 4) +ANM_NODE_FLAG_USR_ANIMATED = (1 << 5) +ANM_NODE_FLAG_ANIMATED = ((1 << 6) - 1) + + +def printdebug(msg): + logger.debug(msg) + + +def printinfo(msg): + logger.info(msg, ) + + +def tb(i): + return 1 if i > 0 else 0 + + +def read_int_and_print(n, b): + a = read_int(b) + printdebug("%s=%s" % (n, a)) + return a + + +def read_float_and_print(n, b): + a = read_float(b) + printdebug("%s=%s" % (n, a)) + return a + + +def read_byte_and_print(n, b): + a = read_byte(b) + printdebug("%s=%s" % (n, a)) + return a + + +def read_short_and_print(n, b): + a = read_short(b) + printdebug("%s=%s" % (n, a)) + return a + + +class ANM_Anim: + def __init__(self): + self.custom = 0 + self.file_version = 0 + self.image = 0 + self.memgroup = 0 + self.node_dictionary = 0 + self.tree_dictionary = 0 + self.default_obj_dictionnary = 0 + self.total_number_trees = 0 + self.total_number_objs = 0 + self.total_number_clusters = 0 + self.name = 0 + + @classmethod + def parse(cls, b): + printinfo("Decoding %s" % b.name) + + printdebug("MAP_Image") + read_int_and_print("size", b) + memgroupoffset = read_int_and_print("memgroupoffset", b) + + b.seek(memgroupoffset) + + printdebug("MAP_MemGroup") + printdebug("\tMAP_Mem") + read_int_and_print("\tNode", b) + read_int_and_print("\tSize", b) + read_int_and_print("\tFlags", b) + + read_int_and_print("pMemGroup", b) + read_int_and_print("MemList", b) + read_int_and_print("TotalSize", b) + read_int_and_print("TotalBlocks", b) + base = read_int_and_print("pBase", b) + + b.seek(base) + printdebug("=========") + printdebug("ANM_Anim") + read_int_and_print("pCustom", b) + read_int_and_print("FileVersion", b) + read_int_and_print("pImage", b) + read_int_and_print("pMemGroup", b) + starttime = read_int_and_print("StartTime", b) + endtime = read_int_and_print("EndTime", b) + ticksperframe = read_int_and_print("TicksPerFrame", b) + framerate = read_int_and_print("FrameRate", b) + tree = read_int_and_print("pTreeDictionary", b) + defaultobj = read_int_and_print("pDefaultObjDictionary", b) + numnodes = read_int_and_print("NumberOfNodes", b) + printdebug("ANM_AnimExtra") + read_int_and_print("ANM_AnimExtra->Stamp", b) + read_int_and_print("ANM_AnimExtra->Flags", b) + read_int_and_print("ANM_AnimExtra->Time1", b) + read_int_and_print("ANM_AnimExtra->Stamp1", b) + read_int_and_print("ANM_AnimExtra->Time2", b) + read_int_and_print("ANM_AnimExtra->Stamp2", b) + read_float_and_print("ANM_AnimExtra->Factor", b) + read_int_and_print("ANM_AnimExtra->OtherAnim", b) + name = read_string_until_none(b) + printdebug(name) + + printinfo("[%s] StartTime:%s EndTime:%s TicksPerFrame:%s FrameRate:%s NumNodes:%s" % (name, starttime, endtime, ticksperframe , framerate, numnodes)) + + printdebug("=========") + + printdebug("ANM_Anim->pTreeDictionary NAM_Dictionary") + b.seek(defaultobj) + read_int_and_print("pMemGroup", b) + namemapper = read_int_and_print("pNameMapper", b) + flags = read_int_and_print("Flags", b) + printdebug("Flags: NAM_FlagHasHandles: %s, NAM_FlagCaseInsensitive: %s" % (flags & NAM_FlagHasHandles, flags & NAM_FlagCaseInsensitive)) + namehandle = read_short_and_print("NameHandle", b) + + + printdebug("MAP_Image->ANM_Anim->NAM_Dictionnary->MAP_Mapper") + b.seek(namemapper) + pMemGroup = read_int_and_print("pMemGroup", b) + read_int_and_print("MemBaseSize", b) + read_int_and_print("MemBlocks", b) + read_int_and_print("MemSize", b) + read_int_and_print("MemFree", b) + mem = read_int_and_print("pMem", b) + read_int_and_print("MaxMappings", b) + totalmappings = read_int_and_print("TotalMappings", b) + read_int_and_print("TotalKeys", b) + pKeyContexts = read_int_and_print("pKeyContexts", b) + + printdebug("MAP_Image->ANM_Anim->NAM_Dictionnary->MAP_Mapper->MAP_KeyContext NAM_STRING_KEY") + b.seek(pKeyContexts) + read_int_and_print("\tSize", b) + read_int_and_print("\tpCallback", b) + read_int_and_print("\tIndex", b) + read_int_and_print("\tTest", b) + pLUTNAM_STRING_KEY = read_int_and_print("pLUT", b) + read_int_and_print("Reserve", b) + read_int_and_print("pData", b) + + def showdictbyindex(i): + assert(0 <= i < totalmappings) + printdebug("LUT NAM_STRING_KEY") + b.seek(pLUTNAM_STRING_KEY) + pind0_string = read_int_and_print("LUT NAM_STRING_KEY[0]", b) + for _ in range(i): + pind0_string = read_int_and_print("LUT NAM_STRING_KEY[0]", b) + printdebug("NAM_StringData") + b.seek(pind0_string) + read_int_and_print("pPtr->ANM_Obj", b) + val = read_int_and_print("Value", b) + printdebug(b.tell()) + nodename = read_string_until_none(b) + printdebug(nodename) + + b.seek(val) + + read_int_and_print("ANM_Node->Custom", b) + read_short_and_print("ANM_Node->Type", b) + read_short_and_print("ANM_Node->XformType", b) + nodeflags = read_int_and_print("ANM_Node->Flags", b) + read_int_and_print("ANM_Node->pAnim", b) + read_int_and_print("ANM_Node->pParent", b) + read_int_and_print("ANM_Node->pTarget", b) + read_int_and_print("ANM_Node->pUserCall", b) + read_int_and_print("ANM_Node->pUserContext", b) + stamp = read_int_and_print("ANM_Node->Stamp", b) + printdebug("ANM_Node->Mat") + read_int_and_print("GEO_Mat->Class", b) + for _i in range(4): + for _j in range(4): + read_float_and_print("GEO_Mat->E", b) + + printdebug("ANM_Node->Transform") + transformtime = read_int_and_print("ANM_Transform->Time", b) + printdebug("ANM_Transform->Affine") + read_float_and_print("GEO_Affine->Trans[x]", b) + read_float_and_print("GEO_Affine->Trans[y]", b) + read_float_and_print("GEO_Affine->Trans[z]", b) + read_float_and_print("GEO_Affine->Quat[x]", b) + read_float_and_print("GEO_Affine->Quat[y]", b) + read_float_and_print("GEO_Affine->Quat[z]", b) + read_float_and_print("GEO_Affine->Quat[w]", b) + read_float_and_print("GEO_Affine->Scale[x]", b) + read_float_and_print("GEO_Affine->Scale[y]", b) + read_float_and_print("GEO_Affine->Scale[z]", b) + read_int_and_print("GEO_Affine->Class", b) + + posKeys = read_int_and_print("ANM_Node->pPosKeys", b) + rotKeys = read_int_and_print("ANM_Node->pRotKeys", b) + sclKeys = read_int_and_print("ANM_Node->pSclKeys", b) + + printinfo("\t[%s] Animated:%s[!n]" % (nodename, bool(nodeflags & ANM_NODE_FLAG_ANIMATED))) + if nodeflags & ANM_NODE_FLAG_POS_ANIMATED: + printinfo(" PosAnimated:True[!n]") + if nodeflags & ANM_NODE_FLAG_ROT_ANIMATED: + printinfo(" RotAnimated:True[!n]") + if nodeflags & ANM_NODE_FLAG_ROL_ANIMATED: + printinfo(" RolAnimated:True[!n]") + if nodeflags & ANM_NODE_FLAG_SCL_ANIMATED: + printinfo(" SclAnimated:True[!n]") + if nodeflags & ANM_NODE_FLAG_AFF_ANIMATED: + printinfo(" AffAnimated:True[!n]") + if nodeflags & ANM_NODE_FLAG_USR_ANIMATED: + printinfo(" UsrAnimated:True[!n]") + printinfo("") + + """ + printinfo("\t[%s] Anim:%s Pos:%s Rot:%s Rol:%s Scl:%s Aff:%s Usr:%s" % ( + nodename, tb(nodeflags & ANM_NODE_FLAG_ANIMATED), tb(nodeflags & ANM_NODE_FLAG_POS_ANIMATED), tb(nodeflags & ANM_NODE_FLAG_ROT_ANIMATED), + tb(nodeflags & ANM_NODE_FLAG_ROL_ANIMATED), tb(nodeflags & ANM_NODE_FLAG_SCL_ANIMATED), tb(nodeflags & ANM_NODE_FLAG_AFF_ANIMATED), + tb(nodeflags & ANM_NODE_FLAG_USR_ANIMATED))) + """ + + if nodeflags & ANM_NODE_FLAG_POS_ANIMATED: + b.seek(posKeys) + read_byte_and_print("\t\tType", b) + read_byte_and_print("\t\tORTBefore", b) + read_byte_and_print("\t\tORTAfter", b) + read_byte_and_print("\t\tFlags", b) + read_int_and_print("\t\tpInterpolate", b) + read_int_and_print("\t\tNumberOfKeys", b) + read_int_and_print("\t\tpKeys", b) + + for p in range(totalmappings): + showdictbyindex(p) + + +def main(): + #with open("/home/tasty/Projects/gck-map-extract-objects/anm_skn/sm_book.anm", "rb") as fp: + # with open("/home/tasty/Projects/gck-map-extract-objects/anm_skn/vp_hit.anm", "rb") as fp: + with open("/home/tasty/Projects/gck-map-extract-objects/anm_skn/Mc_salute.anm", "rb") as fp: + ANM_Anim.parse(fp) + +if __name__ == "__main__": + main() diff --git a/skn.py b/skn.py index 8a6cdc2..752ee39 100644 --- a/skn.py +++ b/skn.py @@ -1,65 +1,193 @@ from lib.fileutils import * +from dataclasses import dataclass, field +from typing import List, Union + + +@dataclass +class Vec3Indexed: + x: float + y: float + z: float + index: int + + @classmethod + def create(cls, b, offset=None): + old = b.tell() + if offset: + b.seek(offset) + x = read_float_and_print("Vec3->x", b) + y = read_float_and_print("Vec3->y", b) + z = read_float_and_print("Vec3->z", b) + index = read_int_and_print("Vec3->index", b) + if offset: + b.seek(old) + return cls(x=x, y=y, z=z, index=index) + + +@dataclass +class Vec3: + x: float + y: float + z: float + + @classmethod + def create(cls, b, offset=None): + old = b.tell() + if offset: + b.seek(offset) + x = read_float_and_print("Vec3->x", b) + y = read_float_and_print("Vec3->y", b) + z = read_float_and_print("Vec3->z", b) + if offset: + b.seek(old) + return cls(x=x, y=y, z=z) + + +@dataclass +class AnmObj: + custom: int + skin: int = field(repr=False) + zero_cluster: int + total_number_vertices: int + num_clusters: int + clusters: List['AnmCluster'] + + @classmethod + def create(cls, b, offset=None): + old = b.tell() + if offset: + b.seek(offset) + custom = read_int_and_print("ANM_Obj->Custom", b) + skin = read_int_and_print("ANM_Obj->Skin", b) + zero = read_int_and_print("ANM_Obj->ZeroCluster", b) + total_vertices = read_int_and_print("ANM_Obj->TotalNumberOfVertices", b) + num_clusters = read_int_and_print("ANM_Obj->NumberOfClusters", b) + clusters_offset = read_int_and_print("ANM_Obj->Clusters", b) + clusters = [] + _old1 = b.tell() + b.seek(clusters_offset) + for _ in range(num_clusters): + cluster = AnmCluster.create(b) + clusters.append(cluster) + + b.seek(_old1) + if offset: + b.seek(old) + r = cls(custom=custom, skin=skin, zero_cluster=zero, total_number_vertices=total_vertices, num_clusters=num_clusters, clusters=clusters) + for cluster in clusters: + cluster.obj = r + return r + + +@dataclass +class AnmCluster: + custom: int = field(repr=False) + obj: Union[AnmObj, None] + handle: int + bounding_box: List[Vec3] = field(repr=False) # size 2 + num_vertices: int + vertices: List[Vec3Indexed] = field(repr=False) + bone_name: str = "" + + @classmethod + def create(cls, b, offset=None): + old = b.tell() + if offset: + b.seek(offset) + custom = read_int_and_print("ANM_Cluster->Custom", b) + obj_offset = read_int_and_print("ANM_Cluster->Obj", b) + if obj_offset == 0: # ugly hack, dunno why we need that + _ = read_int_and_print("ANM_Cluster->Custom", b) + _ = read_int_and_print("ANM_Cluster->Obj", b) + obj = None # is set by parent Obj + handle = read_int_and_print("ANM_Cluster->Handle", b) + bbox1 = Vec3.create(b) + bbox2 = Vec3.create(b) + bounding_box = [bbox1, bbox2] + num_vertices = read_int_and_print("ANM_Cluster->num_vertices", b) + vertices = [] + for _ in range(num_vertices): + v = Vec3Indexed.create(b) + vertices.append(v) + + if offset: + b.seek(old) + return cls(custom=custom, obj=obj, handle=handle, bounding_box=bounding_box, num_vertices=num_vertices, vertices=vertices) + + +class NamDictionnary: + @staticmethod + def create(b, cls, depth=1, offset=None): + r = {} + + old = b.tell() + if offset: + b.seek(offset) + + read_int_and_print("NAM_Dictionnary->pMemGroup", b) + namemapper = read_int_and_print("NAM_Dictionnary->pNameMapper", b) + flags = read_int_and_print("NAM_Dictionnary->Flags", b) + print("Flags: NAM_FlagHasHandles: %s, NAM_FlagCaseInsensitive: %s" % (flags & NAM_FlagHasHandles, flags & NAM_FlagCaseInsensitive)) + read_short_and_print("NAM_Dictionnary->NameHandle", b) + + b.seek(namemapper) + read_int_and_print("pMemGroup", b) + read_int_and_print("MemBaseSize", b) + read_int_and_print("MemBlocks", b) + read_int_and_print("MemSize", b) + read_int_and_print("MemFree", b) + read_int_and_print("pMem", b) + read_int_and_print("MaxMappings", b) + totalmappings = read_int_and_print("TotalMappings", b) + read_int_and_print("TotalKeys", b) + p_key_contexts = read_int_and_print("pKeyContexts", b) + + print("MAP_Image->ANM_Skin->NAM_Dictionnary->MAP_Mapper->MAP_KeyContext") + b.seek(p_key_contexts) + print("\tMAP_Image->ANM_Skin->NAM_Dictionnary->MAP_Mapper->MAP_KeyContext->MAP_BinSearchContext") + _ = read_int_and_print("\tSize", b) + read_int_and_print("\tpCallback", b) + read_int_and_print("\tIndex", b) + read_int_and_print("\tTest", b) + p_lut = read_int_and_print("pLUT", b) + read_int_and_print("Reserve", b) + read_int_and_print("pData", b) + + for i in range(totalmappings): + b.seek(p_lut) + pindx = read_int(b) + for _ in range(i): + pindx = read_int(b) + print("LUT INDEX: %s" % pindx) + b.seek(pindx) + if not flags & NAM_FlagHasHandles: + read_short_and_print("pPtr", b) + read_short_and_print("pPtr2", b) + val = read_int_and_print("Value", b) + name = read_string_until_none_and_print("name", b) + if depth > 1: + item = NamDictionnary.create(b, cls, depth-1, val) + else: + item = cls.create(b, val) + r[name] = item + else: + refcnt = read_short_and_print("RefCnt", b) + handle = read_short_and_print("Handle", b) + read_int_and_print("Test", b) + read_int_and_print("Test", b) + bone_name = read_string_until_none_and_print("BoneName", b) + r[str(i)] = {"RefCnt": refcnt, "Handle": handle, "BoneName": bone_name} + + if offset: + b.seek(old) + + return r + NAM_FlagHasHandles = (1 << 0) NAM_FlagCaseInsensitive = (1 << 1) -class MAP_KeyContext: - def __init__(self): - self.context = 0 - self.ppLUT = 0 - self.reserve = 0 - self.pData = 0 - - @classmethod - def parse(cls, b): - r = cls() - r.context = read_int(b) - r.ppLUT = read_int(b) - r.reserve = read_int(b) - r.pData = read_int(b) - return r - - -class MAP_Mapper: - def __init__(self): - self.pMemgroup = 0 - self.MemBaseSize = 0 - self.MemBlocks = 0 - self.MemSize = 0 - self.MemFree = 0 - self.pMem = 0 - self.MaxMappings = 0 - self.TotalMappings = 0 - self.TotalKeys = 0 - self.pKeyContexts = 0 - - @classmethod - def parse(cls, b): - r = cls() - r.pMemgroup = read_int(b) - r.MemBaseSize = read_int(b) - r.MemBlocks = read_int(b) - r.MemSize = read_int(b) - r.MemFree = read_int(b) - r.pMem = read_int(b) - r.MaxMappings = read_int(b) - r.TotalMappings = read_int(b) - r.TotalKeys = read_int(b) - r.pKeyContexts = read_int(b) - return r - -class MAP_Mapping: - def __init__(self): - self.index = 0 - - @classmethod - def parse(cls, b): - r = cls() - r.index = read_short(b) - return r - - def read_int_and_print(n, b): a = read_int(b) print("%s=%s" % (n, a)) @@ -84,24 +212,21 @@ def read_short_and_print(n, b): return a -class MAP_MemGroup: - def __init__(self): - self.mem = 0 - self.memgroup = 0 - self.memlist = 0 - self.total_size = 0 - self.total_blocks = 0 - self.base = 0 +def read_string_until_none_and_print(n, b): + s = read_string_until_none(b) + print("%s=%s" % (n, s)) + return s -class MAP_Image: - def __init__(self): - self.size = 0 - self.memgroupoffset = 0 +def link(nodedict, defaultobjtree): + for obj_name, obj in defaultobjtree.items(): + for cluster in obj.clusters: + cluster_handle = cluster.handle + k = str(cluster_handle-1) + cluster.bone_name = nodedict[k]["BoneName"] - -class ANM_Skin: +class AnmSkin: def __init__(self): self.custom = 0 self.file_version = 0 @@ -117,9 +242,7 @@ class ANM_Skin: @classmethod def parse(cls, b): - print("MAP_Image") - read_int_and_print("size", b) - ret = b.tell() + _ = read_int_and_print("size", b) memgroupoffset = read_int_and_print("memgroupoffset", b) b.seek(memgroupoffset) @@ -143,110 +266,36 @@ class ANM_Skin: read_int_and_print("FileVersion", b) read_int_and_print("pImage", b) read_int_and_print("pMemGroup", b) - read_int_and_print("pNodeDictionary", b) + node = read_int_and_print("pNodeDictionary", b) tree = read_int_and_print("pTreeDictionary", b) defaultobj = read_int_and_print("pDefaultObjDictionary", b) read_int_and_print("TotalNumberOfTrees", b) read_int_and_print("TotalNumberOfObjs", b) read_int_and_print("TotalNumberOfClusters", b) - print(read_string_until_none(b)) + read_string_until_none_and_print("Name", b) print("=========") - print("ANM_Skin->pTreeDictionary NAM_Dictionary") - b.seek(defaultobj) - read_int_and_print("pMemGroup", b) - namemapper = read_int_and_print("pNameMapper", b) - flags = read_int_and_print("Flags", b) - print("Flags: NAM_FlagHasHandles: %s, NAM_FlagCaseInsensitive: %s" % (flags & NAM_FlagHasHandles, flags & NAM_FlagCaseInsensitive)) - namehandle = read_short_and_print("NameHandle", b) + nodedict = NamDictionnary.create(b, AnmObj, offset=node) + treedict = NamDictionnary.create(b, AnmObj, depth=2, offset=tree) + defaultobjdict = NamDictionnary.create(b, AnmObj, offset=defaultobj) + link(nodedict, defaultobjdict) - print("MAP_Image->ANM_Skin->NAM_Dictionnary->MAP_Mapper") - b.seek(namemapper) - pMemGroup = read_int_and_print("pMemGroup", b) - read_int_and_print("MemBaseSize", b) - read_int_and_print("MemBlocks", b) - read_int_and_print("MemSize", b) - read_int_and_print("MemFree", b) - mem = read_int_and_print("pMem", b) - read_int_and_print("MaxMappings", b) - totalmappings = read_int_and_print("TotalMappings", b) - read_int_and_print("TotalKeys", b) - pKeyContexts = read_int_and_print("pKeyContexts", b) - - print("MAP_Image->ANM_Skin->NAM_Dictionnary->MAP_Mapper->MAP_KeyContext NAM_STRING_KEY") - b.seek(pKeyContexts) - print("\tMAP_Image->ANM_Skin->NAM_Dictionnary->MAP_Mapper->MAP_KeyContext NAM_STRING_KEY->MAP_BinSearchContext") - read_int_and_print("\tSize", b) - read_int_and_print("\tpCallback", b) - read_int_and_print("\tIndex", b) - read_int_and_print("\tTest", b) - pLUTNAM_STRING_KEY = read_int_and_print("pLUT", b) - read_int_and_print("Reserve", b) - read_int_and_print("pData", b) - - def showdictbyindex(i): - assert(0 <= i < totalmappings) - print("LUT NAM_STRING_KEY") - b.seek(pLUTNAM_STRING_KEY) - pind0_string = read_int_and_print("LUT NAM_STRING_KEY[0]", b) - for _ in range(i): - pind0_string = read_int_and_print("LUT NAM_STRING_KEY[0]", b) - print("NAM_StringData") - b.seek(pind0_string) - print("BELOW IS CUSTOM vv") - pptr = read_short_and_print("pPtr->ANM_Obj", b) - pptr2 = read_short_and_print("pPtr2->ANM_Obj", b) - val = read_int_and_print("Value", b) - print(b.tell()) - print(read_string_until_none(b)) - - b.seek(val) - read_int_and_print("ANM_Obj->Custom", b) - read_int_and_print("ANM_Obj->Skin", b) - read_int_and_print("ANM_Obj->ZeroCluster", b) - total_vertices = read_int_and_print("ANM_Obj->TotalNumberOfVertices", b) - num_clusters = read_int_and_print("ANM_Obj->NumberOfClusters", b) - clusters = read_int_and_print("ANM_Obj->Clusters", b) - - SEEN_VERTICES_INDEX = [] - - b.seek(clusters) - for i in range(num_clusters): - print("READING CLUSTER %s" % i) - read_int_and_print("ANM_Cluster->Custom", b) - read_int_and_print("ANM_Cluster->Obj", b) - read_int_and_print("ANM_Cluster->Handle", b) - print("ANM_Cluster->BoundingBox") - print("ANM_BoundingBox->Box[0]") - read_float_and_print("X", b) - read_float_and_print("Y", b) - read_float_and_print("Z", b) - print("ANM_BoundingBox->Box[1]") - read_float_and_print("X", b) - read_float_and_print("Y", b) - read_float_and_print("Z", b) - numverts = read_int_and_print("ANM_Cluster->NumberOfVertices", b) - - for _ in range(numverts): - read_float_and_print("X", b) - read_float_and_print("Y", b) - read_float_and_print("Z", b) - vindex = read_int_and_print("Index", b) - # read_int_and_print("Weight", b) - assert(vindex not in SEEN_VERTICES_INDEX) - SEEN_VERTICES_INDEX.append(vindex) - - read_int_and_print("Unk", b) - read_int_and_print("Unk", b) - print("%s vertices in this cluster (vs %s reported)" % (len(SEEN_VERTICES_INDEX), total_vertices)) - showdictbyindex(2) + print("nodedict_len:%s" % len(nodedict)) + print("treedict_len:%s" % len(treedict)) + print(defaultobjdict) + print("defaultobjtreedict_len:%s" % len(defaultobjdict)) def main(): with open("/home/tasty/Projects/gck-map-extract-objects/anm_skn/mc_l0.skn", "rb") as fp: - # with open("/home/tasty/Projects/gck-map-extract-objects/anm_skn/dust.skn", "rb") as fp: - ANM_Skin.parse(fp) + AnmSkin.parse(fp) + + with open("/home/tasty/Projects/gck-map-extract-objects/anm_skn/rp_l0.skn", "rb") as fp: + AnmSkin.parse(fp) + + with open("/home/tasty/Projects/gck-map-extract-objects/anm_skn/kb_l0.skn", "rb") as fp: + AnmSkin.parse(fp) if __name__ == "__main__":