-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathmergevmd.cc
140 lines (124 loc) · 3.57 KB
/
mergevmd.cc
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// merge VMD files generated by readfacevmd and another tool
#include <Eigen/Core>
#include <Eigen/Geometry>
#include <fstream>
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include "VMD.h"
#include "MMDFileIOUtil.h"
#include "interpolate.h"
//#include "reducevmd.h"
using namespace Eigen;
using namespace MMDFileIOUtil;
using namespace std;
void usage(char *prog)
{
cerr << "usage: " << prog << " body.vmd face.vmd out.vmd\n";
}
Quaternionf rot_frame(const vector<VMD_Frame>& frames, uint32_t n)
{
VMD_Frame f_old;
f_old.rotation = Quaternionf::Identity();
for (const VMD_Frame& f : frames) {
if (f.number == n) {
return f.rotation;
} else if (f.number > n) {
VMD_Frame f_i = interpolate_frame(f_old, f, n, false);
return f_i.rotation;
}
f_old = f;
}
return f_old.rotation;
}
void merge_vmd(VMD& body, VMD& face)
{
// キーフレームをボーンごとに分ける
map<string, vector<VMD_Frame>> body_frame_map;
for (VMD_Frame& f : body.frame) {
string name;
sjis_to_utf8(f.bonename, name, f.bonename_len);
body_frame_map[name].push_back(f);
}
map<string, vector<VMD_Frame>> face_frame_map;
for (VMD_Frame& f : face.frame) {
string name;
sjis_to_utf8(f.bonename, name, f.bonename_len);
face_frame_map[name].push_back(f);
}
// フレーム番号順にソートしておく
for (auto iter = body_frame_map.begin(); iter != body_frame_map.end(); iter++) {
vector<VMD_Frame>& fv = iter->second;
sort(fv.begin(), fv.end());
}
for (auto iter = face_frame_map.begin(); iter != face_frame_map.end(); iter++) {
vector<VMD_Frame>& fv = iter->second;
sort(fv.begin(), fv.end());
}
// body motion と face motionを接続するボーンを決める
string connector_bone = u8"頭";
decltype(face_frame_map)::iterator it = face_frame_map.find(u8"首");
if (it != face_frame_map.end()) {
connector_bone = u8"首";
}
vector<string> head_hierarchy = {u8"全ての親", u8"センター", u8"上半身", u8"上半身2", u8"首"};
// ボーンキーフレームをbody.frame に格納する
body.frame.clear();
for (auto iter = body_frame_map.begin(); iter != body_frame_map.end(); iter++) {
string name = iter->first;
if (name == u8"頭" || name == connector_bone) {
continue;
}
vector<VMD_Frame>& fv = iter->second;
for (VMD_Frame& f : fv) {
body.frame.push_back(f);
}
}
for (auto iter = face_frame_map.begin(); iter != face_frame_map.end(); iter++) {
string name = iter->first;
if (name == u8"センター" || name == u8"全ての親") {
continue;
}
vector<VMD_Frame>& fv = iter->second;
for (VMD_Frame& f : fv) {
if (name == connector_bone) {
Quaternionf rot = Quaternionf::Identity();
for (string bonename : head_hierarchy) {
if (bonename != connector_bone) {
rot = rot * rot_frame(body_frame_map[bonename], f.number);
}
}
f.rotation = rot.inverse() * f.rotation;
}
body.frame.push_back(f);
}
}
// 表情キーフレームをマージする
for (VMD_Morph& m : face.morph) {
body.morph.push_back(m);
}
}
int main(int argc, char* argv[])
{
if (argc < 4) {
usage(argv[0]);
return 1;
}
string fname_vmdl = argv[1];
string fname_rfv = argv[2];
string fname_out = argv[3];
ifstream in1(fname_vmdl, ios::binary);
VMD body;
body.input(in1);
in1.close();
ifstream in2(fname_rfv, ios::binary);
VMD face;
face.input(in2);
in2.close();
merge_vmd(body, face);
ofstream out(fname_out, ios::binary);
body.output(out);
out.close();
return 0;
}