import numpy as np from scipy import interpolate from anim import bvh, quat def change_bvh(filename, savename, order=None, fps=None, pace=1.0, center=False): anim_data = bvh.load(filename) output = anim_data.copy() if order is not None: output["order"] = order rotations = quat.unroll(quat.from_euler(np.radians(anim_data['rotations']), order=anim_data['order'])) output["rotations"] = np.degrees(quat.to_euler(rotations, order=output["order"])) if pace is not None or fps is not None: if fps is None: fps = 1.0 / anim_data["frametime"] positions = anim_data['positions'] rotations = quat.unroll(quat.from_euler(np.radians(anim_data['rotations']), order=anim_data['order'])) nframes = positions.shape[0] nbones = positions.shape[1] original_times = np.linspace(0, nframes - 1, nframes) sample_times = np.linspace( 0, nframes - 1, int(pace * (nframes * (fps * anim_data["frametime"]) - 1)) ) output["positions"] = interpolate.griddata(original_times, output["positions"].reshape([nframes, -1]), sample_times, method='cubic').reshape([len(sample_times), nbones, 3]) rotations = interpolate.griddata(original_times, rotations.reshape([nframes, -1]), sample_times, method='cubic').reshape([len(sample_times), nbones, 4]) rotations = quat.normalize(rotations) output["rotations"] = np.degrees(quat.to_euler(rotations, order=output["order"])) output["frametime"] = 1.0 / fps if center: lrot = quat.from_euler(np.radians(output["rotations"]), output["order"]) offset_pos = output["positions"][0:1, 0:1].copy() * np.array([1, 0, 1]) offset_rot = lrot[0:1, 0:1].copy() * np.array([1, 0, 1, 0]) root_pos = quat.mul_vec(quat.inv(offset_rot), output["positions"][:, 0:1] - offset_pos) output["positions"][:, 0:1] = quat.mul_vec(quat.inv(offset_rot), output["positions"][:, 0:1] - offset_pos) output["rotations"][:, 0:1] = np.degrees( quat.to_euler(quat.mul(quat.inv(offset_rot), lrot[:, 0:1]), order=output["order"])) bvh.save(savename, output) def write_bvh( filename, V_root_pos, V_root_rot, V_lpos, V_lrot, parents, names, order, dt, start_position=None, start_rotation=None, ): if start_position is not None and start_rotation is not None: offset_pos = V_root_pos[0:1].copy() offset_rot = V_root_rot[0:1].copy() V_root_pos = quat.mul_vec(quat.inv(offset_rot), V_root_pos - offset_pos) V_root_rot = quat.mul(quat.inv(offset_rot), V_root_rot) V_root_pos = ( quat.mul_vec(start_rotation[np.newaxis], V_root_pos) + start_position[np.newaxis] ) V_root_rot = quat.mul(start_rotation[np.newaxis], V_root_rot) V_lpos = V_lpos.copy() V_lrot = V_lrot.copy() V_lpos[:, 0] = quat.mul_vec(V_root_rot, V_lpos[:, 0]) + V_root_pos V_lrot[:, 0] = quat.mul(V_root_rot, V_lrot[:, 0]) bvh.save( filename, dict( order=order, offsets=V_lpos[0], names=names, frametime=dt, parents=parents, positions=V_lpos, rotations=np.degrees(quat.to_euler(V_lrot, order=order)), ), )