File size: 3,526 Bytes
da855ff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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)),
        ),
    )