OSDN Git Service

merge local update
authorousttrue <ousttrue@gmail.com>
Sun, 1 May 2011 01:51:18 +0000 (10:51 +0900)
committerU-theremin\focke <ousttrue@gmail.com>
Sun, 1 May 2011 01:51:18 +0000 (10:51 +0900)
17 files changed:
meshio.lua [deleted file]
premake4.lua [deleted file]
src/binary.cpp
src/binary.h
src/color.h
src/la.h
src/linereader.h [new file with mode: 0644]
src/mqo.cpp
src/mqo.h
src/pmd.cpp
src/pmd.h
src/premake4.lua [new file with mode: 0644]
src/text.h
src/vmd.cpp
src/vmd.h
test/meshio_test.lua [changed mode: 0644->0755]
test/premake4.lua [changed mode: 0644->0755]

diff --git a/meshio.lua b/meshio.lua
deleted file mode 100644 (file)
index b5cbb65..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
--- A project defines one build target
-project "meshio"
---kind "WindowedApp"
---kind "ConsoleApp"
---kind "SharedLib"
-kind "StaticLib"
-language "C++"
-files { "include/*.h", "src/**.h", "src/**.cpp" }
-flags {
-       --"Unicode", 
-       "StaticRuntime",
-}
-
-includedirs {
-       "include", "boost",
-}
-defines {}
-linkoptions {}
-libdirs {}
-links {}
-
-configuration { "windows", "not gmake" }
-do
-  -- VC
-  buildoptions {
-    "/wd4996",
-  }
-end
-
-configuration { "gmake" }
-do
-  buildoptions {
-    "-fPIC"
-  }
-end
-
-configuration "Debug"
-do
-  defines { "DEBUG" }
-  flags { "Symbols" }
-  targetdir "debug"
-end
-
-configuration "Release"
-do
-  defines { "NDEBUG" }
-  flags { "Optimize" }
-  targetdir "release"
-end
-
diff --git a/premake4.lua b/premake4.lua
deleted file mode 100644 (file)
index 0ba26f6..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
--- A solution contains projects, and defines the available configurations
-solution "meshio"
-configurations { "Debug", "Release" }
-
-dofile "meshio.lua"
-
index d10292e..6c1a589 100644 (file)
 #include "binary.h"
 
 namespace meshio {
-namespace binary {
-
-///////////////////////////////////////////////////////////////////////////////
-// FileReader
-///////////////////////////////////////////////////////////////////////////////
-FileReader::FileReader(const char *path)
-: io_(path, std::ios::binary), pos_(0), eof_(false)
-{
-}
-
-FileReader::~FileReader()
-{
-}
-
-unsigned int FileReader::read(char *buf, unsigned int size)
-{
-       if(size==0){
-               return 0;
-       }
-       io_.read(buf, size);
-       size=io_.gcount();
-       if(size==0){
-               eof_=true;
-       }
-       pos_+=size;
-       return size;
-}
-
-unsigned int FileReader::getPos()const
-{
-       return pos_;
-}
-
-bool FileReader::isEnd()const
-{
-       return eof_;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// MemoryReader
-///////////////////////////////////////////////////////////////////////////////
-MemoryReader::MemoryReader(const char *buf, unsigned int size)
-: buf_(buf), size_(size), pos_(0)
-{
-}
-
-MemoryReader::~MemoryReader()
-{
-}
-
-unsigned int MemoryReader::read(char *buf, unsigned int size)
-{
-       if(pos_+size>=size_){
-               size=size_-pos_;
-       }
-       std::copy(&buf_[pos_], &buf_[pos_+size], buf);
-       pos_+=size;
-       return size;
-}
-
-unsigned int MemoryReader::getPos()const
-{
-       return pos_;
-}
-
-bool MemoryReader::isEnd()const
-{
-       return pos_>=size_;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// readALL
-///////////////////////////////////////////////////////////////////////////////
-static void readALL_(FILE *fp, std::vector<char> &buf)
-{
-       int iRet = fseek(fp, 0L, SEEK_END);
-       if(iRet!=0){
-               return;
-       }
-
-       long pos=ftell(fp);
-       if(pos == -1){
-               return;
-       }
-
-       iRet = fseek(fp, 0L, SEEK_SET);
-       if(iRet != 0){
-               return;
-       }
-
-       buf.resize(pos);
-       iRet=fread(&buf[0], pos, 1, fp);
-}
-
-void readAll(const char *path, std::vector<char> &buf)
-{
-       FILE* fp = fopen(path, "rb");
-       if(fp){
-               readALL_(fp, buf);
-               fclose(fp);
-       }
-}
+  namespace binary {
+
+    // FileReader
+    FileReader::FileReader(const char *path)
+      : io_(path, std::ios::binary), pos_(0), eof_(false)
+    {
+    }
+
+    FileReader::~FileReader()
+    {
+    }
+
+    unsigned int FileReader::read(char *buf, unsigned int size)
+    {
+      if(size==0){
+        return 0;
+      }
+      io_.read(buf, size);
+      size=io_.gcount();
+      if(size==0){
+        eof_=true;
+      }
+      pos_+=size;
+      return size;
+    }
+
+    unsigned int FileReader::getPos()const
+    {
+      return pos_;
+    }
+
+    bool FileReader::isEnd()const
+    {
+      return eof_;
+    }
+
+    // MemoryReader
+    MemoryReader::MemoryReader(const char *buf, unsigned int size)
+      : buf_(buf), size_(size), pos_(0)
+    {
+    }
+
+    MemoryReader::~MemoryReader()
+    {
+    }
+
+    unsigned int MemoryReader::read(char *buf, unsigned int size)
+    {
+      if(pos_+size>=size_){
+        size=size_-pos_;
+      }
+      std::copy(&buf_[pos_], &buf_[pos_+size], buf);
+      pos_+=size;
+      return size;
+    }
+
+    unsigned int MemoryReader::getPos()const
+    {
+      return pos_;
+    }
+
+    bool MemoryReader::isEnd()const
+    {
+      return pos_>=size_;
+    }
+
+    // readALL
+    static void readALL_(FILE *fp, std::vector<char> &buf)
+    {
+      int iRet = fseek(fp, 0L, SEEK_END);
+      if(iRet!=0){
+        return;
+      }
+
+      long pos=ftell(fp);
+      if(pos == -1){
+        return;
+      }
+
+      iRet = fseek(fp, 0L, SEEK_SET);
+      if(iRet != 0){
+        return;
+      }
+
+      buf.resize(pos);
+      iRet=fread(&buf[0], pos, 1, fp);
+    }
+
+    void readAll(const char *path, std::vector<char> &buf)
+    {
+      FILE* fp = fopen(path, "rb");
+      if(fp){
+        readALL_(fp, buf);
+        fclose(fp);
+      }
+    }
 
 #ifdef _WIN32
-void readAll(const wchar_t *path, std::vector<char> &buf)
-{
-       FILE* fp = _wfopen(path, L"rb");
-       if(fp){
-               readALL_(fp, buf);
-               fclose(fp);
-       }
-}
+    void readAll(const wchar_t *path, std::vector<char> &buf)
+    {
+      FILE* fp = _wfopen(path, L"rb");
+      if(fp){
+        readALL_(fp, buf);
+        fclose(fp);
+      }
+    }
 #endif
 
-///////////////////////////////////////////////////////////////////////////////
-// FileWriter
-///////////////////////////////////////////////////////////////////////////////
-FileWriter::FileWriter(const char *path)
-{
-       io_=fopen(path, "wb");
-}
+    // FileWriter
+    FileWriter::FileWriter(const char *path)
+    {
+      io_=fopen(path, "wb");
+    }
 
 #if _WIN32
-FileWriter::FileWriter(const wchar_t *path)
-{
-    io_=_wfopen(path, L"wb");
-}
+    FileWriter::FileWriter(const wchar_t *path)
+    {
+      io_=_wfopen(path, L"wb");
+    }
 #endif
 
-FileWriter::~FileWriter()
-{
-       fclose(io_);
-}
+    FileWriter::~FileWriter()
+    {
+      fclose(io_);
+    }
 
-void FileWriter::write(const char *buf, unsigned int size)
-{
-       fwrite(buf, size, 1, io_);
-}
+    void FileWriter::write(const char *buf, unsigned int size)
+    {
+      fwrite(buf, size, 1, io_);
+    }
 
 
-} // namespace binary
+  } // namespace binary
 } // namespace meshio
index db76719..0f39795 100644 (file)
@@ -1,6 +1,10 @@
+/**
+ * \83o\83C\83i\83\8a\83t\83@\83C\83\8b\82Ì\93Ç\82Ý\8d\9e\82Ý\95â\8f\95\83\89\83C\83u\83\89\83\8a
+ */
 #ifndef MESH_IO_BINARY_H_INCLUDED
 #define MESH_IO_BINARY_H_INCLUDED
 
+#include "text.h"
 #include <fstream>
 #include <vector>
 #include <assert.h>
 #include <string.h>
 
 namespace meshio {
-namespace binary {
+  namespace binary {
 
-/**
- * \83f\81[\83^\93Ç\82Ý\8d\9e\82Ý\83C\83\93\83^\81[\83t\83F\81[\83X
- */
-class IReader
-{
-public:
-       virtual ~IReader(){}
-       virtual unsigned int read(char *buf, unsigned int size)=0;
-       virtual unsigned int getPos()const=0;
-       virtual bool isEnd()const=0;
-
-       template<typename T>
-               bool get(T &t)
-               {
-                       if(read(reinterpret_cast<char*>(&t), sizeof(t))){
-                               return true;
-                       }
-                       else{
-                               return false;
-                       }
-               }
-       char getChar()
-       {
-               char byte;
-               return get(byte) ? byte : 0;
-       }
-       std::string getString(unsigned int length, bool isTrim=false)
-       {
-               std::vector<char> buf(length);
-               read(&buf[0], buf.size());
-
-               std::vector<char>::iterator it;
-               if(isTrim){
-                       it=buf.begin();
-                       for(; it!=buf.end(); ++it){
-                               if(*it=='\0'){
-                                       break;
-                               }
-                       }
-               }
-               else{
-                       it=buf.end();
-               }
-               return std::string(buf.begin(), it);
-       }
-       unsigned char getUchar()
-       {
-               unsigned char value;
-               return get(value) ? value : 0;
-       }
-       unsigned short getUshort()
-       {
-               unsigned short value;
-               return get(value) ? value : 0;
-       }
-       unsigned int getUint()
-       {
-               unsigned int value;
-               return get(value) ? value : 0;
-       }
-};
+    static void copyStringAndFillZero(char *dst, const std::string &src)
+    {
+      size_t i=0;
+      for(; i<src.size(); ++i)
+      {
+        dst[i]=src[i];
+        if(src[i]=='\0'){
+          break;
+        }
+      }
+      for(; i<src.size(); ++i)
+      {
+        dst[i]='\0';
+      }
+    }
 
-/**
- * \83t\83@\83C\83\8b\82©\82ç\82Ì\93Ç\82Ý\8d\9e\82Ý
- */
-class FileReader : public IReader
-{
-       std::ifstream io_;
-       unsigned int pos_;
-       bool eof_;
-
-public:
-       FileReader(const char *path);
-       virtual ~FileReader();
-       virtual unsigned int read(char *buf, unsigned int size);
-       virtual unsigned int getPos()const;
-       virtual bool isEnd()const;
-};
+    /**
+     * \83f\81[\83^\93Ç\82Ý\8d\9e\82Ý\83C\83\93\83^\81[\83t\83F\81[\83X
+     */
+    class IReader
+    {
+    public:
+      virtual ~IReader(){}
+      virtual unsigned int read(char *buf, unsigned int size)=0;
+      virtual unsigned int getPos()const=0;
+      virtual bool isEnd()const=0;
 
-/**
- * \83\81\83\82\83\8a\82©\82ç\82Ì\93Ç\82Ý\8d\9e\82Ý
- */
-class MemoryReader : public IReader
-{
-       const char *buf_;
-       unsigned int size_;
-       unsigned int pos_;
-
-public:
-       MemoryReader(const char *buf, unsigned int size);
-       virtual ~MemoryReader();
-       virtual unsigned int read(char *buf, unsigned int size);
-       virtual unsigned int getPos()const;
-       virtual bool isEnd()const;
-};
-
- void readAll(const char *path, std::vector<char> &all);
+      template<typename T>
+        bool get(T &t)
+        {
+          if(read(reinterpret_cast<char*>(&t), sizeof(t))){
+            return true;
+          }
+          else{
+            return false;
+          }
+        }
+      template<int LENGTH>
+        bool get(fixed_string<LENGTH> &t)
+        {
+          copyStringAndFillZero(t.begin(), getString(t.size()));
+          return true;
+        }
+      char getChar()
+      {
+        char byte;
+        return get(byte) ? byte : 0;
+      }
+      std::string getString(unsigned int length, bool isTrim=false)
+      {
+        std::vector<char> buf(length);
+        read(&buf[0], buf.size());
+
+        std::vector<char>::iterator it;
+        if(isTrim){
+          it=buf.begin();
+          for(; it!=buf.end(); ++it){
+            if(*it=='\0'){
+              break;
+            }
+          }
+        }
+        else{
+          it=buf.end();
+        }
+        return std::string(buf.begin(), it);
+      }
+      unsigned char getUchar()
+      {
+        unsigned char value;
+        return get(value) ? value : 0;
+      }
+      unsigned short getUshort()
+      {
+        unsigned short value;
+        return get(value) ? value : 0;
+      }
+      unsigned int getUint()
+      {
+        unsigned int value;
+        return get(value) ? value : 0;
+      }
+    };
+
+    /**
+     * \83t\83@\83C\83\8b\82©\82ç\82Ì\93Ç\82Ý\8d\9e\82Ý
+     */
+    class FileReader : public IReader
+    {
+      std::ifstream io_;
+      unsigned int pos_;
+      bool eof_;
+
+    public:
+      FileReader(const char *path);
+      virtual ~FileReader();
+      virtual unsigned int read(char *buf, unsigned int size);
+      virtual unsigned int getPos()const;
+      virtual bool isEnd()const;
+    };
+
+    /**
+     * \83\81\83\82\83\8a\82©\82ç\82Ì\93Ç\82Ý\8d\9e\82Ý
+     */
+    class MemoryReader : public IReader
+    {
+      const char *buf_;
+      unsigned int size_;
+      unsigned int pos_;
+
+    public:
+      MemoryReader(const char *buf, unsigned int size);
+      virtual ~MemoryReader();
+      virtual unsigned int read(char *buf, unsigned int size);
+      virtual unsigned int getPos()const;
+      virtual bool isEnd()const;
+    };
+
+    void readAll(const char *path, std::vector<char> &all);
 #ifdef _WIN32
- void readAll(const wchar_t *path, std::vector<char> &all);
   void readAll(const wchar_t *path, std::vector<char> &all);
 #endif
 
-/**
- * \83f\81[\83^\8f\91\82«\8d\9e\82Ý\83C\83\93\83^\81[\83t\83F\81[\83X
- */
-class IWriter
-{
-public:
-       virtual ~IWriter(){}
-       virtual void write(const char *buf, unsigned int size)=0;
-       void printLn(const char *fmt, ...)
-       {
-               char buf[1024];
-               va_list list;
-               va_start(list, fmt);
-               vsprintf(buf, fmt, list);
-               write(buf, strlen(buf));
-               write("\r\n", 2);
-               va_end(list);
-       }
-       template<typename T>
-               void writeArray(const T *array, size_t element_count)
-               {
-                       write(
-                                       reinterpret_cast<const char*>(array), 
-                                       sizeof(T)*element_count);
-               }
-       template<typename T>
-               void writeValue(T value)
-               {
-                       writeArray(&value, 1);
-               }
-};
-
-class FileWriter : public IWriter
-{
-       FILE *io_;
-
-public:
-       FileWriter(const char *path);
-       FileWriter(const wchar_t *path);
-       virtual ~FileWriter();
-       virtual void write(const char *buf, unsigned int size);
-};
-
-} // namespace binary
+    /**
+     * \83f\81[\83^\8f\91\82«\8d\9e\82Ý\83C\83\93\83^\81[\83t\83F\81[\83X
+     */
+    class IWriter
+    {
+    public:
+      virtual ~IWriter(){}
+      virtual void write(const char *buf, unsigned int size)=0;
+      void printLn(const char *fmt, ...)
+      {
+        char buf[1024];
+        va_list list;
+        va_start(list, fmt);
+        vsprintf(buf, fmt, list);
+        write(buf, strlen(buf));
+        write("\r\n", 2);
+        va_end(list);
+      }
+      template<int LENGTH>
+        void write(const fixed_string<LENGTH> &src)
+        {
+          write(
+              reinterpret_cast<const char*>(src.begin()), 
+              src.size());
+        }
+      template<typename T>
+        void writeArray(const T *array, size_t element_count)
+        {
+          write(
+              reinterpret_cast<const char*>(array), 
+              sizeof(T)*element_count);
+        }
+      template<typename T>
+        void writeValue(T value)
+        {
+          writeArray(&value, 1);
+        }
+    };
+
+    class FileWriter : public IWriter
+    {
+      FILE *io_;
+
+    public:
+      FileWriter(const char *path);
+      FileWriter(const wchar_t *path);
+      virtual ~FileWriter();
+      virtual void write(const char *buf, unsigned int size);
+    };
+
+  } // namespace binary
 } // namespace meshio
 
 #endif // MESH_IO_BINARY_H_INCLUDED
index ca07f1b..37b62f2 100644 (file)
@@ -1,94 +1,94 @@
+/**
+ * Color
+ */
 #ifndef MESH_IO_COLOR_H_INCLUDED
 #define MESH_IO_COLOR_H_INCLUDED
 
 namespace meshio {
-namespace color {
 
-//! Byte\95Û\8e\9d\82ÌGBA
-struct bRGBA
-{
-       int r;
-       int g;
-       int b;
-       int a;
+  struct bRGBA
+  {
+    int r;
+    int g;
+    int b;
+    int a;
 
-       bRGBA()
-       {}
+    bRGBA()
+    {}
 
-       bRGBA(int _r, int _g, int _b, int _a)
-               : r(_r), g(_g), b(_b), a(_a)
-       {}
+    bRGBA(int _r, int _g, int _b, int _a)
+      : r(_r), g(_g), b(_b), a(_a)
+    {}
 
-       static bRGBA createFromUInt(unsigned int uint)
-       {
-               return bRGBA(
-                       uint & 0x000000FF,
-                       uint & 0x0000FF00 >> 8,
-                       uint & 0x00FF0000 >> 16,
-                       uint & 0xFF000000 >> 24
-                       );
-       }
-};
+    static bRGBA createFromUInt(unsigned int uint)
+    {
+      return bRGBA(
+          uint & 0x000000FF,
+          uint & 0x0000FF00 >> 8,
+          uint & 0x00FF0000 >> 16,
+          uint & 0xFF000000 >> 24
+          );
+    }
+  };
 #ifndef SWIG
-inline std::ostream &operator<<(std::ostream &os, const bRGBA &rhs)
-{
-       return os
-               << '[' << rhs.r << ',' << rhs.g << ',' << rhs.b << ',' << rhs.a << ']';
-}
+  inline std::ostream &operator<<(std::ostream &os, const bRGBA &rhs)
+  {
+    return os
+      << '[' << rhs.r << ',' << rhs.g << ',' << rhs.b << ',' << rhs.a << ']';
+  }
 #endif
 
 
-//! Float\95Û\8e\9d\82ÌRGBA
-struct fRGBA
-{
-       float r;
-       float g;
-       float b;
-       float a;
+  //! Float RGBA
+  struct fRGBA
+  {
+    float r;
+    float g;
+    float b;
+    float a;
 
-       fRGBA()
-       {}
+    fRGBA()
+    {}
 
-       fRGBA(float _r, float _g, float _b, float _a)
-               : r(_r), g(_g), b(_b), a(_a)
-       {}
+    fRGBA(float _r, float _g, float _b, float _a)
+      : r(_r), g(_g), b(_b), a(_a)
+    {}
 
-       static fRGBA createFromUInt(unsigned int uint)
-       {
-               return fRGBA(
-                       (uint & 0x000000FF) / 255.0f,
-                       (uint & 0x0000FF00 >> 8) / 255.0f,
-                       (uint & 0x00FF0000 >> 16) / 255.0f,
-                       (uint & 0xFF000000 >> 24) / 255.0f
-                       );
-       }
-};
+    static fRGBA createFromUInt(unsigned int uint)
+    {
+      return fRGBA(
+          (uint & 0x000000FF) / 255.0f,
+          (uint & 0x0000FF00 >> 8) / 255.0f,
+          (uint & 0x00FF0000 >> 16) / 255.0f,
+          (uint & 0xFF000000 >> 24) / 255.0f
+          );
+    }
+  };
 #ifndef SWIG
-inline std::ostream &operator<<(std::ostream &os, const fRGBA &rhs)
-{
-       return os
-               << '[' << rhs.r << ',' << rhs.g << ',' << rhs.b << ',' << rhs.a << ']';
-}
+  inline std::ostream &operator<<(std::ostream &os, const fRGBA &rhs)
+  {
+    return os
+      << '[' << rhs.r << ',' << rhs.g << ',' << rhs.b << ',' << rhs.a << ']';
+  }
 #endif
 
 
-//! Float\95Û\8e\9d\82ÌRGB
-struct fRGB
-{
-       float r;
-       float g;
-       float b;
-};
+  //! Float RGB
+  struct fRGB
+  {
+    float r;
+    float g;
+    float b;
+  };
 #ifndef SWIG
-inline std::ostream &operator<<(std::ostream &os, const fRGB &rhs)
-{
-       return os
-               << '[' << rhs.r << ',' << rhs.g << ',' << rhs.b << ',' << ']';
-}
+  inline std::ostream &operator<<(std::ostream &os, const fRGB &rhs)
+  {
+    return os
+      << '[' << rhs.r << ',' << rhs.g << ',' << rhs.b << ',' << ']';
+  }
 #endif
 
 
-} // namespace color
 } // namespace meshio
 
 #endif // MESH_IO_COLOR_H_INCLUDED
index 0ef6ee8..33f8f59 100644 (file)
--- a/src/la.h
+++ b/src/la.h
+/**
+ * Linear Algebra 
+ */
 #ifndef MESH_IO_LA_H_INCLUDED
 #define MESH_IO_LA_H_INCLUDED
 
 #include <ostream>
 
 namespace meshio {
-namespace la {
-/**
- * \e$B@~7ABe?t\e(B(Linear Algebra)
- */
-
-struct Vector2
-{
-       float x;
-       float y;
-
-       Vector2()
-       {}
-
-       Vector2(float _x, float _y)
-               : x(_x), y(_y)
-               {}
-};
+  struct Vector2
+  {
+    float x;
+    float y;
+
+    Vector2()
+    {}
+
+    Vector2(float _x, float _y)
+      : x(_x), y(_y)
+    {}
+  };
 #ifndef SWIG
-inline std::ostream &operator<<(std::ostream &os, const Vector2 &rhs)
-{
-       return os
-               << '[' << rhs.x << ',' << rhs.y << ']';
-}
+  inline std::ostream &operator<<(std::ostream &os, const Vector2 &rhs)
+  {
+    return os
+      << '[' << rhs.x << ',' << rhs.y << ']';
+  }
 #endif
 
-
-struct Vector3
-{
-       float x;
-       float y;
-       float z;
-
-       Vector3()
-       {}
-
-       Vector3(float _x, float _y, float _z)
-               : x(_x), y(_y), z(_z)
-               {}
-
-       bool operator==(const Vector3 &rhs)const
-       {
-               return x==rhs.x && y==rhs.y && z==rhs.z;
-       }
-
-       Vector3 operator+(const Vector3 &rhs)
-       {
-               return Vector3(x+rhs.x, y+rhs.y, z+rhs.z);
-       }
-
-       Vector3 operator-(const Vector3 &rhs)
-       {
-               return Vector3(x-rhs.x, y-rhs.y, z-rhs.z);
-       }
-};
+  struct Vector3
+  {
+    float x;
+    float y;
+    float z;
+
+    Vector3()
+    {}
+
+    Vector3(float _x, float _y, float _z)
+      : x(_x), y(_y), z(_z)
+    {}
+
+    bool operator==(const Vector3 &rhs)const
+    {
+      return x==rhs.x && y==rhs.y && z==rhs.z;
+    }
+
+    Vector3 operator+(const Vector3 &rhs)
+    {
+      return Vector3(x+rhs.x, y+rhs.y, z+rhs.z);
+    }
+
+    Vector3 operator-(const Vector3 &rhs)
+    {
+      return Vector3(x-rhs.x, y-rhs.y, z-rhs.z);
+    }
+  };
 #ifndef SWIG
-inline std::ostream &operator<<(std::ostream &os, const Vector3 &rhs)
-{
-       return os
-               << '[' << rhs.x << ',' << rhs.y << ',' << rhs.z << ']';
-}
+  inline std::ostream &operator<<(std::ostream &os, const Vector3 &rhs)
+  {
+    return os
+      << '[' << rhs.x << ',' << rhs.y << ',' << rhs.z << ']';
+  }
 #endif
 
 
-struct Vector4
-{
-       float x;
-       float y;
-       float z;
-       float w;
+  struct Vector4
+  {
+    float x;
+    float y;
+    float z;
+    float w;
 
-       Vector4()
-       {}
+    Vector4()
+    {}
 
-       Vector4(float _x, float _y, float _z, float _w)
-               : x(_x), y(_y), z(_z), w(_w)
-               {}
-};
+    Vector4(float _x, float _y, float _z, float _w)
+      : x(_x), y(_y), z(_z), w(_w)
+    {}
+  };
 #ifndef SWIG
-inline std::ostream &operator<<(std::ostream &os, const Vector4 &rhs)
-{
-       return os
-               << '[' << rhs.x << ',' << rhs.y << ',' << rhs.z << ',' << rhs.w << ']';
-}
+  inline std::ostream &operator<<(std::ostream &os, const Vector4 &rhs)
+  {
+    return os
+      << '[' << rhs.x << ',' << rhs.y << ',' << rhs.z << ',' << rhs.w << ']';
+  }
 #endif
 
 
-struct Quaternion
-{
-       float x;
-       float y;
-       float z;
-       float w;
+  struct Quaternion
+  {
+    float x;
+    float y;
+    float z;
+    float w;
 
-       Quaternion()
-       {}
+    Quaternion()
+    {}
 
-       Quaternion(float _x, float _y, float _z, float _w)
-               : x(_x), y(_y), z(_z), w(_w)
-               {}
+    Quaternion(float _x, float _y, float _z, float _w)
+      : x(_x), y(_y), z(_z), w(_w)
+    {}
 
-       float dot(const Quaternion &rhs)
-       {
-               return x*rhs.x + y*rhs.y + z*rhs.z + w*rhs.w;
-       }
-};
+    float dot(const Quaternion &rhs)
+    {
+      return x*rhs.x + y*rhs.y + z*rhs.z + w*rhs.w;
+    }
+  };
 #ifndef SWIG
-inline std::ostream &operator<<(std::ostream &os, const Quaternion &rhs)
-{
-       return os
-               << '[' << rhs.x << ',' << rhs.y << ',' << rhs.z << ',' << rhs.w << ']';
-}
+  inline std::ostream &operator<<(std::ostream &os, const Quaternion &rhs)
+  {
+    return os
+      << '[' << rhs.x << ',' << rhs.y << ',' << rhs.z << ',' << rhs.w << ']';
+  }
 #endif
 
-
-}
 }
 
 #endif // MESH_IO_LA_H_INCLUDED
diff --git a/src/linereader.h b/src/linereader.h
new file mode 100644 (file)
index 0000000..e5ea46d
--- /dev/null
@@ -0,0 +1,265 @@
+#ifndef LINEREADER_H
+#define LINEREADER_H
+
+#include "text.h"
+
+namespace meshio 
+{
+  struct IsCRLF
+  {
+    bool operator()(char byte)const
+    {
+      switch(byte)
+      {
+        case '\n':
+        case '\r': // fall through
+          return true;
+
+        default:
+          return false;
+      }
+    }
+  };
+
+  struct IsWhiteSpace
+  {
+    bool operator()(char byte)const
+    {
+      switch(byte)
+      {
+        case ' ':
+        case '\t': // fall through
+          return true;
+
+        default:
+          return false;
+      }
+    }
+  };
+
+  struct IsEmpty
+  {
+    bool operator()(cstr line)const
+    {
+      return line.empty();
+    }
+  };
+
+  template<class DELIMITER=IsCRLF, 
+    class TRIM=IsWhiteSpace,
+    class LINESKIP=IsEmpty>
+      class LineReader
+      {
+        binary::IReader &reader_;
+        unsigned int lineCount_;
+        std::vector<char> buf_;
+        bool isEnd_;
+
+      public:
+        LineReader(binary::IReader &reader)
+          : reader_(reader), lineCount_(0), isEnd_(false)
+        {
+        }
+
+        cstr getLine()
+        {
+          while(!isEnd_){
+            fill_();
+            cstr line;
+            if(!buf_.empty()){
+              line=trim_();
+            }
+            if(LINESKIP()(line)){
+              continue;
+            }
+            ++lineCount_;
+            return line;
+          }
+          return cstr();
+        }
+
+        unsigned int getLineCount()const
+        {
+          return lineCount_;
+        }
+
+        bool isEnd()const
+        {
+          return isEnd_;
+        }
+
+      private:
+        void fill_()
+        {
+          buf_.clear();
+          // skip delimeter
+          while(char byte=reader_.getChar()){
+            if(DELIMITER()(byte)){
+              continue;
+            }
+            buf_.push_back(byte);
+            break;
+          }
+          while(char byte=reader_.getChar()){
+            if(DELIMITER()(byte)){
+              break;
+            }
+            buf_.push_back(byte);
+          }
+          if(buf_.empty()){
+            isEnd_=true;
+            return;
+          }
+        }
+
+        cstr trim_()
+        {
+          if(buf_.empty()){
+            return cstr();
+          }
+
+          size_t front=0;
+          while(true){
+            if(front>=buf_.size()){
+              return cstr();
+            }
+            if(!TRIM()(buf_[front])){
+              break;
+            }
+            ++front;
+          }
+
+          size_t back=buf_.size()-1;
+          for(; back>=0; --back){
+            if(!TRIM()(buf_[back])){
+              break;
+            }
+          }
+          assert(front<=back);
+          return cstr(&buf_[0]+front, &buf_[0]+back+1);
+        }
+      };
+
+  template<class DELIMITER=IsWhiteSpace>
+    class LineSplitter
+    {
+      cstr line_;
+
+    public:
+      LineSplitter(cstr line)
+        : line_(line)
+      {
+      }
+
+      cstr get()
+      {
+        const char* head=0;
+        const char* tail=0;
+        const char *current=line_.begin();
+        for(; current!=line_.end();){
+          for(; current!=line_.end(); ++current){
+            if(!DELIMITER()(*current)){
+              head=current;
+              break;
+            }
+          }
+          if(head){
+            for(; current!=line_.end(); ++current){
+              if(DELIMITER()(*current)){
+                break;
+              }
+            }
+            tail=current;
+          }
+          if(tail){
+            break;
+          }
+        }
+        if(!tail){
+          return cstr();
+        }
+        line_=cstr(tail+1, line_.end());
+        return cstr(head, tail);
+      }
+
+      int getInt()
+      {
+        return atoi(get().begin());
+      }
+
+      float getFloat()
+      {
+        return static_cast<float>(atof(get().begin()));
+      }
+
+      Vector2 getVector2()
+      {
+        float x=getFloat();
+        float y=getFloat();
+        return Vector2(x, y);
+      }
+
+      Vector3 getVector3()
+      {
+        float x=getFloat();
+        float y=getFloat();
+        float z=getFloat();
+        return Vector3(x, y, z);
+      }
+
+      Vector4 getVector4()
+      {
+        float x=getFloat();
+        float y=getFloat();
+        float z=getFloat();
+        float w=getFloat();
+        return Vector4(x, y, z, w);
+      }
+
+      fRGBA getFloatRGBA()
+      {
+        float r=getFloat();
+        float g=getFloat();
+        float b=getFloat();
+        float a=getFloat();
+        return fRGBA(r, g, b, a);
+      }
+
+      bRGBA getByteRGBA()
+      {
+        int r=getInt();
+        int g=getInt();
+        int b=getInt();
+        int a=getInt();
+        return bRGBA(r, g, b, a);
+      }
+
+      cstr getQuated()
+      {
+        const char *begin=line_.begin();
+        for(; begin!=line_.end(); ++begin){
+          if(*begin=='"'){
+            break;
+          }
+        }
+        begin++;
+        assert(begin<=line_.end());
+
+        const char *c=begin+1;
+        for(; c!=line_.end(); ++c){
+          if(*c=='"'){
+            break;
+          }
+        }
+
+        cstr token=cstr(begin, c);
+
+        // advance
+        line_=cstr(c+1, line_.end());
+
+        return token;
+      }
+    };
+}
+
+#endif
index 8c27c03..ca6834d 100644 (file)
 #include "mqo.h"
+#include "linereader.h"
 #include <iostream>
 #include <fstream>
 #include <sstream>
 #include <iomanip>
 #include <vector>
 
-#include "text.h"
-
 namespace meshio {
-namespace mqo {
-
-std::wstring 
-       Material::getName()const
-       {
-               return text::trim(text::cp932_to_unicode(name));
-       }
-
-std::wstring 
-       Material::getTexture()const
-       {
-               return text::trim(text::cp932_to_unicode(texture));
-       }
-
-std::wstring 
-       Object::getName()const
-       {
-               return text::trim(text::cp932_to_unicode(name));
-       }
-
-//! Tokenizer
-struct DELIMITER
-{
-       bool operator()(char c)
-       {
-               switch(c)
-               {
-               case ' ':
-               case '\t':
-               case '(':
-               case ')':
-                       return true;
-               default:
-                       return false;
-               }
-       }
-};
-typedef text::LineSplitter<DELIMITER> SPLITTER;
-
-
-//! \8eÀ\91\95
-class Implementation
-{
-       Scene &scene;
-       std::vector<Material> &materials;
-       std::vector<Object> &objects;
-
-public:
-       Implementation(Scene &_scene, std::vector<Material> &_materials,
-                       std::vector<Object> &_objects)
-               : scene(_scene), materials(_materials), objects(_objects)
-               {}
-
-       template<class READER> bool 
-               parse(READER reader)
-               {
-                       while(!reader.isEnd()){
-                               text::cstr line=reader.getLine();
-                               SPLITTER splitter(line);
-                               text::cstr key=splitter.get();
-                               if(key=="Scene"){
-                                       if(!readSceneChunk(reader)){
-                                               return false;
-                                       }
-                               }
-                               else if(key=="Material"){
-                                       if(!readMaterialChunk(reader, splitter.getInt())){
-                                               return false;
-                                       }
-                               }
-                               else if(key=="Object"){
-                                       if(!readObjectChunk(reader, splitter.getQuated())){
-                                               return false;
-                                       }
-                               }
-                               else if(key=="Eof"){
-                                       if(materials.empty()){
-                                               // fallback
-                                               //materials.push_back(Material());
-                                       }
-                                       return true;
-                               }
-                       }
-                       std::cout << "not found 'EOF'" << std::endl;
-                       return true;
-               }
-
-
-private:
-       template<class READER> bool 
-               readObjectChunk(READER &reader, text::cstr name)
-               {
-                       objects.push_back(Object());
-                       Object &object=objects.back();
-                       object.name=name.str();
-                       while(!reader.isEnd()){
-                               text::cstr line=reader.getLine();
-                               if(line=="}"){
-                                       return true;
-                               }
-                               SPLITTER splitter(line);
-                               text::cstr key=splitter.get();
-                               if(key=="depth"){
-                                       object.depth=splitter.getInt();
-                               }
-                               else if(key=="folding"){
-                                       object.folding=splitter.getInt();
-                               }
-                               else if(key=="scale"){
-                                       object.scale=splitter.getVector3();
-                               }
-                               else if(key=="rotation"){
-                                       object.rotation=splitter.getVector3();
-                               }
-                               else if(key=="translation"){
-                                       object.translation=splitter.getVector3();
-                               }
-                               else if(key=="visible"){
-                                       object.visible=splitter.getInt();
-                               }
-                               else if(key=="locking"){
-                                       object.locking=splitter.getInt();
-                               }
-                               else if(key=="shading"){
-                                       object.shading=splitter.getInt();
-                               }
-                               else if(key=="facet"){
-                                       object.smoothing=splitter.getFloat();
-                               }
-                               else if(key=="color"){
-                                       object.color=splitter.getVector3();
-                               }
-                               else if(key=="color_type"){
-                                       object.color_type=splitter.getInt();
-                               }
-                               else if(key=="vertex"){
-                                       if(!readObjectVertexChunk(reader, object, splitter.getInt())){
-                                               return false;
-                                       }
-                               }
-                               else if(key=="face"){
-                                       if(!readObjectFaceChunk(reader, object, splitter.getInt())){
-                                               return false;
-                                       }
-                               }
-                               else if(key=="segment"){
-                                       // ToDo
-                                       continue;
-                               }
-                               else if(key=="patch"){
-                                       // ToDo
-                                       continue;
-                               }
-                               else if(key=="mirror"){
-                                       object.mirror=splitter.getInt();
-                               }
-                               else{
-                                       std::cout << "unknown object key: " << key << std::endl;
-                               }
-                       }
-                       std::cout << "fail to readObjectChunk" << std::endl;
-                       return false;
-               }
-       template<class READER> bool 
-               readObjectVertexChunk(READER &reader, 
-                               Object &object, size_t vertex_count)
-               {
-                       while(!reader.isEnd()){
-                               text::cstr line=reader.getLine();
-                               if(line=="}"){
-                                       if(object.vertices.size()!=vertex_count){
-                                               std::cout << "invalid vertex count." 
-                                                       << " expected " << vertex_count
-                                                       << ", but " << object.vertices.size()
-                                                       << std::endl;
-                                               return false;
-                                       }
-                                       return true;
-                               }
-                               object.vertices.push_back(SPLITTER(line).getVector3());
-                       }
-                       std::cout << "fail to readObjectVertexChunk" << std::endl;
-                       return false;
-               }
-
-       template<class READER> bool 
-               readObjectFaceChunk(READER &reader,
-                               Object &object, size_t face_count)
-               {
-                       while(!reader.isEnd()){
-                               text::cstr line=reader.getLine();
-                               if(line=="}"){
-                                       if(object.faces.size()!=face_count){
-                                               std::cout << "invalid face count."
-                                                       << " expected " << face_count
-                                                       << ", but " << object.faces.size()
-                                                       << std::endl;
-                                               return false;
-                                       }
-                                       return true;
-                               }
-                               if(!readObjectFaceLine(object, line)){
-                                       return false;
-                               }
-                       }
-                       std::cout << "fail to readFaceChunk" << std::endl;
-                       return false;
-               }
-
-       bool 
-               readObjectFaceLine(Object &object, text::cstr line)
-               {
-                       object.faces.push_back(Face());
-                       Face &face=object.faces.back();
-                       SPLITTER splitter(line);
-                       face.index_count=splitter.getInt();
-                       while(true){
-                               text::cstr key=splitter.get();
-                               if(key==""){
-                                       break;
-                               }
-
-                               if(key=="V"){
-                                       for(size_t i=0; i<face.index_count; ++i){
-                                               face.indices[i]=splitter.getInt();
-                                       }
-                               }
-                               else if(key=="M"){
-                                       face.material_index=splitter.getInt();
-                               }
-                               else if(key=="UV"){
-                                       for(size_t i=0; i<face.index_count; ++i){
-                                               face.uv[i]=splitter.getVector2();
-                                       }
-                               }
-                               else if(key=="COL"){
-                                       for(size_t i=0; i<face.index_count; ++i){
-                                               face.color[i]=
-                                                       color::fRGBA::createFromUInt(splitter.getInt());
-                                       }
-                               }
-                               else{
-                                       std::cout << "unknown face key: " 
-                                               << '"' << key << '"'  << std::endl
-                                               ;
-                                       //return false;
-                                       break;
-                               }
-                       }
-                       return true;
-               }
-
-       template<class READER> bool 
-               readMaterialChunk(READER &reader, size_t material_count)
-               {
-                       while(!reader.isEnd()){
-                               text::cstr line=reader.getLine();
-                               if(line=="}"){
-                                       if(materials.size()!=material_count){
-                                               std::cout << "invalid material count." 
-                                                       << " expected " << material_count
-                                                       << ", but " << materials.size()
-                                                       << std::endl;
-                                               return false;
-                                       }
-                                       return true;
-                               }
-                               readMaterialLine(line);
-                       }
-                       std::cout << "fail to readMaterialChunk" << std::endl;
-                       return false;
-               }
-
-       void 
-               readMaterialLine(text::cstr line)
-               {
-                       materials.push_back(Material());
-                       Material &material=materials.back();
-
-                       SPLITTER splitter(line);
-                       material.name=splitter.getQuated().str();
-                       while(true){
-                               text::cstr key=splitter.get();
-                               if(key==""){
-                                       break;
-                               }
-                               else if(key=="shader"){
-                                       material.shader=splitter.getInt();
-                               }
-                               else if(key=="col"){
-                                       material.color=splitter.getFloatRGBA();
-                               }
-                               else if(key=="dif"){
-                                       material.diffuse=splitter.getFloat();
-                               }
-                               else if(key=="amb"){
-                                       material.ambient=splitter.getFloat();
-                               }
-                               else if(key=="emi"){
-                                       material.emit=splitter.getFloat();
-                               }
-                               else if(key=="spc"){
-                                       material.specular=splitter.getFloat();
-                               }
-                               else if(key=="power"){
-                                       material.power=splitter.getFloat();
-                               }
-                               else if(key=="tex"){
-                                       material.texture=splitter.getQuated().str();
-                               }
-                               else if(key=="aplane"){
-                                       material.alphamap=splitter.getQuated().str();
-                               }
-                               else if(key=="bump"){
-                                       material.bumpmap=splitter.getQuated().str();
-                               }
-                               else if(key=="vcol"){
-                                       material.vcol=splitter.getInt();
-                               }
-                               else{
-                                       std::cout << "unknown material key: \"" << key << '"' << std::endl;
-                                       //assert(false);
-                                       return;
-                               }
-                       }
-               }
-
-       template<class READER> bool 
-               readSceneChunk(READER &reader)
-               {
-                       while(!reader.isEnd()){
-                               text::cstr line=reader.getLine();
-                               if(line=="}"){
-                                       return true;
-                               }
-                               SPLITTER splitter(line);
-                               text::cstr key=splitter.get();
-                               if(key=="pos"){
-                                       scene.pos=splitter.getVector3();
-                               }
-                               else if(key=="lookat"){
-                                       scene.lookat=splitter.getVector3();
-                               }
-                               else if(key=="head"){
-                                       scene.head=splitter.getFloat();
-                               }
-                               else if(key=="pich") {
-                                       scene.pitch=splitter.getFloat();
-                               }
-                               else if(key=="ortho"){
-                                       scene.ortho=splitter.getInt();
-                               }
-                               else if(key=="zoom2"){
-                                       scene.zoom2=splitter.getFloat();
-                               }
-                               else if(key=="amb"){
-                                       scene.ambient=splitter.getVector3();
-                               }
-                               else{
-                                       std::cout << "unknown scene key: " << key << std::endl;
-                               }
-                       }
-                       std::cout << "fail to readSceneChunk" << std::endl;
-                       return false;
-               }
-
-       template<class READER> bool 
-               readChunk(READER &reader)
-               {
-                       int level=1;
-                       while(!reader.isEnd()){
-                               text::cstr line=reader.getLine();
-                               if(line=="}"){
-                                       level--;
-                                       if(level==0){
-                                               return true;
-                                       }
-                               }
-                               else if(line.include('{')){
-                                       level+=1;
-                               }
-                       }
-                       return false;
-               }
-
-};
-
-
-///////////////////////////////////////////////////////////////////////////////
-// IO
-///////////////////////////////////////////////////////////////////////////////
-bool IO::read(binary::IReader &input)
-{
-       text::LineReader<text::IsCRLF, text::IsWhiteSpace, text::IsEmpty> 
-               reader(input);
-       text::cstr line=reader.getLine();
-       if(line!="Metasequoia Document"){
-               return false;
-       }
-       line=reader.getLine();
-       if(line!="Format Text Ver 1.0"){
-               return false;
-       }
-
-       return Implementation(scene, materials, objects).parse(reader);
-}
-
-bool IO::read(const char *path)
-{
-       std::vector<char> all;
-       binary::readAll(path, all);
-       if(all.empty()){
-               return false;
-       }
-       binary::MemoryReader reader(&all[0], all.size());
-       return read(reader);
-}
-
-#ifdef _WIN32
-bool IO::read(const wchar_t *path)
-{
-       std::vector<char> all;
-       binary::readAll(path, all);
-       if(all.empty()){
-               return false;
-       }
-       binary::MemoryReader reader(&all[0], all.size());
-       return read(reader);
-}
-#endif
-
-bool IO::write(binary::IWriter &writer)
-{
-       // header
-       writer.printLn("Metasequoia Document");
-       writer.printLn("Format Text Ver 1.0");
-       writer.printLn("");
-
-       // scene
-       writer.printLn("Scene {");
-       writer.printLn("\tpos 0.0000 0.0000 1500.0000");
-       writer.printLn("\tlookat 0.0000 0.0000 0.0000");
-       writer.printLn("\thead -0.5236");
-       writer.printLn("\tpich 0.5236");
-       writer.printLn("\tortho 0");
-       writer.printLn("\tzoom2 5.0000");
-       writer.printLn("\tamb 0.250 0.250 0.250");
-       writer.printLn("}");
-
-       // materials
-       if(materials.size()>0){
-               writer.printLn("Material %d {", materials.size());
-               for(size_t i=0; i<materials.size(); ++i){
-                       Material &m=materials[i];
-               }
-               writer.printLn("}");
-       }
-
-       // objects
-       for(size_t i=0; i<objects.size(); ++i){
-               Object &o=objects[i];
-               writer.printLn("Object \"%s\" {", o.name.c_str());
-               writer.printLn("\tdepth 0");
-               writer.printLn("\tfolding 0");
-               writer.printLn("\tscale 1.000000 1.000000 1.000000");
-               writer.printLn("\trotation 0.000000 0.000000 0.000000");
-               writer.printLn("\ttranslation 0.000000 0.000000 0.000000");
-               writer.printLn("\tvisible 15");
-               writer.printLn("\tlocking 0");
-               writer.printLn("\tshading 1");
-               writer.printLn("\tfacet 59.5");
-               writer.printLn("\tcolor 0.898 0.400 0.137");
-               writer.printLn("\tcolor_type 0");
-               // vertex
-               writer.printLn("\tvertex %d {", o.vertices.size());
-               for(size_t j=0; j<o.vertices.size(); ++j){
-                       Vector3 &v=o.vertices[j];
-                       writer.printLn("\t\t%.4f %.4f %.4f", v.x, v.y, v.z);
-               }
-               writer.printLn("\t}");
-               // face
-               writer.printLn("\tface %d {", o.faces.size());
-               for(size_t j=0; j<o.faces.size(); ++j){
-                       Face &f=o.faces[j];
-
-                       std::stringstream ss;
-                       ss.setf(std::ios_base::fixed, std::ios_base::floatfield);
-                       ss 
-                               << "\t\t"
-                               << f.index_count
-                               ;
-                       ss << " V(";
-                       for(size_t k=0; k<f.index_count; ++k){
-                               if(k){
-                                       ss << ' ';
-                               }
-                               ss << f.indices[k];
-                       }
-                       ss << ") UV(";
-                       for(size_t k=0; k<f.index_count; ++k){
-                               if(k){
-                                       ss << ' ';
-                               }
-                               Vector2 &uv=f.uv[k];
-                               ss 
-                                       << std::setprecision(5) << uv.x 
-                                       << ' ' << std::setprecision(5) << uv.y;
-                       }
-                       ss << ")";
-
-                       writer.printLn(ss.str().c_str());
-               }
-               writer.printLn("\t}");
-               // close
-               writer.printLn("}");
-       }
-       // Eof
-       writer.printLn("Eof");
-
-       return true;
-}
-
-bool IO::write(const char *path)
-{
-       binary::FileWriter writer(path);
-       return write(writer);
-}
-
-}
+  namespace mqo {
+
+    //! Tokenizer
+    struct DELIMITER
+    {
+      bool operator()(char c)
+      {
+        switch(c)
+        {
+          case ' ':
+          case '\t':
+          case '(':
+          case ')':
+            return true;
+          default:
+            return false;
+        }
+      }
+    };
+    typedef LineSplitter<DELIMITER> SPLITTER;
+
+
+    //! \8eÀ\91\95
+    class Implementation
+    {
+      Scene &scene;
+      std::vector<Material> &materials;
+      std::vector<Object> &objects;
+
+    public:
+      Implementation(Scene &_scene, std::vector<Material> &_materials,
+          std::vector<Object> &_objects)
+        : scene(_scene), materials(_materials), objects(_objects)
+      {}
+
+      template<class READER> bool 
+        parse(READER reader)
+        {
+          while(!reader.isEnd()){
+            cstr line=reader.getLine();
+            SPLITTER splitter(line);
+            cstr key=splitter.get();
+            if(key=="Scene"){
+              if(!readSceneChunk(reader)){
+                return false;
+              }
+            }
+            else if(key=="Material"){
+              if(!readMaterialChunk(reader, splitter.getInt())){
+                return false;
+              }
+            }
+            else if(key=="Object"){
+              if(!readObjectChunk(reader, splitter.getQuated())){
+                return false;
+              }
+            }
+            else if(key=="Eof"){
+              if(materials.empty()){
+                // fallback
+                //materials.push_back(Material());
+              }
+              return true;
+            }
+          }
+          std::cout << "not found 'EOF'" << std::endl;
+          return true;
+        }
+
+
+    private:
+      template<class READER> bool 
+        readObjectChunk(READER &reader, cstr name)
+        {
+          objects.push_back(Object());
+          Object &object=objects.back();
+          object.name=name.str();
+          while(!reader.isEnd()){
+            cstr line=reader.getLine();
+            if(line=="}"){
+              return true;
+            }
+            SPLITTER splitter(line);
+            cstr key=splitter.get();
+            if(key=="depth"){
+              object.depth=splitter.getInt();
+            }
+            else if(key=="folding"){
+              object.folding=splitter.getInt();
+            }
+            else if(key=="scale"){
+              object.scale=splitter.getVector3();
+            }
+            else if(key=="rotation"){
+              object.rotation=splitter.getVector3();
+            }
+            else if(key=="translation"){
+              object.translation=splitter.getVector3();
+            }
+            else if(key=="visible"){
+              object.visible=splitter.getInt();
+            }
+            else if(key=="locking"){
+              object.locking=splitter.getInt();
+            }
+            else if(key=="shading"){
+              object.shading=splitter.getInt();
+            }
+            else if(key=="facet"){
+              object.smoothing=splitter.getFloat();
+            }
+            else if(key=="color"){
+              object.color=splitter.getVector3();
+            }
+            else if(key=="color_type"){
+              object.color_type=splitter.getInt();
+            }
+            else if(key=="vertex"){
+              if(!readObjectVertexChunk(reader, object, splitter.getInt())){
+                return false;
+              }
+            }
+            else if(key=="face"){
+              if(!readObjectFaceChunk(reader, object, splitter.getInt())){
+                return false;
+              }
+            }
+            else if(key=="segment"){
+              // ToDo
+              continue;
+            }
+            else if(key=="patch"){
+              // ToDo
+              continue;
+            }
+            else if(key=="mirror"){
+              object.mirror=splitter.getInt();
+            }
+            else{
+              std::cout << "unknown object key: " << key << std::endl;
+            }
+          }
+          std::cout << "fail to readObjectChunk" << std::endl;
+          return false;
+        }
+      template<class READER> bool 
+        readObjectVertexChunk(READER &reader, 
+            Object &object, size_t vertex_count)
+        {
+          while(!reader.isEnd()){
+            cstr line=reader.getLine();
+            if(line=="}"){
+              if(object.vertices.size()!=vertex_count){
+                std::cout << "invalid vertex count." 
+                  << " expected " << vertex_count
+                  << ", but " << object.vertices.size()
+                  << std::endl;
+                return false;
+              }
+              return true;
+            }
+            object.vertices.push_back(SPLITTER(line).getVector3());
+          }
+          std::cout << "fail to readObjectVertexChunk" << std::endl;
+          return false;
+        }
+
+      template<class READER> bool 
+        readObjectFaceChunk(READER &reader,
+            Object &object, size_t face_count)
+        {
+          while(!reader.isEnd()){
+            cstr line=reader.getLine();
+            if(line=="}"){
+              if(object.faces.size()!=face_count){
+                std::cout << "invalid face count."
+                  << " expected " << face_count
+                  << ", but " << object.faces.size()
+                  << std::endl;
+                return false;
+              }
+              return true;
+            }
+            if(!readObjectFaceLine(object, line)){
+              return false;
+            }
+          }
+          std::cout << "fail to readFaceChunk" << std::endl;
+          return false;
+        }
+
+      bool 
+        readObjectFaceLine(Object &object, cstr line)
+        {
+          object.faces.push_back(Face());
+          Face &face=object.faces.back();
+          SPLITTER splitter(line);
+          face.index_count=splitter.getInt();
+          while(true){
+            cstr key=splitter.get();
+            if(key==""){
+              break;
+            }
+
+            if(key=="V"){
+              for(size_t i=0; i<face.index_count; ++i){
+                face.indices[i]=splitter.getInt();
+              }
+            }
+            else if(key=="M"){
+              face.material_index=splitter.getInt();
+            }
+            else if(key=="UV"){
+              for(size_t i=0; i<face.index_count; ++i){
+                face.uv[i]=splitter.getVector2();
+              }
+            }
+            else if(key=="COL"){
+              for(size_t i=0; i<face.index_count; ++i){
+                face.color[i]=
+                  fRGBA::createFromUInt(splitter.getInt());
+              }
+            }
+            else{
+              std::cout << "unknown face key: " 
+                << '"' << key << '"'  << std::endl
+                ;
+              //return false;
+              break;
+            }
+          }
+          return true;
+        }
+
+      template<class READER> bool 
+        readMaterialChunk(READER &reader, size_t material_count)
+        {
+          while(!reader.isEnd()){
+            cstr line=reader.getLine();
+            if(line=="}"){
+              if(materials.size()!=material_count){
+                std::cout << "invalid material count." 
+                  << " expected " << material_count
+                  << ", but " << materials.size()
+                  << std::endl;
+                return false;
+              }
+              return true;
+            }
+            readMaterialLine(line);
+          }
+          std::cout << "fail to readMaterialChunk" << std::endl;
+          return false;
+        }
+
+      void 
+        readMaterialLine(cstr line)
+        {
+          materials.push_back(Material());
+          Material &material=materials.back();
+
+          SPLITTER splitter(line);
+          material.name=splitter.getQuated().str();
+          while(true){
+            cstr key=splitter.get();
+            if(key==""){
+              break;
+            }
+            else if(key=="shader"){
+              material.shader=splitter.getInt();
+            }
+            else if(key=="col"){
+              material.color=splitter.getFloatRGBA();
+            }
+            else if(key=="dif"){
+              material.diffuse=splitter.getFloat();
+            }
+            else if(key=="amb"){
+              material.ambient=splitter.getFloat();
+            }
+            else if(key=="emi"){
+              material.emit=splitter.getFloat();
+            }
+            else if(key=="spc"){
+              material.specular=splitter.getFloat();
+            }
+            else if(key=="power"){
+              material.power=splitter.getFloat();
+            }
+            else if(key=="tex"){
+              material.texture=splitter.getQuated().str();
+            }
+            else if(key=="aplane"){
+              material.alphamap=splitter.getQuated().str();
+            }
+            else if(key=="bump"){
+              material.bumpmap=splitter.getQuated().str();
+            }
+            else if(key=="vcol"){
+              material.vcol=splitter.getInt();
+            }
+            else{
+              std::cout << "unknown material key: \"" << key << '"' << std::endl;
+              //assert(false);
+              return;
+            }
+          }
+        }
+
+      template<class READER> bool 
+        readSceneChunk(READER &reader)
+        {
+          while(!reader.isEnd()){
+            cstr line=reader.getLine();
+            if(line=="}"){
+              return true;
+            }
+            SPLITTER splitter(line);
+            cstr key=splitter.get();
+            if(key=="pos"){
+              scene.pos=splitter.getVector3();
+            }
+            else if(key=="lookat"){
+              scene.lookat=splitter.getVector3();
+            }
+            else if(key=="head"){
+              scene.head=splitter.getFloat();
+            }
+            else if(key=="pich") {
+              scene.pitch=splitter.getFloat();
+            }
+            else if(key=="ortho"){
+              scene.ortho=splitter.getInt();
+            }
+            else if(key=="zoom2"){
+              scene.zoom2=splitter.getFloat();
+            }
+            else if(key=="amb"){
+              scene.ambient=splitter.getVector3();
+            }
+            else{
+              std::cout << "unknown scene key: " << key << std::endl;
+            }
+          }
+          std::cout << "fail to readSceneChunk" << std::endl;
+          return false;
+        }
+
+      template<class READER> bool 
+        readChunk(READER &reader)
+        {
+          int level=1;
+          while(!reader.isEnd()){
+            cstr line=reader.getLine();
+            if(line=="}"){
+              level--;
+              if(level==0){
+                return true;
+              }
+            }
+            else if(line.include('{')){
+              level+=1;
+            }
+          }
+          return false;
+        }
+
+    };
+
+
+    // IO
+    bool IO::read(binary::IReader &input)
+    {
+      LineReader<IsCRLF, IsWhiteSpace, IsEmpty> 
+        reader(input);
+      cstr line=reader.getLine();
+      if(line!="Metasequoia Document"){
+        return false;
+      }
+      line=reader.getLine();
+      if(line!="Format Text Ver 1.0"){
+        return false;
+      }
+
+      return Implementation(scene, materials, objects).parse(reader);
+    }
+
+    bool IO::read(const char *path)
+    {
+      std::vector<char> all;
+      binary::readAll(path, all);
+      if(all.empty()){
+        return false;
+      }
+      binary::MemoryReader reader(&all[0], all.size());
+      return read(reader);
+    }
+
+    bool IO::write(binary::IWriter &writer)
+    {
+      // header
+      writer.printLn("Metasequoia Document");
+      writer.printLn("Format Text Ver 1.0");
+      writer.printLn("");
+
+      // scene
+      writer.printLn("Scene {");
+      writer.printLn("\tpos 0.0000 0.0000 1500.0000");
+      writer.printLn("\tlookat 0.0000 0.0000 0.0000");
+      writer.printLn("\thead -0.5236");
+      writer.printLn("\tpich 0.5236");
+      writer.printLn("\tortho 0");
+      writer.printLn("\tzoom2 5.0000");
+      writer.printLn("\tamb 0.250 0.250 0.250");
+      writer.printLn("}");
+
+      // materials
+      if(materials.size()>0){
+        writer.printLn("Material %d {", materials.size());
+        /*
+        for(size_t i=0; i<materials.size(); ++i){
+          Material &m=materials[i];
+        }
+        */
+        writer.printLn("}");
+      }
+
+      // objects
+      for(size_t i=0; i<objects.size(); ++i){
+        Object &o=objects[i];
+        writer.printLn("Object \"%s\" {", o.name.c_str());
+        writer.printLn("\tdepth 0");
+        writer.printLn("\tfolding 0");
+        writer.printLn("\tscale 1.000000 1.000000 1.000000");
+        writer.printLn("\trotation 0.000000 0.000000 0.000000");
+        writer.printLn("\ttranslation 0.000000 0.000000 0.000000");
+        writer.printLn("\tvisible 15");
+        writer.printLn("\tlocking 0");
+        writer.printLn("\tshading 1");
+        writer.printLn("\tfacet 59.5");
+        writer.printLn("\tcolor 0.898 0.400 0.137");
+        writer.printLn("\tcolor_type 0");
+        // vertex
+        writer.printLn("\tvertex %d {", o.vertices.size());
+        for(size_t j=0; j<o.vertices.size(); ++j){
+          Vector3 &v=o.vertices[j];
+          writer.printLn("\t\t%.4f %.4f %.4f", v.x, v.y, v.z);
+        }
+        writer.printLn("\t}");
+        // face
+        writer.printLn("\tface %d {", o.faces.size());
+        for(size_t j=0; j<o.faces.size(); ++j){
+          Face &f=o.faces[j];
+
+          std::stringstream ss;
+          ss.setf(std::ios_base::fixed, std::ios_base::floatfield);
+          ss 
+            << "\t\t"
+            << f.index_count
+            ;
+          ss << " V(";
+          for(size_t k=0; k<f.index_count; ++k){
+            if(k){
+              ss << ' ';
+            }
+            ss << f.indices[k];
+          }
+          ss << ") UV(";
+          for(size_t k=0; k<f.index_count; ++k){
+            if(k){
+              ss << ' ';
+            }
+            Vector2 &uv=f.uv[k];
+            ss 
+              << std::setprecision(5) << uv.x 
+              << ' ' << std::setprecision(5) << uv.y;
+          }
+          ss << ")";
+
+          writer.printLn(ss.str().c_str());
+        }
+        writer.printLn("\t}");
+        // close
+        writer.printLn("}");
+      }
+      // Eof
+      writer.printLn("Eof");
+
+      return true;
+    }
+
+    bool IO::write(const char *path)
+    {
+      binary::FileWriter writer(path);
+      return write(writer);
+    }
+
+  }
 }
index 1878689..6324b1b 100644 (file)
--- a/src/mqo.h
+++ b/src/mqo.h
 
 #include <iosfwd>
 #include <vector>
+#include <assert.h>
 #include "la.h"
 #include "color.h"
 #include "text.h"
+#include "binary.h"
 
 namespace meshio {
-namespace mqo {
-
-typedef ::meshio::la::Vector2 Vector2;
-typedef ::meshio::la::Vector3 Vector3;
-typedef ::meshio::la::Vector4 Vector4;
-typedef ::meshio::color::fRGBA RGBA;
-
-//! Scene\83`\83\83\83\93\83N
-struct Scene
-{
-       Vector3 pos;
-       Vector3 lookat;
-       float head;
-       float pitch;
-       int ortho;
-       float zoom2;
-       Vector3 ambient;
-       Scene()
-               : head(0), pitch(0), ortho(false), zoom2(2)
-               {}
-};
-inline std::ostream &operator<<(std::ostream &os, const Scene &rhs)
-{
-       os
-               << "<Scene"
-               << " pos: " << rhs.pos
-               << ", lookat: " << rhs.lookat
-               << ", head: " << rhs.head
-               << ", pitch: " << rhs.pitch
-               << ", ortho: " << rhs.ortho
-               << ", zoom2: " << rhs.zoom2
-               << ", ambient: " << rhs.ambient
-               << ">"
-               ;
-       return os;
-}
-
-//! Material\83`\83\83\83\93\83N
-struct Material
-{
-       std::string name;
-       int shader;
-       RGBA color;
-       float diffuse;
-       float ambient;
-       float emit;
-       float specular;
-       float power;
-       std::string texture;
-       std::string alphamap;
-       std::string bumpmap;
-       int vcol;
-
-       Material()
-               : shader(0), diffuse(1), ambient(0), emit(0), specular(0), power(0),
-               vcol(0)
-               {}
-
-       // for python3 unicode
-       std::wstring getName()const;
-       std::wstring getTexture()const;
-};
-inline std::ostream &operator<<(std::ostream &os, const Material &rhs)
-{
-       os
-               << "<Material "
-               << '"' << rhs.name << '"'
-               << " shader:" << rhs.shader
-               << ", color:" << rhs.color
-               << ", diffuse:" << rhs.diffuse
-               << ", ambient:" << rhs.ambient
-               << ", emit:" << rhs.emit
-               << ", specular:" << rhs.specular
-               << ", power:" << rhs.power
-               << ", texture:\"" << rhs.texture << '"'
-               << ", alphamap:\"" << rhs.alphamap << '"'
-               << ", bumpmap:\"" << rhs.bumpmap << '"'
-               << ">"
-               ;
-       return os;
-}
-
-//! face\83`\83\83\83\93\83N
-struct Face
-{
-       unsigned int index_count;
-       unsigned int indices[4];
-       unsigned int material_index;
-       Vector2 uv[4];
-       RGBA color[4];
-       Face()
-               : index_count(0), material_index(0)
-               {
-                       indices[0]=0;
-                       indices[1]=0;
-                       indices[2]=0;
-                       indices[3]=0;
-                       uv[0]=Vector2();
-                       uv[1]=Vector2();
-                       uv[2]=Vector2();
-                       uv[3]=Vector2();
-               }
-       int getIndex(int i){ return indices[i]; }
-       Vector2 getUV(int i){ return uv[i]; }
-};
-inline std::ostream &operator<<(std::ostream &os, const Face &rhs)
-{
-       switch(rhs.index_count)
-       {
-       case 2:
-               os
-                       << "<Edge "
-                       << "indices:{" << rhs.indices[0] << ',' << rhs.indices[1] << "}"
-                       << ", material_index: " << rhs.material_index
-                       << ", uv:{" << rhs.uv[0] << ',' << rhs.uv[1] << "}"
-                       << ", color:{" << rhs.color[0] << ',' << rhs.color[1] << "}"
-                       << ">"
-                       ;
-               break;
-
-       case 3:
-               os
-                       << "<Triangle "
-                       << "indices:{" << rhs.indices[0] 
-                       << ',' << rhs.indices[1] 
-                       << ',' << rhs.indices[2] << "}"
-                       << ", material_index: " << rhs.material_index
-                       << ", uv:{" << rhs.uv[0] << ',' << rhs.uv[1] << ',' << rhs.uv[2] << "}"
-                       << ", color:{" 
-                       << rhs.color[0] << ',' << rhs.color[1] << ',' <<  rhs.color[2] << "}"
-                       << ">"
-                       ;
-               break;
-
-       case 4:
-               os
-                       << "<Rectangle "
-                       << "indices:{" << rhs.indices[0] 
-                       << ',' << rhs.indices[1] 
-                       << ',' << rhs.indices[2] 
-                       << ',' << rhs.indices[3] << "}"
-                       << ", material_index: " << rhs.material_index
-                       << ", uv:{" << rhs.uv[0] << ',' << rhs.uv[1] 
-                       << ',' <<  rhs.uv[2] << ',' << rhs.uv[3] << "}"
-                       << ", color:{" << rhs.color[0] 
-                       << ',' << rhs.color[1] 
-                       << ',' <<  rhs.color[2] 
-                       << ',' <<  rhs.color[3] << "}"
-                       << ">"
-                       ;
-               break;
-       default:
-               assert(false);
-       }
-
-       return os;
-}
-
-//! Object\83`\83\83\83\93\83N
-struct Object
-{
-       std::string name;
-       int depth;
-       int folding;
-       Vector3 scale;
-       Vector3 rotation;
-       Vector3 translation;
-       int visible;
-       int locking;
-       int shading;
-       float smoothing;
-       Vector3 color;
-       int color_type;
-       int mirror;
-
-       std::vector<Vector3> vertices;
-       std::vector<Face> faces;
-
-       Object()
-               : depth(0), folding(0), visible(1), locking(0), shading(0), 
-               smoothing(60.0f), color_type(0), mirror(0)
-       {}
-
-       std::wstring getName()const;
-};
-inline std::ostream &operator<<(std::ostream &os, const Object &rhs)
-{
-       os
-               << "<Object "
-               << '"' << rhs.name << '"'
-               << " vertices:" << rhs.vertices.size()
-               << ", faces:" << rhs.faces.size()
-               << ">"
-               ;
-       return os;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// IO
-///////////////////////////////////////////////////////////////////////////////
-struct IO
-{
-       Scene scene;
-       std::vector<Material> materials;
-       std::vector<Object> objects;
-
-       bool read(binary::IReader &reader);
-       bool read(const char *path);
-#ifdef _WIN32
-       bool read(const wchar_t *path);
-#endif
-       bool write(binary::IWriter &writer);
-       bool write(const char *path);
-};
-
-} // namespace mqo
+  namespace mqo {
+
+    //! Scene\83`\83\83\83\93\83N
+    struct Scene
+    {
+      Vector3 pos;
+      Vector3 lookat;
+      float head;
+      float pitch;
+      int ortho;
+      float zoom2;
+      Vector3 ambient;
+      Scene()
+        : head(0), pitch(0), ortho(false), zoom2(2)
+      {}
+    };
+    inline std::ostream &operator<<(std::ostream &os, const Scene &rhs)
+    {
+      os
+        << "<Scene"
+        << " pos: " << rhs.pos
+        << ", lookat: " << rhs.lookat
+        << ", head: " << rhs.head
+        << ", pitch: " << rhs.pitch
+        << ", ortho: " << rhs.ortho
+        << ", zoom2: " << rhs.zoom2
+        << ", ambient: " << rhs.ambient
+        << ">"
+        ;
+      return os;
+    }
+
+    //! Material\83`\83\83\83\93\83N
+    struct Material
+    {
+      std::string name;
+      int shader;
+      fRGBA color;
+      float diffuse;
+      float ambient;
+      float emit;
+      float specular;
+      float power;
+      std::string texture;
+      std::string alphamap;
+      std::string bumpmap;
+      int vcol;
+
+      Material()
+        : shader(0), diffuse(1), ambient(0), emit(0), specular(0), power(0),
+        vcol(0)
+      {}
+    };
+    inline std::ostream &operator<<(std::ostream &os, const Material &rhs)
+    {
+      os
+        << "<Material "
+        << '"' << rhs.name << '"'
+        << " shader:" << rhs.shader
+        << ", color:" << rhs.color
+        << ", diffuse:" << rhs.diffuse
+        << ", ambient:" << rhs.ambient
+        << ", emit:" << rhs.emit
+        << ", specular:" << rhs.specular
+        << ", power:" << rhs.power
+        << ", texture:\"" << rhs.texture << '"'
+        << ", alphamap:\"" << rhs.alphamap << '"'
+        << ", bumpmap:\"" << rhs.bumpmap << '"'
+        << ">"
+        ;
+      return os;
+    }
+
+    //! face\83`\83\83\83\93\83N
+    struct Face
+    {
+      unsigned int index_count;
+      unsigned int indices[4];
+      unsigned int material_index;
+      Vector2 uv[4];
+      fRGBA color[4];
+      Face()
+        : index_count(0), material_index(0)
+      {
+        indices[0]=0;
+        indices[1]=0;
+        indices[2]=0;
+        indices[3]=0;
+        uv[0]=Vector2();
+        uv[1]=Vector2();
+        uv[2]=Vector2();
+        uv[3]=Vector2();
+      }
+    };
+    inline std::ostream &operator<<(std::ostream &os, const Face &rhs)
+    {
+      switch(rhs.index_count)
+      {
+        case 2:
+          os
+            << "<Edge "
+            << "indices:{" << rhs.indices[0] << ',' << rhs.indices[1] << "}"
+            << ", material_index: " << rhs.material_index
+            << ", uv:{" << rhs.uv[0] << ',' << rhs.uv[1] << "}"
+            << ", color:{" << rhs.color[0] << ',' << rhs.color[1] << "}"
+            << ">"
+            ;
+          break;
+
+        case 3:
+          os
+            << "<Triangle "
+            << "indices:{" << rhs.indices[0] 
+            << ',' << rhs.indices[1] 
+            << ',' << rhs.indices[2] << "}"
+            << ", material_index: " << rhs.material_index
+            << ", uv:{" << rhs.uv[0] << ',' << rhs.uv[1] << ',' << rhs.uv[2] << "}"
+            << ", color:{" 
+            << rhs.color[0] << ',' << rhs.color[1] << ',' <<  rhs.color[2] << "}"
+            << ">"
+            ;
+          break;
+
+        case 4:
+          os
+            << "<Rectangle "
+            << "indices:{" << rhs.indices[0] 
+            << ',' << rhs.indices[1] 
+            << ',' << rhs.indices[2] 
+            << ',' << rhs.indices[3] << "}"
+            << ", material_index: " << rhs.material_index
+            << ", uv:{" << rhs.uv[0] << ',' << rhs.uv[1] 
+            << ',' <<  rhs.uv[2] << ',' << rhs.uv[3] << "}"
+            << ", color:{" << rhs.color[0] 
+            << ',' << rhs.color[1] 
+            << ',' <<  rhs.color[2] 
+            << ',' <<  rhs.color[3] << "}"
+            << ">"
+            ;
+          break;
+        default:
+          assert(false);
+      }
+
+      return os;
+    }
+
+    //! Object\83`\83\83\83\93\83N
+    struct Object
+    {
+      std::string name;
+      int depth;
+      int folding;
+      Vector3 scale;
+      Vector3 rotation;
+      Vector3 translation;
+      int visible;
+      int locking;
+      int shading;
+      float smoothing;
+      Vector3 color;
+      int color_type;
+      int mirror;
+
+      std::vector<Vector3> vertices;
+      std::vector<Face> faces;
+
+      Object()
+        : depth(0), folding(0), visible(1), locking(0), shading(0), 
+        smoothing(60.0f), color_type(0), mirror(0)
+      {}
+    };
+    inline std::ostream &operator<<(std::ostream &os, const Object &rhs)
+    {
+      os
+        << "<Object "
+        << '"' << rhs.name << '"'
+        << " vertices:" << rhs.vertices.size()
+        << ", faces:" << rhs.faces.size()
+        << ">"
+        ;
+      return os;
+    }
+
+    // IO
+    struct IO
+    {
+      Scene scene;
+      std::vector<Material> materials;
+      std::vector<Object> objects;
+
+      bool read(binary::IReader &reader);
+      bool read(const char *path);
+      bool write(binary::IWriter &writer);
+      bool write(const char *path);
+    };
+
+  } // namespace mqo
 } // namespace meshio
 
 #endif // MESH_IO_MQO_H_INCLUDED
index c74707e..cc0459f 100755 (executable)
 #include "pmd.h"
-#include <iostream>
 #include "text.h"
 #ifndef _WIN32
 #include "win32.h"
 #endif
+#include <iostream>
 
 
 namespace meshio {
-namespace pmd {
-
-// IO
-bool IO::write(const char *path)
-{
-       binary::FileWriter w(path);
-       return write(w);
-}
-
-#ifdef _WIN32
-bool IO::write(const wchar_t *path)
-{
-       binary::FileWriter w(path);
-       return write(w);
-}
-#endif
-
-std::wstring 
-IO::getName()const
-{
-       return text::trim(text::cp932_to_unicode(
-                std::string(name, name+20)));
-}
-
-std::wstring 
-IO::getComment()const
-{
-       return text::trim(text::cp932_to_unicode(
-                std::string(comment, comment+256)));
-}
-
-std::wstring 
-IO::getEnglishName()const
-{
-       return text::trim(text::cp932_to_unicode(
-                std::string(english_name, english_name+20)));
-}
-
-std::wstring 
-IO::getEnglishComment()const
-{
-       return text::trim(text::cp932_to_unicode(
-                               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::cp932_to_unicode(
-                               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::cp932_to_unicode(
-                                       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::cp932_to_unicode(
-                                       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::cp932_to_unicode(
-                                       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::cp932_to_unicode(
-                                       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::cp932_to_unicode(
-                                       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::cp932_to_unicode(
-                                       std::string(name, name+100)));
-       }
-
-void ToonTexture::setName(const char *src)
-{
-       strncpy(name, src, 100);
-}
-
-
-// 38bytes
-template<class READER>
-       void
-       read(READER &reader, Vertex &v)
-       {
-               unsigned int pos=reader.getPos();
-               reader.get(v.pos);
-               reader.get(v.normal);
-               reader.get(v.uv);
-               reader.get(v.bone0);
-               reader.get(v.bone1);
-               reader.get(v.weight0);
-               reader.get(v.edge_flag);
-               assert(reader.getPos()-pos==38);
-       }
-
-
-// 70bytes
-template<class READER>
-       void
-       read(READER &reader, Material &m)
-       {
-               unsigned int pos=reader.getPos();
-               reader.get(m.diffuse);
-               reader.get(m.shinness);
-               reader.get(m.specular);
-               reader.get(m.ambient);
-               reader.get(m.toon_index);
-               reader.get(m.flag);
-               reader.get(m.vertex_count);
-               text::copyStringAndFillZero(m.texture, reader.getString(20));
-               assert(reader.getPos()-pos==70);
-       }
-
-// 39bytes
-template<class READER>
-       void
-       read(READER &reader, Bone &b)
-       {
-               unsigned int pos=reader.getPos();
-               text::copyStringAndFillZero(b.name, reader.getString(20));
-               reader.get(b.parent_index);
-               reader.get(b.tail_index);
-               b.type=static_cast<BONE_TYPE>(reader.getUchar());
-               reader.get(b.ik_index);
-               reader.get(b.pos);
-               assert(reader.getPos()-pos==39);
-       }
-
-// 11+2xIK_COUNT bytes
-template<class READER>
-       void
-       read(READER &reader, IK &ik)
-       {
-               // 11bytes
-               reader.get(ik.index);
-               reader.get(ik.target);
-               reader.get(ik.length);
-               reader.get(ik.iterations);
-               reader.get(ik.weight);
-               // 2 x length bytes
-               for(unsigned short j=0; j<ik.length; ++j){
-                       ik.children.push_back(reader.getUshort());
-               }
-       }
-
-// 25+12xMORPH_COUNT bytes
-template<class READER>
-       void
-       read(READER &reader, Morph &m)
-       {
-               // 25bytes
-               text::copyStringAndFillZero(m.name, reader.getString(20));
-               reader.get(m.vertex_count);
-               m.type=static_cast<MORPH_TYPE>(reader.getUchar());
-               // 12 x vertex_count bytes
-               for(unsigned short i=0; i<m.vertex_count; ++i){
-                       m.indices.push_back(reader.getUint());
-                       m.pos_list.push_back(Vector3());
-                       reader.get(m.pos_list.back());
-               }
-       }
-
-// 83bytes
-template<class READER>
-       void
-       read(READER &reader, RigidBody &r)
-       {
-               unsigned int pos=reader.getPos();
-               text::copyStringAndFillZero(r.name, reader.getString(20));
-               reader.get(r.boneIndex);
-               reader.get(r.group);
-               reader.get(r.target);
-               r.shapeType=static_cast<SHAPE_TYPE>(reader.getUchar());
-               reader.get(r.w);
-               reader.get(r.h);
-               reader.get(r.d);
-               reader.get(r.position);
-               reader.get(r.rotation);
-               reader.get(r.weight);
-               reader.get(r.linearDamping);
-               reader.get(r.angularDamping);
-               reader.get(r.restitution);
-               reader.template get<float>(r.friction);
-               r.processType=static_cast<PROCESS_TYPE>(reader.getUchar());
-               assert(reader.getPos()-pos==83);
-       }
-
-// 124bytes
-template<class READER>
-       void
-       read(READER &reader, Constraint &c)
-       {
-               unsigned int base_pos=reader.getPos();
-               text::copyStringAndFillZero(c.name, reader.getString(20));
-               reader.get(c.rigidA);
-               reader.get(c.rigidB);
-               reader.get(c.pos);
-               reader.get(c.rot);
-               reader.get(c.constraintPosMin);
-               reader.get(c.constraintPosMax);
-               reader.get(c.constraintRotMin);
-               reader.get(c.constraintRotMax);
-               reader.get(c.springPos);
-               reader.get(c.springRot);
-               assert(reader.getPos()-base_pos==124);
-       }
-
-class Impl
-{
-       IO &io_;
-       binary::IReader &reader_;
-
-public:
-       Impl(IO &io, binary::IReader &reader)
-               : io_(io), reader_(reader)
-               {}
-
-       bool parse()
-       {
-               if(!parseHeader()){
-                       return false;
-               }
-               if(!parseVertices()){
-                       return false;
-               }
-               if(!parseIndices()){
-                       return false;
-               }
-               if(!parseMaterials()){
-                       return false;
-               }
-               if(!parseBones()){
-                       return false;
-               }
-               if(!parseIK()){
-                       return false;
-               }
-               if(!parseMorph()){
-                       return false;
-               }
-               if(!parseFaceList()){
-                       return false;
-               }
-               if(!parseBoneGroupList()){
-                       return false;
-               }
-               if(!parseBoneList()){
-                       return false;
-               }
-               if(reader_.isEnd()){
-                       return true;
-               }
-
-               ////////////////////////////////////////////////////////////
-               // extended data
-               ////////////////////////////////////////////////////////////
-               // english
-               ////////////////////////////////////////////////////////////
-               if(reader_.getChar()){
-                       if(!parseEnglishName()){
-                               return false;
-                       }
-                       if(!parseEnglishBone()){
-                               return false;
-                       }
-                       if(!parseEnglishMorph()){
-                               return false;
-                       }
-                       if(!parseEnglishBoneList()){
-                               return false;
-                       }
-               }
-               if(reader_.isEnd()){
-                       return true;
-               }
-
-               // toone texture
-               ////////////////////////////////////////////////////////////
-               if(!parseToonTextures()){
-                       return false;
-               }
-               if(reader_.isEnd()){
-                       return true;
-               }
-
-               // physics
-               ////////////////////////////////////////////////////////////
-               if(!parseRigid()){
-                       return false;
-               }
-               if(!parseConstraint()){
-                       return false;
-               }
-
-               // end
-               assert(reader_.isEnd());
-
-               return true;
-       }
-
-private:
-       bool parseConstraint()
-       {
-               unsigned int count=reader_.getUint();
-               for(unsigned int i=0; i<count; ++i){
-                       io_.constraints.push_back(Constraint());
-                       read(reader_, io_.constraints.back());
-               }
-               return true;
-       }
-
-       bool parseRigid()
-       {
-               unsigned int count=reader_.getUint();
-               for(unsigned int i=0; i<count; ++i){
-                       io_.rigidbodies.push_back(RigidBody());
-                       read(reader_, io_.rigidbodies.back());
-               }
-               return true;
-       }
-
-       bool parseToonTextures()
-       {
-               for(size_t i=0; i<10; ++i){
-                       text::copyStringAndFillZero(
-                                       io_.toon_textures[i].name,
-                                       reader_.getString(100));
-               }
-               return true;
-       }
-
-       bool parseEnglishBoneList()
-       {
-               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;
-       }
-
-       bool parseEnglishMorph()
-       {
-               int count=io_.morph_list.size()-1;
-               for(int i=0; i<count; ++i){
-                       text::copyStringAndFillZero(
-                                       io_.morph_list[i].english_name, reader_.getString(20));
-               }
-               return true;
-       }
-
-       bool parseEnglishBone()
-       {
-               for(size_t i=0; i<io_.bones.size(); ++i){
-                       text::copyStringAndFillZero(
-                                       io_.bones[i].english_name, reader_.getString(20));
-               }
-               return true;
-       }
-
-       bool parseEnglishName()
-       {
-               text::copyStringAndFillZero(io_.english_name, 
-                               reader_.getString(20));
-               text::copyStringAndFillZero(io_.english_comment, 
-                               reader_.getString(256));
-               return true;
-       }
-
-       bool parseBoneList()
-       {
-               unsigned int count=reader_.getUint();
-               for(unsigned int i=0; i<count; ++i){
-                       unsigned short bone=reader_.getUshort();
-                       unsigned char disp=reader_.getUchar();
-                       io_.bone_display_list.push_back(std::make_pair(bone, disp));
-               }
-               return true;
-       }
-
-       bool parseBoneGroupList()
-       {
-               unsigned int count=reader_.getUchar();
-               for(unsigned int i=0; i<count; ++i){
-                       io_.bone_group_list.push_back(BoneGroup());
-                       text::copyStringAndFillZero(
-                                       io_.bone_group_list.back().name,
-                                       reader_.getString(50));
-               }
-               return true;
-       }
-
-       bool parseFaceList()
-       {
-               unsigned int count=reader_.getUchar();
-               for(unsigned int i=0; i<count; ++i){
-                       io_.face_list.push_back(reader_.getUshort());
-               }
-               return true;
-       }
-
-       bool parseMorph()
-       {
-               unsigned int count=reader_.getUshort();
-               for(unsigned int i=0; i<count; ++i){
-                       io_.morph_list.push_back(Morph());
-                       read(reader_, io_.morph_list.back());
-               }
-               return true;
-       }
-
-       bool parseIK()
-       {
-               unsigned int count=reader_.getUshort();
-               for(unsigned int i=0; i<count; ++i){
-                       io_.ik_list.push_back(IK());
-                       read(reader_, io_.ik_list.back());
-               }
-               return true;
-       }
-
-       bool parseBones()
-       {
-               unsigned int count=reader_.getUshort();
-               for(unsigned int i=0; i<count; ++i){
-                       io_.bones.push_back(Bone());
-                       read(reader_, io_.bones.back());
-               }
-               return true;
-       }
-
-       bool parseMaterials()
-       {
-               unsigned int count=reader_.getUint();
-               for(unsigned int i=0; i<count; ++i){
-                       io_.materials.push_back(new Material());
-                       read(reader_, *io_.materials.back());
-               }
-               return true;
-       }
-
-       bool parseIndices()
-       {
-               unsigned int count=reader_.getUint();
-               for(unsigned int i=0; i<count; ++i){
-                       io_.indices.push_back(reader_.getUshort());
-               }
-               return true;
-       }
-
-       bool parseVertices()
-       {
-               unsigned int count=reader_.getUint();
-               for(unsigned int i=0; i<count; ++i){
-                       io_.vertices.push_back(Vertex());
-                       read(reader_, io_.vertices.back());
-               }
-               return true;
-       }
-
-       bool parseHeader()
-       {
-               if(reader_.getString(3)!="Pmd"){
-                       //std::cout << "invalid pmd" << std::endl;
-                       return false;
-               }
-               reader_.get(io_.version);
-               if(io_.version!=1.0){
-                       std::cout << "invalid vesion: " << io_.version <<std::endl;
-                       return false;
-               }
-               text::copyStringAndFillZero(io_.name, reader_.getString(20));
-               text::copyStringAndFillZero(io_.comment, reader_.getString(256));
-
-               return true;
-       }
-
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// IO
-///////////////////////////////////////////////////////////////////////////////
-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);
-       if(!impl.parse()){
-               return false;
-       }
-
-       ////////////////////////////////////////////////////////////
-       // post process
-       ////////////////////////////////////////////////////////////
-       if(!morph_list.empty()){
-               // validate morph
-               assert(morph_list[0].type==MORPH_BASE);
-               // check base
-               Morph &base=morph_list[0];
-               for(size_t i=0; i<base.vertex_count; ++i){
-                       assert(vertices[base.indices[i]].pos==base.pos_list[i]);
-               }
-               // check each face
-               for(size_t i=1; i<morph_list.size(); ++i){
-                       Morph &m=morph_list[i];
-                       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::vector<char> all;
-       binary::readAll(path, all);
-       if(all.empty()){
-               return false;
-       }
-       binary::MemoryReader reader(&all[0], all.size());
-       return read(reader);
-}
-
-#ifdef _WIN32
-bool IO::read(const wchar_t *path)
-{
-       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);
-}
-#endif
-
-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
+  namespace pmd {
+
+    // IO
+    bool IO::write(const char *path)
+    {
+      binary::FileWriter w(path);
+      return write(w);
+    }
+
+    // 38bytes
+    template<class READER>
+      void
+      read(READER &reader, Vertex &v)
+      {
+        unsigned int pos=reader.getPos();
+        reader.get(v.pos);
+        reader.get(v.normal);
+        reader.get(v.uv);
+        reader.get(v.bone0);
+        reader.get(v.bone1);
+        reader.get(v.weight0);
+        reader.get(v.edge_flag);
+        assert(reader.getPos()-pos==38);
+      }
+
+    // 70bytes
+    template<class READER>
+      void
+      read(READER &reader, Material &m)
+      {
+        unsigned int pos=reader.getPos();
+        reader.get(m.diffuse);
+        reader.get(m.shinness);
+        reader.get(m.specular);
+        reader.get(m.ambient);
+        reader.get(m.toon_index);
+        reader.get(m.flag);
+        reader.get(m.vertex_count);
+        reader.get(m.texture);
+        assert(reader.getPos()-pos==70);
+      }
+
+    // 39bytes
+    template<class READER>
+      void
+      read(READER &reader, Bone &b)
+      {
+        unsigned int pos=reader.getPos();
+        reader.get(b.name);
+        reader.get(b.parent_index);
+        reader.get(b.tail_index);
+        b.type=static_cast<BONE_TYPE>(reader.getUchar());
+        reader.get(b.ik_index);
+        reader.get(b.pos);
+        assert(reader.getPos()-pos==39);
+      }
+
+    // 11+2xIK_COUNT bytes
+    template<class READER>
+      void
+      read(READER &reader, IK &ik)
+      {
+        // 11bytes
+        reader.get(ik.index);
+        reader.get(ik.target);
+        reader.get(ik.length);
+        reader.get(ik.iterations);
+        reader.get(ik.weight);
+        // 2 x length bytes
+        for(unsigned short j=0; j<ik.length; ++j){
+          ik.children.push_back(reader.getUshort());
+        }
+      }
+
+    // 25+12xMORPH_COUNT bytes
+    template<class READER>
+      void
+      read(READER &reader, Morph &m)
+      {
+        // 25bytes
+        reader.get(m.name);
+        reader.get(m.vertex_count);
+        m.type=static_cast<MORPH_TYPE>(reader.getUchar());
+        // 12 x vertex_count bytes
+        for(unsigned short i=0; i<m.vertex_count; ++i){
+          m.indices.push_back(reader.getUint());
+          m.pos_list.push_back(Vector3());
+          reader.get(m.pos_list.back());
+        }
+      }
+
+    // 83bytes
+    template<class READER>
+      void
+      read(READER &reader, RigidBody &r)
+      {
+        unsigned int pos=reader.getPos();
+        reader.get(r.name);
+        reader.get(r.boneIndex);
+        reader.get(r.group);
+        reader.get(r.target);
+        r.shapeType=static_cast<SHAPE_TYPE>(reader.getUchar());
+        reader.get(r.w);
+        reader.get(r.h);
+        reader.get(r.d);
+        reader.get(r.position);
+        reader.get(r.rotation);
+        reader.get(r.weight);
+        reader.get(r.linearDamping);
+        reader.get(r.angularDamping);
+        reader.get(r.restitution);
+        reader.template get<float>(r.friction);
+        r.processType=static_cast<PROCESS_TYPE>(reader.getUchar());
+        assert(reader.getPos()-pos==83);
+      }
+
+    // 124bytes
+    template<class READER>
+      void
+      read(READER &reader, Constraint &c)
+      {
+        unsigned int base_pos=reader.getPos();
+        reader.get(c.name);
+        reader.get(c.rigidA);
+        reader.get(c.rigidB);
+        reader.get(c.pos);
+        reader.get(c.rot);
+        reader.get(c.constraintPosMin);
+        reader.get(c.constraintPosMax);
+        reader.get(c.constraintRotMin);
+        reader.get(c.constraintRotMax);
+        reader.get(c.springPos);
+        reader.get(c.springRot);
+        assert(reader.getPos()-base_pos==124);
+      }
+
+    class Impl
+    {
+      IO &io_;
+      binary::IReader &reader_;
+
+    public:
+      Impl(IO &io, binary::IReader &reader)
+        : io_(io), reader_(reader)
+      {}
+
+      bool parse()
+      {
+        if(!parseHeader()){
+          return false;
+        }
+        if(!parseVertices()){
+          return false;
+        }
+        if(!parseIndices()){
+          return false;
+        }
+        if(!parseMaterials()){
+          return false;
+        }
+        if(!parseBones()){
+          return false;
+        }
+        if(!parseIK()){
+          return false;
+        }
+        if(!parseMorph()){
+          return false;
+        }
+        if(!parseFaceList()){
+          return false;
+        }
+        if(!parseBoneGroupList()){
+          return false;
+        }
+        if(!parseBoneList()){
+          return false;
+        }
+        if(reader_.isEnd()){
+          return true;
+        }
+
+        ////////////////////////////////////////////////////////////
+        // extended data
+        ////////////////////////////////////////////////////////////
+        // english
+        ////////////////////////////////////////////////////////////
+        if(reader_.getChar()){
+          if(!parseEnglishName()){
+            return false;
+          }
+          if(!parseEnglishBone()){
+            return false;
+          }
+          if(!parseEnglishMorph()){
+            return false;
+          }
+          if(!parseEnglishBoneList()){
+            return false;
+          }
+        }
+        if(reader_.isEnd()){
+          return true;
+        }
+
+        // toone texture
+        ////////////////////////////////////////////////////////////
+        if(!parseToonTextures()){
+          return false;
+        }
+        if(reader_.isEnd()){
+          return true;
+        }
+
+        // physics
+        ////////////////////////////////////////////////////////////
+        if(!parseRigid()){
+          return false;
+        }
+        if(!parseConstraint()){
+          return false;
+        }
+
+        // end
+        assert(reader_.isEnd());
+
+        return true;
+      }
+
+    private:
+      bool parseConstraint()
+      {
+        unsigned int count=reader_.getUint();
+        for(unsigned int i=0; i<count; ++i){
+          io_.constraints.push_back(Constraint());
+          read(reader_, io_.constraints.back());
+        }
+        return true;
+      }
+
+      bool parseRigid()
+      {
+        unsigned int count=reader_.getUint();
+        for(unsigned int i=0; i<count; ++i){
+          io_.rigidbodies.push_back(RigidBody());
+          read(reader_, io_.rigidbodies.back());
+        }
+        return true;
+      }
+
+      bool parseToonTextures()
+      {
+        for(size_t i=0; i<10; ++i){
+          reader_.get(io_.toon_textures[i]);
+        }
+        return true;
+      }
+
+      bool parseEnglishBoneList()
+      {
+        for(size_t i=0; i<io_.bone_group_list.size(); ++i){
+            reader_.get(io_.bone_group_list[i].english_name);
+        }
+        return true;
+      }
+
+      bool parseEnglishMorph()
+      {
+        int count=io_.morph_list.size()-1;
+        for(int i=0; i<count; ++i){
+          reader_.get(io_.morph_list[i].english_name);
+        }
+        return true;
+      }
+
+      bool parseEnglishBone()
+      {
+        for(size_t i=0; i<io_.bones.size(); ++i){
+          reader_.get(io_.bones[i].english_name);
+        }
+        return true;
+      }
+
+      bool parseEnglishName()
+      {
+        reader_.get(io_.english_name);
+        reader_.get(io_.english_comment);
+        return true;
+      }
+
+      bool parseBoneList()
+      {
+        unsigned int count=reader_.getUint();
+        for(unsigned int i=0; i<count; ++i){
+          unsigned short bone=reader_.getUshort();
+          unsigned char disp=reader_.getUchar();
+          io_.bone_display_list.push_back(std::make_pair(bone, disp));
+        }
+        return true;
+      }
+
+      bool parseBoneGroupList()
+      {
+        unsigned int count=reader_.getUchar();
+        for(unsigned int i=0; i<count; ++i){
+          io_.bone_group_list.push_back(BoneGroup());
+          reader_.get(io_.bone_group_list.back().name);
+        }
+        return true;
+      }
+
+      bool parseFaceList()
+      {
+        unsigned int count=reader_.getUchar();
+        for(unsigned int i=0; i<count; ++i){
+          io_.face_list.push_back(reader_.getUshort());
+        }
+        return true;
+      }
+
+      bool parseMorph()
+      {
+        unsigned int count=reader_.getUshort();
+        for(unsigned int i=0; i<count; ++i){
+          io_.morph_list.push_back(Morph());
+          read(reader_, io_.morph_list.back());
+        }
+        return true;
+      }
+
+      bool parseIK()
+      {
+        unsigned int count=reader_.getUshort();
+        for(unsigned int i=0; i<count; ++i){
+          io_.ik_list.push_back(IK());
+          read(reader_, io_.ik_list.back());
+        }
+        return true;
+      }
+
+      bool parseBones()
+      {
+        unsigned int count=reader_.getUshort();
+        for(unsigned int i=0; i<count; ++i){
+          io_.bones.push_back(Bone());
+          read(reader_, io_.bones.back());
+        }
+        return true;
+      }
+
+      bool parseMaterials()
+      {
+        unsigned int count=reader_.getUint();
+        for(unsigned int i=0; i<count; ++i){
+          io_.materials.push_back(Material());
+          read(reader_, io_.materials.back());
+        }
+        return true;
+      }
+
+      bool parseIndices()
+      {
+        unsigned int count=reader_.getUint();
+        for(unsigned int i=0; i<count; ++i){
+          io_.indices.push_back(reader_.getUshort());
+        }
+        return true;
+      }
+
+      bool parseVertices()
+      {
+        unsigned int count=reader_.getUint();
+        for(unsigned int i=0; i<count; ++i){
+          io_.vertices.push_back(Vertex());
+          read(reader_, io_.vertices.back());
+        }
+        return true;
+      }
+
+      bool parseHeader()
+      {
+        if(reader_.getString(3)!="Pmd"){
+          //std::cout << "invalid pmd" << std::endl;
+          return false;
+        }
+        reader_.get(io_.version);
+        if(io_.version!=1.0){
+          std::cout << "invalid vesion: " << io_.version <<std::endl;
+          return false;
+        }
+        reader_.get(io_.name);
+        reader_.get(io_.comment);
+        return true;
+      }
+
+    };
+
+    // IO
+    IO::IO()
+      : version(0)
+    {
+        int i=1;
+        for(auto it=toon_textures.begin(); it!=toon_textures.end(); ++it){
+            char toon[100];
+            sprintf(toon, "toon%02d.bmp", i);
+            *it=toon;
+        }
+    }
+
+    bool IO::read(binary::IReader &input)
+    {
+      Impl impl(*this, input);
+      if(!impl.parse()){
+        return false;
+      }
+
+      ////////////////////////////////////////////////////////////
+      // post process
+      ////////////////////////////////////////////////////////////
+      if(!morph_list.empty()){
+        // validate morph
+        assert(morph_list[0].type==MORPH_BASE);
+        // check base
+        Morph &base=morph_list[0];
+        for(size_t i=0; i<base.vertex_count; ++i){
+          assert(vertices[base.indices[i]].pos==base.pos_list[i]);
+        }
+        // check each face
+        for(size_t i=1; i<morph_list.size(); ++i){
+          Morph &m=morph_list[i];
+          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::vector<char> all;
+      binary::readAll(path, all);
+      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);
+      w.write(comment);
+
+      // 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.write(m.texture);
+      }
+
+      // 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.write(b.name);
+        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.write(m.name);
+        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.write(bone_group_list[i].name);
+      }
+
+      // 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.write(english_name);
+      w.write(english_comment);
+
+      for(size_t i=0; i<bones.size(); ++i){
+        w.write(bones[i].english_name);
+      }
+
+      // skip base
+      for(size_t i=1; i<morph_list.size(); ++i){
+        w.write(morph_list[i].english_name);
+      }
+
+      for(size_t i=0; i<bone_group_list.size(); ++i){
+        w.write(bone_group_list[i].english_name);
+      }
+
+      ////////////////////////////////////////////////////////////
+      // toon textures
+      ////////////////////////////////////////////////////////////
+      for(size_t i=0; i<10; ++i){
+        w.write(toon_textures[i]);
+      }
+
+      ////////////////////////////////////////////////////////////
+      // rigid bodies
+      ////////////////////////////////////////////////////////////
+      w.writeValue<DWORD>(rigidbodies.size());
+      for(size_t i=0; i<rigidbodies.size(); ++i){
+        RigidBody &rb=rigidbodies[i];
+        w.write(rb.name);
+        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.write(c.name);
+        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 pmd
+} // namespace meshio
 
index e1e25f9..3a41a19 100644 (file)
--- a/src/pmd.h
+++ b/src/pmd.h
 #ifndef MESH_IO_PMD_H_INCLUDED
 #define MESH_IO_PMD_H_INCLUDED 
 
-#include <ostream>
-#include <vector>
 #include "la.h"
 #include "text.h"
+#include "binary.h"
+#include <ostream>
+#include <vector>
+#include <array>
 
 namespace meshio {
-namespace pmd {
-
-typedef ::meshio::la::Vector2 Vector2;
-typedef ::meshio::la::Vector3 Vector3;
-typedef ::meshio::la::Vector4 Vector4;
-typedef ::meshio::color::fRGBA fRGBA;
-typedef ::meshio::color::fRGB fRGB;
-
-////////////////////////////////////////////////////////////
-//! \92¸\93_
-////////////////////////////////////////////////////////////
-struct Vertex
-{
-       //! \8dÀ\95W
-       Vector3 pos;
-       //! \96@\90ü\83x\83N\83g\83\8b
-       Vector3 normal;
-       //! \83e\83N\83X\83`\83\83UV
-       Vector2 uv;
-       //! \83u\83\8c\83\93\83f\83B\83\93\83O\83{\81[\83\931
-       unsigned short bone0;
-       //! \83u\83\8c\83\93\83f\83B\83\93\83O\83{\81[\83\932
-       unsigned short bone1;
-       //! \83E\83F\83C\83g[0 - 100]
-       unsigned char weight0;
-       //! \94ñ\83G\83b\83W
-       unsigned char edge_flag;
-};
-inline std::ostream &operator<<(std::ostream &os, const Vertex &rhs)
-{
-       os
-               << "[Vertex"
-               << " pos:" << rhs.pos
-               << " normal:" << rhs.normal
-               << " uv:" << rhs.uv
-               << " bone0:" << rhs.bone0
-               << " bone1:" << rhs.bone1
-               << " weight0:" << (int)rhs.weight0
-               << " edge_flag:" << (int)rhs.edge_flag
-               << "]"
-               ;
-       return os;
-}
-
-////////////////////////////////////////////////////////////
-//! \8dÞ\8e¿
-////////////////////////////////////////////////////////////
-struct Material
-{
-       //! Diffuse
-       fRGBA diffuse;
-       //! Shinness
-       float shinness;
-       //! Specular
-       fRGB specular;
-       //! Ambient
-       fRGB ambient;
-       //! \83g\83D\81[\83\93\83e\83N\83X\83`\83\83
-       unsigned char toon_index;
-       //! \97Ö\8as/\89e
-       unsigned char flag;
-       //! \96Ê\92¸\93_\90\94
-       unsigned int vertex_count;
-       //! \83e\83N\83X\83`\83\83
-       char texture[20];
-
-       std::wstring getTexture()const;
-       void setTexture(const char *src);
-};
-inline std::ostream &operator<<(std::ostream &os,
-               const Material &rhs)
-{
-       os
-               << "[Material"
-               << " diffuse:" << rhs.diffuse
-               << " toon_index:" << (int)rhs.toon_index
-               << " flag:" << (int)rhs.flag
-               << " vertex_count:" << rhs.vertex_count
-               << " texture:" << rhs.texture
-               << "]"
-               ;
-       return os;
-}
-
-////////////////////////////////////////////////////////////
-//! \83{\81[\83\93 
-////////////////////////////////////////////////////////////
-//! \83{\81[\83\93\82Ì\8eí\97Þ
-enum BONE_TYPE
-{
-       // \89ñ\93]
-       BONE_ROTATE=0,
-       // \89ñ\93]\82Æ\88Ú\93®
-       BONE_ROTATE_MOVE,
-       // IK
-       BONE_IK,
-       // \95s\96¾
-       BONE_UNKNOWN,
-       // IK\89e\8b¿\89º
-       BONE_IK_INFLUENCED,
-       // \89ñ\93]\89e\8b¿\89º
-       BONE_ROTATE_INFLUENCED,
-       // IK\90Ú\91±\90æ
-       BONE_IK_CONNECT,
-       // \94ñ\95\\8e¦
-       BONE_INVISIBLE,
-       // \94P\82è
-       BONE_TWIST,
-       // \89ñ\93]\98A\93®
-       BONE_REVOLVE,
-};
-struct Bone
-{
-       //! \96¼\91O
-       char name[20];
-       //! \90e\83{\81[\83\93
-       unsigned short parent_index;
-       //! \8eq\83{\81[\83\93
-       unsigned short tail_index;
-       //! \83{\81[\83\93\8eí\97Þ
-       BONE_TYPE type;
-       //! \89e\8b¿IK\83{\81[\83\93
-       unsigned short ik_index;
-       // \83{\81[\83\93\8dÀ\95W
-       Vector3 pos;
-       //! \89p\8cê\96¼
-       char english_name[20];
-       //! \83{\81[\83\93\8aK\91w\8d\\92z\97p
-       Bone* parent;
-       Vector3 tail;
-       std::vector<Bone*> children;
-       unsigned short index;
-
-       Bone()
-               : parent(0)
-               {}
-       std::wstring getName()const;
-       void setName(const char *src);
-       void setEnglishName(const char *src);
-};
-inline std::ostream &operator<<(std::ostream &os,
-               const Bone &rhs)
-{
-       os
-               << "[Bone "
-               << '"' << rhs.name << '"'
-               << "]"
-               ;
-       return os;
-}
-
-////////////////////////////////////////////////////////////
-//! IK
-////////////////////////////////////////////////////////////
-struct IK
-{
-       //! IK(IK\83^\81[\83Q\83b\83g)
-       unsigned short index;
-       //! Target(\83G\83t\83F\83N\83^\81[)
-       unsigned short target;
-       //! \83G\83t\83F\83N\83^\82É\98A\93®\82·\82é\83{\81[\83\93\90\94
-       unsigned char length;
-       //! IK\92l1\81BCCD-IK\8e\8e\8ds\89ñ\90\94
-       unsigned short iterations;
-       //! IK\92l2\81BCCD-IK\8e\8e\8ds\88ê\89ñ\95Ó\82è\82Ì\89e\8b¿\93x
-       float weight;
-       //! \83G\83t\83F\83N\83^\82É\98A\93®\82·\82é\83{\81[\83\93(\8aî\96{\93I\82É\90e\83{\81[\83\93\82É\91k\82é)
-       std::vector<unsigned short> children;
-};
-inline std::ostream &operator<<(std::ostream &os, const IK &rhs)
-{
-       os
-               << "[IK "
-               << "]"
-               ;
-       return os;
-}
-
-////////////////////////////////////////////////////////////
-//! \95\\8fî
-////////////////////////////////////////////////////////////
-//! \95\\8fî\82Ì\8eí\97Þ
-enum MORPH_TYPE
-{
-       //! \83x\81[\83X\95\\8fî
-       MORPH_BASE=0,
-       //! \82Ü\82ä
-       MORPH_MAYU,
-       //! \96Ú
-       MORPH_ME,
-       //! \83\8a\83b\83v
-       MORPH_LIP,
-       //! \82»\82Ì\91¼
-       MORPH_OTHER,
-};
-struct Morph
-{
-       //! \95\\8fî\96¼
-       char name[20];
-       //! \8eg\97p\82·\82é\92¸\93_\90\94
-       unsigned int vertex_count;
-       //! \95ª\97Þ
-       unsigned char type;
-       //! \92¸\93_Index
-       std::vector<unsigned int> indices;
-       //! \88Ú\93®\97Ê
-       std::vector<Vector3> pos_list;
-       //! \89p\8cê\96¼
-       char english_name[20];
-
-       void append(int index, float x, float y, float z);
-       std::wstring getName()const;
-       void setName(const char *src);
-       void setEnglishName(const char *src);
-};
-inline std::ostream &operator<<(std::ostream &os, const Morph &rhs)
-{
-       os
-               << "[Morph "
-               << '"' << rhs.name << '"'
-               << "]"
-               ;
-       return os;
-}
-
-////////////////////////////////////////////////////////////
-//! \83{\81[\83\93\95\\8e¦\98g
-////////////////////////////////////////////////////////////
-struct BoneGroup
-{
-       char name[50];
-       char english_name[50];
-
-       void setName(const char *src);
-       void setEnglishName(const char *src);
-       std::wstring getName()const;
-};
-
-////////////////////////////////////////////////////////////
-//! \83g\83D\81[\83\93\83e\83N\83X\83`\83\83
-////////////////////////////////////////////////////////////
-struct ToonTexture
-{
-       char name[100];
-       std::wstring getName()const;
-       void setName(const char *src);
-};
-
-////////////////////////////////////////////////////////////
-//! \8d\84\91Ì
-////////////////////////////////////////////////////////////
-//! \8c`\8fó
-enum SHAPE_TYPE
-{
-       //! \8b\85
-       SHAPE_SPHERE=0,
-       //! \94 
-       SHAPE_BOX,
-       //! \83J\83v\83Z\83\8b
-       SHAPE_CAPSULE,
-};
-//! \8d\84\91Ì\83^\83C\83v
-enum PROCESS_TYPE
-{
-       //! \83{\81[\83\93\82Æ\93¯\82\93®\82«
-       RIGIDBODY_KINEMATICS=0,
-       //! \95¨\97\9d\89\89\8eZ
-       RIGIDBODY_PHYSICS,
-       //! \95¨\97\9d\89\89\8eZ\8c\8b\89Ê\82ð\83{\81[\83\93\82É\94½\89f\82·\82é
-       RIGIDBODY_PHYSICS_WITH_BONE,
-};
-
-struct RigidBody
-{
-       //! \8d\84\91Ì\96¼
-       char name[20];
-       //! \8aÖ\98A\83{\81[\83\93(\83{\81[\83\93\92Ç\8f]\82Æ\83{\81[\83\93\88Ê\92u\8d\87\82í\82¹\82Å\95K\97v)
-       unsigned short boneIndex;
-       //! \83O\83\8b\81[\83v
-       unsigned char group;
-       //! \94ñ\8fÕ\93Ë\83O\83\8b\81[\83v
-       unsigned short target;
-       //! \8c`\8fó
-       SHAPE_TYPE shapeType;
-       //! \83T\83C\83Y
-       float w;
-       float h;
-       float d;
-       //! \8ep\90¨
-       Vector3 position;
-       Vector3 rotation;
-       //! \8e¿\97Ê
-       float weight;
-       //! \95¨\97\9d\89\89\8eZ\83p\83\89\83\81\81[\83^(bullet)
-       float linearDamping;
-       float angularDamping;
-       float restitution;
-       float friction;
-       //! \8d\84\91Ì\83^\83C\83v
-       PROCESS_TYPE processType;
-
-       std::wstring getName()const;
-       void setName(const char *src);
-};
-
-//! Joint(\95¨\97\9d\89\89\8eZ\82Å\82ÌJoint\82ÆConstraint\82Í\93¯\82\88Ó\96¡)
-struct Constraint
-{
-       //! Joint\96¼
-       char name[20];
-       //! \90Ú\91±\8d\84\91ÌA
-       unsigned int rigidA;
-       //! \90Ú\91±\8d\84\91ÌB
-       unsigned int rigidB;
-       //! \88Ê\92u
-       Vector3 pos;
-       //! \89ñ\93]
-       Vector3 rot;
-       //! \88Ú\93®\90§\8cÀ
-       Vector3 constraintPosMin;
-       Vector3 constraintPosMax;
-       //! \89ñ\93]\90§\8cÀ
-       Vector3 constraintRotMin;
-       Vector3 constraintRotMax;
-       //! \82Î\82Ë
-       Vector3 springPos;
-       Vector3 springRot;
-
-       std::wstring getName()const;
-       void setName(const char *src);
-};
-
-
-///////////////////////////////////////////////////////////////////////////////
-// IO
-///////////////////////////////////////////////////////////////////////////////
-struct IO
-{
-       float version;
-       char name[20];
-       char comment[256];
-       std::vector<Vertex> vertices;
-       std::vector<unsigned short> indices;
-       std::vector<Material*> materials;
-       std::vector<Bone> bones;
-       std::vector<IK> ik_list;
-       std::vector<Morph> morph_list;
-       std::vector<unsigned short> face_list;
-       std::vector<BoneGroup> bone_group_list;
-       std::vector<std::pair<unsigned short, unsigned char> > bone_display_list;
-       ToonTexture toon_textures[10];
-       std::vector<RigidBody> rigidbodies;
-       std::vector<Constraint> constraints;
-
-       char english_name[20];
-       char english_comment[256];
-
-       IO();
-       ~IO();
-       bool read(const char *path);
-       bool write(const char *path);
-       bool read(binary::IReader &reader);
-       bool write(binary::IWriter &writer);
-#ifdef _WIN32
-       bool read(const wchar_t *path);
-       bool write(const wchar_t *path);
-#endif
-
-       const Vector2* getUV(int index)const;
-       std::wstring getName()const;
-       std::wstring getComment()const;
-       std::wstring getEnglishName()const;
-       std::wstring getEnglishComment()const;
-       void setName(const char *src);
-       void setComment(const char *src);
-       void setEnglishName(const char *src);
-       void setEnglishComment(const char *src);
-};
-inline std::ostream &operator<<(std::ostream &os, const IO &rhs)
-{
-       os
-               << "<PMD " << rhs.name << std::endl
-               << rhs.comment << std::endl
-               << "[vertices] " << rhs.vertices.size() << std::endl
-               << "[indices] " << rhs.indices.size() << std::endl
-               << "[materials] " << rhs.materials.size() << std::endl
-               ;
-       /*
-       std::copy(rhs.materials.begin(), rhs.materials.end(), 
-                       std::ostream_iterator<Material>(os, ""));
-
-       os
-               << "[bones] " << rhs.bones.size() << std::endl
-               ;
-       std::copy(rhs.bones.begin(), rhs.bones.end(), 
-                       std::ostream_iterator<Bone>(os, ""));
-
-       os
-               << "[ik] " << rhs.ik_list.size() << std::endl
-               ;
-       std::copy(rhs.ik_list.begin(), rhs.ik_list.end(), 
-                       std::ostream_iterator<IK>(os, ""));
-
-       os
-               << "[morph] " << rhs.morph_list.size() << std::endl
-               ;
-       std::copy(rhs.morph_list.begin(), rhs.morph_list.end(), 
-                       std::ostream_iterator<Morph>(os, ""));
-                       */
-
-       os
-               << ">" << std::endl
-               ;
-       return os;
-}
-
-
-} // namespace pmd
+  namespace pmd {
+
+    ////////////////////////////////////////////////////////////
+    //! \92¸\93_
+    ////////////////////////////////////////////////////////////
+    struct Vertex
+    {
+      //! \8dÀ\95W
+      Vector3 pos;
+      //! \96@\90ü\83x\83N\83g\83\8b
+      Vector3 normal;
+      //! \83e\83N\83X\83`\83\83UV
+      Vector2 uv;
+      //! \83u\83\8c\83\93\83f\83B\83\93\83O\83{\81[\83\931
+      unsigned short bone0;
+      //! \83u\83\8c\83\93\83f\83B\83\93\83O\83{\81[\83\932
+      unsigned short bone1;
+      //! \83E\83F\83C\83g[0 - 100]
+      unsigned char weight0;
+      //! \94ñ\83G\83b\83W
+      unsigned char edge_flag;
+    };
+    inline std::ostream &operator<<(std::ostream &os, const Vertex &rhs)
+    {
+      os
+        << "[Vertex"
+        << " pos:" << rhs.pos
+        << " normal:" << rhs.normal
+        << " uv:" << rhs.uv
+        << " bone0:" << rhs.bone0
+        << " bone1:" << rhs.bone1
+        << " weight0:" << (int)rhs.weight0
+        << " edge_flag:" << (int)rhs.edge_flag
+        << "]"
+        ;
+      return os;
+    }
+
+    ////////////////////////////////////////////////////////////
+    //! \8dÞ\8e¿
+    ////////////////////////////////////////////////////////////
+    struct Material
+    {
+      //! Diffuse
+      fRGBA diffuse;
+      //! Shinness
+      float shinness;
+      //! Specular
+      fRGB specular;
+      //! Ambient
+      fRGB ambient;
+      //! \83g\83D\81[\83\93\83e\83N\83X\83`\83\83
+      unsigned char toon_index;
+      //! \97Ö\8as/\89e
+      unsigned char flag;
+      //! \96Ê\92¸\93_\90\94
+      unsigned int vertex_count;
+      //! \83e\83N\83X\83`\83\83
+      fixed_string<20> texture;
+    };
+    inline std::ostream &operator<<(std::ostream &os,
+        const Material &rhs)
+    {
+      os
+        << "[Material"
+        << " diffuse:" << rhs.diffuse
+        << " toon_index:" << (int)rhs.toon_index
+        << " flag:" << (int)rhs.flag
+        << " vertex_count:" << rhs.vertex_count
+        << " texture:" << rhs.texture
+        << "]"
+        ;
+      return os;
+    }
+
+    ////////////////////////////////////////////////////////////
+    //! \83{\81[\83\93 
+    ////////////////////////////////////////////////////////////
+    //! \83{\81[\83\93\82Ì\8eí\97Þ
+    enum BONE_TYPE
+    {
+      // \89ñ\93]
+      BONE_ROTATE=0,
+      // \89ñ\93]\82Æ\88Ú\93®
+      BONE_ROTATE_MOVE,
+      // IK
+      BONE_IK,
+      // \95s\96¾
+      BONE_UNKNOWN,
+      // IK\89e\8b¿\89º
+      BONE_IK_INFLUENCED,
+      // \89ñ\93]\89e\8b¿\89º
+      BONE_ROTATE_INFLUENCED,
+      // IK\90Ú\91±\90æ
+      BONE_IK_CONNECT,
+      // \94ñ\95\\8e¦
+      BONE_INVISIBLE,
+      // \94P\82è
+      BONE_TWIST,
+      // \89ñ\93]\98A\93®
+      BONE_REVOLVE,
+    };
+    struct Bone
+    {
+      //! \96¼\91O
+      fixed_string<20> name;
+      //! \90e\83{\81[\83\93
+      unsigned short parent_index;
+      //! \8eq\83{\81[\83\93
+      unsigned short tail_index;
+      //! \83{\81[\83\93\8eí\97Þ
+      BONE_TYPE type;
+      //! \89e\8b¿IK\83{\81[\83\93
+      unsigned short ik_index;
+      // \83{\81[\83\93\8dÀ\95W
+      Vector3 pos;
+      //! \89p\8cê\96¼
+      fixed_string<20> english_name;
+      //! \83{\81[\83\93\8aK\91w\8d\\92z\97p
+      Bone* parent;
+      Vector3 tail;
+      std::vector<Bone*> children;
+      unsigned short index;
+
+      Bone()
+        : parent_index(-1), tail_index(-1), type(BONE_UNKNOWN), ik_index(-1), parent(0), index(-1)
+      {}
+    };
+    inline std::ostream &operator<<(std::ostream &os,
+        const Bone &rhs)
+    {
+      os
+        << "[Bone "
+        << '"' << rhs.name << '"'
+        << "]"
+        ;
+      return os;
+    }
+
+    ////////////////////////////////////////////////////////////
+    //! IK
+    ////////////////////////////////////////////////////////////
+    struct IK
+    {
+      //! IK(IK\83^\81[\83Q\83b\83g)
+      unsigned short index;
+      //! Target(\83G\83t\83F\83N\83^\81[)
+      unsigned short target;
+      //! \83G\83t\83F\83N\83^\82É\98A\93®\82·\82é\83{\81[\83\93\90\94
+      unsigned char length;
+      //! IK\92l1\81BCCD-IK\8e\8e\8ds\89ñ\90\94
+      unsigned short iterations;
+      //! IK\92l2\81BCCD-IK\8e\8e\8ds\88ê\89ñ\95Ó\82è\82Ì\89e\8b¿\93x
+      float weight;
+      //! \83G\83t\83F\83N\83^\82É\98A\93®\82·\82é\83{\81[\83\93(\8aî\96{\93I\82É\90e\83{\81[\83\93\82É\91k\82é)
+      std::vector<unsigned short> children;
+    };
+    inline std::ostream &operator<<(std::ostream &os, const IK &rhs)
+    {
+      os
+        << "[IK "
+        << "]"
+        ;
+      return os;
+    }
+
+    ////////////////////////////////////////////////////////////
+    //! \95\\8fî
+    ////////////////////////////////////////////////////////////
+    //! \95\\8fî\82Ì\8eí\97Þ
+    enum MORPH_TYPE
+    {
+      //! \83x\81[\83X\95\\8fî
+      MORPH_BASE=0,
+      //! \82Ü\82ä
+      MORPH_MAYU,
+      //! \96Ú
+      MORPH_ME,
+      //! \83\8a\83b\83v
+      MORPH_LIP,
+      //! \82»\82Ì\91¼
+      MORPH_OTHER,
+    };
+    struct Morph
+    {
+      //! \95\\8fî\96¼
+      fixed_string<20> name;
+      //! \8eg\97p\82·\82é\92¸\93_\90\94
+      unsigned int vertex_count;
+      //! \95ª\97Þ
+      unsigned char type;
+      //! \92¸\93_Index
+      std::vector<unsigned int> indices;
+      //! \88Ú\93®\97Ê
+      std::vector<Vector3> pos_list;
+      //! \89p\8cê\96¼
+      fixed_string<20> english_name;
+    };
+    inline std::ostream &operator<<(std::ostream &os, const Morph &rhs)
+    {
+      os
+        << "[Morph "
+        << '"' << rhs.name << '"'
+        << "]"
+        ;
+      return os;
+    }
+
+    ////////////////////////////////////////////////////////////
+    //! \83{\81[\83\93\95\\8e¦\98g
+    ////////////////////////////////////////////////////////////
+    struct BoneGroup
+    {
+      fixed_string<50> name;
+      fixed_string<50> english_name;
+    };
+
+    ////////////////////////////////////////////////////////////
+    //! \8d\84\91Ì
+    ////////////////////////////////////////////////////////////
+    //! \8c`\8fó
+    enum SHAPE_TYPE
+    {
+      //! \8b\85
+      SHAPE_SPHERE=0,
+      //! \94 
+      SHAPE_BOX,
+      //! \83J\83v\83Z\83\8b
+      SHAPE_CAPSULE,
+    };
+    //! \8d\84\91Ì\83^\83C\83v
+    enum PROCESS_TYPE
+    {
+      //! \83{\81[\83\93\82Æ\93¯\82\93®\82«
+      RIGIDBODY_KINEMATICS=0,
+      //! \95¨\97\9d\89\89\8eZ
+      RIGIDBODY_PHYSICS,
+      //! \95¨\97\9d\89\89\8eZ\8c\8b\89Ê\82ð\83{\81[\83\93\82É\94½\89f\82·\82é
+      RIGIDBODY_PHYSICS_WITH_BONE,
+    };
+
+    struct RigidBody
+    {
+      //! \8d\84\91Ì\96¼
+      fixed_string<20> name;
+      //! \8aÖ\98A\83{\81[\83\93(\83{\81[\83\93\92Ç\8f]\82Æ\83{\81[\83\93\88Ê\92u\8d\87\82í\82¹\82Å\95K\97v)
+      unsigned short boneIndex;
+      //! \83O\83\8b\81[\83v
+      unsigned char group;
+      //! \94ñ\8fÕ\93Ë\83O\83\8b\81[\83v
+      unsigned short target;
+      //! \8c`\8fó
+      SHAPE_TYPE shapeType;
+      //! \83T\83C\83Y
+      float w;
+      float h;
+      float d;
+      //! \8ep\90¨
+      Vector3 position;
+      Vector3 rotation;
+      //! \8e¿\97Ê
+      float weight;
+      //! \95¨\97\9d\89\89\8eZ\83p\83\89\83\81\81[\83^(bullet)
+      float linearDamping;
+      float angularDamping;
+      float restitution;
+      float friction;
+      //! \8d\84\91Ì\83^\83C\83v
+      PROCESS_TYPE processType;
+    };
+
+    //! Joint(\95¨\97\9d\89\89\8eZ\82Å\82ÌJoint\82ÆConstraint\82Í\93¯\82\88Ó\96¡)
+    struct Constraint
+    {
+      //! Joint\96¼
+      fixed_string<20> name;
+      //! \90Ú\91±\8d\84\91ÌA
+      unsigned int rigidA;
+      //! \90Ú\91±\8d\84\91ÌB
+      unsigned int rigidB;
+      //! \88Ê\92u
+      Vector3 pos;
+      //! \89ñ\93]
+      Vector3 rot;
+      //! \88Ú\93®\90§\8cÀ
+      Vector3 constraintPosMin;
+      Vector3 constraintPosMax;
+      //! \89ñ\93]\90§\8cÀ
+      Vector3 constraintRotMin;
+      Vector3 constraintRotMax;
+      //! \82Î\82Ë
+      Vector3 springPos;
+      Vector3 springRot;
+    };
+
+
+    // IO
+    struct IO
+    {
+      float version;
+      fixed_string<20> name;
+      fixed_string<256> comment;
+      std::vector<Vertex> vertices;
+      std::vector<unsigned short> indices;
+      std::vector<Material> materials;
+      std::vector<Bone> bones;
+      std::vector<IK> ik_list;
+      std::vector<Morph> morph_list;
+      std::vector<unsigned short> face_list;
+      std::vector<BoneGroup> bone_group_list;
+      std::vector<std::pair<unsigned short, unsigned char> > bone_display_list;
+      std::array<fixed_string<100>, 10> toon_textures;
+      std::vector<RigidBody> rigidbodies;
+      std::vector<Constraint> constraints;
+
+      fixed_string<20> english_name;
+      fixed_string<256> english_comment;
+
+      IO();
+      bool read(const char *path);
+      bool write(const char *path);
+      bool read(binary::IReader &reader);
+      bool write(binary::IWriter &writer);
+    };
+    inline std::ostream &operator<<(std::ostream &os, const IO &rhs)
+    {
+      os
+        << "<PMD " << rhs.name << std::endl
+        << rhs.comment << std::endl
+        << "[vertices] " << rhs.vertices.size() << std::endl
+        << "[indices] " << rhs.indices.size() << std::endl
+        << "[materials] " << rhs.materials.size() << std::endl
+        ;
+      /*
+         std::copy(rhs.materials.begin(), rhs.materials.end(), 
+         std::ostream_iterator<Material>(os, ""));
+
+         os
+         << "[bones] " << rhs.bones.size() << std::endl
+         ;
+         std::copy(rhs.bones.begin(), rhs.bones.end(), 
+         std::ostream_iterator<Bone>(os, ""));
+
+         os
+         << "[ik] " << rhs.ik_list.size() << std::endl
+         ;
+         std::copy(rhs.ik_list.begin(), rhs.ik_list.end(), 
+         std::ostream_iterator<IK>(os, ""));
+
+         os
+         << "[morph] " << rhs.morph_list.size() << std::endl
+         ;
+         std::copy(rhs.morph_list.begin(), rhs.morph_list.end(), 
+         std::ostream_iterator<Morph>(os, ""));
+       */
+
+      os
+        << ">" << std::endl
+        ;
+      return os;
+    }
+
+
+  } // namespace pmd
 } // namespace meshio
 
 #endif // MESH_IO_PMD_H_INCLUDED
diff --git a/src/premake4.lua b/src/premake4.lua
new file mode 100644 (file)
index 0000000..437da6c
--- /dev/null
@@ -0,0 +1,54 @@
+solution "meshio"
+configurations { "Debug", "Release" }
+
+configuration "Debug"
+do
+    targetdir "../debug"
+    flags { "Symbols" }
+    buildoptions { "-g", "-Wall" }
+    defines { "DEBUG" }
+    linkoptions { "-g" }
+end
+
+configuration "Release"
+do
+    targetdir "../release"
+    flags { "Optimize" }
+    defines { "NDEBUG" }
+end
+
+
+-- A project defines one build target
+project "meshio"
+--kind "WindowedApp"
+--kind "ConsoleApp"
+--kind "SharedLib"
+kind "StaticLib"
+
+language "C++"
+files { "*.h", "*.cpp" }
+flags {
+    "StaticRuntime",
+}
+includedirs {
+}
+defines {}
+linkoptions {}
+libdirs {}
+links {}
+
+configuration { "windows", "not gmake" }
+do
+    -- VC
+    buildoptions {
+        "/wd4996",
+    }
+end
+
+configuration { "gmake" }
+do
+    buildoptions {
+        "-std=c++0x",
+    }
+end
+
index 666c8f9..4921d0a 100644 (file)
 #ifndef MESH_IO_TEXT_H_INCLUDED
 #define MESH_IO_TEXT_H_INCLUDED
 
-#include "binary.h"
+//#include "binary.h"
 #include "la.h"
 #include "color.h"
 #include <string>
 #include <iostream>
+#include <vector>
 #include <stdlib.h>
 #include <cstring>
 
-#ifdef _WIN32
+#if defined(_WIN32)
 #include <windows.h>
 #else
 #include <iconv.h>
 #endif
 
 namespace meshio {
-namespace text {
-
-/**
- * \8eQ\8fÆ\83I\83\93\83\8a\81[\82Ì\8aÈ\88Õ\95\8e\9a\97ñ\83N\83\89\83X
- */
-class cstr
-{
-       const char *begin_;
-       const char *end_;
-
-public:
-       cstr()
-               : begin_(0), end_(0)
-               {}
-
-       cstr(const char *begin, const char *end)
-               : begin_(begin), end_(end)
-               { }
-
-       bool operator==(const char *rhs)const
-       {
-               const char *l=begin_;
-               for(const char *r=rhs; *r; ++r, ++l){
-                       if(l==end_){
-                               return false;
-                       }
-                       if(*l!=*r){
-                               return false;
-                       }
-               }
-               return l==end_;
-       }
-
-       bool operator!=(const char *rhs)const
-       {
-               return !(*this==rhs);
-       }
-
-       bool include(char c)const
-       {
-               for(const char *l=begin_; l!=end_; ++l){
-                       if(*l==c){
-                               return true;
-                       }
-               }
-               return false;
-       }
-
-       bool startswith(const char *rhs)
-       {
-               const char *r=rhs;
-               for(const char *l=begin_; l!=end_ && *r!='\0'; ++l, ++r){
-                       if(*l!=*r){
-                               return false;
-                       }
-               }
-               return true;
-       }
-
-       bool empty()const
-       {
-               return begin_==end_;
-       }
-
-       std::string str()const{ return std::string(begin_, end_); }
-       const char* begin()const{ return begin_; }
-       const char* end()const{ return end_; }
-       std::pair<const char*, const char*> range()const{ 
-               return std::make_pair(begin_, end_); 
-       }
-
-       template<typename IsTrim>
-               cstr &trim(IsTrim isTrim){
-                       while(begin_!=end_ && isTrim(*begin_)){
-                               begin_++;
-                       }
-                       while(end_!=begin_ && isTrim(end_[-1])){
-                               end_--;
-                       }
-                       return *this;
-               }
-};
-inline std::ostream &operator<<(std::ostream &os, const cstr &rhs)
-{
-       return os << rhs.str();
-}
-
-struct IsCRLF
-{
-       bool operator()(char byte)const
-       {
-               switch(byte)
-               {
-               case '\n':
-               case '\r': // fall through
-                       return true;
-
-               default:
-                       return false;
-               }
-       }
-};
-
-struct IsWhiteSpace
-{
-       bool operator()(char byte)const
-       {
-               switch(byte)
-               {
-               case ' ':
-               case '\t': // fall through
-                       return true;
-
-               default:
-                       return false;
-               }
-       }
-};
-
-struct IsEmpty
-{
-       bool operator()(cstr line)const
-       {
-               return line.empty();
-       }
-};
-
-template<class DELIMITER=IsCRLF, 
-       class TRIM=IsWhiteSpace,
-       class LINESKIP=IsEmpty>
-       class LineReader
-{
-       binary::IReader &reader_;
-       unsigned int lineCount_;
-       std::vector<char> buf_;
-       bool isEnd_;
-
-public:
-       LineReader(binary::IReader &reader)
-               : reader_(reader), lineCount_(0), isEnd_(false)
-               {
-               }
-
-       cstr getLine()
-       {
-               while(!isEnd_){
-                       fill_();
-                       cstr line;
-                       if(!buf_.empty()){
-                               line=trim_();
-                       }
-                       if(LINESKIP()(line)){
-                               continue;
-                       }
-                       ++lineCount_;
-                       return line;
-               }
-               return cstr();
-       }
-
-       unsigned int getLineCount()const
-       {
-               return lineCount_;
-       }
-
-       bool isEnd()const
-       {
-               return isEnd_;
-       }
-
-private:
-       void fill_()
-       {
-               buf_.clear();
-               // skip delimeter
-               while(char byte=reader_.getChar()){
-                       if(DELIMITER()(byte)){
-                               continue;
-                       }
-                       buf_.push_back(byte);
-                       break;
-               }
-               while(char byte=reader_.getChar()){
-                       if(DELIMITER()(byte)){
-                               break;
-                       }
-                       buf_.push_back(byte);
-               }
-               if(buf_.empty()){
-                       isEnd_=true;
-                       return;
-               }
-       }
-       
-       cstr trim_()
-       {
-               if(buf_.empty()){
-                       return cstr();
-               }
-
-               size_t front=0;
-               while(true){
-                       if(front>=buf_.size()){
-                               return cstr();
-                       }
-                       if(!TRIM()(buf_[front])){
-                               break;
-                       }
-                       ++front;
-               }
-
-               size_t back=buf_.size()-1;
-               for(; back>=0; --back){
-                       if(!TRIM()(buf_[back])){
-                               break;
-                       }
-               }
-               assert(front<=back);
-               return cstr(&buf_[0]+front, &buf_[0]+back+1);
-       }
-};
-
-template<class DELIMITER=IsWhiteSpace>
-class LineSplitter
-{
-       cstr line_;
-
-public:
-       LineSplitter(cstr line)
-               : line_(line)
-               {
-               }
-
-       cstr get()
-       {
-               const char* head=0;
-               const char* tail=0;
-               const char *current=line_.begin();
-               for(; current!=line_.end();){
-                       for(; current!=line_.end(); ++current){
-                               if(!DELIMITER()(*current)){
-                                       head=current;
-                                       break;
-                               }
-                       }
-                       if(head){
-                               for(; current!=line_.end(); ++current){
-                                       if(DELIMITER()(*current)){
-                                               break;
-                                       }
-                               }
-                               tail=current;
-                       }
-                       if(tail){
-                               break;
-                       }
-               }
-               if(!tail){
-                       return cstr();
-               }
-               line_=cstr(tail+1, line_.end());
-               return cstr(head, tail);
-       }
-
-       int getInt()
-       {
-               return atoi(get().begin());
-       }
 
-       float getFloat()
-       {
-               return static_cast<float>(atof(get().begin()));
-       }
-
-       la::Vector2 getVector2()
-       {
-               float x=getFloat();
-               float y=getFloat();
-               return la::Vector2(x, y);
-       }
-
-       la::Vector3 getVector3()
-       {
-               float x=getFloat();
-               float y=getFloat();
-               float z=getFloat();
-               return la::Vector3(x, y, z);
-       }
-
-       la::Vector4 getVector4()
-       {
-               float x=getFloat();
-               float y=getFloat();
-               float z=getFloat();
-               float w=getFloat();
-               return la::Vector4(x, y, z, w);
-       }
-
-       color::fRGBA getFloatRGBA()
-       {
-               float r=getFloat();
-               float g=getFloat();
-               float b=getFloat();
-               float a=getFloat();
-               return color::fRGBA(r, g, b, a);
-       }
-
-       color::bRGBA getByteRGBA()
-       {
-               int r=getInt();
-               int g=getInt();
-               int b=getInt();
-               int a=getInt();
-               return color::bRGBA(r, g, b, a);
-       }
+  class cstr
+  {
+    const char *begin_;
+    const char *end_;
+
+  public:
+    cstr()
+      : begin_(0), end_(0)
+    {}
+
+    cstr(const char *begin, const char *end)
+      : begin_(begin), end_(end)
+    { }
+
+    bool operator==(const char *rhs)const
+    {
+      const char *l=begin_;
+      for(const char *r=rhs; *r; ++r, ++l){
+        if(l==end_){
+          return false;
+        }
+        if(*l!=*r){
+          return false;
+        }
+      }
+      return l==end_;
+    }
 
-       cstr getQuated()
-       {
-               const char *begin=line_.begin();
-               for(; begin!=line_.end(); ++begin){
-                       if(*begin=='"'){
-                               break;
-                       }
-               }
-               begin++;
-               assert(begin<=line_.end());
+    bool operator!=(const char *rhs)const
+    {
+      return !(*this==rhs);
+    }
 
-               const char *c=begin+1;
-               for(; c!=line_.end(); ++c){
-                       if(*c=='"'){
-                               break;
-                       }
-               }
+    bool include(char c)const
+    {
+      for(const char *l=begin_; l!=end_; ++l){
+        if(*l==c){
+          return true;
+        }
+      }
+      return false;
+    }
 
-               cstr token=cstr(begin, c);
+    bool startswith(const char *rhs)
+    {
+      const char *r=rhs;
+      for(const char *l=begin_; l!=end_ && *r!='\0'; ++l, ++r){
+        if(*l!=*r){
+          return false;
+        }
+      }
+      return true;
+    }
 
-               // advance
-               line_=cstr(c+1, line_.end());
+    bool empty()const
+    {
+      return begin_==end_;
+    }
 
-               return token;
-       }
-};
+    std::string str()const{ return std::string(begin_, end_); }
+    const char* begin()const{ return begin_; }
+    const char* end()const{ return end_; }
+    std::pair<const char*, const char*> range()const{ 
+      return std::make_pair(begin_, end_); 
+    }
 
-inline void copyStringAndFillZero(char *dst, const std::string &src)
-{
-       size_t i=0;
-       for(; i<src.size(); ++i)
-       {
-               dst[i]=src[i];
-               if(src[i]=='\0'){
-                       break;
-               }
-       }
-       for(; i<src.size(); ++i)
-       {
-               dst[i]='\0';
-       }
-}
+    template<typename IsTrim>
+      cstr &trim(IsTrim isTrim){
+        while(begin_!=end_ && isTrim(*begin_)){
+          begin_++;
+        }
+        while(end_!=begin_ && isTrim(end_[-1])){
+          end_--;
+        }
+        return *this;
+      }
+  };
+  inline std::ostream &operator<<(std::ostream &os, const cstr &rhs)
+  {
+    return os << rhs.str();
+  }
+
+  template<int LENGTH>
+    class fixed_string
+    {
+      char begin_[LENGTH];
+      char *end_;
+    public:
+      fixed_string()
+        : end_(begin_)
+      {
+        begin_[0]='\0';;
+      }
+      fixed_string(const std::string &str)
+        : end_(begin_)
+      {
+        assign(str);
+      }
+      fixed_string& operator=(const std::string &src)
+      {
+        assign(src);
+        return *this;
+      }
+      void assign(const std::string &src)
+      {
+        if(src.empty()){
+          return;
+        }
+        auto it=src.begin();
+        for(int i=0; i<LENGTH && *it; ++i, ++it, ++end_){
+          begin_[i]=*it;
+        }
+        if(std::distance(
+              static_cast<char*>(begin_), 
+              static_cast<char*>(end_))<LENGTH)
+        {
+          *end_='\0';
+        }
+      }
+      size_t size()const { return LENGTH; }
+      char *begin() { return begin_; }
+      const char *begin() const { return begin_; }
+      std::string str() const
+      {
+        auto end=begin_;
+        for(; end!=end_ && *end!='\0'; ++end){
+        }
+        return std::string(
+            static_cast<const char*>(begin_), 
+            static_cast<const char*>(end));
+      }
+    };
+  template<int LENGTH>
+    inline std::ostream &operator<<(std::ostream &os, const fixed_string<LENGTH> &rhs)
+    {
+      return os << rhs.str();
+    }
 
 #ifdef _WIN32
-inline std::wstring to_WideChar(UINT uCodePage, const std::string &text)
-{
-       int size=MultiByteToWideChar(uCodePage, 0, text.c_str(), -1, NULL, 0);
-       std::vector<wchar_t> buf(size);
-       size=MultiByteToWideChar(uCodePage, 0, text.c_str(), -1, &buf[0], buf.size());
-       return std::wstring(buf.begin(), buf.begin()+size);
-}
-
-inline std::string to_MultiByte(UINT uCodePage, const std::wstring &text)
-{
-       int size=WideCharToMultiByte(uCodePage, 0, text.c_str(), -1, NULL, 0, 0, NULL);
-       std::vector<char> buf(size);
-       size=WideCharToMultiByte(uCodePage, 0, text.c_str(), -1, &buf[0], buf.size(), 0, NULL);
-       return std::string(buf.begin(), buf.begin()+size);
-}
-
-inline std::wstring cp932_to_unicode(const std::string &text)
-{
+  inline std::wstring to_WideChar(UINT uCodePage, const std::string &text)
+  {
+    int size=MultiByteToWideChar(uCodePage, 0, text.c_str(), -1, NULL, 0);
+    std::vector<wchar_t> buf(size);
+    size=MultiByteToWideChar(uCodePage, 0, text.c_str(), -1, &buf[0], buf.size());
+    return std::wstring(buf.begin(), buf.begin()+size);
+  }
+
+  inline std::string to_MultiByte(UINT uCodePage, const std::wstring &text)
+  {
+    int size=WideCharToMultiByte(uCodePage, 0, text.c_str(), -1, NULL, 0, 0, NULL);
+    std::vector<char> buf(size);
+    size=WideCharToMultiByte(uCodePage, 0, text.c_str(), -1, &buf[0], buf.size(), 0, NULL);
+    return std::string(buf.begin(), buf.begin()+size);
+  }
+
+  inline std::wstring cp932_to_unicode(const std::string &text)
+  {
     return to_WideChar(CP_OEMCP, text);
-}
+  }
 
-inline std::string cp932_to_utf8(const std::string &text)
-{
-       return to_MultiByte(CP_UTF8, to_WideChar(CP_OEMCP, text));
-}
+  inline std::string cp932_to_utf8(const std::string &text)
+  {
+    return to_MultiByte(CP_UTF8, to_WideChar(CP_OEMCP, text));
+  }
 
 #else
-inline std::wstring to_unicode(const char *text, const char *fromcode)
-{
+  inline std::wstring to_unicode(const char *text, const char *fromcode)
+  {
     const char* tocode="WCHAR_T";
     iconv_t cd=iconv_open(tocode, fromcode);
     if(cd==(iconv_t)-1){
-        std::cerr << "fail to iconv_open: " << fromcode << " --> " << tocode << std::endl;
-        return L"";
+      std::cerr << "fail to iconv_open: " << fromcode << " --> " << tocode << std::endl;
+      return L"";
     }
 
     // inbuf
@@ -421,41 +202,40 @@ inline std::wstring to_unicode(const char *text, const char *fromcode)
     size_t outbytesleft=0;
 
     while(inbytesleft){
-        buf.resize(buf.size()+inbytesleft);
-        wchar_t *woutbuf=&buf[pos];
-        outbytesleft=(buf.size()-pos)*sizeof(wchar_t);
-        int ret=iconv(cd, &inbuf, &inbytesleft, (char**)&woutbuf, &outbytesleft);
-        if(ret==-1){
-            std::cerr << "fail to iconv" <<  std::endl;
-            return L"";
-        }
-        pos=woutbuf-&buf[0];
+      buf.resize(buf.size()+inbytesleft);
+      wchar_t *woutbuf=&buf[pos];
+      outbytesleft=(buf.size()-pos)*sizeof(wchar_t);
+      int ret=iconv(cd, &inbuf, &inbytesleft, (char**)&woutbuf, &outbytesleft);
+      if(ret==-1){
+        std::cerr << "fail to iconv" <<  std::endl;
+        return L"";
+      }
+      pos=woutbuf-&buf[0];
     }
     if(outbytesleft==0){
-        buf.push_back('\0');
+      buf.push_back('\0');
     }
     iconv_close(cd);
 
     return &buf[0];
-}
+  }
 
-inline std::wstring cp932_to_unicode(const std::string &text)
-{
+  inline std::wstring cp932_to_unicode(const std::string &text)
+  {
     return to_unicode(text.c_str(), "CP932");
-}
+  }
 
 #endif
 
-inline std::wstring trim(const std::wstring &src){
-       std::wstring::const_iterator end=src.begin();
-       for(; end!=src.end(); ++end){
-               if(*end==L'\0'){
-                       break;
-               }
-       }
-       return std::wstring(src.begin(), end);
-}
+  inline std::wstring trim(const std::wstring &src){
+    std::wstring::const_iterator end=src.begin();
+    for(; end!=src.end(); ++end){
+      if(*end==L'\0'){
+        break;
+      }
+    }
+    return std::wstring(src.begin(), end);
+  }
 
-} // namespace text
 } // namespace meshio
 #endif // MESH_IO_TEXT_H_INCLUDED
index f69b55c..e69c79a 100755 (executable)
 #include <string>
 
 namespace meshio {
-namespace vmd {
-
-template<typename T>
-struct SortKeyFrameList
-{
-       typedef T MAP;
-       void operator()(typename MAP::value_type &channel)
-       {
-               channel.second->sort();
-       }
-};
-
-template<class READER>
-       void
-       readBoneMap(READER &reader, IO &io)
-       {
-               std::wstring name=
-                       text::trim(text::cp932_to_unicode(reader.getString(15, true)));
-               unsigned int frame=reader.getUint();
-               IO::BoneMap::iterator found=io.boneMap.find(name);
-               if(found==io.boneMap.end()){
-                       // not found
-                       found=io.boneMap.insert(
-                                               std::make_pair(name, 
-                            new KeyFrameList<KeyFrame<BoneKey> >())).first;
-                       io.boneKeys.push_back(name);
-               }
-               BoneKey &key=found->second->push(frame).key;
-
-               reader.get(key.pos);
-               reader.get(key.q);
-               reader.get(key.interpolationX);
-               reader.get(key.interpolationY);
-               reader.get(key.interpolationZ);
-               reader.get(key.interpolationRot);
-       }
-
-template<class READER>
-       void
-       readMorphMap(READER &reader, IO &io)
-       {
-               std::wstring name=
-                       text::trim(text::cp932_to_unicode(reader.getString(15, true)));
-               unsigned int frame=reader.getUint();
-               IO::MorphMap::iterator found=io.morphMap.find(name);
-               if(found==io.morphMap.end()){
-                       // not found
-                       found=io.morphMap.insert(
-                                       std::make_pair(name, 
-                        new KeyFrameList<KeyFrame<MorphKey> >())).first;
-                       io.morphKeys.push_back(name);
-               }
-               MorphKey &key=found->second->push(frame).key;
-
-               reader.get(key.weight);
-       }
-
-class Implementation
-{
-       IO &io_;
-       binary::IReader &reader_;
-
-public:
-       Implementation(IO &io, binary::IReader &reader)
-               : io_(io), reader_(reader)
-               {}
-
-       bool parse()
-       {
-               // check header
-               std::string line=reader_.getString(30, true);
-               if(line=="Vocaloid Motion Data file"){
-                       io_.version="1";
-                       text::copyStringAndFillZero(io_.name, reader_.getString(10));
-                       return parseBody();
-               }
-               else if(line=="Vocaloid Motion Data 0002"){
-                       io_.version="2";
-                       text::copyStringAndFillZero(io_.name, reader_.getString(20));
-                       return parseBody();
-               }
-               else{
-                       //std::cout << "unknown header:" << line << std::endl;
-                       return false;
-               }
-       }
-
-
-private:
-       bool parseBody()
-       {
-               if(!parseFrame()){
-                       return false;
-               }
-               if(!parseMorph()){
-                       return false;
-               }
-               if(!parseCamera()){
-                       return false;
-               }
-               if(!parseLight()){
-                       return false;
-               }
-               // sort
-               std::for_each(io_.boneMap.begin(), io_.boneMap.end(), 
-                               SortKeyFrameList<IO::BoneMap>());
-               std::for_each(io_.morphMap.begin(), io_.morphMap.end(), 
-                               SortKeyFrameList<IO::MorphMap>());
-               return true;
-       }
-
-       bool parseMorph()
-       {
-               unsigned int count=reader_.getUint();
-               for(unsigned int i=0; i<count; ++i){
-                       readMorphMap(reader_, io_);
-               }
-               return true;
-       }
-
-       bool parseFrame()
-       {
-               unsigned int count=reader_.getUint();
-               for(unsigned int i=0; i<count; ++i){
-                       readBoneMap(reader_, io_);
-               }
-               return true;
-       }
-
-       bool parseCamera()
-       {
-               return true;
-       }
-
-       bool parseLight()
-       {
-               return true;
-       }
-};
-
-
-///////////////////////////////////////////////////////////////////////////////
-//! IO
-///////////////////////////////////////////////////////////////////////////////
-IO::IO()
-{
-}
-
-IO::~IO()
-{
-       for(BoneMap::iterator it=boneMap.begin(); it!=boneMap.end(); ++it){
-               delete it->second;
-       }
-       boneMap.clear();
-
-       for(MorphMap::iterator it=morphMap.begin(); it!=morphMap.end(); ++it){
-               delete it->second;
-       }
-       morphMap.clear();
-
-}
-
-bool IO::read(binary::IReader &reader)
-{
-       return Implementation(*this, reader).parse();
-}
-
-#ifdef _WIN32 
-bool IO::read(const wchar_t *path)
-{
-       std::vector<char> all;
-       binary::readAll(path, all);
-       if(all.empty()){
-               return false;
-       }
-       binary::MemoryReader reader(&all[0], all.size());
-       return read(reader);
-}
-#endif
-
-bool IO::read(const char *path)
-{
-       std::vector<char> all;
-       binary::readAll(path, all);
-       if(all.empty()){
-               return false;
-       }
-       binary::MemoryReader reader(&all[0], all.size());
-       return read(reader);
-}
-
-bool IO::write(std::ostream &os)
-{
-       return false;
-}
-
-BoneKeyFrameList* IO::getBoneKeyFrameList(const std::wstring &name)
-{
-       return boneMap[name];
-}
-
-MorphKeyFrameList* IO::getMorphKeyFrameList(const std::wstring &name)
-{
-       return morphMap[name];
-}
-
-} // namespace vmd
+  namespace vmd {
+
+    template<typename T>
+      struct SortKeyFrameList
+      {
+        typedef T MAP;
+        void operator()(typename MAP::value_type &channel)
+        {
+          channel.second->sort();
+        }
+      };
+
+    template<class READER>
+      void
+      readBoneMap(READER &reader, IO &io)
+      {
+        std::wstring name=
+          trim(cp932_to_unicode(reader.getString(15, true)));
+        unsigned int frame=reader.getUint();
+        IO::BoneMap::iterator found=io.boneMap.find(name);
+        if(found==io.boneMap.end()){
+          // not found
+          found=io.boneMap.insert(
+              std::make_pair(name, 
+                new KeyFrameList<KeyFrame<BoneKey> >())).first;
+          io.boneKeys.push_back(name);
+        }
+        BoneKey &key=found->second->push(frame).key;
+
+        reader.get(key.pos);
+        reader.get(key.q);
+        reader.get(key.interpolationX);
+        reader.get(key.interpolationY);
+        reader.get(key.interpolationZ);
+        reader.get(key.interpolationRot);
+      }
+
+    template<class READER>
+      void
+      readMorphMap(READER &reader, IO &io)
+      {
+        std::wstring name=
+          trim(cp932_to_unicode(reader.getString(15, true)));
+        unsigned int frame=reader.getUint();
+        IO::MorphMap::iterator found=io.morphMap.find(name);
+        if(found==io.morphMap.end()){
+          // not found
+          found=io.morphMap.insert(
+              std::make_pair(name, 
+                new KeyFrameList<KeyFrame<MorphKey> >())).first;
+          io.morphKeys.push_back(name);
+        }
+        MorphKey &key=found->second->push(frame).key;
+
+        reader.get(key.weight);
+      }
+
+    class Implementation
+    {
+      IO &io_;
+      binary::IReader &reader_;
+
+    public:
+      Implementation(IO &io, binary::IReader &reader)
+        : io_(io), reader_(reader)
+      {}
+
+      bool parse()
+      {
+        // check header
+        std::string line=reader_.getString(30, true);
+        if(line=="Vocaloid Motion Data file"){
+          io_.version="1";
+          reader_.get(io_.name);
+          return parseBody();
+        }
+        else if(line=="Vocaloid Motion Data 0002"){
+          io_.version="2";
+          reader_.get(io_.name);
+          return parseBody();
+        }
+        else{
+          //std::cout << "unknown header:" << line << std::endl;
+          return false;
+        }
+      }
+
+
+    private:
+      bool parseBody()
+      {
+        if(!parseFrame()){
+          return false;
+        }
+        if(!parseMorph()){
+          return false;
+        }
+        if(!parseCamera()){
+          return false;
+        }
+        if(!parseLight()){
+          return false;
+        }
+        // sort
+        std::for_each(io_.boneMap.begin(), io_.boneMap.end(), 
+            SortKeyFrameList<IO::BoneMap>());
+        std::for_each(io_.morphMap.begin(), io_.morphMap.end(), 
+            SortKeyFrameList<IO::MorphMap>());
+        return true;
+      }
+
+      bool parseMorph()
+      {
+        unsigned int count=reader_.getUint();
+        for(unsigned int i=0; i<count; ++i){
+          readMorphMap(reader_, io_);
+        }
+        return true;
+      }
+
+      bool parseFrame()
+      {
+        unsigned int count=reader_.getUint();
+        for(unsigned int i=0; i<count; ++i){
+          readBoneMap(reader_, io_);
+        }
+        return true;
+      }
+
+      bool parseCamera()
+      {
+        return true;
+      }
+
+      bool parseLight()
+      {
+        return true;
+      }
+    };
+
+
+    ///////////////////////////////////////////////////////////////////////////////
+    //! IO
+    ///////////////////////////////////////////////////////////////////////////////
+    IO::IO()
+    {
+    }
+
+    IO::~IO()
+    {
+      for(BoneMap::iterator it=boneMap.begin(); it!=boneMap.end(); ++it){
+        delete it->second;
+      }
+      boneMap.clear();
+
+      for(MorphMap::iterator it=morphMap.begin(); it!=morphMap.end(); ++it){
+        delete it->second;
+      }
+      morphMap.clear();
+
+    }
+
+    bool IO::read(binary::IReader &reader)
+    {
+      return Implementation(*this, reader).parse();
+    }
+
+    bool IO::read(const char *path)
+    {
+      std::vector<char> all;
+      binary::readAll(path, all);
+      if(all.empty()){
+        return false;
+      }
+      binary::MemoryReader reader(&all[0], all.size());
+      return read(reader);
+    }
+
+    bool IO::write(std::ostream &os)
+    {
+      // not implemented
+      return false;
+    }
+
+  } // namespace vmd
 } // namespace meshio
index eba3a0f..265c49e 100644 (file)
--- a/src/vmd.h
+++ b/src/vmd.h
@@ -8,7 +8,6 @@
  * http://blog.goo.ne.jp/torisu_tetosuki/e/bc9f1c4d597341b394bd02b64597499d
  * http://atupdate.web.fc2.com/vmd_format.htm
  */
-
 #ifndef MESH_IO_VMD_H_INCLUDED
 #define MESH_IO_VMD_H_INCLUDED 
 
 #include <algorithm>
 
 namespace meshio {
-namespace vmd {
-
-typedef ::meshio::la::Vector2 Vector2;
-typedef ::meshio::la::Vector3 Vector3;
-typedef ::meshio::la::Quaternion Quaternion;
-typedef ::meshio::color::fRGB fRGB;
-
-////////////////////////////////////////////////////////////
-//! \83\82\81[\83V\83\87\83\93
-////////////////////////////////////////////////////////////
-struct BoneKey
-{
-       Vector3 pos;
-       Quaternion q;
-       char interpolationX[16];
-       char interpolationY[16];
-       char interpolationZ[16];
-       char interpolationRot[16];
-};
-inline std::ostream& operator<<(std::ostream &os, const BoneKey &rhs)
-{
-       return os
-               << "<BoneKey: " << rhs.pos << rhs.q << ">" 
-               ;
-}
-
-////////////////////////////////////////////////////////////
-//! \95\\8fî
-////////////////////////////////////////////////////////////
-struct MorphKey
-{
-       float weight;
-};
-inline std::ostream& operator<<(std::ostream &os, const MorphKey &rhs)
-{
-       return os
-               << "<MorphKey: " << rhs.weight << ">" 
-               ;
-}
-
-
-////////////////////////////////////////////////////////////
-//! \83J\83\81\83\89
-////////////////////////////////////////////////////////////
-struct CameraKey
-{
-       //! \89½\82Ì\8b\97\97£\81H
-       float length;
-       //! \88Ê\92u
-       Vector3 pos;
-       //! \83I\83C\83\89\81[\8ap
-       Vector3 euler;
-       //! \95â\8aÔ
-       char interpolation[24];
-       //! \8e\8b\96ì\8ap
-       unsigned short viewAngle;
-       //! \89\93\8bß\8a´ 0\82ªon
-       unsigned char perspective;
-};
-inline std::ostream& operator<<(std::ostream &os, const CameraKey &rhs)
-{
-       return os
-               << "<CameraKey: " << rhs.length 
-               << rhs.pos << rhs.euler << ">" 
-               ;
-}
-
-
-////////////////////////////////////////////////////////////
-//! \8cõ\8c¹
-////////////////////////////////////////////////////////////
-struct LightKey
-{
-       fRGB color;
-       Vector3 pos;
-};
-inline std::ostream& operator<<(std::ostream &os, const LightKey &rhs)
-{
-       return os
-               << "<LightKey: " << rhs.color << rhs.pos << ">" 
-               ;
-}
-
-
-////////////////////////////////////////////////////////////
-//! \83Z\83\8b\83t\83V\83\83\83h\83E
-////////////////////////////////////////////////////////////
-struct SelfShadowKey
-{
-};
-
-////////////////////////////////////////////////////////////
-//! KeyFrame
-////////////////////////////////////////////////////////////
-template<typename T>
-struct KeyFrame
-{
-       typedef T VALUE_TYPE;
-
-       //! \83t\83\8c\81[\83\80\94Ô\8d\86
-       unsigned int frame;
-       //! \83L\81[
-       T key;
-
-       //! \83t\83\8c\81[\83\80\94Ô\8d\86\82Å\83L\81[\82ð\83\\81[\83g\82·\82é
-       bool operator<(const KeyFrame &rhs)const{ return frame<rhs.frame; }
-};
-
-////////////////////////////////////////////////////////////
-//! 1\83`\83\83\83\93\83l\83\8b\95ª\82Ì\83L\81[\83t\83\8c\81[\83\80\82Ì\83\8a\83X\83g\81B
-//! \93Ç\82Ý\8d\9e\82ñ\82¾\8cã\82Å\83t\83\8c\81[\83\80\94Ô\8d\86\82Å\83\\81[\83g\82·\82é\81B
-////////////////////////////////////////////////////////////
-template<typename T>
-struct KeyFrameList
-{
-       typedef T KEYFRAME_TYPE;
-
-       std::vector<KEYFRAME_TYPE> list;
-       void sort(){ std::sort(list.begin(), list.end()); }
-    KEYFRAME_TYPE& push(unsigned int frame)
-       {
-               list.push_back(KEYFRAME_TYPE());
-               KEYFRAME_TYPE &keyFrame=list.back();
-               keyFrame.frame=frame;
-               return keyFrame;
-       }
-       unsigned int getFrame(int index)
-       {
-               return list[index].frame;
-       }
-       typename KEYFRAME_TYPE::VALUE_TYPE* getKey(int index)
-       {
-               return &list[index].key;
-       }
-};
-
-////////////////////////////////////////////////////////////
-//! IO
-////////////////////////////////////////////////////////////
-typedef KeyFrame<BoneKey> BoneKeyFrame;
-typedef KeyFrameList<BoneKeyFrame> BoneKeyFrameList;
-
-typedef KeyFrame<MorphKey> MorphKeyFrame;
-typedef KeyFrameList<MorphKeyFrame> MorphKeyFrameList;
-
-struct IO
-{
-       std::string version;
-       char name[20];
-
-       //! \83\82\81[\83V\83\87\83\93
-       typedef std::map<std::wstring, BoneKeyFrameList*> BoneMap;
-       BoneMap boneMap;
-       std::vector<std::wstring> boneKeys;
-
-       //! \95\\8fî
-       typedef std::map<std::wstring, MorphKeyFrameList*> MorphMap;
-       MorphMap morphMap;
-       std::vector<std::wstring> morphKeys;
-
-       IO();
-       ~IO();
-       bool read(binary::IReader &reader);
-       bool read(const wchar_t *path);
-       bool read(const char *path);
-       bool write(std::ostream &os);
-
-       BoneKeyFrameList* getBoneKeyFrameList(const std::wstring &name);
-       MorphKeyFrameList* getMorphKeyFrameList(const std::wstring &name);
-};
-inline std::ostream& operator<<(std::ostream &os, const IO &rhs)
-{
-       os
-               << "<VMD " << rhs.name << std::endl
-               << "[bones] " << rhs.boneMap.size() << std::endl
-               << "[morphs] " << rhs.morphMap.size() << std::endl
-               << ">"
-               ;
-       return os;
-}
-
-} // namespace vmd
+  namespace vmd {
+
+    ////////////////////////////////////////////////////////////
+    //! \83\82\81[\83V\83\87\83\93
+    ////////////////////////////////////////////////////////////
+    struct BoneKey
+    {
+      Vector3 pos;
+      Quaternion q;
+      char interpolationX[16];
+      char interpolationY[16];
+      char interpolationZ[16];
+      char interpolationRot[16];
+    };
+    inline std::ostream& operator<<(std::ostream &os, const BoneKey &rhs)
+    {
+      return os
+        << "<BoneKey: " << rhs.pos << rhs.q << ">" 
+        ;
+    }
+
+    ////////////////////////////////////////////////////////////
+    //! \95\\8fî
+    ////////////////////////////////////////////////////////////
+    struct MorphKey
+    {
+      float weight;
+    };
+    inline std::ostream& operator<<(std::ostream &os, const MorphKey &rhs)
+    {
+      return os
+        << "<MorphKey: " << rhs.weight << ">" 
+        ;
+    }
+
+
+    ////////////////////////////////////////////////////////////
+    //! \83J\83\81\83\89
+    ////////////////////////////////////////////////////////////
+    struct CameraKey
+    {
+      //! \89½\82Ì\8b\97\97£\81H
+      float length;
+      //! \88Ê\92u
+      Vector3 pos;
+      //! \83I\83C\83\89\81[\8ap
+      Vector3 euler;
+      //! \95â\8aÔ
+      char interpolation[24];
+      //! \8e\8b\96ì\8ap
+      unsigned short viewAngle;
+      //! \89\93\8bß\8a´ 0\82ªon
+      unsigned char perspective;
+    };
+    inline std::ostream& operator<<(std::ostream &os, const CameraKey &rhs)
+    {
+      return os
+        << "<CameraKey: " << rhs.length 
+        << rhs.pos << rhs.euler << ">" 
+        ;
+    }
+
+
+    ////////////////////////////////////////////////////////////
+    //! \8cõ\8c¹
+    ////////////////////////////////////////////////////////////
+    struct LightKey
+    {
+      fRGB color;
+      Vector3 pos;
+    };
+    inline std::ostream& operator<<(std::ostream &os, const LightKey &rhs)
+    {
+      return os
+        << "<LightKey: " << rhs.color << rhs.pos << ">" 
+        ;
+    }
+
+
+    ////////////////////////////////////////////////////////////
+    //! \83Z\83\8b\83t\83V\83\83\83h\83E
+    ////////////////////////////////////////////////////////////
+    struct SelfShadowKey
+    {
+    };
+
+    ////////////////////////////////////////////////////////////
+    //! KeyFrame
+    ////////////////////////////////////////////////////////////
+    template<typename T>
+      struct KeyFrame
+      {
+        typedef T VALUE_TYPE;
+
+        //! \83t\83\8c\81[\83\80\94Ô\8d\86
+        unsigned int frame;
+        //! \83L\81[
+        T key;
+
+        //! \83t\83\8c\81[\83\80\94Ô\8d\86\82Å\83L\81[\82ð\83\\81[\83g\82·\82é
+        bool operator<(const KeyFrame &rhs)const{ return frame<rhs.frame; }
+      };
+
+    ////////////////////////////////////////////////////////////
+    //! 1\83`\83\83\83\93\83l\83\8b\95ª\82Ì\83L\81[\83t\83\8c\81[\83\80\82Ì\83\8a\83X\83g\81B
+    //! \93Ç\82Ý\8d\9e\82ñ\82¾\8cã\82Å\83t\83\8c\81[\83\80\94Ô\8d\86\82Å\83\\81[\83g\82·\82é\81B
+    ////////////////////////////////////////////////////////////
+    template<typename T>
+      struct KeyFrameList
+      {
+        typedef T KEYFRAME_TYPE;
+
+        std::vector<KEYFRAME_TYPE> list;
+        void sort(){ std::sort(list.begin(), list.end()); }
+        KEYFRAME_TYPE& push(unsigned int frame)
+        {
+          list.push_back(KEYFRAME_TYPE());
+          KEYFRAME_TYPE &keyFrame=list.back();
+          keyFrame.frame=frame;
+          return keyFrame;
+        }
+      };
+
+    ////////////////////////////////////////////////////////////
+    //! IO
+    ////////////////////////////////////////////////////////////
+    typedef KeyFrame<BoneKey> BoneKeyFrame;
+    typedef KeyFrameList<BoneKeyFrame> BoneKeyFrameList;
+
+    typedef KeyFrame<MorphKey> MorphKeyFrame;
+    typedef KeyFrameList<MorphKeyFrame> MorphKeyFrameList;
+
+    struct IO
+    {
+      std::string version;
+      char name[20];
+
+      //! \83\82\81[\83V\83\87\83\93
+      typedef std::map<std::wstring, BoneKeyFrameList*> BoneMap;
+      BoneMap boneMap;
+      std::vector<std::wstring> boneKeys;
+
+      //! \95\\8fî
+      typedef std::map<std::wstring, MorphKeyFrameList*> MorphMap;
+      MorphMap morphMap;
+      std::vector<std::wstring> morphKeys;
+
+      IO();
+      ~IO();
+      bool read(binary::IReader &reader);
+      bool read(const char *path);
+      bool write(std::ostream &os);
+    };
+    inline std::ostream& operator<<(std::ostream &os, const IO &rhs)
+    {
+      os
+        << "<VMD " << rhs.name << std::endl
+        << "[bones] " << rhs.boneMap.size() << std::endl
+        << "[morphs] " << rhs.morphMap.size() << std::endl
+        << ">"
+        ;
+      return os;
+    }
+
+  } // namespace vmd
 } // namespace meshio
 
 #endif // MESH_IO_VMD_H_INCLUDED
old mode 100644 (file)
new mode 100755 (executable)
index 4dc4768..756eabc
@@ -14,7 +14,7 @@ buildoptions {
        "/wd4996",
 }
 includedirs {
-       "../include",
+       "../src",
        "T:/vc/gtest-1.5.0/include",
 }
 defines {}
old mode 100644 (file)
new mode 100755 (executable)
index b025894..73f4a32
@@ -3,5 +3,4 @@ solution "meshio_test"
 configurations { "Debug", "Release" }
 
 dofile "meshio_test.lua"
-dofile "../meshio.lua"