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