|
@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
|
|
|
|
|
Copyright (c) 2006-2022, assimp team
|
|
|
|
|
|
-
|
|
|
All rights reserved.
|
|
|
|
|
|
Redistribution and use of this software in source and binary forms,
|
|
@@ -48,550 +47,594 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
#include <fstream>
|
|
|
#include "MMDCpp14.h"
|
|
|
|
|
|
-namespace pmd
|
|
|
-{
|
|
|
- class PmdHeader
|
|
|
- {
|
|
|
- public:
|
|
|
- std::string name;
|
|
|
- std::string name_english;
|
|
|
- std::string comment;
|
|
|
- std::string comment_english;
|
|
|
-
|
|
|
- bool Read(std::ifstream* stream)
|
|
|
- {
|
|
|
- char buffer[256];
|
|
|
- stream->read(buffer, 20);
|
|
|
- name = std::string(buffer);
|
|
|
- stream->read(buffer, 256);
|
|
|
- comment = std::string(buffer);
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- bool ReadExtension(std::ifstream* stream)
|
|
|
- {
|
|
|
- char buffer[256];
|
|
|
- stream->read(buffer, 20);
|
|
|
- name_english = std::string(buffer);
|
|
|
- stream->read(buffer, 256);
|
|
|
- comment_english = std::string(buffer);
|
|
|
- return true;
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- class PmdVertex
|
|
|
- {
|
|
|
- public:
|
|
|
- float position[3];
|
|
|
-
|
|
|
- float normal[3];
|
|
|
-
|
|
|
- float uv[2];
|
|
|
-
|
|
|
- uint16_t bone_index[2];
|
|
|
-
|
|
|
- uint8_t bone_weight;
|
|
|
-
|
|
|
- bool edge_invisible;
|
|
|
-
|
|
|
- bool Read(std::ifstream* stream)
|
|
|
- {
|
|
|
- stream->read((char*) position, sizeof(float) * 3);
|
|
|
- stream->read((char*) normal, sizeof(float) * 3);
|
|
|
- stream->read((char*) uv, sizeof(float) * 2);
|
|
|
- stream->read((char*) bone_index, sizeof(uint16_t) * 2);
|
|
|
- stream->read((char*) &bone_weight, sizeof(uint8_t));
|
|
|
- stream->read((char*) &edge_invisible, sizeof(uint8_t));
|
|
|
- return true;
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- class PmdMaterial
|
|
|
- {
|
|
|
- public:
|
|
|
- float diffuse[4];
|
|
|
- float power;
|
|
|
- float specular[3];
|
|
|
- float ambient[3];
|
|
|
- uint8_t toon_index;
|
|
|
- uint8_t edge_flag;
|
|
|
- uint32_t index_count;
|
|
|
- std::string texture_filename;
|
|
|
- std::string sphere_filename;
|
|
|
-
|
|
|
- bool Read(std::ifstream* stream)
|
|
|
- {
|
|
|
- char buffer[20];
|
|
|
- stream->read((char*) &diffuse, sizeof(float) * 4);
|
|
|
- stream->read((char*) &power, sizeof(float));
|
|
|
- stream->read((char*) &specular, sizeof(float) * 3);
|
|
|
- stream->read((char*) &ambient, sizeof(float) * 3);
|
|
|
- stream->read((char*) &toon_index, sizeof(uint8_t));
|
|
|
- stream->read((char*) &edge_flag, sizeof(uint8_t));
|
|
|
- stream->read((char*) &index_count, sizeof(uint32_t));
|
|
|
- stream->read((char*) &buffer, sizeof(char) * 20);
|
|
|
- char* pstar = strchr(buffer, '*');
|
|
|
- if (nullptr == pstar)
|
|
|
- {
|
|
|
- texture_filename = std::string(buffer);
|
|
|
- sphere_filename.clear();
|
|
|
- }
|
|
|
- else {
|
|
|
- *pstar = 0;
|
|
|
- texture_filename = std::string(buffer);
|
|
|
- sphere_filename = std::string(pstar+1);
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- enum class BoneType : uint8_t
|
|
|
- {
|
|
|
- Rotation,
|
|
|
- RotationAndMove,
|
|
|
- IkEffector,
|
|
|
- Unknown,
|
|
|
- IkEffectable,
|
|
|
- RotationEffectable,
|
|
|
- IkTarget,
|
|
|
- Invisible,
|
|
|
- Twist,
|
|
|
- RotationMovement
|
|
|
- };
|
|
|
-
|
|
|
- class PmdBone
|
|
|
- {
|
|
|
- public:
|
|
|
- std::string name;
|
|
|
- std::string name_english;
|
|
|
- uint16_t parent_bone_index;
|
|
|
- uint16_t tail_pos_bone_index;
|
|
|
- BoneType bone_type;
|
|
|
- uint16_t ik_parent_bone_index;
|
|
|
- float bone_head_pos[3];
|
|
|
-
|
|
|
- void Read(std::istream *stream)
|
|
|
- {
|
|
|
- char buffer[20];
|
|
|
- stream->read(buffer, 20);
|
|
|
- name = std::string(buffer);
|
|
|
- stream->read((char*) &parent_bone_index, sizeof(uint16_t));
|
|
|
- stream->read((char*) &tail_pos_bone_index, sizeof(uint16_t));
|
|
|
- stream->read((char*) &bone_type, sizeof(uint8_t));
|
|
|
- stream->read((char*) &ik_parent_bone_index, sizeof(uint16_t));
|
|
|
- stream->read((char*) &bone_head_pos, sizeof(float) * 3);
|
|
|
- }
|
|
|
-
|
|
|
- void ReadExpantion(std::istream *stream)
|
|
|
- {
|
|
|
- char buffer[20];
|
|
|
- stream->read(buffer, 20);
|
|
|
- name_english = std::string(buffer);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- class PmdIk
|
|
|
- {
|
|
|
- public:
|
|
|
- uint16_t ik_bone_index;
|
|
|
- uint16_t target_bone_index;
|
|
|
- uint16_t iterations;
|
|
|
- float angle_limit;
|
|
|
- std::vector<uint16_t> ik_child_bone_index;
|
|
|
-
|
|
|
- void Read(std::istream *stream)
|
|
|
- {
|
|
|
- stream->read((char *) &ik_bone_index, sizeof(uint16_t));
|
|
|
- stream->read((char *) &target_bone_index, sizeof(uint16_t));
|
|
|
- uint8_t ik_chain_length;
|
|
|
- stream->read((char*) &ik_chain_length, sizeof(uint8_t));
|
|
|
- stream->read((char *) &iterations, sizeof(uint16_t));
|
|
|
- stream->read((char *) &angle_limit, sizeof(float));
|
|
|
- ik_child_bone_index.resize(ik_chain_length);
|
|
|
- for (int i = 0; i < ik_chain_length; i++)
|
|
|
- {
|
|
|
- stream->read((char *) &ik_child_bone_index[i], sizeof(uint16_t));
|
|
|
- }
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- class PmdFaceVertex
|
|
|
- {
|
|
|
- public:
|
|
|
- int vertex_index;
|
|
|
- float position[3];
|
|
|
-
|
|
|
- void Read(std::istream *stream)
|
|
|
- {
|
|
|
- stream->read((char *) &vertex_index, sizeof(int));
|
|
|
- stream->read((char *) position, sizeof(float) * 3);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- enum class FaceCategory : uint8_t
|
|
|
- {
|
|
|
- Base,
|
|
|
- Eyebrow,
|
|
|
- Eye,
|
|
|
- Mouth,
|
|
|
- Other
|
|
|
- };
|
|
|
-
|
|
|
- class PmdFace
|
|
|
- {
|
|
|
- public:
|
|
|
- std::string name;
|
|
|
- FaceCategory type;
|
|
|
- std::vector<PmdFaceVertex> vertices;
|
|
|
- std::string name_english;
|
|
|
-
|
|
|
- void Read(std::istream *stream)
|
|
|
- {
|
|
|
- char buffer[20];
|
|
|
- stream->read(buffer, 20);
|
|
|
- name = std::string(buffer);
|
|
|
- int vertex_count;
|
|
|
- stream->read((char*) &vertex_count, sizeof(int));
|
|
|
- stream->read((char*) &type, sizeof(uint8_t));
|
|
|
- vertices.resize(vertex_count);
|
|
|
- for (int i = 0; i < vertex_count; i++)
|
|
|
- {
|
|
|
- vertices[i].Read(stream);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- void ReadExpantion(std::istream *stream)
|
|
|
- {
|
|
|
- char buffer[20];
|
|
|
- stream->read(buffer, 20);
|
|
|
- name_english = std::string(buffer);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- class PmdBoneDispName
|
|
|
- {
|
|
|
- public:
|
|
|
- std::string bone_disp_name;
|
|
|
- std::string bone_disp_name_english;
|
|
|
-
|
|
|
- void Read(std::istream *stream)
|
|
|
- {
|
|
|
- char buffer[50];
|
|
|
- stream->read(buffer, 50);
|
|
|
- bone_disp_name = std::string(buffer);
|
|
|
- bone_disp_name_english.clear();
|
|
|
- }
|
|
|
- void ReadExpantion(std::istream *stream)
|
|
|
- {
|
|
|
- char buffer[50];
|
|
|
- stream->read(buffer, 50);
|
|
|
- bone_disp_name_english = std::string(buffer);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- class PmdBoneDisp
|
|
|
- {
|
|
|
- public:
|
|
|
- uint16_t bone_index;
|
|
|
- uint8_t bone_disp_index;
|
|
|
-
|
|
|
- void Read(std::istream *stream)
|
|
|
- {
|
|
|
- stream->read((char*) &bone_index, sizeof(uint16_t));
|
|
|
- stream->read((char*) &bone_disp_index, sizeof(uint8_t));
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- enum class RigidBodyShape : uint8_t
|
|
|
- {
|
|
|
- Sphere = 0,
|
|
|
- Box = 1,
|
|
|
- Cpusel = 2
|
|
|
- };
|
|
|
-
|
|
|
- enum class RigidBodyType : uint8_t
|
|
|
- {
|
|
|
- BoneConnected = 0,
|
|
|
- Physics = 1,
|
|
|
- ConnectedPhysics = 2
|
|
|
- };
|
|
|
-
|
|
|
- class PmdRigidBody
|
|
|
- {
|
|
|
- public:
|
|
|
- std::string name;
|
|
|
- uint16_t related_bone_index;
|
|
|
- uint8_t group_index;
|
|
|
- uint16_t mask;
|
|
|
- RigidBodyShape shape;
|
|
|
- float size[3];
|
|
|
- float position[3];
|
|
|
- float orientation[3];
|
|
|
- float weight;
|
|
|
- float linear_damping;
|
|
|
- float anglar_damping;
|
|
|
- float restitution;
|
|
|
- float friction;
|
|
|
- RigidBodyType rigid_type;
|
|
|
-
|
|
|
- void Read(std::istream *stream)
|
|
|
- {
|
|
|
- char buffer[20];
|
|
|
- stream->read(buffer, sizeof(char) * 20);
|
|
|
- name = (std::string(buffer));
|
|
|
- stream->read((char*) &related_bone_index, sizeof(uint16_t));
|
|
|
- stream->read((char*) &group_index, sizeof(uint8_t));
|
|
|
- stream->read((char*) &mask, sizeof(uint16_t));
|
|
|
- stream->read((char*) &shape, sizeof(uint8_t));
|
|
|
- stream->read((char*) size, sizeof(float) * 3);
|
|
|
- stream->read((char*) position, sizeof(float) * 3);
|
|
|
- stream->read((char*) orientation, sizeof(float) * 3);
|
|
|
- stream->read((char*) &weight, sizeof(float));
|
|
|
- stream->read((char*) &linear_damping, sizeof(float));
|
|
|
- stream->read((char*) &anglar_damping, sizeof(float));
|
|
|
- stream->read((char*) &restitution, sizeof(float));
|
|
|
- stream->read((char*) &friction, sizeof(float));
|
|
|
- stream->read((char*) &rigid_type, sizeof(char));
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- class PmdConstraint
|
|
|
- {
|
|
|
- public:
|
|
|
- std::string name;
|
|
|
- uint32_t rigid_body_index_a;
|
|
|
- uint32_t rigid_body_index_b;
|
|
|
- float position[3];
|
|
|
- float orientation[3];
|
|
|
- float linear_lower_limit[3];
|
|
|
- float linear_upper_limit[3];
|
|
|
- float angular_lower_limit[3];
|
|
|
- float angular_upper_limit[3];
|
|
|
- float linear_stiffness[3];
|
|
|
- float angular_stiffness[3];
|
|
|
-
|
|
|
- void Read(std::istream *stream)
|
|
|
- {
|
|
|
- char buffer[20];
|
|
|
- stream->read(buffer, 20);
|
|
|
- name = std::string(buffer);
|
|
|
- stream->read((char *) &rigid_body_index_a, sizeof(uint32_t));
|
|
|
- stream->read((char *) &rigid_body_index_b, sizeof(uint32_t));
|
|
|
- stream->read((char *) position, sizeof(float) * 3);
|
|
|
- stream->read((char *) orientation, sizeof(float) * 3);
|
|
|
- stream->read((char *) linear_lower_limit, sizeof(float) * 3);
|
|
|
- stream->read((char *) linear_upper_limit, sizeof(float) * 3);
|
|
|
- stream->read((char *) angular_lower_limit, sizeof(float) * 3);
|
|
|
- stream->read((char *) angular_upper_limit, sizeof(float) * 3);
|
|
|
- stream->read((char *) linear_stiffness, sizeof(float) * 3);
|
|
|
- stream->read((char *) angular_stiffness, sizeof(float) * 3);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- class PmdModel
|
|
|
- {
|
|
|
- public:
|
|
|
- float version;
|
|
|
- PmdHeader header;
|
|
|
- std::vector<PmdVertex> vertices;
|
|
|
- std::vector<uint16_t> indices;
|
|
|
- std::vector<PmdMaterial> materials;
|
|
|
- std::vector<PmdBone> bones;
|
|
|
- std::vector<PmdIk> iks;
|
|
|
- std::vector<PmdFace> faces;
|
|
|
- std::vector<uint16_t> faces_indices;
|
|
|
- std::vector<PmdBoneDispName> bone_disp_name;
|
|
|
- std::vector<PmdBoneDisp> bone_disp;
|
|
|
- std::vector<std::string> toon_filenames;
|
|
|
- std::vector<PmdRigidBody> rigid_bodies;
|
|
|
- std::vector<PmdConstraint> constraints;
|
|
|
-
|
|
|
- static std::unique_ptr<PmdModel> LoadFromFile(const char *filename)
|
|
|
- {
|
|
|
- std::ifstream stream(filename, std::ios::binary);
|
|
|
- if (stream.fail())
|
|
|
- {
|
|
|
- std::cerr << "could not open \"" << filename << "\"" << std::endl;
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
- auto result = LoadFromStream(&stream);
|
|
|
- stream.close();
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
- static std::unique_ptr<PmdModel> LoadFromStream(std::ifstream *stream)
|
|
|
- {
|
|
|
- auto result = mmd::make_unique<PmdModel>();
|
|
|
- char buffer[100];
|
|
|
-
|
|
|
- // magic
|
|
|
- char magic[3];
|
|
|
- stream->read(magic, 3);
|
|
|
- if (magic[0] != 'P' || magic[1] != 'm' || magic[2] != 'd')
|
|
|
- {
|
|
|
- std::cerr << "invalid file" << std::endl;
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
-
|
|
|
- // version
|
|
|
- stream->read((char*) &(result->version), sizeof(float));
|
|
|
- if (result ->version != 1.0f)
|
|
|
- {
|
|
|
- std::cerr << "invalid version" << std::endl;
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
-
|
|
|
- // header
|
|
|
- result->header.Read(stream);
|
|
|
-
|
|
|
- // vertices
|
|
|
- uint32_t vertex_num;
|
|
|
- stream->read((char*) &vertex_num, sizeof(uint32_t));
|
|
|
- result->vertices.resize(vertex_num);
|
|
|
- for (uint32_t i = 0; i < vertex_num; i++)
|
|
|
- {
|
|
|
- result->vertices[i].Read(stream);
|
|
|
- }
|
|
|
-
|
|
|
- // indices
|
|
|
- uint32_t index_num;
|
|
|
- stream->read((char*) &index_num, sizeof(uint32_t));
|
|
|
- result->indices.resize(index_num);
|
|
|
- for (uint32_t i = 0; i < index_num; i++)
|
|
|
- {
|
|
|
- stream->read((char*) &result->indices[i], sizeof(uint16_t));
|
|
|
- }
|
|
|
-
|
|
|
- // materials
|
|
|
- uint32_t material_num;
|
|
|
- stream->read((char*) &material_num, sizeof(uint32_t));
|
|
|
- result->materials.resize(material_num);
|
|
|
- for (uint32_t i = 0; i < material_num; i++)
|
|
|
- {
|
|
|
- result->materials[i].Read(stream);
|
|
|
- }
|
|
|
-
|
|
|
- // bones
|
|
|
- uint16_t bone_num;
|
|
|
- stream->read((char*) &bone_num, sizeof(uint16_t));
|
|
|
- result->bones.resize(bone_num);
|
|
|
- for (uint32_t i = 0; i < bone_num; i++)
|
|
|
- {
|
|
|
- result->bones[i].Read(stream);
|
|
|
- }
|
|
|
-
|
|
|
- // iks
|
|
|
- uint16_t ik_num;
|
|
|
- stream->read((char*) &ik_num, sizeof(uint16_t));
|
|
|
- result->iks.resize(ik_num);
|
|
|
- for (uint32_t i = 0; i < ik_num; i++)
|
|
|
- {
|
|
|
- result->iks[i].Read(stream);
|
|
|
- }
|
|
|
-
|
|
|
- // faces
|
|
|
- uint16_t face_num;
|
|
|
- stream->read((char*) &face_num, sizeof(uint16_t));
|
|
|
- result->faces.resize(face_num);
|
|
|
- for (uint32_t i = 0; i < face_num; i++)
|
|
|
- {
|
|
|
- result->faces[i].Read(stream);
|
|
|
- }
|
|
|
-
|
|
|
- // face frames
|
|
|
- uint8_t face_frame_num;
|
|
|
- stream->read((char*) &face_frame_num, sizeof(uint8_t));
|
|
|
- result->faces_indices.resize(face_frame_num);
|
|
|
- for (uint32_t i = 0; i < face_frame_num; i++)
|
|
|
- {
|
|
|
- stream->read((char*) &result->faces_indices[i], sizeof(uint16_t));
|
|
|
- }
|
|
|
-
|
|
|
- // bone names
|
|
|
- uint8_t bone_disp_num;
|
|
|
- stream->read((char*) &bone_disp_num, sizeof(uint8_t));
|
|
|
- result->bone_disp_name.resize(bone_disp_num);
|
|
|
- for (uint32_t i = 0; i < bone_disp_num; i++)
|
|
|
- {
|
|
|
- result->bone_disp_name[i].Read(stream);
|
|
|
- }
|
|
|
-
|
|
|
- // bone frame
|
|
|
- uint32_t bone_frame_num;
|
|
|
- stream->read((char*) &bone_frame_num, sizeof(uint32_t));
|
|
|
- result->bone_disp.resize(bone_frame_num);
|
|
|
- for (uint32_t i = 0; i < bone_frame_num; i++)
|
|
|
- {
|
|
|
- result->bone_disp[i].Read(stream);
|
|
|
- }
|
|
|
-
|
|
|
- // english name
|
|
|
- bool english;
|
|
|
- stream->read((char*) &english, sizeof(char));
|
|
|
- if (english)
|
|
|
- {
|
|
|
- result->header.ReadExtension(stream);
|
|
|
- for (uint32_t i = 0; i < bone_num; i++)
|
|
|
- {
|
|
|
- result->bones[i].ReadExpantion(stream);
|
|
|
- }
|
|
|
- for (uint32_t i = 0; i < face_num; i++)
|
|
|
- {
|
|
|
- if (result->faces[i].type == pmd::FaceCategory::Base)
|
|
|
- {
|
|
|
- continue;
|
|
|
- }
|
|
|
- result->faces[i].ReadExpantion(stream);
|
|
|
- }
|
|
|
- for (uint32_t i = 0; i < result->bone_disp_name.size(); i++)
|
|
|
- {
|
|
|
- result->bone_disp_name[i].ReadExpantion(stream);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // toon textures
|
|
|
- if (stream->peek() == std::ios::traits_type::eof())
|
|
|
- {
|
|
|
- result->toon_filenames.clear();
|
|
|
- }
|
|
|
- else {
|
|
|
- result->toon_filenames.resize(10);
|
|
|
- for (uint32_t i = 0; i < 10; i++)
|
|
|
- {
|
|
|
- stream->read(buffer, 100);
|
|
|
- result->toon_filenames[i] = std::string(buffer);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // physics
|
|
|
- if (stream->peek() == std::ios::traits_type::eof())
|
|
|
- {
|
|
|
- result->rigid_bodies.clear();
|
|
|
- result->constraints.clear();
|
|
|
- }
|
|
|
- else {
|
|
|
- uint32_t rigid_body_num;
|
|
|
- stream->read((char*) &rigid_body_num, sizeof(uint32_t));
|
|
|
- result->rigid_bodies.resize(rigid_body_num);
|
|
|
- for (uint32_t i = 0; i < rigid_body_num; i++)
|
|
|
- {
|
|
|
- result->rigid_bodies[i].Read(stream);
|
|
|
- }
|
|
|
- uint32_t constraint_num;
|
|
|
- stream->read((char*) &constraint_num, sizeof(uint32_t));
|
|
|
- result->constraints.resize(constraint_num);
|
|
|
- for (uint32_t i = 0; i < constraint_num; i++)
|
|
|
- {
|
|
|
- result->constraints[i].Read(stream);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (stream->peek() != std::ios::traits_type::eof())
|
|
|
- {
|
|
|
- std::cerr << "there is unknown data" << std::endl;
|
|
|
- }
|
|
|
-
|
|
|
- return result;
|
|
|
- }
|
|
|
- };
|
|
|
-}
|
|
|
+namespace pmd {
|
|
|
+
|
|
|
+struct PmdHeader {
|
|
|
+ std::string name;
|
|
|
+ std::string name_english;
|
|
|
+ std::string comment;
|
|
|
+ std::string comment_english;
|
|
|
+
|
|
|
+ PmdHeader() = default;
|
|
|
+ ~PmdHeader() = default;
|
|
|
+
|
|
|
+ bool Read(std::ifstream *stream) {
|
|
|
+ if (stream == nullptr) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ char buffer[256] = {};
|
|
|
+ stream->read(buffer, 20);
|
|
|
+ name = std::string(buffer);
|
|
|
+ stream->read(buffer, 256);
|
|
|
+ comment = std::string(buffer);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool ReadExtension(std::ifstream *stream) {
|
|
|
+ if (stream == nullptr) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ char buffer[256] = {};
|
|
|
+ stream->read(buffer, 20);
|
|
|
+ name_english = std::string(buffer);
|
|
|
+ stream->read(buffer, 256);
|
|
|
+ comment_english = std::string(buffer);
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+struct PmdVertex {
|
|
|
+ float position[3];
|
|
|
+ float normal[3];
|
|
|
+ float uv[2];
|
|
|
+ uint16_t bone_index[2];
|
|
|
+ uint8_t bone_weight;
|
|
|
+ bool edge_invisible;
|
|
|
+
|
|
|
+ PmdVertex() :
|
|
|
+ position{ 0.0f }, normal{ 0.0f }, uv{ 0.0f }, bone_index{ 0 }, bone_weight(0), edge_invisible(false) {}
|
|
|
+
|
|
|
+ ~PmdVertex() = default;
|
|
|
+
|
|
|
+ bool Read(std::ifstream *stream) {
|
|
|
+ if (stream == nullptr) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ stream->read((char *)position, sizeof(float) * 3);
|
|
|
+ stream->read((char *)normal, sizeof(float) * 3);
|
|
|
+ stream->read((char *)uv, sizeof(float) * 2);
|
|
|
+ stream->read((char *)bone_index, sizeof(uint16_t) * 2);
|
|
|
+ stream->read((char *)&bone_weight, sizeof(uint8_t));
|
|
|
+ stream->read((char *)&edge_invisible, sizeof(uint8_t));
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+struct PmdMaterial {
|
|
|
+ float diffuse[4];
|
|
|
+ float power;
|
|
|
+ float specular[3];
|
|
|
+ float ambient[3];
|
|
|
+ uint8_t toon_index;
|
|
|
+ uint8_t edge_flag;
|
|
|
+ uint32_t index_count;
|
|
|
+ std::string texture_filename;
|
|
|
+ std::string sphere_filename;
|
|
|
+
|
|
|
+ PmdMaterial() :
|
|
|
+ diffuse{ 0.0f }, power(0.0f), specular{ 0.0f }, ambient{ 0.0f }, toon_index(0), edge_flag(0), index_count(0), texture_filename(), sphere_filename() {}
|
|
|
+
|
|
|
+ ~PmdMaterial() = default;
|
|
|
+
|
|
|
+ bool Read(std::ifstream *stream) {
|
|
|
+ if (stream == nullptr) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ constexpr size_t BufferSize = 20;
|
|
|
+
|
|
|
+ char buffer[BufferSize] = {};
|
|
|
+ stream->read((char *)&diffuse, sizeof(float) * 4);
|
|
|
+ stream->read((char *)&power, sizeof(float));
|
|
|
+ stream->read((char *)&specular, sizeof(float) * 3);
|
|
|
+ stream->read((char *)&ambient, sizeof(float) * 3);
|
|
|
+ stream->read((char *)&toon_index, sizeof(uint8_t));
|
|
|
+ stream->read((char *)&edge_flag, sizeof(uint8_t));
|
|
|
+ stream->read((char *)&index_count, sizeof(uint32_t));
|
|
|
+ stream->read((char *)&buffer, sizeof(char) * BufferSize);
|
|
|
+ char *pstar = strchr(buffer, '*');
|
|
|
+ if (nullptr == pstar) {
|
|
|
+ texture_filename = std::string(buffer);
|
|
|
+ sphere_filename.clear();
|
|
|
+ } else {
|
|
|
+ *pstar = 0;
|
|
|
+ texture_filename = std::string(buffer);
|
|
|
+ sphere_filename = std::string(pstar + 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+enum class BoneType : uint8_t {
|
|
|
+ Rotation,
|
|
|
+ RotationAndMove,
|
|
|
+ IkEffector,
|
|
|
+ Unknown,
|
|
|
+ IkEffectable,
|
|
|
+ RotationEffectable,
|
|
|
+ IkTarget,
|
|
|
+ Invisible,
|
|
|
+ Twist,
|
|
|
+ RotationMovement
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+struct PmdBone {
|
|
|
+ std::string name;
|
|
|
+ std::string name_english;
|
|
|
+ uint16_t parent_bone_index;
|
|
|
+ uint16_t tail_pos_bone_index;
|
|
|
+ BoneType bone_type;
|
|
|
+ uint16_t ik_parent_bone_index;
|
|
|
+ float bone_head_pos[3];
|
|
|
+
|
|
|
+ PmdBone() :
|
|
|
+ name(), name_english(), parent_bone_index(0), tail_pos_bone_index(0), bone_type(BoneType::Unknown), ik_parent_bone_index(0), bone_head_pos{ 0.0f } {}
|
|
|
+
|
|
|
+ ~PmdBone() = default;
|
|
|
+
|
|
|
+ void Read(std::istream *stream) {
|
|
|
+ if (stream == nullptr) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ constexpr size_t BufferSize = 20;
|
|
|
+ char buffer[BufferSize] = {};
|
|
|
+ stream->read(buffer, BufferSize);
|
|
|
+ name = std::string(buffer);
|
|
|
+ stream->read((char *)&parent_bone_index, sizeof(uint16_t));
|
|
|
+ stream->read((char *)&tail_pos_bone_index, sizeof(uint16_t));
|
|
|
+ stream->read((char *)&bone_type, sizeof(uint8_t));
|
|
|
+ stream->read((char *)&ik_parent_bone_index, sizeof(uint16_t));
|
|
|
+ stream->read((char *)&bone_head_pos, sizeof(float) * 3);
|
|
|
+ }
|
|
|
+
|
|
|
+ void ReadExpantion(std::istream *stream) {
|
|
|
+ if (stream == nullptr) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ constexpr size_t BufferSize = 20;
|
|
|
+ char buffer[BufferSize] = {};
|
|
|
+ stream->read(buffer, BufferSize);
|
|
|
+ name_english = std::string(buffer);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+struct PmdIk {
|
|
|
+ uint16_t ik_bone_index;
|
|
|
+ uint16_t target_bone_index;
|
|
|
+ uint16_t iterations;
|
|
|
+ float angle_limit;
|
|
|
+ std::vector<uint16_t> ik_child_bone_index;
|
|
|
+
|
|
|
+ PmdIk() : ik_bone_index(0), target_bone_index(0), iterations(0), angle_limit(0.0f) {}
|
|
|
+
|
|
|
+ ~PmdIk() = default;
|
|
|
+
|
|
|
+ void Read(std::istream *stream) {
|
|
|
+ if (stream == nullptr) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ stream->read((char *)&ik_bone_index, sizeof(uint16_t));
|
|
|
+ stream->read((char *)&target_bone_index, sizeof(uint16_t));
|
|
|
+ uint8_t ik_chain_length;
|
|
|
+ stream->read((char *)&ik_chain_length, sizeof(uint8_t));
|
|
|
+ stream->read((char *)&iterations, sizeof(uint16_t));
|
|
|
+ stream->read((char *)&angle_limit, sizeof(float));
|
|
|
+ ik_child_bone_index.resize(ik_chain_length);
|
|
|
+ for (int i = 0; i < ik_chain_length; i++) {
|
|
|
+ stream->read((char *)&ik_child_bone_index[i], sizeof(uint16_t));
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+struct PmdFaceVertex {
|
|
|
+ int vertex_index;
|
|
|
+ float position[3];
|
|
|
+
|
|
|
+ PmdFaceVertex() :
|
|
|
+ vertex_index(0), position{ 0.0f } {}
|
|
|
+
|
|
|
+ ~PmdFaceVertex() = default;
|
|
|
+
|
|
|
+ void Read(std::istream *stream) {
|
|
|
+ if (stream == nullptr) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ stream->read((char *)&vertex_index, sizeof(int));
|
|
|
+ stream->read((char *)position, sizeof(float) * 3);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+enum class FaceCategory : uint8_t {
|
|
|
+ Base,
|
|
|
+ Eyebrow,
|
|
|
+ Eye,
|
|
|
+ Mouth,
|
|
|
+ Other
|
|
|
+};
|
|
|
+
|
|
|
+struct PmdFace {
|
|
|
+ std::string name;
|
|
|
+ FaceCategory type;
|
|
|
+ std::vector<PmdFaceVertex> vertices;
|
|
|
+ std::string name_english;
|
|
|
+
|
|
|
+ PmdFace() :
|
|
|
+ name(), type(FaceCategory::Other), vertices(), name_english() {}
|
|
|
+
|
|
|
+ ~PmdFace() = default;
|
|
|
+
|
|
|
+ void Read(std::istream *stream) {
|
|
|
+ if (stream == nullptr) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ constexpr size_t BufferSize = 20;
|
|
|
+ char buffer[BufferSize];
|
|
|
+ stream->read(buffer, BufferSize);
|
|
|
+ name = std::string(buffer);
|
|
|
+ int vertex_count;
|
|
|
+ stream->read((char *)&vertex_count, sizeof(int));
|
|
|
+ stream->read((char *)&type, sizeof(uint8_t));
|
|
|
+ vertices.resize(vertex_count);
|
|
|
+ for (int i = 0; i < vertex_count; i++) {
|
|
|
+ vertices[i].Read(stream);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void ReadExpantion(std::istream *stream) {
|
|
|
+ if (stream == nullptr) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ char buffer[20];
|
|
|
+ stream->read(buffer, 20);
|
|
|
+ name_english = std::string(buffer);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+struct PmdBoneDispName {
|
|
|
+ std::string bone_disp_name;
|
|
|
+ std::string bone_disp_name_english;
|
|
|
+
|
|
|
+ PmdBoneDispName() = default;
|
|
|
+
|
|
|
+ ~PmdBoneDispName() = default;
|
|
|
+
|
|
|
+ void Read(std::istream *stream) {
|
|
|
+ if (stream == nullptr) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ char buffer[50];
|
|
|
+ stream->read(buffer, 50);
|
|
|
+ bone_disp_name = std::string(buffer);
|
|
|
+ bone_disp_name_english.clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ void ReadExpantion(std::istream *stream) {
|
|
|
+ if (stream == nullptr) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ char buffer[50];
|
|
|
+ stream->read(buffer, 50);
|
|
|
+ bone_disp_name_english = std::string(buffer);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+struct PmdBoneDisp {
|
|
|
+ uint16_t bone_index;
|
|
|
+ uint8_t bone_disp_index;
|
|
|
+
|
|
|
+ PmdBoneDisp() :
|
|
|
+ bone_index(0), bone_disp_index(0) {}
|
|
|
+
|
|
|
+ ~PmdBoneDisp() = default;
|
|
|
+
|
|
|
+ void Read(std::istream *stream) {
|
|
|
+ if (stream == nullptr) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ stream->read((char *)&bone_index, sizeof(uint16_t));
|
|
|
+ stream->read((char *)&bone_disp_index, sizeof(uint8_t));
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+enum class RigidBodyShape : uint8_t {
|
|
|
+ Sphere = 0,
|
|
|
+ Box = 1,
|
|
|
+ Cpusel = 2
|
|
|
+};
|
|
|
+
|
|
|
+enum class RigidBodyType : uint8_t {
|
|
|
+ BoneConnected = 0,
|
|
|
+ Physics = 1,
|
|
|
+ ConnectedPhysics = 2
|
|
|
+};
|
|
|
+
|
|
|
+struct PmdRigidBody {
|
|
|
+ std::string name;
|
|
|
+ uint16_t related_bone_index;
|
|
|
+ uint8_t group_index;
|
|
|
+ uint16_t mask;
|
|
|
+ RigidBodyShape shape;
|
|
|
+ float size[3];
|
|
|
+ float position[3];
|
|
|
+ float orientation[3];
|
|
|
+ float weight;
|
|
|
+ float linear_damping;
|
|
|
+ float anglar_damping;
|
|
|
+ float restitution;
|
|
|
+ float friction;
|
|
|
+ RigidBodyType rigid_type;
|
|
|
+
|
|
|
+ PmdRigidBody() :
|
|
|
+ name(), related_bone_index(0), group_index(0), mask(0), shape(RigidBodyShape::Box), size{ 0.0f }, position{ 0.0f }, weight(0.0f), linear_damping(0.0f), anglar_damping(0.0f), restitution(0.0f), friction(0.0f), rigid_type(RigidBodyType::BoneConnected) {}
|
|
|
+
|
|
|
+ ~PmdRigidBody() = default;
|
|
|
+
|
|
|
+ void Read(std::istream *stream) {
|
|
|
+ if (stream == nullptr) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ char buffer[20];
|
|
|
+ stream->read(buffer, sizeof(char) * 20);
|
|
|
+ name = (std::string(buffer));
|
|
|
+ stream->read((char *)&related_bone_index, sizeof(uint16_t));
|
|
|
+ stream->read((char *)&group_index, sizeof(uint8_t));
|
|
|
+ stream->read((char *)&mask, sizeof(uint16_t));
|
|
|
+ stream->read((char *)&shape, sizeof(uint8_t));
|
|
|
+ stream->read((char *)size, sizeof(float) * 3);
|
|
|
+ stream->read((char *)position, sizeof(float) * 3);
|
|
|
+ stream->read((char *)orientation, sizeof(float) * 3);
|
|
|
+ stream->read((char *)&weight, sizeof(float));
|
|
|
+ stream->read((char *)&linear_damping, sizeof(float));
|
|
|
+ stream->read((char *)&anglar_damping, sizeof(float));
|
|
|
+ stream->read((char *)&restitution, sizeof(float));
|
|
|
+ stream->read((char *)&friction, sizeof(float));
|
|
|
+ stream->read((char *)&rigid_type, sizeof(char));
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+struct PmdConstraint {
|
|
|
+ std::string name;
|
|
|
+ uint32_t rigid_body_index_a;
|
|
|
+ uint32_t rigid_body_index_b;
|
|
|
+ float position[3];
|
|
|
+ float orientation[3];
|
|
|
+ float linear_lower_limit[3];
|
|
|
+ float linear_upper_limit[3];
|
|
|
+ float angular_lower_limit[3];
|
|
|
+ float angular_upper_limit[3];
|
|
|
+ float linear_stiffness[3];
|
|
|
+ float angular_stiffness[3];
|
|
|
+
|
|
|
+ PmdConstraint() :
|
|
|
+ name(), rigid_body_index_a(0), rigid_body_index_b(0), position{ 0.0f }, orientation{ 0.0f }, linear_lower_limit{ 0.0f }, linear_upper_limit{ 0.0f }, angular_lower_limit{ 0.0f }, angular_upper_limit{ 0.0f }, linear_stiffness{ 0.0f }, angular_stiffness{ 0.0f } {}
|
|
|
+
|
|
|
+ ~PmdConstraint() = default;
|
|
|
+
|
|
|
+ void Read(std::istream *stream) {
|
|
|
+ if (stream == nullptr) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ char buffer[20];
|
|
|
+ stream->read(buffer, 20);
|
|
|
+ name = std::string(buffer);
|
|
|
+ stream->read((char *)&rigid_body_index_a, sizeof(uint32_t));
|
|
|
+ stream->read((char *)&rigid_body_index_b, sizeof(uint32_t));
|
|
|
+ stream->read((char *)position, sizeof(float) * 3);
|
|
|
+ stream->read((char *)orientation, sizeof(float) * 3);
|
|
|
+ stream->read((char *)linear_lower_limit, sizeof(float) * 3);
|
|
|
+ stream->read((char *)linear_upper_limit, sizeof(float) * 3);
|
|
|
+ stream->read((char *)angular_lower_limit, sizeof(float) * 3);
|
|
|
+ stream->read((char *)angular_upper_limit, sizeof(float) * 3);
|
|
|
+ stream->read((char *)linear_stiffness, sizeof(float) * 3);
|
|
|
+ stream->read((char *)angular_stiffness, sizeof(float) * 3);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+struct PmdModel {
|
|
|
+ float version;
|
|
|
+ PmdHeader header;
|
|
|
+ std::vector<PmdVertex> vertices;
|
|
|
+ std::vector<uint16_t> indices;
|
|
|
+ std::vector<PmdMaterial> materials;
|
|
|
+ std::vector<PmdBone> bones;
|
|
|
+ std::vector<PmdIk> iks;
|
|
|
+ std::vector<PmdFace> faces;
|
|
|
+ std::vector<uint16_t> faces_indices;
|
|
|
+ std::vector<PmdBoneDispName> bone_disp_name;
|
|
|
+ std::vector<PmdBoneDisp> bone_disp;
|
|
|
+ std::vector<std::string> toon_filenames;
|
|
|
+ std::vector<PmdRigidBody> rigid_bodies;
|
|
|
+ std::vector<PmdConstraint> constraints;
|
|
|
+
|
|
|
+ PmdModel() :
|
|
|
+ version(0.0f) {}
|
|
|
+
|
|
|
+ ~PmdModel() = default;
|
|
|
+
|
|
|
+ static std::unique_ptr<PmdModel> LoadFromFile(const char *filename) {
|
|
|
+ if (filename == nullptr) {
|
|
|
+ return nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::ifstream stream(filename, std::ios::binary);
|
|
|
+ if (stream.fail()) {
|
|
|
+ std::cerr << "could not open \"" << filename << "\"" << std::endl;
|
|
|
+ return nullptr;
|
|
|
+ }
|
|
|
+ auto result = LoadFromStream(&stream);
|
|
|
+ stream.close();
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ static std::unique_ptr<PmdModel> LoadFromStream(std::ifstream *stream) {
|
|
|
+ auto result = mmd::make_unique<PmdModel>();
|
|
|
+ char buffer[100];
|
|
|
+
|
|
|
+ // magic
|
|
|
+ char magic[3];
|
|
|
+ stream->read(magic, 3);
|
|
|
+ if (magic[0] != 'P' || magic[1] != 'm' || magic[2] != 'd') {
|
|
|
+ std::cerr << "invalid file" << std::endl;
|
|
|
+ return nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
+ // version
|
|
|
+ stream->read((char *)&(result->version), sizeof(float));
|
|
|
+ if (result->version != 1.0f) {
|
|
|
+ std::cerr << "invalid version" << std::endl;
|
|
|
+ return nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
+ // header
|
|
|
+ result->header.Read(stream);
|
|
|
+
|
|
|
+ // vertices
|
|
|
+ uint32_t vertex_num;
|
|
|
+ stream->read((char *)&vertex_num, sizeof(uint32_t));
|
|
|
+ result->vertices.resize(vertex_num);
|
|
|
+ for (uint32_t i = 0; i < vertex_num; i++) {
|
|
|
+ result->vertices[i].Read(stream);
|
|
|
+ }
|
|
|
+
|
|
|
+ // indices
|
|
|
+ uint32_t index_num;
|
|
|
+ stream->read((char *)&index_num, sizeof(uint32_t));
|
|
|
+ result->indices.resize(index_num);
|
|
|
+ for (uint32_t i = 0; i < index_num; i++) {
|
|
|
+ stream->read((char *)&result->indices[i], sizeof(uint16_t));
|
|
|
+ }
|
|
|
+
|
|
|
+ // materials
|
|
|
+ uint32_t material_num;
|
|
|
+ stream->read((char *)&material_num, sizeof(uint32_t));
|
|
|
+ result->materials.resize(material_num);
|
|
|
+ for (uint32_t i = 0; i < material_num; i++) {
|
|
|
+ result->materials[i].Read(stream);
|
|
|
+ }
|
|
|
+
|
|
|
+ // bones
|
|
|
+ uint16_t bone_num;
|
|
|
+ stream->read((char *)&bone_num, sizeof(uint16_t));
|
|
|
+ result->bones.resize(bone_num);
|
|
|
+ for (uint32_t i = 0; i < bone_num; i++) {
|
|
|
+ result->bones[i].Read(stream);
|
|
|
+ }
|
|
|
+
|
|
|
+ // iks
|
|
|
+ uint16_t ik_num;
|
|
|
+ stream->read((char *)&ik_num, sizeof(uint16_t));
|
|
|
+ result->iks.resize(ik_num);
|
|
|
+ for (uint32_t i = 0; i < ik_num; i++) {
|
|
|
+ result->iks[i].Read(stream);
|
|
|
+ }
|
|
|
+
|
|
|
+ // faces
|
|
|
+ uint16_t face_num;
|
|
|
+ stream->read((char *)&face_num, sizeof(uint16_t));
|
|
|
+ result->faces.resize(face_num);
|
|
|
+ for (uint32_t i = 0; i < face_num; i++) {
|
|
|
+ result->faces[i].Read(stream);
|
|
|
+ }
|
|
|
+
|
|
|
+ // face frames
|
|
|
+ uint8_t face_frame_num;
|
|
|
+ stream->read((char *)&face_frame_num, sizeof(uint8_t));
|
|
|
+ result->faces_indices.resize(face_frame_num);
|
|
|
+ for (uint32_t i = 0; i < face_frame_num; i++) {
|
|
|
+ stream->read((char *)&result->faces_indices[i], sizeof(uint16_t));
|
|
|
+ }
|
|
|
+
|
|
|
+ // bone names
|
|
|
+ uint8_t bone_disp_num;
|
|
|
+ stream->read((char *)&bone_disp_num, sizeof(uint8_t));
|
|
|
+ result->bone_disp_name.resize(bone_disp_num);
|
|
|
+ for (uint32_t i = 0; i < bone_disp_num; i++) {
|
|
|
+ result->bone_disp_name[i].Read(stream);
|
|
|
+ }
|
|
|
+
|
|
|
+ // bone frame
|
|
|
+ uint32_t bone_frame_num;
|
|
|
+ stream->read((char *)&bone_frame_num, sizeof(uint32_t));
|
|
|
+ result->bone_disp.resize(bone_frame_num);
|
|
|
+ for (uint32_t i = 0; i < bone_frame_num; i++) {
|
|
|
+ result->bone_disp[i].Read(stream);
|
|
|
+ }
|
|
|
+
|
|
|
+ // english name
|
|
|
+ bool english;
|
|
|
+ stream->read((char *)&english, sizeof(char));
|
|
|
+ if (english) {
|
|
|
+ result->header.ReadExtension(stream);
|
|
|
+ for (uint32_t i = 0; i < bone_num; i++) {
|
|
|
+ result->bones[i].ReadExpantion(stream);
|
|
|
+ }
|
|
|
+ for (uint32_t i = 0; i < face_num; i++) {
|
|
|
+ if (result->faces[i].type == pmd::FaceCategory::Base) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ result->faces[i].ReadExpantion(stream);
|
|
|
+ }
|
|
|
+ for (uint32_t i = 0; i < result->bone_disp_name.size(); i++) {
|
|
|
+ result->bone_disp_name[i].ReadExpantion(stream);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // toon textures
|
|
|
+ if (stream->peek() == std::ios::traits_type::eof()) {
|
|
|
+ result->toon_filenames.clear();
|
|
|
+ } else {
|
|
|
+ result->toon_filenames.resize(10);
|
|
|
+ for (uint32_t i = 0; i < 10; i++) {
|
|
|
+ stream->read(buffer, 100);
|
|
|
+ result->toon_filenames[i] = std::string(buffer);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // physics
|
|
|
+ if (stream->peek() == std::ios::traits_type::eof()) {
|
|
|
+ result->rigid_bodies.clear();
|
|
|
+ result->constraints.clear();
|
|
|
+ } else {
|
|
|
+ uint32_t rigid_body_num;
|
|
|
+ stream->read((char *)&rigid_body_num, sizeof(uint32_t));
|
|
|
+ result->rigid_bodies.resize(rigid_body_num);
|
|
|
+ for (uint32_t i = 0; i < rigid_body_num; i++) {
|
|
|
+ result->rigid_bodies[i].Read(stream);
|
|
|
+ }
|
|
|
+ uint32_t constraint_num;
|
|
|
+ stream->read((char *)&constraint_num, sizeof(uint32_t));
|
|
|
+ result->constraints.resize(constraint_num);
|
|
|
+ for (uint32_t i = 0; i < constraint_num; i++) {
|
|
|
+ result->constraints[i].Read(stream);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (stream->peek() != std::ios::traits_type::eof()) {
|
|
|
+ std::cerr << "there is unknown data" << std::endl;
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+} // namespace pmd
|
|
|
+
|