1/*
2Open Asset Import Library (assimp)
3----------------------------------------------------------------------
4
5Copyright (c) 2006-2017, assimp team
6
7All rights reserved.
8
9Redistribution and use of this software in source and binary forms,
10with or without modification, are permitted provided that the
11following conditions are met:
12
13* Redistributions of source code must retain the above
14copyright notice, this list of conditions and the
15following disclaimer.
16
17* Redistributions in binary form must reproduce the above
18copyright notice, this list of conditions and the
19following disclaimer in the documentation and/or other
20materials provided with the distribution.
21
22* Neither the name of the assimp team, nor the names of its
23contributors may be used to endorse or promote products
24derived from this software without specific prior
25written permission of the assimp team.
26
27THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
39----------------------------------------------------------------------
40*/
41#pragma once
42
43#include <vector>
44#include <string>
45#include <memory>
46#include <iostream>
47#include <fstream>
48#include <ostream>
49#include "MMDCpp14.h"
50
51namespace vmd
52{
53 class VmdBoneFrame
54 {
55 public:
56 std::string name;
57 int frame;
58 float position[3];
59 float orientation[4];
60 char interpolation[4][4][4];
61
62 void Read(std::istream* stream)
63 {
64 char buffer[15];
65 stream->read((char*) buffer, sizeof(char)*15);
66 name = std::string(buffer);
67 stream->read((char*) &frame, sizeof(int));
68 stream->read((char*) position, sizeof(float)*3);
69 stream->read((char*) orientation, sizeof(float)*4);
70 stream->read((char*) interpolation, sizeof(char) * 4 * 4 * 4);
71 }
72
73 void Write(std::ostream* stream)
74 {
75 stream->write((char*)name.c_str(), sizeof(char) * 15);
76 stream->write((char*)&frame, sizeof(int));
77 stream->write((char*)position, sizeof(float) * 3);
78 stream->write((char*)orientation, sizeof(float) * 4);
79 stream->write((char*)interpolation, sizeof(char) * 4 * 4 * 4);
80 }
81 };
82
83 class VmdFaceFrame
84 {
85 public:
86 std::string face_name;
87 float weight;
88 uint32_t frame;
89
90 void Read(std::istream* stream)
91 {
92 char buffer[15];
93 stream->read((char*) &buffer, sizeof(char) * 15);
94 face_name = std::string(buffer);
95 stream->read((char*) &frame, sizeof(int));
96 stream->read((char*) &weight, sizeof(float));
97 }
98
99 void Write(std::ostream* stream)
100 {
101 stream->write((char*)face_name.c_str(), sizeof(char) * 15);
102 stream->write((char*)&frame, sizeof(int));
103 stream->write((char*)&weight, sizeof(float));
104 }
105 };
106
107 class VmdCameraFrame
108 {
109 public:
110 int frame;
111 float distance;
112 float position[3];
113 float orientation[3];
114 char interpolation[6][4];
115 float angle;
116 char unknown[3];
117
118 void Read(std::istream *stream)
119 {
120 stream->read((char*) &frame, sizeof(int));
121 stream->read((char*) &distance, sizeof(float));
122 stream->read((char*) position, sizeof(float) * 3);
123 stream->read((char*) orientation, sizeof(float) * 3);
124 stream->read((char*) interpolation, sizeof(char) * 24);
125 stream->read((char*) &angle, sizeof(float));
126 stream->read((char*) unknown, sizeof(char) * 3);
127 }
128
129 void Write(std::ostream *stream)
130 {
131 stream->write((char*)&frame, sizeof(int));
132 stream->write((char*)&distance, sizeof(float));
133 stream->write((char*)position, sizeof(float) * 3);
134 stream->write((char*)orientation, sizeof(float) * 3);
135 stream->write((char*)interpolation, sizeof(char) * 24);
136 stream->write((char*)&angle, sizeof(float));
137 stream->write((char*)unknown, sizeof(char) * 3);
138 }
139 };
140
141 class VmdLightFrame
142 {
143 public:
144 int frame;
145 float color[3];
146 float position[3];
147
148 void Read(std::istream* stream)
149 {
150 stream->read((char*) &frame, sizeof(int));
151 stream->read((char*) color, sizeof(float) * 3);
152 stream->read((char*) position, sizeof(float) * 3);
153 }
154
155 void Write(std::ostream* stream)
156 {
157 stream->write((char*)&frame, sizeof(int));
158 stream->write((char*)color, sizeof(float) * 3);
159 stream->write((char*)position, sizeof(float) * 3);
160 }
161 };
162
163 class VmdIkEnable
164 {
165 public:
166 std::string ik_name;
167 bool enable;
168 };
169
170 class VmdIkFrame
171 {
172 public:
173 int frame;
174 bool display;
175 std::vector<VmdIkEnable> ik_enable;
176
177 void Read(std::istream *stream)
178 {
179 char buffer[20];
180 stream->read((char*) &frame, sizeof(int));
181 stream->read((char*) &display, sizeof(uint8_t));
182 int ik_count;
183 stream->read((char*) &ik_count, sizeof(int));
184 ik_enable.resize(ik_count);
185 for (int i = 0; i < ik_count; i++)
186 {
187 stream->read(buffer, 20);
188 ik_enable[i].ik_name = std::string(buffer);
189 stream->read((char*) &ik_enable[i].enable, sizeof(uint8_t));
190 }
191 }
192
193 void Write(std::ostream *stream)
194 {
195 stream->write((char*)&frame, sizeof(int));
196 stream->write((char*)&display, sizeof(uint8_t));
197 int ik_count = static_cast<int>(ik_enable.size());
198 stream->write((char*)&ik_count, sizeof(int));
199 for (int i = 0; i < ik_count; i++)
200 {
201 const VmdIkEnable& ik_enable = this->ik_enable.at(i);
202 stream->write(ik_enable.ik_name.c_str(), 20);
203 stream->write((char*)&ik_enable.enable, sizeof(uint8_t));
204 }
205 }
206 };
207
208 class VmdMotion
209 {
210 public:
211 std::string model_name;
212 int version;
213 std::vector<VmdBoneFrame> bone_frames;
214 std::vector<VmdFaceFrame> face_frames;
215 std::vector<VmdCameraFrame> camera_frames;
216 std::vector<VmdLightFrame> light_frames;
217 std::vector<VmdIkFrame> ik_frames;
218
219 static std::unique_ptr<VmdMotion> LoadFromFile(char const *filename)
220 {
221 std::ifstream stream(filename, std::ios::binary);
222 auto result = LoadFromStream(&stream);
223 stream.close();
224 return result;
225 }
226
227 static std::unique_ptr<VmdMotion> LoadFromStream(std::ifstream *stream)
228 {
229
230 char buffer[30];
231 auto result = mmd::make_unique<VmdMotion>();
232
233 // magic and version
234 stream->read((char*) buffer, 30);
235 if (strncmp(buffer, "Vocaloid Motion Data", 20))
236 {
237 std::cerr << "invalid vmd file." << std::endl;
238 return nullptr;
239 }
240 result->version = std::atoi(buffer + 20);
241
242 // name
243 stream->read(buffer, 20);
244 result->model_name = std::string(buffer);
245
246 // bone frames
247 int bone_frame_num;
248 stream->read((char*) &bone_frame_num, sizeof(int));
249 result->bone_frames.resize(bone_frame_num);
250 for (int i = 0; i < bone_frame_num; i++)
251 {
252 result->bone_frames[i].Read(stream);
253 }
254
255 // face frames
256 int face_frame_num;
257 stream->read((char*) &face_frame_num, sizeof(int));
258 result->face_frames.resize(face_frame_num);
259 for (int i = 0; i < face_frame_num; i++)
260 {
261 result->face_frames[i].Read(stream);
262 }
263
264 // camera frames
265 int camera_frame_num;
266 stream->read((char*) &camera_frame_num, sizeof(int));
267 result->camera_frames.resize(camera_frame_num);
268 for (int i = 0; i < camera_frame_num; i++)
269 {
270 result->camera_frames[i].Read(stream);
271 }
272
273 // light frames
274 int light_frame_num;
275 stream->read((char*) &light_frame_num, sizeof(int));
276 result->light_frames.resize(light_frame_num);
277 for (int i = 0; i < light_frame_num; i++)
278 {
279 result->light_frames[i].Read(stream);
280 }
281
282 // unknown2
283 stream->read(buffer, 4);
284
285 // ik frames
286 if (stream->peek() != std::ios::traits_type::eof())
287 {
288 int ik_num;
289 stream->read((char*) &ik_num, sizeof(int));
290 result->ik_frames.resize(ik_num);
291 for (int i = 0; i < ik_num; i++)
292 {
293 result->ik_frames[i].Read(stream);
294 }
295 }
296
297 if (stream->peek() != std::ios::traits_type::eof())
298 {
299 std::cerr << "vmd stream has unknown data." << std::endl;
300 }
301
302 return result;
303 }
304
305 bool SaveToFile(const std::u16string& /*filename*/)
306 {
307 // TODO: How to adapt u16string to string?
308 /*
309 std::ofstream stream(filename.c_str(), std::ios::binary);
310 auto result = SaveToStream(&stream);
311 stream.close();
312 return result;
313 */
314 return false;
315 }
316
317 bool SaveToStream(std::ofstream *stream)
318 {
319 std::string magic = "Vocaloid Motion Data 0002\0";
320 magic.resize(30);
321
322 // magic and version
323 stream->write(magic.c_str(), 30);
324
325 // name
326 stream->write(model_name.c_str(), 20);
327
328 // bone frames
329 const int bone_frame_num = static_cast<int>(bone_frames.size());
330 stream->write(reinterpret_cast<const char*>(&bone_frame_num), sizeof(int));
331 for (int i = 0; i < bone_frame_num; i++)
332 {
333 bone_frames[i].Write(stream);
334 }
335
336 // face frames
337 const int face_frame_num = static_cast<int>(face_frames.size());
338 stream->write(reinterpret_cast<const char*>(&face_frame_num), sizeof(int));
339 for (int i = 0; i < face_frame_num; i++)
340 {
341 face_frames[i].Write(stream);
342 }
343
344 // camera frames
345 const int camera_frame_num = static_cast<int>(camera_frames.size());
346 stream->write(reinterpret_cast<const char*>(&camera_frame_num), sizeof(int));
347 for (int i = 0; i < camera_frame_num; i++)
348 {
349 camera_frames[i].Write(stream);
350 }
351
352 // light frames
353 const int light_frame_num = static_cast<int>(light_frames.size());
354 stream->write(reinterpret_cast<const char*>(&light_frame_num), sizeof(int));
355 for (int i = 0; i < light_frame_num; i++)
356 {
357 light_frames[i].Write(stream);
358 }
359
360 // self shadow datas
361 const int self_shadow_num = 0;
362 stream->write(reinterpret_cast<const char*>(&self_shadow_num), sizeof(int));
363
364 // ik frames
365 const int ik_num = static_cast<int>(ik_frames.size());
366 stream->write(reinterpret_cast<const char*>(&ik_num), sizeof(int));
367 for (int i = 0; i < ik_num; i++)
368 {
369 ik_frames[i].Write(stream);
370 }
371
372 return true;
373 }
374 };
375}
376