OSDN Git Service

separate vertex with uv or normal.
[meshio/meshio.git] / src / pmd.cpp
old mode 100644 (file)
new mode 100755 (executable)
index 8618d53..c5ac48f
@@ -1,9 +1,191 @@
 #include "pmd.h"
 #include <iostream>
+#include "text.h"
 
 namespace meshio {
 namespace pmd {
 
+// IO
+bool IO::write(const char *path)
+{
+       binary::FileWriter w(path);
+       return write(w);
+}
+
+bool IO::write(const wchar_t *path)
+{
+       binary::FileWriter w(path);
+       return write(w);
+}
+
+std::wstring 
+IO::getName()const
+{
+       return text::trim(text::to_WideChar(CP_OEMCP, 
+                               std::string(name, name+20)));
+}
+
+std::wstring 
+IO::getComment()const
+{
+       return text::trim(text::to_WideChar(CP_OEMCP, 
+                               std::string(comment, comment+256)));
+}
+
+std::wstring 
+IO::getEnglishName()const
+{
+       return text::trim(text::to_WideChar(CP_OEMCP, 
+                               std::string(english_name, english_name+20)));
+}
+
+std::wstring 
+IO::getEnglishComment()const
+{
+       return text::trim(text::to_WideChar(CP_OEMCP, 
+                               std::string(english_comment, english_comment+256)));
+}
+
+const Vector2* IO::getUV(int index)const
+{
+       return &vertices[index].uv;
+}
+
+void IO::setName(const char *src)
+{
+       strncpy(name, src, 20);
+}
+
+void IO::setComment(const char *src)
+{
+       strncpy(comment, src, 256);
+}
+
+void IO::setEnglishName(const char *src)
+{
+       strncpy(english_name, src, 20);
+}
+
+void IO::setEnglishComment(const char *src)
+{
+       strncpy(english_comment, src, 256);
+}
+
+
+// Material
+std::wstring 
+Material::getTexture()const
+{
+       return text::trim(text::to_WideChar(CP_OEMCP, 
+                               std::string(texture, texture+20)));
+}
+
+void Material::setTexture(const char *src)
+{
+       strncpy(texture, src, 20);
+}
+
+// Bone
+std::wstring 
+       Bone::getName()const
+       {
+               return text::trim(text::to_WideChar(CP_OEMCP, 
+                                       std::string(name, name+20)));
+       }
+
+void Bone::setName(const char *src)
+{
+       strncpy(name, src, 20);
+}
+
+void Bone::setEnglishName(const char *src)
+{
+       strncpy(english_name, src, 20);
+}
+
+// Morph
+std::wstring 
+       Morph::getName()const
+       {
+               return text::trim(text::to_WideChar(CP_OEMCP, 
+                                       std::string(name, name+20)));
+       }
+
+void
+       Morph::append(int index, float x, float y, float z)
+       {
+               indices.push_back(index);
+               pos_list.push_back(Vector3(x, y, z));
+       }
+
+void Morph::setName(const char *src)
+{
+       strncpy(name, src, 20);
+}
+
+void Morph::setEnglishName(const char *src)
+{
+       strncpy(english_name, src, 20);
+}
+
+// BoneGroup
+std::wstring 
+       BoneGroup::getName()const
+       {
+               return text::trim(text::to_WideChar(CP_OEMCP, 
+                                       std::string(name, name+50)));
+       }
+
+void BoneGroup::setName(const char *src)
+{
+       strncpy(name, src, 50);
+}
+
+void BoneGroup::setEnglishName(const char *src)
+{
+       strncpy(english_name, src, 50);
+}
+
+// RigidBody
+std::wstring 
+       RigidBody::getName()const
+       {
+               return text::trim(text::to_WideChar(CP_OEMCP, 
+                                       std::string(name, name+20)));
+       }
+
+void RigidBody::setName(const char *src)
+{
+       strncpy(name, src, 20);
+}
+
+// Constraint
+std::wstring 
+       Constraint::getName()const
+       {
+               return text::trim(text::to_WideChar(CP_OEMCP, 
+                                       std::string(name, name+20)));
+       }
+
+void Constraint::setName(const char *src)
+{
+       strncpy(name, src, 20);
+}
+
+// ToonTexture
+std::wstring 
+       ToonTexture::getName()const
+       {
+               return text::trim(text::to_WideChar(CP_OEMCP, 
+                                       std::string(name, name+100)));
+       }
+
+void ToonTexture::setName(const char *src)
+{
+       strncpy(name, src, 100);
+}
+
+
 // 38bytes
 template<class READER>
        void
@@ -168,7 +350,7 @@ public:
                if(!parseFaceList()){
                        return false;
                }
-               if(!parseBoneNameList()){
+               if(!parseBoneGroupList()){
                        return false;
                }
                if(!parseBoneList()){
@@ -249,15 +431,19 @@ private:
        bool parseToonTextures()
        {
                for(size_t i=0; i<10; ++i){
-                       reader_.getString(100);
+                       text::copyStringAndFillZero(
+                                       io_.toon_textures[i].name,
+                                       reader_.getString(100));
                }
                return true;
        }
 
        bool parseEnglishBoneList()
        {
-               for(size_t i=0; i<io_.bone_name_list.size(); ++i){
-                       std::string english=reader_.getString(50);
+               for(size_t i=0; i<io_.bone_group_list.size(); ++i){
+                       text::copyStringAndFillZero(
+                                       io_.bone_group_list[i].english_name, 
+                                       reader_.getString(50));
                }
                return true;
        }
@@ -266,7 +452,8 @@ private:
        {
                int count=io_.morph_list.size()-1;
                for(int i=0; i<count; ++i){
-                       std::string english_morph_name=reader_.getString(20);
+                       text::copyStringAndFillZero(
+                                       io_.morph_list[i].english_name, reader_.getString(20));
                }
                return true;
        }
@@ -274,15 +461,18 @@ private:
        bool parseEnglishBone()
        {
                for(size_t i=0; i<io_.bones.size(); ++i){
-                       std::string english_bone_name=reader_.getString(20);
+                       text::copyStringAndFillZero(
+                                       io_.bones[i].english_name, reader_.getString(20));
                }
                return true;
        }
 
        bool parseEnglishName()
        {
-               std::string english_mdoel_name=reader_.getString(20);
-               std::string english_comment=reader_.getString(256);
+               text::copyStringAndFillZero(io_.english_name, 
+                               reader_.getString(20));
+               text::copyStringAndFillZero(io_.english_comment, 
+                               reader_.getString(256));
                return true;
        }
 
@@ -292,16 +482,19 @@ private:
                for(unsigned int i=0; i<count; ++i){
                        unsigned short bone=reader_.getUshort();
                        unsigned char disp=reader_.getUchar();
-                       io_.bone_list.push_back(std::make_pair(bone, disp));
+                       io_.bone_display_list.push_back(std::make_pair(bone, disp));
                }
                return true;
        }
 
-       bool parseBoneNameList()
+       bool parseBoneGroupList()
        {
                unsigned int count=reader_.getUchar();
                for(unsigned int i=0; i<count; ++i){
-                       io_.bone_name_list.push_back(reader_.getString(50));
+                       io_.bone_group_list.push_back(BoneGroup());
+                       text::copyStringAndFillZero(
+                                       io_.bone_group_list.back().name,
+                                       reader_.getString(50));
                }
                return true;
        }
@@ -310,7 +503,7 @@ private:
        {
                unsigned int count=reader_.getUchar();
                for(unsigned int i=0; i<count; ++i){
-                       reader_.getUshort();
+                       io_.face_list.push_back(reader_.getUshort());
                }
                return true;
        }
@@ -349,8 +542,8 @@ private:
        {
                unsigned int count=reader_.getUint();
                for(unsigned int i=0; i<count; ++i){
-                       io_.materials.push_back(Material());
-                       read(reader_, io_.materials.back());
+                       io_.materials.push_back(new Material());
+                       read(reader_, *io_.materials.back());
                }
                return true;
        }
@@ -400,6 +593,14 @@ IO::IO()
 : version(0)
 {}
 
+IO::~IO()
+{
+       for(size_t i=0; i<materials.size(); ++i){
+               delete materials[i];
+       }
+       materials.clear();
+}
+
 bool IO::read(binary::IReader &input)
 {
        Impl impl(*this, input);
@@ -408,7 +609,7 @@ bool IO::read(binary::IReader &input)
        }
 
        ////////////////////////////////////////////////////////////
-       // validation
+       // post process
        ////////////////////////////////////////////////////////////
        if(!morph_list.empty()){
                // validate morph
@@ -424,13 +625,30 @@ bool IO::read(binary::IReader &input)
                        assert(m.type!=MORPH_BASE);
                }
        }
+       ////////////////////////////////////////////////////////////
+       // setup bone
+       ////////////////////////////////////////////////////////////
+       for(size_t i=0; i<bones.size(); ++i){
+               Bone &bone=bones[i];
+               bone.index=i;
+               if(bone.parent_index!=0xFFFF){
+                       bone.parent=&bones[bone.parent_index];
+                       bone.parent->children.push_back(&bone);
+               }
+               if(bone.tail_index==0){
+                       bone.tail=Vector3(0, 0, 0);
+               }
+               else{
+                       bone.tail=bones[bone.tail_index].pos;
+               }
+       }
 
        return true;
 }
 
+/*
 bool IO::read(const char *path)
 {
-       //std::locale::global(std::locale("japanese"));
        std::vector<char> all;
        binary::readAll(path, all);
        if(all.empty()){
@@ -439,12 +657,245 @@ bool IO::read(const char *path)
        binary::MemoryReader reader(&all[0], all.size());
        return read(reader);
 }
+*/
 
-bool IO::write(std::ostream &os)
+bool IO::read(const wchar_t *path)
 {
-       return false;
+       std::vector<char> all;
+       binary::readAll(path, all);
+       std::cerr << all.size() << "bytes" << std::endl;
+       if(all.empty()){
+               return false;
+       }
+       binary::MemoryReader reader(&all[0], all.size());
+       return read(reader);
+}
+
+bool IO::write(binary::IWriter &w)
+{
+       w.write("Pmd", 3);
+       w.writeValue<float>(version);
+       w.write(name, 20);
+       w.write(comment, 256);
+
+       // vertices
+       //std::cout << "vertices" << std::endl;
+       w.writeValue<DWORD>(vertices.size());
+       for(size_t i=0; i<vertices.size(); ++i){
+               Vertex &v=vertices[i];
+               w.writeValue<float>(v.pos.x);
+               w.writeValue<float>(v.pos.y);
+               w.writeValue<float>(v.pos.z);
+               w.writeValue<float>(v.normal.x);
+               w.writeValue<float>(v.normal.y);
+               w.writeValue<float>(v.normal.z);
+               w.writeValue<float>(v.uv.x);
+               w.writeValue<float>(v.uv.y);
+               w.writeValue<WORD>(v.bone0);
+               w.writeValue<WORD>(v.bone1);
+               w.writeValue<BYTE>(v.weight0);
+               w.writeValue<BYTE>(v.edge_flag);
+       }
+
+       // faces
+       //std::cout << "faces" << std::endl;
+       w.writeValue<DWORD>(indices.size());
+       if(indices.size()>0){
+               w.writeArray<WORD>(&indices[0], indices.size());
+       }
+
+       // materials
+       //std::cout << "materials" << std::endl;
+       w.writeValue<DWORD>(materials.size());
+       for(size_t i=0; i<materials.size(); ++i){
+               Material &m=*materials[i];
+               w.writeValue<float>(m.diffuse.r);
+               w.writeValue<float>(m.diffuse.g);
+               w.writeValue<float>(m.diffuse.b);
+               w.writeValue<float>(m.diffuse.a);
+               w.writeValue<float>(m.shinness);
+               w.writeValue<float>(m.specular.r);
+               w.writeValue<float>(m.specular.g);
+               w.writeValue<float>(m.specular.b);
+               w.writeValue<float>(m.ambient.r);
+               w.writeValue<float>(m.ambient.g);
+               w.writeValue<float>(m.ambient.b);
+               w.writeValue<BYTE>(m.toon_index);
+               w.writeValue<BYTE>(m.flag);
+               w.writeValue<DWORD>(m.vertex_count);
+               w.writeArray<char>(m.texture, 20);
+       }
+
+       // bones
+       //std::cout << "bones" << std::endl;
+       w.writeValue<WORD>(bones.size());
+       for(size_t i=0; i<bones.size(); ++i){
+               Bone &b=bones[i];
+               w.writeArray<char>(b.name, 20);
+               w.writeValue<WORD>(b.parent_index);
+               w.writeValue<WORD>(b.tail_index);
+               w.writeValue<BYTE>(b.type);
+               w.writeValue<WORD>(b.ik_index);
+               w.writeValue<float>(b.pos.x);
+               w.writeValue<float>(b.pos.y);
+               w.writeValue<float>(b.pos.z);
+       }
+
+       // ik
+       //std::cout << "ik" << std::endl;
+       w.writeValue<WORD>(ik_list.size());
+       for(size_t i=0; i<ik_list.size(); ++i){
+               IK &ik=ik_list[i];
+               w.writeValue<WORD>(ik.index);
+               w.writeValue<WORD>(ik.target);
+               w.writeValue<BYTE>(ik.length);
+               w.writeValue<WORD>(ik.iterations);
+               w.writeValue<float>(ik.weight);
+               WORD parent_index=bones[ik.target].parent_index;
+               for(size_t j=0; j<ik.length; 
+                               ++j, parent_index=bones[parent_index].parent_index){
+                       w.writeValue<WORD>(parent_index);
+               }
+       }
+
+       // morph
+       //std::cout << "morph" << std::endl;
+       w.writeValue<WORD>(morph_list.size());
+       for(size_t i=0; i<morph_list.size(); ++i){
+               Morph &m=morph_list[i];
+               w.writeArray<char>(m.name, 20);
+               w.writeValue<DWORD>(m.indices.size());
+               w.writeValue<BYTE>(m.type);
+               for(size_t j=0; j<m.indices.size(); ++j){
+                       w.writeValue<DWORD>(m.indices[j]);
+                       Vector3 &pos=m.pos_list[j];
+                       w.writeValue<float>(pos.x);
+                       w.writeValue<float>(pos.y);
+                       w.writeValue<float>(pos.z);
+               }
+       }
+
+       // face list
+       //std::cout << "face list" << std::endl;
+       w.writeValue<BYTE>(face_list.size());
+       if(face_list.size()>0){
+               w.writeArray<WORD>(&face_list[0], face_list.size());
+       }
+
+       // bone name list
+       //std::cout << "bone name list" << std::endl;
+       w.writeValue<BYTE>(bone_group_list.size());
+       for(size_t i=0; i<bone_group_list.size(); ++i){
+               // 50bytes
+               w.writeArray<char>(bone_group_list[i].name, 50);
+       }
+
+       // bone list
+       //std::cout << "bone list" << std::endl;
+       w.writeValue<DWORD>(bone_display_list.size());
+       for(size_t i=0; i<bone_display_list.size(); ++i){
+               w.writeValue<WORD>(bone_display_list[i].first);
+               w.writeValue<BYTE>(bone_display_list[i].second);
+       }
+
+       ////////////////////////////////////////////////////////////
+       // extend
+       ////////////////////////////////////////////////////////////
+       w.writeValue<char>(0x01);
+
+       ////////////////////////////////////////////////////////////
+       // english names
+       ////////////////////////////////////////////////////////////
+       w.writeArray<char>(english_name, 20);
+       w.writeArray<char>(english_comment, 256);
+
+       for(size_t i=0; i<bones.size(); ++i){
+               w.writeArray<char>(bones[i].english_name, 20);
+       }
+
+       // skip base
+       for(size_t i=1; i<morph_list.size(); ++i){
+               w.writeArray<char>(morph_list[i].english_name, 20);
+       }
+
+       for(size_t i=0; i<bone_group_list.size(); ++i){
+               w.writeArray<char>(bone_group_list[i].english_name, 50);
+       }
+
+       ////////////////////////////////////////////////////////////
+       // toon textures
+       ////////////////////////////////////////////////////////////
+       for(size_t i=0; i<10; ++i){
+               w.writeArray<char>(toon_textures[i].name, 100);
+       }
+
+       ////////////////////////////////////////////////////////////
+       // rigid bodies
+       ////////////////////////////////////////////////////////////
+       w.writeValue<DWORD>(rigidbodies.size());
+       for(size_t i=0; i<rigidbodies.size(); ++i){
+               RigidBody &rb=rigidbodies[i];
+               w.writeArray<char>(rb.name, 20);
+               w.writeValue<WORD>(rb.boneIndex);
+               w.writeValue<BYTE>(rb.group);
+               w.writeValue<WORD>(rb.target);
+               w.writeValue<BYTE>(rb.shapeType);
+               w.writeValue<float>(rb.w);
+               w.writeValue<float>(rb.h);
+               w.writeValue<float>(rb.d);
+               w.writeValue<float>(rb.position.x);
+               w.writeValue<float>(rb.position.y);
+               w.writeValue<float>(rb.position.z);
+               w.writeValue<float>(rb.rotation.x);
+               w.writeValue<float>(rb.rotation.y);
+               w.writeValue<float>(rb.rotation.z);
+               w.writeValue<float>(rb.weight);
+               w.writeValue<float>(rb.linearDamping);
+               w.writeValue<float>(rb.angularDamping);
+               w.writeValue<float>(rb.restitution);
+               w.writeValue<float>(rb.friction);
+               w.writeValue<BYTE>(rb.processType);
+       }
+
+       ////////////////////////////////////////////////////////////
+       // constraints
+       ////////////////////////////////////////////////////////////
+       w.writeValue<DWORD>(constraints.size());
+       for(size_t i=0; i<constraints.size(); ++i){
+               Constraint &c=constraints[i];
+               w.writeArray<char>(c.name, 20);
+               w.writeValue<DWORD>(c.rigidA);
+               w.writeValue<DWORD>(c.rigidB);
+               w.writeValue<float>(c.pos.x);
+               w.writeValue<float>(c.pos.y);
+               w.writeValue<float>(c.pos.z);
+               w.writeValue<float>(c.rot.x);
+               w.writeValue<float>(c.rot.y);
+               w.writeValue<float>(c.rot.z);
+               w.writeValue<float>(c.constraintPosMin.x);
+               w.writeValue<float>(c.constraintPosMin.y);
+               w.writeValue<float>(c.constraintPosMin.z);
+               w.writeValue<float>(c.constraintPosMax.x);
+               w.writeValue<float>(c.constraintPosMax.y);
+               w.writeValue<float>(c.constraintPosMax.z);
+               w.writeValue<float>(c.constraintRotMin.x);
+               w.writeValue<float>(c.constraintRotMin.y);
+               w.writeValue<float>(c.constraintRotMin.z);
+               w.writeValue<float>(c.constraintRotMax.x);
+               w.writeValue<float>(c.constraintRotMax.y);
+               w.writeValue<float>(c.constraintRotMax.z);
+               w.writeValue<float>(c.springPos.x);
+               w.writeValue<float>(c.springPos.y);
+               w.writeValue<float>(c.springPos.z);
+               w.writeValue<float>(c.springRot.x);
+               w.writeValue<float>(c.springRot.y);
+               w.writeValue<float>(c.springRot.z);
+       }
+
+       return true;
 }
 
+
 } // namespace
 } // namespace