--- /dev/null
+MeshIO\83\89\83C\83u\83\89\83\8a
+
+\82±\82ê\82Í\81Amqo, pmd, vmd\82Ì\93Ç\82Ý\8d\9e\82Ý\82ð\96Ú\93I\82Æ\82µ\82½\83\89\83C\83u\83\89\83\8a\82Å\82·\81B
+\91Î\8fÛ\82Ì\83t\83@\83C\83\8b\82ð\83p\81[\83X\82µ\82Ä\93Ç\82Ý\8d\9e\82Þ\82Æ\82±\82ë\82Ü\82Å\82ð\8eÀ\8ds\82µ\82Ü\82·\81B
+
+*\83\89\83C\83Z\83\93\83X
+zlib\83\89\83C\83Z\83\93\83X
+
+*VC2008\82Å\82Ì\83r\83\8b\83h\95û\96@
+**\83\\83\8a\83\85\81[\83V\83\87\83\93\82Ì\90¶\90¬
+\83v\83\8d\83W\83F\83N\83g\82Ì\8aÇ\97\9d\82Épremake4(http://industriousone.com/premake)\82ð\97\98\97p\82µ\82Ä\82¢\82Ü\82·\81B Windows\8cü\82¯\82Ì\8eÀ\8ds\83t\83@\83C\83\8b\82ð\93¯\8d«\82µ\82Ä\82¢\82é\82Ì\82Å\88È\89º\82Ì\83R\83}\83\93\83h\82ðDOS\83v\83\8d\83\93\83v\83g\82Å\8eÀ\8ds\82µ\82Ä\82\82¾\82³\82¢\81B
+
+> cd MeshIO
+> bin\premake4.exe vs2008
+
+meshio.sln\82ª\90¶\90¬\82³\82ê\82é\82Ì\82Å\82±\82ê\82ðVC\82Å\8aJ\82¢\82Ä\83r\83\8b\83h\82µ\82Ä\82\82¾\82³\82¢\81B
+
+\88È\89º\82Ìstatic\83\89\83C\83u\83\89\83\8a\82ª\90¶\90¬\82³\82ê\82Ü\82·\81B
+debug/meshio.lib
+release/meshio.lib
+
+*\8eg\82¢\95û
+\82Æ\82è\82 \82¦\82¸test/main.cpp\82Æinclude/{mqo,pmd,vmd}.h\82ð\8c©\82Ä\82\82¾\82³\82¢\81B
+
+*\97\\92è
+-vpd, DirextX9\82Ìx\8c`\8e®, bvh\82Ö\82Ì\91Î\89\9e
+-\8f\91\82«\8d\9e\82Ý\8b@\94\
+-python\83o\83C\83\93\83f\83B\83\93\83O
+-blender\8cü\82¯\82Ìmqo, pmd, vmd\83C\83\93\83|\81[\83^\81E\83G\83N\83X\83|\81[\83^
+-gcc\91Î\89\9e
+
+*\97\9a\97ð
+2010/04/30 SourceForge\82É\8fê\8f\8a\8am\95Û\81Bmqo, pmd, vmd\82Ì\93Ç\82Ý\8d\9e\82Ý\82ð\8eÀ\91\95\81B
+
+*URL
+https://sourceforge.jp/projects/meshio
+
--- /dev/null
+#ifndef MESH_IO_BINARY_H_INCLUDED
+#define MESH_IO_BINARY_H_INCLUDED
+
+#include <fstream>
+#include <vector>
+#include <assert.h>
+
+namespace meshio {
+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;
+ }
+};
+
+/**
+ * \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);
+
+} // namespace binary
+} // namespace meshio
+
+#endif // MESH_IO_BINARY_H_INCLUDED
--- /dev/null
+#ifndef MESH_IO_COLOR_H_INCLUDED
+#define MESH_IO_COLOR_H_INCLUDED
+
+namespace meshio {
+namespace color {
+
+//! Byte\95Û\8e\9d\82ÌGBA
+struct bRGBA
+{
+ char r;
+ char g;
+ char b;
+ char a;
+
+ bRGBA()
+ {}
+
+ 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
+ );
+ }
+};
+inline std::ostream &operator<<(std::ostream &os, const bRGBA &rhs)
+{
+ return os
+ << '[' << rhs.r << ',' << rhs.g << ',' << rhs.b << ',' << rhs.a << ']';
+}
+
+//! Float\95Û\8e\9d\82ÌRGBA
+struct fRGBA
+{
+ float r;
+ float g;
+ float b;
+ float a;
+};
+inline std::ostream &operator<<(std::ostream &os, const fRGBA &rhs)
+{
+ return os
+ << '[' << rhs.r << ',' << rhs.g << ',' << rhs.b << ',' << rhs.a << ']';
+}
+
+
+//! Float\95Û\8e\9d\82ÌRGB
+struct fRGB
+{
+ float r;
+ float g;
+ float b;
+};
+inline std::ostream &operator<<(std::ostream &os, const fRGB &rhs)
+{
+ return os
+ << '[' << rhs.r << ',' << rhs.g << ',' << rhs.b << ',' << ']';
+}
+
+
+} // namespace color
+} // namespace meshio
+
+#endif // MESH_IO_COLOR_H_INCLUDED
--- /dev/null
+#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)
+ {}
+};
+inline std::ostream &operator<<(std::ostream &os, const Vector2 &rhs)
+{
+ return os
+ << '[' << rhs.x << ',' << rhs.y << ']';
+}
+
+
+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;
+ }
+};
+inline std::ostream &operator<<(std::ostream &os, const Vector3 &rhs)
+{
+ return os
+ << '[' << rhs.x << ',' << rhs.y << ',' << rhs.z << ']';
+}
+
+
+struct Vector4
+{
+ float x;
+ float y;
+ float z;
+ float w;
+
+ Vector4()
+ {}
+
+ Vector4(float _x, float _y, float _z, float _w)
+ : x(_x), y(_y), z(_z), w(_w)
+ {}
+};
+inline std::ostream &operator<<(std::ostream &os, const Vector4 &rhs)
+{
+ return os
+ << '[' << rhs.x << ',' << rhs.y << ',' << rhs.z << ',' << rhs.w << ']';
+}
+
+
+struct Quaternion
+{
+ float x;
+ float y;
+ float z;
+ float w;
+
+ Quaternion()
+ {}
+
+ Quaternion(float _x, float _y, float _z, float _w)
+ : x(_x), y(_y), z(_z), w(_w)
+ {}
+};
+inline std::ostream &operator<<(std::ostream &os, const Quaternion &rhs)
+{
+ return os
+ << '[' << rhs.x << ',' << rhs.y << ',' << rhs.z << ',' << rhs.w << ']';
+}
+
+
+}
+}
+
+#endif // MESH_IO_LA_H_INCLUDED
--- /dev/null
+#ifndef MESH_IO_H_INCLUCDED
+#define MESH_IO_H_INCLUCDED
+
+#include "binary.h"
+#include "text.h"
+#include "mqo.h"
+#include "pmd.h"
+#include "vmd.h"
+
+#endif // MESH_IO_H_INCLUCDED
--- /dev/null
+/**
+ * MQO\8c`\8e®
+ * \83\81\83^\83Z\83R\83C\83A\82Ì\83\82\83f\83\8b\83f\81[\83^\81B\83e\83L\83X\83g\8c`\8e®\81B
+ * \83}\83e\83\8a\83A\83\8b\8fî\95ñ\82Æ\8c`\8fó\83f\81[\83^\82ð\95Û\8e\9d\82·\82é\81B
+ * \83\82\83f\83\8a\83\93\83O\8cü\82¯\82É\88Ù\82È\82é\92¸\93_\91®\90«\82ð\8e\9d\82Â\92¸\93_\82ð\82Ð\82Æ\82Â\82Ì\92¸\93_\82Æ\82µ\82Ä\88µ\82Á\82Ä\82¢\82é\82Ì\82Å\81A
+ * \83v\83\8d\83O\83\89\83\80\82Å\92¸\93_\94z\97ñ\82ð\8dì\82é\8fê\8d\87\82Í\83}\83e\83\8a\83A\83\8b\81AUV\82È\82Ç\82ª\88Ù\82È\82é\92l\82ð\8e\9d\82Â\92¸\93_\82ð
+ * \95Ê\82Ì\92¸\93_\82Æ\82µ\82Ä\95ª\97£\82·\82é\8dì\8bÆ\82ª\95K\97v\82É\82È\82é\81B
+ * \96@\90ü\82Í\8cv\8eZ\82µ\82Ä\8eZ\8fo\82·\82é\95K\97v\82ª\82 \82é\81B
+ *
+ * \8dÀ\95W\8cn
+ * \89E\8eè Y-UP
+ *
+ * \96Ê\82Ì\95\
+ * clock wise ?
+ *
+ * UV\8c´\93_
+ * left top ?
+ *
+ * \96@\90ü
+ * \83I\83u\83W\83F\83N\83g\82Ì\95Û\8e\9d\82·\82é\83X\83\80\81[\83W\83\93\83O\92l\82ð\8eQ\8fÆ\82µ\82Ä\96Ê\96@\90ü\82©\82ç\8cv\8eZ\82·\82é\81B
+ *
+ * \97 \96Ê\82Ì\88µ\82¢
+ * \83I\83\8a\83W\83i\83\8b\82Å\82Í\83o\83b\83N\83J\83\8a\83\93\83O\97L\8cø\81B
+ *
+ * MIKOTO\95û\8e®\82Ì\83{\81[\83\93
+ * MQO\82Í\95W\8f\80\82Å\83X\83L\83j\83\93\83O\8fî\95ñ\82ð\8e\9d\82½\82È\82¢\82ª\81A\93Á\92è\82Ì\83\8b\81[\83\8b\82Å\83}\83e\83\8a\83A\83\8b\82Æ\83I\83u\83W\83F\83N\83g
+ * \82ð\8dì\90¬\82·\82é\82±\82Æ\82Å\82±\82ê\82ð\8dì\90¬\82·\82é\81B
+ *
+ * \8eQ\8dl\83T\83C\83g
+ * http://www.metaseq.net/metaseq/format.html
+ */
+
+#ifndef MESH_IO_MQO_H_INCLUDED
+#define MESH_IO_MQO_H_INCLUDED
+
+#include <iosfwd>
+#include <vector>
+#include "la.h"
+#include "color.h"
+#include "text.h"
+
+namespace meshio {
+namespace mqo {
+
+typedef la::Vector2 Vector2;
+typedef la::Vector3 Vector3;
+typedef la::Vector4 Vector4;
+typedef color::bRGBA 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 emmit;
+ float specular;
+ float power;
+ std::string texture;
+ std::string alphamap;
+ std::string bumpmap;
+ int vcol;
+
+ Material()
+ : shader(0), diffuse(1), ambient(0), emmit(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
+ << ", emmit:" << rhs.emmit
+ << ", 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();
+ }
+};
+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;
+
+ std::vector<Vector3> vertices;
+ std::vector<Face> faces;
+};
+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 write(std::ostream &os);
+};
+
+} // namespace mqo
+} // namespace meshio
+
+#endif // MESH_IO_MQO_H_INCLUDED
--- /dev/null
+/**
+ * PMD\8c`\8e®
+ * MMD\82Ì\83\82\83f\83\8b\83f\81[\83^\81B\83o\83C\83i\83\8a\8c`\8e®\82Å\82Ð\82Æ\82Â\82Ì\92¸\93_\82ª\8dÅ\91å\82Q\82Â\82Ü\82Å\82Ì\83{\81[\83\93\82Ì
+ * \83E\83F\83C\83g\82ð\95Û\8e\9d\82·\82é\92P\88ê\82Ì\92¸\93_\94z\97ñ\82Æ\92¸\93_\83C\83\93\83f\83b\83N\83X\94z\97ñ\82ð\82à\82Â\81B\96Ê\82Í
+ * \8eO\8ap\8c`\82Ì\82Ý\81B
+ * \82Ü\82½\95\\8fî\83\82\81[\83t\83B\83\93\83O\8fî\95ñ\81A\95¨\97\9d\89\89\8eZ\8cü\82¯\82Ì\8d\84\91Ì\8fî\95ñ\82Æ\8dS\91©\8fî\95ñ\82È\82Ç\82ð\82à\82Â\81B
+ *
+ * \8dÀ\95W\8cn
+ * \8d¶\8eè Y-UP
+ *
+ * \95\
+ * clock wise ?
+ *
+ * UV\8c´\93_
+ * left top ?
+ *
+ * \96@\90ü
+ * \92¸\93_\96@\90ü\82ª\8ai\94[\8dÏ\82Ý\81B
+ *
+ * \83\81\83b\83V\83\85
+ * \8dÅ\91å\92¸\93_\90\94
+ * \8dÅ\91å\8eO\8ap\8c`\90\94
+ *
+ * \97 \96Ê\82Ì\88µ\82¢
+ * \83I\83\8a\83W\83i\83\8b\82Å\82Í\83o\83b\83N\83J\83\8a\83\93\83O\82ð\82µ\82Ä\82¢\82È\82¢\82Ì\82Å\82â\82é\8fê\8d\87\82Í\83\82\83f\83\8b\8cÂ\95Ê\82É
+ * \91Î\89\9e\82ª\95K\97v\81B
+ *
+ * \8eQ\8dl\83T\83C\83g
+ * http://blog.goo.ne.jp/torisu_tetosuki/e/209ad341d3ece2b1b4df24abf619d6e4
+ */
+
+#ifndef MESH_IO_PMD_H_INCLUDED
+#define MESH_IO_PMD_H_INCLUDED
+
+#include <ostream>
+#include <vector>
+#include "la.h"
+#include "text.h"
+
+namespace meshio {
+namespace pmd {
+
+typedef la::Vector2 Vector2;
+typedef la::Vector3 Vector3;
+typedef la::Vector4 Vector4;
+typedef color::fRGBA fRGBA;
+typedef 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];
+};
+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;
+};
+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;
+};
+inline std::ostream &operator<<(std::ostream &os, const Morph &rhs)
+{
+ os
+ << "[Morph "
+ << '"' << rhs.name << '"'
+ << "]"
+ ;
+ return os;
+}
+
+////////////////////////////////////////////////////////////
+//! \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;
+};
+
+//! 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;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// 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<std::pair<unsigned short, unsigned char> > bone_list;
+ std::vector<std::string> bone_name_list;
+ std::vector<RigidBody> rigidbodies;
+ std::vector<Constraint> constraints;
+
+ IO();
+ bool read(binary::IReader &reader);
+ bool write(std::ostream &os);
+};
+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
--- /dev/null
+#ifndef MESH_IO_TEXT_H_INCLUDED
+#define MESH_IO_TEXT_H_INCLUDED
+
+#include "binary.h"
+#include "la.h"
+#include "color.h"
+#include <string>
+#include <stdlib.h>
+
+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=IsSpace,
+ class LINESKIP=IsEmptyLine>
+ 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=IsSpace>
+class LineSplitter
+{
+ cstr line_;
+ std::vector<const char*> heads_;
+ std::vector<const char*> tails_;
+ size_t index_;
+
+public:
+ LineSplitter(cstr line)
+ : line_(line), index_(0)
+ {
+ const char *current=line.begin();
+ for(; current!=line_.end();){
+ for(; current!=line_.end(); ++current){
+ if(!DELIMITER()(*current)){
+ break;
+ }
+ }
+ if(current==line_.end()){
+ break;
+ }
+ heads_.push_back(current);
+ for(; current!=line_.end(); ++current){
+ if(DELIMITER()(*current)){
+ break;
+ }
+ }
+ tails_.push_back(current);
+ }
+ }
+
+ cstr get()
+ {
+ if(index_>=heads_.size()){
+ return cstr();
+ }
+ const char* head=heads_[index_];
+ const char* tail=tails_[index_];
+ ++index_;
+ 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::bRGBA getByteRGBA()
+ {
+ int r=getInt();
+ int g=getInt();
+ int b=getInt();
+ int a=getInt();
+ return color::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);
+ begin=c+1;
+ return token;
+ }
+
+};
+
+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';
+ }
+}
+
+} // namespace text
+} // namespace meshio
+#endif // MESH_IO_TEXT_H_INCLUDED
--- /dev/null
+/**
+ * VMD\8c`\8e®
+ * MMD\82Ì\83\82\81[\83V\83\87\83\93\83f\81[\83^\81B
+ * \83o\83C\83i\83\8a\8c`\8e®\82Å\83{\81[\83\93\83\82\81[\83V\83\87\83\93\81A\95\\8fî\83\82\81[\83t\83B\83\93\83O\81A\8cõ\8c¹\81A\89e\82Ì\83L\81[\83t\83\8c\81[\83\80\82ª
+ * \8bL\98^\82³\82ê\82é\81B
+ *
+ * \8eQ\8dl\83T\83C\83g
+ * 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 <ostream>
+#include <vector>
+#include <map>
+#include "la.h"
+#include "color.h"
+#include "binary.h"
+
+namespace meshio {
+namespace vmd {
+
+typedef la::Vector2 Vector2;
+typedef la::Vector3 Vector3;
+typedef la::Quaternion Quaternion;
+typedef 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
+{
+};
+
+////////////////////////////////////////////////////////////
+//! 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
+{
+ struct KeyFrame
+ {
+ //! \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; }
+ };
+ std::vector<KeyFrame> list;
+ void sort(){ std::sort(list.begin(), list.end()); }
+ KeyFrame& push(unsigned int frame)
+ {
+ list.push_back(KeyFrame());
+ KeyFrame &keyFrame=list.back();
+ keyFrame.frame=frame;
+ return keyFrame;
+ }
+};
+
+////////////////////////////////////////////////////////////
+//! IO
+////////////////////////////////////////////////////////////
+struct IO
+{
+ std::string version;
+ char name[20];
+
+ //! \83\82\81[\83V\83\87\83\93
+ typedef std::map<std::string, KeyFrameList<BoneKey> > BoneMap;
+ BoneMap boneMap;
+ //! \95\\8fî
+ typedef std::map<std::string, KeyFrameList<MorphKey> > MorphMap;
+ MorphMap morphMap;
+ //! \83J\83\81\83\89\83\82\81[\83V\83\87\83\93
+ typedef std::map<std::string, KeyFrameList<CameraKey> > CameraMap;
+ CameraMap cameraKey;
+ //! \8fÆ\96¾
+ typedef std::map<std::string, KeyFrameList<LightKey> > LightMap;
+ LightMap lightMap;
+ //! \83Z\83\8b\83t\83V\83\83\83h\81[
+ typedef std::map<std::string, KeyFrameList<SelfShadowKey> > SelfShadowMap;
+ SelfShadowMap selfShadowMap;
+
+ IO();
+ bool read(binary::IReader &reader);
+ 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
--- /dev/null
+-- A solution contains projects, and defines the available configurations
+solution "meshio"
+configurations { "Debug", "Release" }
+
+-- 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",
+}
+buildoptions {
+ "/wd4996",
+}
+includedirs {
+ "include", "boost",
+}
+defines {}
+linkoptions {}
+libdirs {}
+links {}
+
+configuration "Debug"
+do
+ defines { "DEBUG" }
+ flags { "Symbols" }
+ targetdir "debug"
+end
+
+configuration "Release"
+do
+ defines { "NDEBUG" }
+ flags { "Optimize" }
+ targetdir "release"
+end
+
+
--- /dev/null
+#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_;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void readAll(const char *path, std::vector<char> &buf)
+{
+ std::ifstream io(path, std::ios::binary);
+ if(!io){
+ return;
+ }
+ io.seekg(0, std::fstream::end);
+ unsigned int eofPos = io.tellg();
+ io.clear();
+ io.seekg(0, std::fstream::beg);
+ unsigned int begPos = io.tellg();
+ unsigned int size = eofPos - begPos;
+ buf.resize(size);
+ io.read(&buf[0], buf.size());
+}
+
+} // namespace binary
+} // namespace meshio
--- /dev/null
+#include "mqo.h"
+#include <iostream>
+#include <fstream>
+#include <vector>
+
+namespace meshio {
+namespace mqo {
+
+//! Tokenizer
+struct DELIMITER
+{
+ bool operator()(char c)
+ {
+ switch(c)
+ {
+ case ' ':
+ 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{
+ 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::bRGBA::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.getByteRGBA();
+ }
+ else if(key=="dif"){
+ material.diffuse=splitter.getFloat();
+ }
+ else if(key=="amb"){
+ material.ambient=splitter.getFloat();
+ }
+ else if(key=="emi"){
+ material.emmit=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::write(std::ostream &os)
+{
+ return false;
+}
+
+
+}
+}
--- /dev/null
+#include "pmd.h"
+#include <iostream>
+
+namespace meshio {
+namespace pmd {
+
+// 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.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(!parseBoneNameList()){
+ 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_.getString(100);
+ }
+ return true;
+ }
+
+ bool parseEnglishBoneList()
+ {
+ for(size_t i=0; i<io_.bone_name_list.size(); ++i){
+ std::string english=reader_.getString(50);
+ }
+ return true;
+ }
+
+ bool parseEnglishMorph()
+ {
+ int count=io_.morph_list.size()-1;
+ for(int i=0; i<count; ++i){
+ std::string english_morph_name=reader_.getString(20);
+ }
+ return true;
+ }
+
+ bool parseEnglishBone()
+ {
+ for(size_t i=0; i<io_.bones.size(); ++i){
+ std::string english_bone_name=reader_.getString(20);
+ }
+ return true;
+ }
+
+ bool parseEnglishName()
+ {
+ std::string english_mdoel_name=reader_.getString(20);
+ std::string 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_list.push_back(std::make_pair(bone, disp));
+ }
+ return true;
+ }
+
+ bool parseBoneNameList()
+ {
+ unsigned int count=reader_.getUchar();
+ for(unsigned int i=0; i<count; ++i){
+ io_.bone_name_list.push_back(reader_.getString(50));
+ }
+ return true;
+ }
+
+ bool parseFaceList()
+ {
+ unsigned int count=reader_.getUchar();
+ for(unsigned int i=0; i<count; ++i){
+ 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;
+ }
+ text::copyStringAndFillZero(io_.name, reader_.getString(20));
+ text::copyStringAndFillZero(io_.comment, reader_.getString(256));
+
+ return true;
+ }
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// IO
+///////////////////////////////////////////////////////////////////////////////
+IO::IO()
+: version(0)
+{}
+
+bool IO::read(binary::IReader &input)
+{
+ Impl impl(*this, input);
+ if(!impl.parse()){
+ return false;
+ }
+
+ ////////////////////////////////////////////////////////////
+ // validation
+ ////////////////////////////////////////////////////////////
+ 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);
+ }
+ }
+
+ return true;
+}
+
+bool IO::write(std::ostream &os)
+{
+ return false;
+}
+
+} // namespace
+} // namespace
+
--- /dev/null
+#include "vmd.h"
+#include "text.h"
+#include <algorithm>
+#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
+ read(READER &reader, IO::BoneMap &channels)
+ {
+ std::string name=reader.getString(15);
+ unsigned int frame=reader.getUint();
+ IO::BoneMap::iterator found=channels.find(name);
+ if(found==channels.end()){
+ // not found
+ found=channels.insert(
+ std::make_pair(name, KeyFrameList<BoneKey>())).first;
+ }
+ 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
+ read(READER &reader, IO::MorphMap &channels)
+ {
+ std::string name=reader.getString(15);
+ unsigned int frame=reader.getUint();
+ IO::MorphMap::iterator found=channels.find(name);
+ if(found==channels.end()){
+ // not found
+ found=channels.insert(
+ std::make_pair(name, KeyFrameList<MorphKey>())).first;
+ }
+ 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){
+ read(reader_, io_.morphMap);
+ }
+ return true;
+ }
+
+ bool parseFrame()
+ {
+ unsigned int count=reader_.getUint();
+ for(unsigned int i=0; i<count; ++i){
+ read(reader_, io_.boneMap);
+ }
+ return true;
+ }
+
+ bool parseCamera()
+ {
+ return true;
+ }
+
+ bool parseLight()
+ {
+ return true;
+ }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+//! IO
+///////////////////////////////////////////////////////////////////////////////
+IO::IO()
+{
+}
+
+bool IO::read(binary::IReader &reader)
+{
+ return Implementation(*this, reader).parse();
+}
+
+bool IO::write(std::ostream &os)
+{
+ return false;
+}
+
+} // namespace vmd
+} // namespace meshio
--- /dev/null
+Metasequoia Document\r
+Format Text Ver 1.0\r
+\r
+Scene {\r
+ pos 0.0000 0.0000 1500.0000\r
+ lookat 0.0000 0.0000 0.0000\r
+ head -0.5236\r
+ pich 0.5236\r
+ ortho 0\r
+ zoom2 5.0000\r
+ amb 0.250 0.250 0.250\r
+}\r
+Object "obj1" {\r
+ depth 0\r
+ folding 0\r
+ scale 1.000000 1.000000 1.000000\r
+ rotation 0.000000 0.000000 0.000000\r
+ translation 0.000000 0.000000 0.000000\r
+ visible 15\r
+ locking 0\r
+ shading 1\r
+ facet 59.5\r
+ color 0.898 0.400 0.137\r
+ color_type 0\r
+ vertex 8 {\r
+ -100.0000 100.0000 100.0000\r
+ -100.0000 -100.0000 100.0000\r
+ 100.0000 100.0000 100.0000\r
+ 100.0000 -100.0000 100.0000\r
+ 100.0000 100.0000 -100.0000\r
+ 100.0000 -100.0000 -100.0000\r
+ -100.0000 100.0000 -100.0000\r
+ -100.0000 -100.0000 -100.0000\r
+ }\r
+ face 6 {\r
+ 4 V(0 2 3 1) UV(0.00000 0.00000 1.00000 0.00000 1.00000 1.00000 0.00000 1.00000)\r
+ 4 V(2 4 5 3) UV(0.00000 0.00000 1.00000 0.00000 1.00000 1.00000 0.00000 1.00000)\r
+ 4 V(4 6 7 5) UV(0.00000 0.00000 1.00000 0.00000 1.00000 1.00000 0.00000 1.00000)\r
+ 4 V(6 0 1 7) UV(0.00000 0.00000 1.00000 0.00000 1.00000 1.00000 0.00000 1.00000)\r
+ 4 V(6 4 2 0) UV(0.00000 0.00000 1.00000 0.00000 1.00000 1.00000 0.00000 1.00000)\r
+ 4 V(1 3 5 7) UV(0.00000 0.00000 1.00000 0.00000 1.00000 1.00000 0.00000 1.00000)\r
+ }\r
+}\r
+Eof\r
--- /dev/null
+#include <gtest/gtest.h>
+#include <fstream>
+#include <sstream>
+
+#include <meshio.h>
+using namespace meshio;
+
+TEST(binary, FileReader)
+{
+ binary::FileReader reader("cube.mqo");
+
+ char buf[1024];
+ while(reader.read(buf, 1024)){
+ }
+ EXPECT_EQ(1235, reader.getPos());
+}
+
+TEST(binary, MemoryReader)
+{
+ std::vector<char> all;
+ binary::readAll("cube.mqo", all);
+ binary::MemoryReader reader(&all[0], all.size());
+ char buf[1024];
+ while(reader.read(buf, 1024)){
+ }
+ EXPECT_EQ(1235, reader.getPos());
+}
+
+TEST(text, LineReader)
+{
+ binary::FileReader reader("cube.mqo");
+ text::LineReader<
+ text::IsCRLF,
+ text::IsWhiteSpace,
+ text::IsEmpty> l(reader);
+ EXPECT_EQ("Metasequoia Document", l.getLine().str());
+ EXPECT_EQ("Format Text Ver 1.0", l.getLine().str());
+
+ {
+ text::cstr line=l.getLine();
+ text::LineSplitter<text::IsWhiteSpace> splitter(line);
+ EXPECT_EQ("Scene", splitter.get().str());
+ }
+
+ {
+ text::cstr line=l.getLine();
+ text::LineSplitter<text::IsWhiteSpace> splitter(line);
+ EXPECT_EQ("pos", splitter.get().str());
+ EXPECT_EQ(0.0000f, splitter.getFloat());
+ EXPECT_EQ(0.0000f, splitter.getFloat());
+ EXPECT_EQ(1500.0000f, splitter.getFloat());
+ }
+
+ while(true)
+ {
+ text::cstr line=l.getLine();
+ if(l.isEnd()){
+ break;
+ }
+ //std::cout << l.getLineCount() << ',' << line << std::endl;
+ }
+ EXPECT_EQ(43, l.getLineCount());
+}
+
+TEST(mqo, read)
+{
+ //binary::FileReader reader("cube.mqo");
+ std::vector<char> all;
+ binary::readAll("cube.mqo", all);
+ binary::MemoryReader reader(&all[0], all.size());
+
+ mqo::IO io;
+ EXPECT_TRUE(io.read(reader));
+ EXPECT_EQ(1, io.objects.size());
+ EXPECT_EQ(8, io.objects[0].vertices.size());
+ EXPECT_EQ(6, io.objects[0].faces.size());
+}
+
+TEST(pmd, read)
+{
+ std::locale::global(std::locale("japanese"));
+ std::vector<char> all;
+ binary::readAll("\8f\89\89¹\83~\83NVer2.pmd", all);
+ binary::MemoryReader reader(&all[0], all.size());
+
+ pmd::IO io;
+ EXPECT_TRUE(io.read(reader));
+ //std::cout << io << std::endl;
+ EXPECT_STREQ("\8f\89\89¹\83~\83N", io.name);
+ EXPECT_EQ(17, io.materials.size());
+ EXPECT_EQ(12354, io.vertices.size());
+ EXPECT_EQ(68883, io.indices.size());
+ EXPECT_EQ(45, io.rigidbodies.size());
+ EXPECT_EQ(27, io.constraints.size());
+}
+
+TEST(vmd, read)
+{
+ std::locale::global(std::locale("japanese"));
+ std::vector<char> all;
+ binary::readAll("mikumiku.vmd", all);
+ binary::MemoryReader reader(&all[0], all.size());
+
+ vmd::IO io;
+ EXPECT_TRUE(io.read(reader));
+ //std::cout << io << std::endl;
+ EXPECT_EQ(122, io.boneMap.size());
+ EXPECT_EQ(16, io.morphMap.size());
+}
+
+int main(int argc, char **argv)
+{
+ testing::InitGoogleTest(&argc, argv);
+ RUN_ALL_TESTS();
+}
+
--- /dev/null
+-- A solution contains projects, and defines the available configurations
+solution "meshio_test"
+configurations { "Debug", "Release" }
+
+-- A project defines one build target
+project "meshio_test"
+--kind "WindowedApp"
+kind "ConsoleApp"
+--kind "SharedLib"
+--kind "StaticLib"
+language "C++"
+files { "**.h", "**.cpp" }
+flags {
+ --"Unicode",
+ "StaticRuntime",
+}
+buildoptions {
+ "/wd4996",
+}
+includedirs {
+ "../include",
+ "T:/vc/gtest-1.5.0/include",
+}
+defines {}
+linkoptions {}
+libdirs {}
+links {
+ "meshio",
+}
+
+configuration "Debug"
+do
+ defines { "DEBUG" }
+ flags { "Symbols" }
+ targetdir "debug"
+ linkoptions {
+ --"/NODEFAULTLIB:msvcprtd.lib",
+ --"/NODEFAULTLIB:libcmtd.lib",
+ }
+ libdirs {
+ "../Debug",
+ "T:/vc/gtest-1.5.0/msvc/gtest/Debug",
+ }
+ links {
+ "gtestd",
+ }
+end
+
+configuration "Release"
+do
+ defines { "NDEBUG" }
+ flags { "Optimize" }
+ targetdir "release"
+ libdirs {
+ "../Release",
+ "T:/vc/gtest-1.5.0/msvc/gtest/Release",
+ }
+ links {
+ "gtest",
+ }
+end
+