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