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 "MMDCpp14.h"
49
50namespace pmd
51{
52 class PmdHeader
53 {
54 public:
55 std::string name;
56 std::string name_english;
57 std::string comment;
58 std::string comment_english;
59
60 bool Read(std::ifstream* stream)
61 {
62 char buffer[256];
63 stream->read(buffer, 20);
64 name = std::string(buffer);
65 stream->read(buffer, 256);
66 comment = std::string(buffer);
67 return true;
68 }
69
70 bool ReadExtension(std::ifstream* stream)
71 {
72 char buffer[256];
73 stream->read(buffer, 20);
74 name_english = std::string(buffer);
75 stream->read(buffer, 256);
76 comment_english = std::string(buffer);
77 return true;
78 }
79 };
80
81 class PmdVertex
82 {
83 public:
84 float position[3];
85
86 float normal[3];
87
88 float uv[2];
89
90 uint16_t bone_index[2];
91
92 uint8_t bone_weight;
93
94 bool edge_invisible;
95
96 bool Read(std::ifstream* stream)
97 {
98 stream->read((char*) position, sizeof(float) * 3);
99 stream->read((char*) normal, sizeof(float) * 3);
100 stream->read((char*) uv, sizeof(float) * 2);
101 stream->read((char*) bone_index, sizeof(uint16_t) * 2);
102 stream->read((char*) &bone_weight, sizeof(uint8_t));
103 stream->read((char*) &edge_invisible, sizeof(uint8_t));
104 return true;
105 }
106 };
107
108 class PmdMaterial
109 {
110 public:
111 float diffuse[4];
112 float power;
113 float specular[3];
114 float ambient[3];
115 uint8_t toon_index;
116 uint8_t edge_flag;
117 uint32_t index_count;
118 std::string texture_filename;
119 std::string sphere_filename;
120
121 bool Read(std::ifstream* stream)
122 {
123 char buffer[20];
124 stream->read((char*) &diffuse, sizeof(float) * 4);
125 stream->read((char*) &power, sizeof(float));
126 stream->read((char*) &specular, sizeof(float) * 3);
127 stream->read((char*) &ambient, sizeof(float) * 3);
128 stream->read((char*) &toon_index, sizeof(uint8_t));
129 stream->read((char*) &edge_flag, sizeof(uint8_t));
130 stream->read((char*) &index_count, sizeof(uint32_t));
131 stream->read((char*) &buffer, sizeof(char) * 20);
132 char* pstar = strchr(buffer, '*');
133 if (NULL == pstar)
134 {
135 texture_filename = std::string(buffer);
136 sphere_filename.clear();
137 }
138 else {
139 *pstar = 0;
140 texture_filename = std::string(buffer);
141 sphere_filename = std::string(pstar+1);
142 }
143 return true;
144 }
145 };
146
147 enum class BoneType : uint8_t
148 {
149 Rotation,
150 RotationAndMove,
151 IkEffector,
152 Unknown,
153 IkEffectable,
154 RotationEffectable,
155 IkTarget,
156 Invisible,
157 Twist,
158 RotationMovement
159 };
160
161 class PmdBone
162 {
163 public:
164 std::string name;
165 std::string name_english;
166 uint16_t parent_bone_index;
167 uint16_t tail_pos_bone_index;
168 BoneType bone_type;
169 uint16_t ik_parent_bone_index;
170 float bone_head_pos[3];
171
172 void Read(std::istream *stream)
173 {
174 char buffer[20];
175 stream->read(buffer, 20);
176 name = std::string(buffer);
177 stream->read((char*) &parent_bone_index, sizeof(uint16_t));
178 stream->read((char*) &tail_pos_bone_index, sizeof(uint16_t));
179 stream->read((char*) &bone_type, sizeof(uint8_t));
180 stream->read((char*) &ik_parent_bone_index, sizeof(uint16_t));
181 stream->read((char*) &bone_head_pos, sizeof(float) * 3);
182 }
183
184 void ReadExpantion(std::istream *stream)
185 {
186 char buffer[20];
187 stream->read(buffer, 20);
188 name_english = std::string(buffer);
189 }
190 };
191
192 class PmdIk
193 {
194 public:
195 uint16_t ik_bone_index;
196 uint16_t target_bone_index;
197 uint16_t interations;
198 float angle_limit;
199 std::vector<uint16_t> ik_child_bone_index;
200
201 void Read(std::istream *stream)
202 {
203 stream->read((char *) &ik_bone_index, sizeof(uint16_t));
204 stream->read((char *) &target_bone_index, sizeof(uint16_t));
205 uint8_t ik_chain_length;
206 stream->read((char*) &ik_chain_length, sizeof(uint8_t));
207 stream->read((char *) &interations, sizeof(uint16_t));
208 stream->read((char *) &angle_limit, sizeof(float));
209 ik_child_bone_index.resize(ik_chain_length);
210 for (int i = 0; i < ik_chain_length; i++)
211 {
212 stream->read((char *) &ik_child_bone_index[i], sizeof(uint16_t));
213 }
214 }
215 };
216
217 class PmdFaceVertex
218 {
219 public:
220 int vertex_index;
221 float position[3];
222
223 void Read(std::istream *stream)
224 {
225 stream->read((char *) &vertex_index, sizeof(int));
226 stream->read((char *) position, sizeof(float) * 3);
227 }
228 };
229
230 enum class FaceCategory : uint8_t
231 {
232 Base,
233 Eyebrow,
234 Eye,
235 Mouth,
236 Other
237 };
238
239 class PmdFace
240 {
241 public:
242 std::string name;
243 FaceCategory type;
244 std::vector<PmdFaceVertex> vertices;
245 std::string name_english;
246
247 void Read(std::istream *stream)
248 {
249 char buffer[20];
250 stream->read(buffer, 20);
251 name = std::string(buffer);
252 int vertex_count;
253 stream->read((char*) &vertex_count, sizeof(int));
254 stream->read((char*) &type, sizeof(uint8_t));
255 vertices.resize(vertex_count);
256 for (int i = 0; i < vertex_count; i++)
257 {
258 vertices[i].Read(stream);
259 }
260 }
261
262 void ReadExpantion(std::istream *stream)
263 {
264 char buffer[20];
265 stream->read(buffer, 20);
266 name_english = std::string(buffer);
267 }
268 };
269
270 class PmdBoneDispName
271 {
272 public:
273 std::string bone_disp_name;
274 std::string bone_disp_name_english;
275
276 void Read(std::istream *stream)
277 {
278 char buffer[50];
279 stream->read(buffer, 50);
280 bone_disp_name = std::string(buffer);
281 bone_disp_name_english.clear();
282 }
283 void ReadExpantion(std::istream *stream)
284 {
285 char buffer[50];
286 stream->read(buffer, 50);
287 bone_disp_name_english = std::string(buffer);
288 }
289 };
290
291 class PmdBoneDisp
292 {
293 public:
294 uint16_t bone_index;
295 uint8_t bone_disp_index;
296
297 void Read(std::istream *stream)
298 {
299 stream->read((char*) &bone_index, sizeof(uint16_t));
300 stream->read((char*) &bone_disp_index, sizeof(uint8_t));
301 }
302 };
303
304 enum class RigidBodyShape : uint8_t
305 {
306 Sphere = 0,
307 Box = 1,
308 Cpusel = 2
309 };
310
311 enum class RigidBodyType : uint8_t
312 {
313 BoneConnected = 0,
314 Physics = 1,
315 ConnectedPhysics = 2
316 };
317
318 class PmdRigidBody
319 {
320 public:
321 std::string name;
322 uint16_t related_bone_index;
323 uint8_t group_index;
324 uint16_t mask;
325 RigidBodyShape shape;
326 float size[3];
327 float position[3];
328 float orientation[3];
329 float weight;
330 float linear_damping;
331 float anglar_damping;
332 float restitution;
333 float friction;
334 RigidBodyType rigid_type;
335
336 void Read(std::istream *stream)
337 {
338 char buffer[20];
339 stream->read(buffer, sizeof(char) * 20);
340 name = (std::string(buffer));
341 stream->read((char*) &related_bone_index, sizeof(uint16_t));
342 stream->read((char*) &group_index, sizeof(uint8_t));
343 stream->read((char*) &mask, sizeof(uint16_t));
344 stream->read((char*) &shape, sizeof(uint8_t));
345 stream->read((char*) size, sizeof(float) * 3);
346 stream->read((char*) position, sizeof(float) * 3);
347 stream->read((char*) orientation, sizeof(float) * 3);
348 stream->read((char*) &weight, sizeof(float));
349 stream->read((char*) &linear_damping, sizeof(float));
350 stream->read((char*) &anglar_damping, sizeof(float));
351 stream->read((char*) &restitution, sizeof(float));
352 stream->read((char*) &friction, sizeof(float));
353 stream->read((char*) &rigid_type, sizeof(char));
354 }
355 };
356
357 class PmdConstraint
358 {
359 public:
360 std::string name;
361 uint32_t rigid_body_index_a;
362 uint32_t rigid_body_index_b;
363 float position[3];
364 float orientation[3];
365 float linear_lower_limit[3];
366 float linear_upper_limit[3];
367 float angular_lower_limit[3];
368 float angular_upper_limit[3];
369 float linear_stiffness[3];
370 float angular_stiffness[3];
371
372 void Read(std::istream *stream)
373 {
374 char buffer[20];
375 stream->read(buffer, 20);
376 name = std::string(buffer);
377 stream->read((char *) &rigid_body_index_a, sizeof(uint32_t));
378 stream->read((char *) &rigid_body_index_b, sizeof(uint32_t));
379 stream->read((char *) position, sizeof(float) * 3);
380 stream->read((char *) orientation, sizeof(float) * 3);
381 stream->read((char *) linear_lower_limit, sizeof(float) * 3);
382 stream->read((char *) linear_upper_limit, sizeof(float) * 3);
383 stream->read((char *) angular_lower_limit, sizeof(float) * 3);
384 stream->read((char *) angular_upper_limit, sizeof(float) * 3);
385 stream->read((char *) linear_stiffness, sizeof(float) * 3);
386 stream->read((char *) angular_stiffness, sizeof(float) * 3);
387 }
388 };
389
390 class PmdModel
391 {
392 public:
393 float version;
394 PmdHeader header;
395 std::vector<PmdVertex> vertices;
396 std::vector<uint16_t> indices;
397 std::vector<PmdMaterial> materials;
398 std::vector<PmdBone> bones;
399 std::vector<PmdIk> iks;
400 std::vector<PmdFace> faces;
401 std::vector<uint16_t> faces_indices;
402 std::vector<PmdBoneDispName> bone_disp_name;
403 std::vector<PmdBoneDisp> bone_disp;
404 std::vector<std::string> toon_filenames;
405 std::vector<PmdRigidBody> rigid_bodies;
406 std::vector<PmdConstraint> constraints;
407
408 static std::unique_ptr<PmdModel> LoadFromFile(const char *filename)
409 {
410 std::ifstream stream(filename, std::ios::binary);
411 if (stream.fail())
412 {
413 std::cerr << "could not open \"" << filename << "\"" << std::endl;
414 return nullptr;
415 }
416 auto result = LoadFromStream(&stream);
417 stream.close();
418 return result;
419 }
420
421 static std::unique_ptr<PmdModel> LoadFromStream(std::ifstream *stream)
422 {
423 auto result = mmd::make_unique<PmdModel>();
424 char buffer[100];
425
426 // magic
427 char magic[3];
428 stream->read(magic, 3);
429 if (magic[0] != 'P' || magic[1] != 'm' || magic[2] != 'd')
430 {
431 std::cerr << "invalid file" << std::endl;
432 return nullptr;
433 }
434
435 // version
436 stream->read((char*) &(result->version), sizeof(float));
437 if (result ->version != 1.0f)
438 {
439 std::cerr << "invalid version" << std::endl;
440 return nullptr;
441 }
442
443 // header
444 result->header.Read(stream);
445
446 // vertices
447 uint32_t vertex_num;
448 stream->read((char*) &vertex_num, sizeof(uint32_t));
449 result->vertices.resize(vertex_num);
450 for (uint32_t i = 0; i < vertex_num; i++)
451 {
452 result->vertices[i].Read(stream);
453 }
454
455 // indices
456 uint32_t index_num;
457 stream->read((char*) &index_num, sizeof(uint32_t));
458 result->indices.resize(index_num);
459 for (uint32_t i = 0; i < index_num; i++)
460 {
461 stream->read((char*) &result->indices[i], sizeof(uint16_t));
462 }
463
464 // materials
465 uint32_t material_num;
466 stream->read((char*) &material_num, sizeof(uint32_t));
467 result->materials.resize(material_num);
468 for (uint32_t i = 0; i < material_num; i++)
469 {
470 result->materials[i].Read(stream);
471 }
472
473 // bones
474 uint16_t bone_num;
475 stream->read((char*) &bone_num, sizeof(uint16_t));
476 result->bones.resize(bone_num);
477 for (uint32_t i = 0; i < bone_num; i++)
478 {
479 result->bones[i].Read(stream);
480 }
481
482 // iks
483 uint16_t ik_num;
484 stream->read((char*) &ik_num, sizeof(uint16_t));
485 result->iks.resize(ik_num);
486 for (uint32_t i = 0; i < ik_num; i++)
487 {
488 result->iks[i].Read(stream);
489 }
490
491 // faces
492 uint16_t face_num;
493 stream->read((char*) &face_num, sizeof(uint16_t));
494 result->faces.resize(face_num);
495 for (uint32_t i = 0; i < face_num; i++)
496 {
497 result->faces[i].Read(stream);
498 }
499
500 // face frames
501 uint8_t face_frame_num;
502 stream->read((char*) &face_frame_num, sizeof(uint8_t));
503 result->faces_indices.resize(face_frame_num);
504 for (uint32_t i = 0; i < face_frame_num; i++)
505 {
506 stream->read((char*) &result->faces_indices[i], sizeof(uint16_t));
507 }
508
509 // bone names
510 uint8_t bone_disp_num;
511 stream->read((char*) &bone_disp_num, sizeof(uint8_t));
512 result->bone_disp_name.resize(bone_disp_num);
513 for (uint32_t i = 0; i < bone_disp_num; i++)
514 {
515 result->bone_disp_name[i].Read(stream);
516 }
517
518 // bone frame
519 uint32_t bone_frame_num;
520 stream->read((char*) &bone_frame_num, sizeof(uint32_t));
521 result->bone_disp.resize(bone_frame_num);
522 for (uint32_t i = 0; i < bone_frame_num; i++)
523 {
524 result->bone_disp[i].Read(stream);
525 }
526
527 // english name
528 bool english;
529 stream->read((char*) &english, sizeof(char));
530 if (english)
531 {
532 result->header.ReadExtension(stream);
533 for (uint32_t i = 0; i < bone_num; i++)
534 {
535 result->bones[i].ReadExpantion(stream);
536 }
537 for (uint32_t i = 0; i < face_num; i++)
538 {
539 if (result->faces[i].type == pmd::FaceCategory::Base)
540 {
541 continue;
542 }
543 result->faces[i].ReadExpantion(stream);
544 }
545 for (uint32_t i = 0; i < result->bone_disp_name.size(); i++)
546 {
547 result->bone_disp_name[i].ReadExpantion(stream);
548 }
549 }
550
551 // toon textures
552 if (stream->peek() == std::ios::traits_type::eof())
553 {
554 result->toon_filenames.clear();
555 }
556 else {
557 result->toon_filenames.resize(10);
558 for (uint32_t i = 0; i < 10; i++)
559 {
560 stream->read(buffer, 100);
561 result->toon_filenames[i] = std::string(buffer);
562 }
563 }
564
565 // physics
566 if (stream->peek() == std::ios::traits_type::eof())
567 {
568 result->rigid_bodies.clear();
569 result->constraints.clear();
570 }
571 else {
572 uint32_t rigid_body_num;
573 stream->read((char*) &rigid_body_num, sizeof(uint32_t));
574 result->rigid_bodies.resize(rigid_body_num);
575 for (uint32_t i = 0; i < rigid_body_num; i++)
576 {
577 result->rigid_bodies[i].Read(stream);
578 }
579 uint32_t constraint_num;
580 stream->read((char*) &constraint_num, sizeof(uint32_t));
581 result->constraints.resize(constraint_num);
582 for (uint32_t i = 0; i < constraint_num; i++)
583 {
584 result->constraints[i].Read(stream);
585 }
586 }
587
588 if (stream->peek() != std::ios::traits_type::eof())
589 {
590 std::cerr << "there is unknown data" << std::endl;
591 }
592
593 return result;
594 }
595 };
596}
597