123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640 |
- /*
- Open Asset Import Library (assimp)
- ----------------------------------------------------------------------
- Copyright (c) 2006-2025, assimp team
- All rights reserved.
- Redistribution and use of this software in source and binary forms,
- with or without modification, are permitted provided that the
- following conditions are met:
- * Redistributions of source code must retain the above
- copyright notice, this list of conditions and the
- following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the
- following disclaimer in the documentation and/or other
- materials provided with the distribution.
- * Neither the name of the assimp team, nor the names of its
- contributors may be used to endorse or promote products
- derived from this software without specific prior
- written permission of the assimp team.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ----------------------------------------------------------------------
- */
- #pragma once
- #include <vector>
- #include <string>
- #include <memory>
- #include <iostream>
- #include <fstream>
- #include "MMDCpp14.h"
- 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
|