From c320310084a8ef454108829f4d2dbf5c3b4e3874 Mon Sep 17 00:00:00 2001 From: Will Snyder Date: Sun, 10 Jan 2021 12:25:03 -0500 Subject: [PATCH] zaa transforms properly readjusted wrt omitted effectors/roots --- addons/io_scene_swbf_msh/zaa_to_blend.py | 69 +++++++++++++++--------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/addons/io_scene_swbf_msh/zaa_to_blend.py b/addons/io_scene_swbf_msh/zaa_to_blend.py index e59859a..4ae2e52 100644 --- a/addons/io_scene_swbf_msh/zaa_to_blend.py +++ b/addons/io_scene_swbf_msh/zaa_to_blend.py @@ -44,12 +44,18 @@ def decompress_curves(input_file) -> Dict[int, Dict[int, List[ Dict[int,float]]] with head.read_child() as mina: for i in range(num_anims): - mina.skip_bytes(8) + + transBitFlags = mina.read_u32() + mina.skip_bytes(4) anim_crc = mina.read_u32() anim_crcs.append(anim_crc) - anim_metadata[anim_crc] = {"num_frames" : mina.read_u16(), "num_bones" : mina.read_u16()} + anim_metadata[anim_crc] = { + "num_frames" : mina.read_u16(), + "num_bones" : mina.read_u16(), + "transBitFlags" : transBitFlags, + } # Read TADA offsets and quantization parameters for each rot + loc component, for each bone, for each anim with head.read_child() as tnja: @@ -57,10 +63,13 @@ def decompress_curves(input_file) -> Dict[int, Dict[int, List[ Dict[int,float]]] for i, anim_crc in enumerate(anim_crcs): bone_params = {} + bone_list = [] for _ in range(anim_metadata[anim_crc]["num_bones"]): - bone_crc = tnja.read_u32() + bone_crc = tnja.read_u32() + + bone_list.append(bone_crc) bone_params[bone_crc] = { "rot_offsets" : [tnja.read_u32() for _ in range(4)], # Offsets into TADA for rotation @@ -69,6 +78,7 @@ def decompress_curves(input_file) -> Dict[int, Dict[int, List[ Dict[int,float]]] } anim_metadata[anim_crc]["bone_params"] = bone_params + anim_metadata[anim_crc]["bone_list"] = bone_list # Decompress/dequantize frame data into discrete per-component curves with head.read_child() as tada: @@ -80,9 +90,11 @@ def decompress_curves(input_file) -> Dict[int, Dict[int, List[ Dict[int,float]]] num_frames = anim_metadata[anim_crc]["num_frames"] num_bones = anim_metadata[anim_crc]["num_bones"] + transBitFlags = anim_metadata[anim_crc]["transBitFlags"] + #print("\n\tAnim hash: {} Num frames: {} Num joints: {}".format(hex(anim_crc), num_frames, num_bones)) - for bone_num, bone_crc in enumerate(anim_metadata[anim_crc]["bone_params"]): + for bone_num, bone_crc in enumerate(anim_metadata[anim_crc]["bone_list"]): bone_curves = [] @@ -96,9 +108,6 @@ def decompress_curves(input_file) -> Dict[int, Dict[int, List[ Dict[int,float]]] for o, start_offset in enumerate(offsets_list): - # Skip to start of compressed data for component, as specified in TNJA - tada.skip_bytes(start_offset) - # Init curve dict curve : Dict[int,float] = {} @@ -115,6 +124,12 @@ def decompress_curves(input_file) -> Dict[int, Dict[int, List[ Dict[int,float]]] # Translations have specific quantization parameters; biases for each component and # a single multiplier for all three else: + + if (0x00000001 << bone_num) & transBitFlags == 0: + bone_curves.append(None) + continue + + mult = qparams[-1] bias = qparams[o - 4] @@ -122,6 +137,10 @@ def decompress_curves(input_file) -> Dict[int, Dict[int, List[ Dict[int,float]]] #print("\n\t\t\tOffset {}: {} ({}, {} remaining)".format(o,start_offset, tada.get_current_pos(), tada.how_much_left(tada.get_current_pos()))) + # Skip to start of compressed data for component, as specified in TNJA + tada.skip_bytes(start_offset) + + j = 0 while (j < num_frames): accumulator = bias + mult * tada.read_i16() @@ -232,17 +251,14 @@ def extract_and_apply_munged_anim(input_file_path): bone_obj_parent = bone_obj.parent bind_mat = bone_obj.matrix_local - stack_mat = Matrix.Identity(4) - while(True): if bone_obj_parent is None or bone_obj_parent.name in arma.data.bones: break bind_mat = bone_obj_parent.matrix_local @ bind_mat - stack_mat = bone_obj_parent.matrix_local @ stack_mat bone_obj_parent = bone_obj_parent.parent - bone_bind_poses[bone.name] = bind_mat.inverted() @ stack_mat + bone_bind_poses[bone.name] = bind_mat.inverted() @@ -254,8 +270,6 @@ def extract_and_apply_munged_anim(input_file_path): else: anim_str = str(hex(anim_crc)) - #print("\nExtracting anim: " + anim_crc_str) - if anim_str in bpy.data.actions: bpy.data.actions[anim_str].use_fake_user = False bpy.data.actions.remove(bpy.data.actions[anim_str]) @@ -268,8 +282,6 @@ def extract_and_apply_munged_anim(input_file_path): for bone in arma.pose.bones: bone_crc = to_crc(bone.name) - #print("\tGetting curves for bone: " + bone.name) - if bone_crc not in animation: continue; @@ -280,6 +292,8 @@ def extract_and_apply_munged_anim(input_file_path): bone_curves = animation[bone_crc] num_frames = max(bone_curves[0]) + has_translation = bone_curves[4] is not None + #print("\t\tNum frames: " + str(num_frames)) last_values = [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] @@ -322,14 +336,16 @@ def extract_and_apply_munged_anim(input_file_path): fcurve_rot_y = action.fcurves.new(rot_data_path, index=2, action_group=bone.name) fcurve_rot_z = action.fcurves.new(rot_data_path, index=3, action_group=bone.name) - fcurve_loc_x = action.fcurves.new(loc_data_path, index=0, action_group=bone.name) - fcurve_loc_y = action.fcurves.new(loc_data_path, index=1, action_group=bone.name) - fcurve_loc_z = action.fcurves.new(loc_data_path, index=2, action_group=bone.name) + if has_translation: + fcurve_loc_x = action.fcurves.new(loc_data_path, index=0, action_group=bone.name) + fcurve_loc_y = action.fcurves.new(loc_data_path, index=1, action_group=bone.name) + fcurve_loc_z = action.fcurves.new(loc_data_path, index=2, action_group=bone.name) for frame in range(num_frames): q = get_quat(frame) if q is not None: + # Very bloated, but works for now q = (bind_mat @ convert_rotation_space(q).to_matrix().to_4x4()).to_quaternion() fcurve_rot_w.keyframe_points.insert(frame,q.w) @@ -337,13 +353,16 @@ def extract_and_apply_munged_anim(input_file_path): fcurve_rot_y.keyframe_points.insert(frame,q.y) fcurve_rot_z.keyframe_points.insert(frame,q.z) - t = get_vec(frame) - if t is not None: - # '' - t = (bind_mat @ Matrix.Translation(convert_vector_space(t))).translation - fcurve_loc_x.keyframe_points.insert(frame,t.x) - fcurve_loc_y.keyframe_points.insert(frame,t.y) - fcurve_loc_z.keyframe_points.insert(frame,t.z) + if has_translation: + + t = get_vec(frame) + if t is not None: + + t = (bind_mat @ Matrix.Translation(convert_vector_space(t))).translation + + fcurve_loc_x.keyframe_points.insert(frame,t.x) + fcurve_loc_y.keyframe_points.insert(frame,t.y) + fcurve_loc_z.keyframe_points.insert(frame,t.z) arma.animation_data.action = action