def from_anim(cls, f): size = j3d.read_uint32(f) sectioncount = j3d.read_uint32(f) assert sectioncount == 1 svr_data = f.read(16) clf_start = f.tell() clf_magic = f.read(4) #clf1 clf_size = j3d.read_uint32(f) loop_mode = j3d.read_uint8(f) j3d.read_uint8(f) duration = j3d.read_uint16(f) bla = cls(loop_mode, duration) cluster_count = read_uint16(f) scales_count = read_uint16(f) #print(scales_count) cluster_offset = read_uint32(f) + clf_start scales_offset = read_uint32(f) + clf_start # Read floats scales = [] f.seek(scales_offset) for i in range(scales_count): scales.append(read_float(f)) # Read clusters f.seek(cluster_offset) while (f.read(2) != b'Th'): f.seek(f.tell() - 2) new_anim = cluster_anim() clus_durati = j3d.read_uint16(f) clus_offset = j3d.read_uint16(f) #print(clus_durati) for j in range(clus_durati): new_anim.seq.append(scales[j + clus_offset]) bla.animations.append(new_anim) return bla
def get_meshes_from_bmd(bmd_file): strings = [] print("get mesh") with open(bmd_file, "rb") as f: s = f.read() a = s.find(b'\x53\x48\x50\x31') print(a) f.seek(a + 0x8) count = j3d.read_uint16(f) strings = ["Mesh " + str(i) for i in range(count)] print(strings) f.close() return strings
def read_sound_data(cls, filepath): with open(filepath, "rb") as f: header = f.read(4) if header == b"Yaz0": decomp = BytesIO() decompress(f, decomp) #print(decomp) f = decomp f.seek(0x1c) offset = j3d.read_uint32(f) if offset == 0xFFFFFFFF: return None f.seek(offset) num_entries = j3d.read_uint16(f) f.read(6) sound_entries = [] for i in range(num_entries): sound_id = j3d.read_uint32(f) start_time = j3d.read_float(f) end_time = j3d.read_float(f) coarse_pitch = j3d.read_float(f) flags = j3d.read_uint32(f) volume = j3d.read_uint8(f) fine_pitch = j3d.read_uint8(f) loop_count = j3d.read_uint8(f) pan = j3d.read_uint8(f) unk_byte = j3d.read_uint8(f) f.read(0x7) entry = cls(sound_id, start_time, end_time, coarse_pitch, flags, volume, fine_pitch, loop_count, pan, unk_byte) sound_entries.append(entry) return sound_entries
def from_anim(cls, f): size = j3d.read_uint32(f) sectioncount = j3d.read_uint32(f) assert sectioncount == 1 svr_data = f.read(16) ank_start = f.tell() ank_magic = f.read(4) #ank1 ank_size = j3d.read_uint32(f) loop_mode = j3d.read_uint8(f) angle_scale = j3d.read_sint8(f) rotscale = (2.0**angle_scale) * (180.0 / 32768.0); duration = j3d.read_uint16(f) bck = cls(loop_mode, angle_scale, duration) bone_count = read_uint16(f) scale_count = read_uint16(f) rotation_count = read_uint16(f) trans_count = read_uint16(f) bone_offset = read_uint32(f) + ank_start scale_offset = read_uint32(f) + ank_start rotation_offset = read_uint32(f) + ank_start trans_offset = read_uint32(f) + ank_start # Read scales scales = [] f.seek(scale_offset) for i in range(scale_count): scales.append(read_float(f)) # Read rotations rotations = [] f.seek(rotation_offset) for i in range(rotation_count): rotations.append((read_sint16(f))) # Read translations trans = [] f.seek(trans_offset) for i in range(trans_count): trans.append(read_float(f)) tangent_type = 0 f.seek(bone_offset) for i in range(bone_count): values = struct.unpack(">"+"H"*27, f.read(0x36)) x_scale, x_rot, x_trans = values[:3], values[3:6], values[6:9] y_scale, y_rot, y_trans = values[9:12], values[12:15], values[15:18] z_scale, z_rot, z_trans = values[18:21], values[21:24], values[24:27] bone_animation = bone_anim() for scale, axis in ((x_scale, "X"), (y_scale, "Y"), (z_scale, "Z")): count, offset, tan_type = scale tangent_type = max(tan_type, tangent_type) for j in range(count): comp = j3d.AnimComponent.from_array(offset, j, count, scales, tan_type) bone_animation.add_scale(axis, comp) #print(comp) for rotation, axis in ((x_rot, "X"), (y_rot, "Y"), (z_rot, "Z")): count, offset, tan_type = rotation tangent_type = max(tan_type, tangent_type) for j in range(count): comp = j3d.AnimComponent.from_array(offset, j, count, rotations, tan_type) comp.convert_rotation(rotscale) bone_animation.add_rotation(axis, comp) #print(comp) for translation, axis in ((x_trans, "X"), (y_trans, "Y"), (z_trans, "Z")): count, offset, tan_type = translation tangent_type = max(tan_type, tangent_type) for j in range(count): comp = j3d.AnimComponent.from_array(offset, j, count, trans, tan_type) bone_animation.add_translation(axis, comp) #print(comp) bck.animations.append(bone_animation) bck.tan_type = tangent_type return bck
def from_anim(cls, f): size = j3d.read_uint32(f) sectioncount = j3d.read_uint32(f) assert sectioncount == 1 svr_data = f.read(16) clk_start = f.tell() clk_magic = f.read(4) #clk1 clk_size = j3d.read_uint32(f) loop_mode = j3d.read_uint8(f) j3d.read_uint8(f) duration = j3d.read_uint16(f) blk = cls(loop_mode, duration) cluster_count = read_uint16(f) scales_count = int(read_uint16(f)) print("scales count " + str(scales_count)) cluster_offset = read_uint32(f) + clk_start scales_offset = read_uint32(f) + clk_start scales = [] f.seek(scales_offset) for i in range(scales_count): scales.append(read_float(f)) """ time = read_float(f) value = read_float(f) tangentIn = read_float(f) anim = j3d.AnimComponent( time, value, tangentIn ) scales.append(anim) """ tangent_type = 0 f.seek(cluster_offset) while (f.read(2) != b'Th'): f.seek(f.tell() - 2) new_anim = cluster_anim() clus_durati = j3d.read_uint16(f) clus_offset = int(j3d.read_uint16(f)) tan_type = j3d.read_uint16(f) tangent_type = max(tangent_type, tan_type) for j in range(clus_durati): comp = j3d.AnimComponent.from_array(clus_offset, j, clus_durati, scales, tan_type) #new_anim.seq.append( scales[j + clus_offset] ) new_anim.seq.append(comp) blk.animations.append(new_anim) blk.tan_type = tangent_type return blk
def from_anim(cls, f): size = read_uint32(f) #print("Size of btk: {} bytes".format(size)) sectioncount = read_uint32(f) assert sectioncount == 1 svr_data = f.read(16) ttk_start = f.tell() ttk_magic = f.read(4) ttk_sectionsize = j3d.read_uint32(f) loop_mode = j3d.read_uint8(f) angle_scale = j3d.read_sint8(f) rotscale = (2.0**angle_scale) * (180.0 / 32768.0) duration = j3d.read_uint16(f) btk = cls(loop_mode, angle_scale, duration) threetimestexmatanims = read_uint16(f) scale_count = read_uint16(f) rotation_count = read_uint16(f) translation_count = read_uint16(f) """ print("three times texmat anims", threetimestexmatanims) print("scale count", scale_count) print("rotation count", rotation_count) print("translation count", translation_count) """ texmat_anim_offset = read_uint32( f) + ttk_start # J3DAnmTransformKeyTable index_offset = read_uint32(f) + ttk_start # unsigned short stringtable_offset = read_uint32(f) + ttk_start # 0 terminated strings texmat_index_offset = read_uint32(f) + ttk_start # unsigned byte center_offset = read_uint32(f) + ttk_start # Vector with 3 entries scale_offset = read_uint32(f) + ttk_start # float rotation_offset = read_uint32(f) + ttk_start # signed short translation_offset = read_uint32(f) + ttk_start # float """ print("Position:", hex(f.tell())) print("tex anim offset", hex(texmat_anim_offset)) print("index offset", hex(index_offset)) print("mat name offset", hex(stringtable_offset)) print("texmat index offset", hex(texmat_index_offset)) print("center offset", hex(center_offset)) print("scale offset", hex(scale_offset)) print("rotation offset", hex(rotation_offset)) print("translation offset", hex(translation_offset)) """ anim_count = threetimestexmatanims // 3 #print("Animation count:", anim_count) f.seek(0x7C) unknown_address = read_uint32(f) btk.unknown_address = unknown_address # Read indices indices = [] f.seek(index_offset) for i in range(anim_count): indices.append(read_uint16(f)) # Read matrix indices mat_indices = [] f.seek(texmat_index_offset) for i in range(anim_count): mat_indices.append(read_uint8(f)) # Read stringtable f.seek(stringtable_offset) stringtable = StringTable.from_file(f) # Read scales scales = [] f.seek(scale_offset) for i in range(scale_count): scales.append(read_float(f)) # Read rotations rotations = [] f.seek(rotation_offset) for i in range(rotation_count): rotations.append((read_sint16(f))) # Read translations translations = [] f.seek(translation_offset) for i in range(translation_count): translations.append(read_float(f)) tangent_type = 0 # Read data per animation for i in indices: mat_index = mat_indices[i] # Read center for this animation f.seek(center_offset + 12 * i) center = struct.unpack(">fff", f.read(12)) name = stringtable.strings[i] """ print("================") print("anim", i) print("mat index", mat_index, "name", name, "center", center) """ f.seek(texmat_anim_offset + i * 0x36) #print(hex(texmat_anim_offset + i*0x36)) values = struct.unpack(">" + "H" * 27, f.read(0x36)) u_scale, u_rot, u_trans = values[:3], values[3:6], values[6:9] v_scale, v_rot, v_trans = values[9:12], values[12:15], values[ 15:18] w_scale, w_rot, w_trans = values[18:21], values[21:24], values[ 24:27] matrix_animation = MatrixAnimation(i, mat_index, name, center) inter_count = 0 for scale, axis in ((u_scale, "U"), (v_scale, "V"), (w_scale, "W")): count, offset, tan_type = scale tan_inter = 0 tangent_type = max(tan_type, tangent_type) for j in range(count): comp = j3d.AnimComponent.from_array( offset, j, count, scales, tan_type) if comp.tangentIn == 0: matrix_animation.tan_inter[inter_count] = 1 matrix_animation.add_scale(axis, comp) if matrix_animation.tan_inter[inter_count] == -1: matrix_animation.tan_inter[inter_count] = 0 inter_count += 1 for rotation, axis in ((u_rot, "U"), (v_rot, "V"), (w_rot, "W")): count, offset, tan_type = rotation tangent_type = max(tan_type, tangent_type) for j in range(count): comp = j3d.AnimComponent.from_array( offset, j, count, rotations, tan_type) comp.convert_rotation(rotscale) if comp.tangentIn != 0: matrix_animation.tan_inter[inter_count] = 0 matrix_animation.add_rotation(axis, comp) inter_count += 1 if matrix_animation.tan_inter[inter_count] == -1: matrix_animation.tan_inter[inter_count] = 0 for translation, axis in ((u_trans, "U"), (v_trans, "V"), (w_trans, "W")): count, offset, tan_type = translation tangent_type = max(tan_type, tangent_type) for j in range(count): comp = j3d.AnimComponent.from_array( offset, j, count, translations, tan_type) if comp.tangentIn != 0: matrix_animation.tan_inter[inter_count] = 0 matrix_animation.add_translation(axis, comp) if matrix_animation.tan_inter[inter_count] == -1: matrix_animation.tan_inter[inter_count] = 0 inter_count += 1 #btk.tan_type = tangent_type """ print(u_scale, u_rot, u_trans) print(v_scale, v_rot, v_trans) print(w_scale, w_rot, w_trans) """ btk.animations.append(matrix_animation) btk.tan_type = tangent_type return btk
def read_bls(filepath): with open(filepath, "rb") as f: magic = f.read(8) size = j3d.read_uint32(f) sectioncount = j3d.read_uint32(f) assert sectioncount == 1 svr_data = f.read(16) cls_start = f.tell() cls_magic = f.read(4) cls_size = j3d.read_uint32(f) # read counts cluster_count = j3d.read_uint16(f) keycluster_count = j3d.read_uint16(f) nrmblend_count = j3d.read_uint16(f) vtxpos_count = j3d.read_uint16(f) vtxnorm_count = j3d.read_uint16(f) f.read(2) #read offsets cluster_offset = j3d.read_uint32(f) + cls_start keycluster_offset = j3d.read_uint32(f) + cls_start nrmblend_offset = j3d.read_uint32(f) + cls_start vtxpos_offset = j3d.read_uint32(f) + cls_start vtxnorm_offset = j3d.read_uint32(f) + cls_start vtxnorm_part2_offset = vtxnorm_offset + 0xc * vtxnorm_count #index table clustername_offset = j3d.read_uint32(f) + cls_start clusterkeyname_offset = j3d.read_uint32(f) + cls_start #read vertex array vertex_poss = [] f.seek(vtxpos_offset) for i in range(vtxpos_count): x = j3d.read_float(f) y = j3d.read_float(f) z = j3d.read_float(f) vertex_poss.append(position(x, y, z)) #read the table that the normal blends refer to - so the normals vertex_norms = [] f.seek(vtxnorm_offset) for i in range(vtxnorm_count): x = j3d.read_float(f) y = j3d.read_float(f) z = j3d.read_float(f) vertex_norms.append(normal(x, y, z)) #read normal blend data nrmblends = [] f.seek(nrmblend_offset) #the first four shorts starting from offset 0x4e20 are source indices. these source indices are indices into another "blend" table. for i in range(nrmblend_count): f.seek(nrmblend_offset + 0xc * i) num = j3d.read_uint16(f) f.read(2) src = j3d.read_uint32( f ) + cls_start #offsets into section 5 part 2 - point to shorts dest = j3d.read_uint32(f) + cls_start curr_blend = normal_blend() f.seek(src) for j in range(num): index = j3d.read_uint16(f) curr_blend.src.append(vertex_norms[index]) f.seek(dest) for j in range(num): index = j3d.read_uint16(f) curr_blend.dest.append(vertex_norms[index]) #print( curr_blend ) nrmblends.append(curr_blend) f.seek(clustername_offset) cluster_stringtable = j3d.StringTable.from_file(f) f.seek(clusterkeyname_offset) clusterkey_stringtable = j3d.StringTable.from_file(f) blls = bls() for i in range(keycluster_count): f.seek(keycluster_offset + 0xc * i) #uhh only normals ig position_count = j3d.read_uint16(f) normal_count = j3d.read_uint16(f) position_offset = j3d.read_uint32(f) + cls_start normal_offset = j3d.read_uint32(f) + cls_start curr_key = clusterkey() curr_key.name = clusterkey_stringtable.strings[i] f.seek(position_offset) for j in range(position_count): index = j3d.read_uint16(f) sign_bits = (index >> 0xd) index = index & 0x1FFF curr_key.positions.append(vertex_poss[index].neg(sign_bits)) f.seek(normal_offset) for j in range(normal_count): index = j3d.read_uint16(f) sign_bits = (index >> 0xd) index = index & 0x1FFF curr_key.normals.append(vertex_norms[index].neg(sign_bits)) blls.clusters_key.append(curr_key) for i in range(cluster_count): f.seek(cluster_offset + 0x24 * i) max_angle = j3d.read_float(f) min_angle = j3d.read_float(f) unk_addr = j3d.read_uint32(f) #usually the last clusterkeynum flag = j3d.read_uint8(f) f.read(3) key_num = j3d.read_uint16(f) pos_num = j3d.read_uint16(f) normal_num = j3d.read_uint16(f) normalblend_num = j3d.read_uint16(f) position_offset = j3d.read_uint32(f) + cls_start normalblend_offset = j3d.read_uint32(f) + cls_start deformer_offset = j3d.read_uint32(f) + cls_start curr_cluster = cluster(max_angle, min_angle, flag, key_num) curr_cluster.name = cluster_stringtable.strings[i] key_index = int((unk_addr + cls_start - keycluster_offset) / 0xC) curr_cluster.clusterkey = blls.clusters_key[key_index] f.seek(position_offset) for j in range(pos_num): index = j3d.read_uint16(f) sign_bits = (index >> 0xd) #index = index & 0x1FFF curr_cluster.positions.append(index) for i in range(normalblend_num): j = int((normalblend_offset - nrmblend_offset) / 12 + i) curr_cluster.normal_blends.append(nrmblends[j]) #print( nrmblends[j] ) blls.clusters.append(curr_cluster) return blls
def from_anim(cls, f): size = j3d.read_uint32(f) sectioncount = j3d.read_uint32(f) assert sectioncount == 1 svr_data = f.read(12) sound = j3d.read_uint32(f) #print("sound " + str(sound) ) ank_start = f.tell() ank_magic = f.read(4) #ank1 ank_size = j3d.read_uint32(f) loop_mode = j3d.read_uint8(f) angle_scale = j3d.read_sint8(f) rotscale = (2.0**angle_scale) * (180.0 / 32768.0) duration = j3d.read_uint16(f) bck = cls(loop_mode, angle_scale, duration, 1) bone_count = read_uint16(f) scale_count = read_uint16(f) rotation_count = read_uint16(f) trans_count = read_uint16(f) bone_offset = read_uint32(f) + ank_start scale_offset = read_uint32(f) + ank_start rotation_offset = read_uint32(f) + ank_start trans_offset = read_uint32(f) + ank_start # Read scales scales = [] f.seek(scale_offset) for i in range(scale_count): scales.append(read_float(f)) # Read rotations rotations = [] f.seek(rotation_offset) for i in range(rotation_count): rotations.append((read_sint16(f))) # Read translations trans = [] f.seek(trans_offset) for i in range(trans_count): trans.append(read_float(f)) tangent_type = 0 f.seek(bone_offset) for i in range(bone_count): values = struct.unpack(">" + "H" * 27, f.read(0x36)) x_scale, x_rot, x_trans = values[:3], values[3:6], values[6:9] y_scale, y_rot, y_trans = values[9:12], values[12:15], values[ 15:18] z_scale, z_rot, z_trans = values[18:21], values[21:24], values[ 24:27] bone_animation = bone_anim() inter_count = 0 #default tangent interpolation is smooth for scale, axis in ((x_scale, "X"), (y_scale, "Y"), (z_scale, "Z")): count, offset, tan_type = scale tangent_type = max(tan_type, tangent_type) for j in range(count): #print( offset, j, count,tan_type, len(scales) ) comp = j3d.AnimComponent.from_array( offset, j, count, scales, tan_type) if comp.tangentIn == 0: bone_animation.tan_inter[inter_count] = 1 bone_animation.add_scale(axis, comp) #print(comp) if bone_animation.tan_inter[inter_count] == -1: bone_animation.tan_inter[inter_count] = 0 inter_count += 1 for rotation, axis in ((x_rot, "X"), (y_rot, "Y"), (z_rot, "Z")): count, offset, tan_type = rotation tangent_type = max(tan_type, tangent_type) for j in range(count): comp = j3d.AnimComponent.from_array( offset, j, count, rotations, tan_type) comp.convert_rotation(rotscale) if comp.tangentIn != 0: bone_animation.tan_inter[inter_count] = 0 bone_animation.add_rotation(axis, comp) #print(comp) if bone_animation.tan_inter[inter_count] == -1: bone_animation.tan_inter[inter_count] = 1 inter_count += 1 for translation, axis in ((x_trans, "X"), (y_trans, "Y"), (z_trans, "Z")): count, offset, tan_type = translation tangent_type = max(tan_type, tangent_type) for j in range(count): comp = j3d.AnimComponent.from_array( offset, j, count, trans, tan_type) if comp.tangentIn == 0: bone_animation.tan_inter[inter_count] = 1 bone_animation.add_translation(axis, comp) #print(comp) if bone_animation.tan_inter[inter_count] == -1: bone_animation.tan_inter[inter_count] = 0 inter_count += 1 bck.animations.append(bone_animation) bck.tan_type = tangent_type if sound != 0xffffffff: f.seek(sound) num_entries = j3d.read_uint16(f) f.read(6) sound_entries = [] for i in range(num_entries): sound_id = j3d.read_uint32(f) start_time = j3d.read_float(f) end_time = j3d.read_float(f) coarse_pitch = j3d.read_float(f) flags = j3d.read_uint32(f) volume = j3d.read_uint8(f) fine_pitch = j3d.read_uint8(f) loop_count = j3d.read_uint8(f) pan = j3d.read_uint8(f) unk_byte = j3d.read_uint8(f) f.read(0x7) entry = sound_entry(sound_id, start_time, end_time, coarse_pitch, flags, volume, fine_pitch, loop_count, pan, unk_byte) sound_entries.append(entry) bck.sound = sound_entries return bck
def from_anim(cls, f): #at this point, f is at 0x09 size = j3d.read_uint32(f) sectioncount = j3d.read_uint32(f) assert sectioncount == 1 svr_data = f.read(16) #at this point, f is at the actual start of the documentaion tpt_start = f.tell() tpt_magic = f.read(4) #TPT1 tpt_sectionsize = j3d.read_uint32(f) flag = j3d.read_uint8(f) angle = j3d.read_uint8(f) anim_length = j3d.read_uint16(f) num_entries = j3d.read_uint16(f) #also known as "keyframe count in the documentation" print("there are " + str(num_entries) + " entries") unknown1 = j3d.read_uint16(f) btp = cls(flag, angle, unknown1) #offsets facial_animation_entries_os = j3d.read_uint32(f) + tpt_start texture_index_bank_os = j3d.read_uint32(f) + tpt_start remap_table_os = j3d.read_uint32(f) + tpt_start stringtable_os = j3d.read_uint32(f) + tpt_start #at this point, we are at the facial animation entries #make string table f.seek(stringtable_os) stringtable = j3d.StringTable.from_file(f) read_animations = [] for i in range(num_entries): f.seek(facial_animation_entries_os + i * 8) print(f.tell()) this_length = j3d.read_uint16(f) print("length of " + str(i) + " is " + str(this_length)) this_start = j3d.read_uint16(f) indices = [] f.seek(texture_index_bank_os + 2 * this_start) for j in range(this_length): indices.append(j3d.read_uint16(f)) animation = btp_facial_entry(stringtable.strings[i], indices) read_animations.append(animation) btp.animations = read_animations f.close() return btp