Created
May 2, 2015 19:28
-
-
Save jackoalan/72a62f320dbebb52c66d to your computer and use it in GitHub Desktop.
MP1 ANIM-format extractor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* ANIM.c | |
* rwk | |
* | |
* Created on 10/18/13. | |
* | |
*/ | |
#include <stdio.h> | |
#include <math.h> | |
#include <float.h> | |
#include "ANIM.h" | |
/* Intermediate key binary decoder | |
* Reads binary keyframe data, populates Blender action, | |
* deletes file when complete */ | |
static const char* ANIM_BIN_DEC = | |
" def anim_add_kf(fcurve_idx, interp, time, val):\n" | |
" crv = act.fcurves[fcurve_idx]\n" | |
" crv.keyframe_points.add()\n" | |
" crv.keyframe_points[-1].interpolation = interp\n" | |
" crv.keyframe_points[-1].co = (time, val)\n" | |
" \n" | |
" def anim_bin_dec(file_path):\n" | |
" with open(file_path, 'rb') as f:\n" | |
" while True:\n" | |
" data = f.read(24)\n" | |
" if len(data) == 24:\n" | |
" m = struct.unpack('IIiIIf', data)\n" | |
" if m[1] == 0:\n" | |
" interp = 'CONSTANT'\n" | |
" elif m[1] == 1:\n" | |
" interp = 'LINEAR'\n" | |
" if m[2] < 0:\n" | |
" val = m[5]\n" | |
" else:\n" | |
" val = m[5] - bone_trans_heads[m[2]][m[3]]\n" | |
" anim_add_kf(m[0], interp, m[4], val)\n" | |
" else:\n" | |
" break\n" | |
" os.unlink(file_path)\n"; | |
struct ANIM_JointHeader { | |
u16 startCode; | |
u16 jointId; | |
u16 keyCount; | |
s16 alpha_rot; | |
char alpha_rot_sz; | |
s16 beta_rot; | |
char beta_rot_sz; | |
s16 gamma_rot; | |
char gamma_rot_sz; | |
u16 nextCode; | |
s16 x_loc; | |
char x_loc_sz; | |
s16 y_loc; | |
char y_loc_sz; | |
s16 z_loc; | |
char z_loc_sz; | |
s32 rot_accum[3]; | |
s32 trans_accum[3]; | |
}; | |
static u32 pick_out_bit(u8* bs, u32 cur) { | |
/* I suspect this stream to actually be delta-encoded */ | |
/* There is a sign bit and the remaining bits incrementally */ | |
/* adjust the default value provided in the joint header */ | |
/* EDIT: Turns out the bitstream is indeed variable-length */ | |
/* differential values with two's compliment signing */ | |
u32 byteCur = (cur / 32) * 4; | |
u32 bitRem = cur % 32; | |
/* Fill 32 bit buffer with region containing bits */ | |
/* Make them least significant */ | |
u32 tempBuf = *(u32*)(bs + byteCur); | |
tempBuf = swap_u32(tempBuf); | |
tempBuf = tempBuf >> bitRem; | |
/* mask it (excluding sign bit) */ | |
u32 mask = 1; | |
tempBuf &= mask; | |
return tempBuf; | |
} | |
static s32 pick_out_bits(u8* bs, u32 cur, u8 bitLen) { | |
/* I suspect this stream to actually be delta-encoded */ | |
/* There is a sign bit and the remaining bits incrementally */ | |
/* adjust the default value provided in the joint header */ | |
/* EDIT: Turns out the bitstream is indeed variable-length */ | |
/* differential values with two's compliment signing */ | |
if (!bitLen) | |
return 0; | |
/* If there's one bit, simply return pickOutBit debug value */ | |
if (bitLen <= 1) { | |
if (pick_out_bit(bs, cur)) | |
return 10000000; | |
else | |
return 0; | |
} | |
u32 byteCur = (cur / 32) * 4; | |
u32 bitRem = cur % 32; | |
/* Fill 32 bit buffer with region containing bits */ | |
/* Make them least significant */ | |
u32 tempBuf = *(u32*)(bs + byteCur); | |
tempBuf = swap_u32(tempBuf); | |
tempBuf = tempBuf >> bitRem; | |
/* If this shift underflows the value, buffer the next 32 bits */ | |
/* And tack onto shifted buffer */ | |
if((bitRem + bitLen) > 32) | |
{ | |
u32 tempBuf2 = *(u32*)(bs + byteCur + 4); | |
tempBuf2 = swap_u32(tempBuf2); | |
tempBuf |= (tempBuf2 << (32 - bitRem)); | |
} | |
/* Pick out sign */ | |
u32 sign = tempBuf >> (bitLen - 1); | |
sign &= 0x1; | |
/* If signed, invert the bastard (Two's compliment) */ | |
if(sign) | |
tempBuf = ~tempBuf; | |
/* mask it (excluding sign bit) */ | |
u32 mask = (1 << (bitLen - 1)) - 1; | |
tempBuf &= mask; | |
/* Return delta value */ | |
return (s32)(sign ? (tempBuf + 1) * -1 : tempBuf); | |
} | |
static void make_jh_little(struct ANIM_JointHeader* jh) { | |
jh->startCode = swap_s16(jh->startCode); | |
jh->jointId = swap_s16(jh->jointId); | |
jh->keyCount = swap_s16(jh->keyCount); | |
jh->alpha_rot = swap_s16(jh->alpha_rot); | |
jh->beta_rot = swap_s16(jh->beta_rot); | |
jh->gamma_rot = swap_s16(jh->gamma_rot); | |
jh->nextCode = swap_s16(jh->nextCode); | |
if (jh->nextCode) { | |
jh->x_loc = swap_s16(jh->x_loc); | |
jh->y_loc = swap_s16(jh->y_loc); | |
jh->z_loc = swap_s16(jh->z_loc); | |
} | |
} | |
static u32 get_kf_count(u32* kfBitmask, u32 potkfCount) { | |
u32 curKfBit = 0; | |
u32 curKfCnt = 0; | |
while (curKfBit < potkfCount) { | |
u32 curKfBool = kfBitmask[curKfBit / 32]; | |
curKfBool = curKfBool >> (curKfBit % 32); | |
curKfBool &= 0x1; | |
if(curKfBool) | |
++curKfCnt; | |
++curKfBit; | |
} | |
return curKfCnt; | |
} | |
static u32 get_kf_frame(u32 kfIdx, u32* kfBitmask, u32 potkfCount) { | |
u32 curKfBit = 0; | |
s32 curKfIdx = -1; | |
while(curKfBit < potkfCount) { | |
u32 curKfBool = kfBitmask[curKfBit / 32]; | |
curKfBool = curKfBool >> (curKfBit % 32); | |
curKfBool &= 0x1; | |
if(curKfBool) | |
{ | |
++curKfIdx; | |
if(curKfIdx == kfIdx) | |
return curKfBit; | |
} | |
++curKfBit; | |
} | |
/* Ideally shouldn't be reached, but safe value */ | |
return 0; | |
} | |
struct ANIM_JointUpdate | |
{ | |
u32 jointId; | |
s32 alpha_rot; | |
s32 beta_rot; | |
s32 gamma_rot; | |
u8 updTransBool; | |
s32 x_loc; | |
s32 y_loc; | |
s32 z_loc; | |
u8 unBit; | |
}; | |
struct ANIM_JointUpdateFloat | |
{ | |
u32 jointId; | |
float alpha_rot; | |
float beta_rot; | |
float gamma_rot; | |
u8 updTransBool; | |
float x_loc; | |
float y_loc; | |
float z_loc; | |
u8 unBit; | |
}; | |
struct ANIM_Keyframe | |
{ | |
u32 potentialKeyframe; | |
u32 firstJointUpdateIdx; | |
u32 jointUpdateCount; | |
}; | |
struct ANIM_Header_Fmt0 { | |
float duration; | |
u32 val0; | |
float interval; | |
u32 val1, keyframe_count, val3; | |
u32 dict_length; | |
}; | |
struct ANIM_Header_Fmt2 { | |
u32 key_count, event_ref, val3; | |
float duration, interval; | |
u32 val4, val5; | |
s32 rotation_divisor; | |
float translation_multiplier; | |
u32 bone_count; | |
u32 val6; | |
u32 kf_bitfield_len; /* (In Bits) */ | |
}; | |
/* Rotation order enumerations */ | |
#define QUAT 0 | |
#define XYZ 1 | |
#define XZY 2 | |
#define YXZ 3 | |
#define YZX 4 | |
#define ZXY 5 | |
#define ZYX 6 | |
void ANIM_decode(struct pak_entry* entry, FILE* py_out, const char* path_prefix, unsigned action_idx) { | |
/* Get Data */ | |
u8* anim_buf = NULL; | |
pak_lookup_get_data(entry, &anim_buf); | |
u8* anim_cur = anim_buf; | |
/* Format Type */ | |
u32 anim_fmt = swap_u32(*(u32*)anim_cur); | |
anim_cur += 4; | |
if (anim_fmt == 2) { | |
# pragma mark Bitstream-Differential-Compressed Euler-Vector Format | |
struct ANIM_Header_Fmt2* header = (struct ANIM_Header_Fmt2*)anim_cur; | |
/* Swap header information */ | |
header->key_count = swap_u32(header->key_count); | |
header->val3 = swap_u32(header->val3); | |
header->val4 = swap_u32(header->val4); | |
header->val5 = swap_u32(header->val5); | |
header->val6 = swap_u32(header->val6); | |
header->duration = swap_float(header->duration); | |
header->interval = swap_float(header->interval); | |
header->rotation_divisor = swap_u32(header->rotation_divisor); | |
header->translation_multiplier = swap_float(header->translation_multiplier); | |
header->bone_count = swap_u32(header->bone_count); | |
header->kf_bitfield_len = swap_u32(header->kf_bitfield_len); | |
fprintf(py_out, | |
" bone_trans_heads = []\n" | |
" act.rwk_fps = round(%f)\n" | |
" act.rwk_anim_props = '0x%X 0x%X %u %u %u %u'\n", (1.0f / header->interval), | |
header->key_count, header->rotation_divisor, header->val3, header->val4, header->val5, header->val6); | |
/* Read in keyframe bitmask */ | |
u32 bitfield_byte_size = header->kf_bitfield_len / 32; | |
if(header->kf_bitfield_len % 32) | |
++bitfield_byte_size; | |
bitfield_byte_size *= 4; | |
u32* kf_bitfield = (u32*)(anim_buf + 52); | |
/* Make bitmask little */ | |
int i; | |
for(i=0 ; i<(header->kf_bitfield_len/32)+1 ; ++i) | |
kf_bitfield[i] = swap_u32(kf_bitfield[i]); | |
/* Advance to end of bitmask */ | |
anim_cur = anim_buf + 52 + bitfield_byte_size; | |
/* Advance past two joint counts */ | |
anim_cur += 8; | |
/* Allocate temporary buffer to hold joint headers */ | |
struct ANIM_JointHeader* jh_arr = alloca(sizeof(struct ANIM_JointHeader) * header->bone_count); | |
memset(jh_arr, 0, sizeof(struct ANIM_JointHeader) * header->bone_count); | |
/* Populate Joint headers */ | |
u64 kf_size = 0; | |
for (i=0 ; i<header->bone_count ; ++i) { | |
u8* file_jh = anim_cur; | |
struct ANIM_JointHeader* jh = &jh_arr[i]; | |
jh->startCode = *(u16*)(file_jh); | |
jh->jointId = *(u16*)(file_jh + 2); | |
jh->keyCount = *(u16*)(file_jh + 4); | |
jh->alpha_rot = *(u16*)(file_jh + 6); | |
jh->alpha_rot_sz = *(char*)(file_jh + 8); | |
jh->beta_rot = *(u16*)(file_jh + 9); | |
jh->beta_rot_sz = *(char*)(file_jh + 11); | |
jh->gamma_rot = *(u16*)(file_jh + 12); | |
jh->gamma_rot_sz = *(char*)(file_jh + 14); | |
jh->nextCode = *(u16*)(file_jh + 15); | |
kf_size += 1; | |
kf_size += jh->alpha_rot_sz; | |
kf_size += jh->beta_rot_sz; | |
kf_size += jh->gamma_rot_sz; | |
if (jh->nextCode) { | |
jh->x_loc = *(u16*)(file_jh + 17); | |
jh->x_loc_sz = *(char*)(file_jh + 19); | |
jh->y_loc = *(u16*)(file_jh + 20); | |
jh->y_loc_sz = *(char*)(file_jh + 22); | |
jh->z_loc = *(u16*)(file_jh + 23); | |
jh->z_loc_sz = *(char*)(file_jh + 25); | |
kf_size += jh->x_loc_sz; | |
kf_size += jh->y_loc_sz; | |
kf_size += jh->z_loc_sz; | |
} | |
make_jh_little(jh); | |
jh->rot_accum[0] = jh->alpha_rot; | |
jh->rot_accum[1] = jh->beta_rot; | |
jh->rot_accum[2] = jh->gamma_rot; | |
jh->trans_accum[0] = jh->x_loc; | |
jh->trans_accum[1] = jh->y_loc; | |
jh->trans_accum[2] = jh->z_loc; | |
fprintf(py_out, | |
" bone_id = %u\n" | |
" if bone_id in arm_string_table:\n" | |
" bone_string = arm_string_table[bone_id]\n" | |
" else:\n" | |
" bone_string = 'bone_%%u' %% bone_id\n" | |
" action_group = act.groups.new(bone_string)\n" | |
" \n" | |
" crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=0, action_group=bone_string)\n" | |
" crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=1, action_group=bone_string)\n" | |
" crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=2, action_group=bone_string)\n" | |
" crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=3, action_group=bone_string)\n" | |
" \n", | |
jh->jointId); | |
if (jh->nextCode) { | |
fprintf(py_out, | |
" bone_parent_head = (0.0,0.0,0.0)\n" | |
" if arm_obj.data.bones[bone_string].parent is not None:\n" | |
" bone_parent_head = Vector(arm_obj.data.bones[bone_string].head_local) - Vector(arm_obj.data.bones[bone_string].parent.head_local)\n" | |
" bone_trans_heads.append(bone_parent_head)\n" | |
" crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=0, action_group=bone_string)\n" | |
" crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=1, action_group=bone_string)\n" | |
" crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, action_group=bone_string)\n" | |
" \n"); | |
} else { | |
fprintf(py_out, | |
" bone_trans_heads.append((0,0,0))\n"); | |
} | |
fprintf(py_out, | |
" crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_mode', action_group=bone_string)\n" | |
" crv.keyframe_points.add()\n" | |
" crv.keyframe_points[-1].co = (0, 0)\n" | |
" crv.keyframe_points[-1].interpolation = 'LINEAR'\n" | |
" \n"); | |
if (jh->nextCode) | |
anim_cur += 26; | |
else | |
anim_cur += 17; | |
} | |
/* First, allocate space for keyframes */ | |
unsigned keyframe_count = get_kf_count(kf_bitfield, header->kf_bitfield_len); | |
/* Utility to add keyframe to fcurve (with less repeated code) */ | |
fprintf(py_out, "%s\n", ANIM_BIN_DEC); | |
/* Binary file to hold intermediate keys */ | |
char anim_bin_path[MAXPATHLEN]; | |
snprintf(anim_bin_path, MAXPATHLEN, "%s/actors/ANIM_%08X_%u.bin", path_prefix, swap_u32(entry->uid), action_idx); | |
FILE* anim_bin = fopen(anim_bin_path, "wb"); | |
struct bin_key { | |
u32 crv_idx; | |
u32 interp; | |
s32 translation; | |
u32 array_idx; | |
u32 frame; | |
float val; | |
} bin_key; | |
fprintf(py_out, " anim_bin_dec('ANIM_%08X_%u.bin')\n\n", swap_u32(entry->uid), action_idx); | |
/* First pass, generate FCurve */ | |
u32 bitCursor = 0; | |
void* bitstream = anim_cur; | |
for (i=0 ; i<keyframe_count ; ++i) { | |
/* Count of frames into action */ | |
u32 time_stamp = get_kf_frame(i, kf_bitfield, header->kf_bitfield_len); | |
unsigned fcurve_idx = 0; | |
int j; | |
for (j=0 ; j<header->bone_count ; ++j) { | |
struct ANIM_JointHeader* jh = &jh_arr[j]; | |
/* BEGIN JOINT-UPDATE EXTRACTION */ | |
s32 rot_raw[3] = {0,0,0}; | |
bool flip_bit = false; | |
if (i) { | |
/* Advance bit cursor past one bit per update */ | |
flip_bit = pick_out_bit(bitstream, bitCursor) ? true : false; | |
bitCursor += 1; | |
/* This rotation delta */ | |
rot_raw[0] = pick_out_bits(bitstream, bitCursor, jh->alpha_rot_sz); | |
bitCursor += jh->alpha_rot_sz; | |
rot_raw[1] = pick_out_bits(bitstream, bitCursor, jh->beta_rot_sz); | |
bitCursor += jh->beta_rot_sz; | |
rot_raw[2] = pick_out_bits(bitstream, bitCursor, jh->gamma_rot_sz); | |
bitCursor += jh->gamma_rot_sz; | |
jh->rot_accum[0] += rot_raw[0]; | |
jh->rot_accum[1] += rot_raw[1]; | |
jh->rot_accum[2] += rot_raw[2]; | |
/* This translation delta */ | |
if (jh->nextCode) { | |
s32 trans_raw[3]; | |
trans_raw[0] = pick_out_bits(bitstream, bitCursor, jh->x_loc_sz); | |
bitCursor += jh->x_loc_sz; | |
trans_raw[1] = pick_out_bits(bitstream, bitCursor, jh->y_loc_sz); | |
bitCursor += jh->y_loc_sz; | |
trans_raw[2] = pick_out_bits(bitstream, bitCursor, jh->z_loc_sz); | |
bitCursor += jh->z_loc_sz; | |
jh->trans_accum[0] += trans_raw[0]; | |
jh->trans_accum[1] += trans_raw[1]; | |
jh->trans_accum[2] += trans_raw[2]; | |
} | |
} | |
float quantization_factor = M_PI_2 / header->rotation_divisor; | |
rwk_vector euler_vector = { | |
sinf(jh->rot_accum[0] * quantization_factor), | |
sinf(jh->rot_accum[1] * quantization_factor), | |
sinf(jh->rot_accum[2] * quantization_factor) | |
}; | |
float w = | |
euler_vector.v[0] * euler_vector.v[0] + | |
euler_vector.v[1] * euler_vector.v[1] + | |
euler_vector.v[2] * euler_vector.v[2]; | |
w = 1.0 - w; | |
w = MAX(w, 0.0); | |
w = sqrtf(w); | |
rwk_vector final_q = { | |
flip_bit ? -w : w, | |
euler_vector.v[0], | |
euler_vector.v[1], | |
euler_vector.v[2], | |
}; | |
bin_key.crv_idx = fcurve_idx++; | |
bin_key.interp = 1; | |
bin_key.translation = -1; | |
bin_key.frame = time_stamp; | |
bin_key.val = final_q.v[0]; | |
fwrite(&bin_key, 1, sizeof(bin_key), anim_bin); | |
bin_key.crv_idx = fcurve_idx++; | |
bin_key.val = final_q.v[1]; | |
fwrite(&bin_key, 1, sizeof(bin_key), anim_bin); | |
bin_key.crv_idx = fcurve_idx++; | |
bin_key.val = final_q.v[2]; | |
fwrite(&bin_key, 1, sizeof(bin_key), anim_bin); | |
bin_key.crv_idx = fcurve_idx++; | |
bin_key.val = final_q.v[3]; | |
fwrite(&bin_key, 1, sizeof(bin_key), anim_bin); | |
/* Translation */ | |
if (jh->nextCode) { | |
bin_key.crv_idx = fcurve_idx++; | |
bin_key.translation = j; | |
bin_key.array_idx = 0; | |
bin_key.val = jh->trans_accum[0] * header->translation_multiplier; | |
fwrite(&bin_key, 1, sizeof(bin_key), anim_bin); | |
bin_key.crv_idx = fcurve_idx++; | |
bin_key.array_idx = 1; | |
bin_key.val = jh->trans_accum[1] * header->translation_multiplier; | |
fwrite(&bin_key, 1, sizeof(bin_key), anim_bin); | |
bin_key.crv_idx = fcurve_idx++; | |
bin_key.array_idx = 2; | |
bin_key.val = jh->trans_accum[2] * header->translation_multiplier; | |
fwrite(&bin_key, 1, sizeof(bin_key), anim_bin); | |
} | |
++fcurve_idx; | |
} | |
if (i==0) | |
bitCursor = 0; | |
} | |
fclose(anim_bin); | |
} else if (anim_fmt == 0) { | |
# pragma mark Quaternion Array Format | |
/* 4-Component Vector Array (Quaternion Rotations, Optional Translation mappings) */ | |
struct ANIM_Header_Fmt0* header = (struct ANIM_Header_Fmt0*)anim_cur; | |
int i,j; | |
/* Swap header information */ | |
header->duration = swap_float(header->duration); | |
header->interval = swap_float(header->interval); | |
header->dict_length = swap_u32(header->dict_length); | |
header->keyframe_count = swap_u32(header->keyframe_count); | |
fprintf(py_out, | |
" act.rwk_fps = round(%f)\n" | |
" anim_bone_table = {}\n", | |
(1.0f / header->interval)); | |
anim_cur += sizeof(struct ANIM_Header_Fmt0); | |
u8* bone_dict = anim_cur; | |
for (i=0 ; i<header->dict_length ; ++i) { | |
if (bone_dict[i] == 0xff) | |
continue; | |
fprintf(py_out, | |
" bone_id = %u\n" | |
" if bone_id in arm_string_table:\n" | |
" bone_string = arm_string_table[bone_id]\n" | |
" else:\n" | |
" bone_string = 'bone_%%u' %% bone_id\n" | |
" action_group = act.groups.new(bone_string)\n" | |
" anim_bone_table[%u] = action_group\n" | |
" \n" | |
" act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=0, action_group=bone_string)\n" | |
" act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=1, action_group=bone_string)\n" | |
" act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=2, action_group=bone_string)\n" | |
" act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=3, action_group=bone_string)\n", | |
i, bone_dict[i]); | |
fprintf(py_out, | |
" crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_mode', action_group=bone_string)\n" | |
" crv.keyframe_points.add()\n" | |
" crv.keyframe_points[-1].co = (0, 0)\n" | |
" \n"); | |
} | |
anim_cur += header->dict_length; | |
/* Bone Mode Table (for enabling translation) */ | |
u32 bone_count = swap_u32(*(u32*)anim_cur); | |
anim_cur += 4; | |
u8* bone_modes = anim_cur; | |
for (i=0 ; i<bone_count ; ++i) { | |
if (bone_modes[i] == 0xff) | |
continue; | |
fprintf(py_out, | |
" action_group = anim_bone_table[%u]\n" | |
" \n" | |
" act.fcurves.new('pose.bones[\"'+action_group.name+'\"].location', index=0, action_group=action_group.name)\n" | |
" act.fcurves.new('pose.bones[\"'+action_group.name+'\"].location', index=1, action_group=action_group.name)\n" | |
" act.fcurves.new('pose.bones[\"'+action_group.name+'\"].location', index=2, action_group=action_group.name)\n", | |
bone_modes[i]); | |
} | |
anim_cur += bone_count; | |
/* Joint Update Table */ | |
u32 joint_update_count = swap_u32(*(u32*)anim_cur); | |
anim_cur += 4; | |
float* joint_update_table = (float*)anim_cur; | |
for (i=0 ; i<bone_count ; ++i) { | |
fprintf(py_out, | |
" action_group = anim_bone_table[%u]\n", i); | |
for (j=0 ; j<header->keyframe_count ; ++j) { | |
fprintf(py_out, | |
" crv = action_group.channels[0]\n" | |
" crv.keyframe_points.add()\n" | |
" crv.keyframe_points[-1].interpolation = 'LINEAR'\n" | |
" crv.keyframe_points[-1].co = (%u, %f)\n", | |
j, swap_float(joint_update_table[(i * header->keyframe_count + j) * 4 + 0])); | |
fprintf(py_out, | |
" crv = action_group.channels[1]\n" | |
" crv.keyframe_points.add()\n" | |
" crv.keyframe_points[-1].interpolation = 'LINEAR'\n" | |
" crv.keyframe_points[-1].co = (%u, %f)\n", | |
j, swap_float(joint_update_table[(i * header->keyframe_count + j) * 4 + 1])); | |
fprintf(py_out, | |
" crv = action_group.channels[2]\n" | |
" crv.keyframe_points.add()\n" | |
" crv.keyframe_points[-1].interpolation = 'LINEAR'\n" | |
" crv.keyframe_points[-1].co = (%u, %f)\n", | |
j, swap_float(joint_update_table[(i * header->keyframe_count + j) * 4 + 2])); | |
fprintf(py_out, | |
" crv = action_group.channels[3]\n" | |
" crv.keyframe_points.add()\n" | |
" crv.keyframe_points[-1].interpolation = 'LINEAR'\n" | |
" crv.keyframe_points[-1].co = (%u, %f)\n", | |
j, swap_float(joint_update_table[(i * header->keyframe_count + j) * 4 + 3])); | |
} | |
} | |
anim_cur += 16 * joint_update_count; | |
/* Triple Table (Positions) */ | |
u32 triple_count = swap_u32(*(u32*)anim_cur); | |
anim_cur += 4; | |
float* triple_table = (float*)anim_cur; | |
for (i=0 ; i<bone_count ; ++i) { | |
if (bone_modes[i] == 0xff) | |
continue; | |
fprintf(py_out, | |
" action_group = anim_bone_table[%u]\n", bone_modes[i]); | |
for (j=0 ; j<header->keyframe_count ; ++j) { | |
fprintf(py_out, | |
" crv = action_group.channels[5]\n" | |
" crv.keyframe_points.add()\n" | |
" crv.keyframe_points[-1].interpolation = 'LINEAR'\n" | |
" crv.keyframe_points[-1].co = (%u, %f)\n", | |
j, swap_float(triple_table[(i * header->keyframe_count + j) * 3 + 0])); | |
fprintf(py_out, | |
" crv = action_group.channels[6]\n" | |
" crv.keyframe_points.add()\n" | |
" crv.keyframe_points[-1].interpolation = 'LINEAR'\n" | |
" crv.keyframe_points[-1].co = (%u, %f)\n", | |
j, swap_float(triple_table[(i * header->keyframe_count + j) * 3 + 1])); | |
fprintf(py_out, | |
" crv = action_group.channels[7]\n" | |
" crv.keyframe_points.add()\n" | |
" crv.keyframe_points[-1].interpolation = 'LINEAR'\n" | |
" crv.keyframe_points[-1].co = (%u, %f)\n", | |
j, swap_float(triple_table[(i * header->keyframe_count + j) * 3 + 2])); | |
} | |
} | |
anim_cur += 12 * triple_count; | |
/* EVNT Ref */ | |
/*u32 evnt_ref = *(u32*)anim_cur;*/ | |
} else { | |
printf("Unknown ANIM format\n"); | |
} | |
free(anim_buf); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment