1 | /* |
2 | Open Asset Import Library (assimp) |
3 | ---------------------------------------------------------------------- |
4 | |
5 | Copyright (c) 2006-2017, assimp team |
6 | |
7 | All rights reserved. |
8 | |
9 | Redistribution and use of this software in source and binary forms, |
10 | with or without modification, are permitted provided that the |
11 | following conditions are met: |
12 | |
13 | * Redistributions of source code must retain the above |
14 | copyright notice, this list of conditions and the |
15 | following disclaimer. |
16 | |
17 | * Redistributions in binary form must reproduce the above |
18 | copyright notice, this list of conditions and the |
19 | following disclaimer in the documentation and/or other |
20 | materials provided with the distribution. |
21 | |
22 | * Neither the name of the assimp team, nor the names of its |
23 | contributors may be used to endorse or promote products |
24 | derived from this software without specific prior |
25 | written permission of the assimp team. |
26 | |
27 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
28 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
29 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
30 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
31 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
32 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
33 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
34 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
35 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
36 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
37 | OF 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 | |
51 | namespace 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 | |