浏览代码

use SkeletonMeshBuilder to show bone positions.

aoowweenn 8 年之前
父节点
当前提交
2d3dd1d40f
共有 1 个文件被更改,包括 250 次插入194 次删除
  1. 250 194
      code/MMDImporter.cpp

+ 250 - 194
code/MMDImporter.cpp

@@ -41,33 +41,32 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
 
-#include "DefaultIOSystem.h"
 #include "MMDImporter.h"
-#include "MMDPmxParser.h"
+#include "DefaultIOSystem.h"
 #include "MMDPmdParser.h"
+#include "MMDPmxParser.h"
 #include "MMDVmdParser.h"
+#include "SkeletonMeshBuilder.h"
 //#include "IOStreamBuffer.h"
 #include "ConvertToLHProcess.h"
-#include <memory>
+#include <assimp/DefaultLogger.hpp>
 #include <assimp/Importer.hpp>
-#include <assimp/scene.h>
 #include <assimp/ai_assert.h>
-#include <assimp/DefaultLogger.hpp>
+#include <assimp/scene.h>
 #include <fstream>
 #include <iomanip>
+#include <memory>
 
-static const aiImporterDesc desc = {
-    "MMD Importer",
-    "",
-    "",
-    "surfaces supported?",
-    aiImporterFlags_SupportTextFlavour,
-    0,
-    0,
-    0,
-    0,
-    "pmx"
-};
+static const aiImporterDesc desc = {"MMD Importer",
+                                    "",
+                                    "",
+                                    "surfaces supported?",
+                                    aiImporterFlags_SupportTextFlavour,
+                                    0,
+                                    0,
+                                    0,
+                                    0,
+                                    "pmx"};
 
 namespace Assimp {
 
@@ -75,237 +74,294 @@ using namespace std;
 
 // ------------------------------------------------------------------------------------------------
 //  Default constructor
-MMDImporter::MMDImporter() :
-    m_Buffer(),
-    //m_pRootObject( NULL ),
-    m_strAbsPath( "" )
-{
-    DefaultIOSystem io;
-    m_strAbsPath = io.getOsSeparator();
+MMDImporter::MMDImporter()
+    : m_Buffer(),
+      // m_pRootObject( NULL ),
+      m_strAbsPath("") {
+  DefaultIOSystem io;
+  m_strAbsPath = io.getOsSeparator();
 }
 
 // ------------------------------------------------------------------------------------------------
 //  Destructor.
-MMDImporter::~MMDImporter()
-{
-    //delete m_pRootObject;
-    //m_pRootObject = NULL;
+MMDImporter::~MMDImporter() {
+  // delete m_pRootObject;
+  // m_pRootObject = NULL;
 }
 
 // ------------------------------------------------------------------------------------------------
 //  Returns true, if file is an pmx file.
-bool MMDImporter::CanRead( const std::string& pFile, IOSystem*  pIOHandler , bool checkSig ) const
-{
-    if(!checkSig) //Check File Extension
-    {
-        return SimpleExtensionCheck(pFile,"pmx");
-    }
-    else //Check file Header
-    {
-        static const char *pTokens[] = { "PMX " };
-        return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 1 );
-    }
+bool MMDImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler,
+                          bool checkSig) const {
+  if (!checkSig) // Check File Extension
+  {
+    return SimpleExtensionCheck(pFile, "pmx");
+  } else // Check file Header
+  {
+    static const char *pTokens[] = {"PMX "};
+    return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens,
+                                                  1);
+  }
 }
 
 // ------------------------------------------------------------------------------------------------
-const aiImporterDesc* MMDImporter::GetInfo () const
-{
-    return &desc;
-}
+const aiImporterDesc *MMDImporter::GetInfo() const { return &desc; }
 
 // ------------------------------------------------------------------------------------------------
 //  MMD import implementation
-void MMDImporter::InternReadFile( const std::string &file, aiScene* pScene, IOSystem* pIOHandler)
-{
-    // Read file by istream
-    std::filebuf fb;
-    if( !fb.open(file, std::ios::in | std::ios::binary ) ) {
-        throw DeadlyImportError( "Failed to open file " + file + "." );
-    }
+void MMDImporter::InternReadFile(const std::string &file, aiScene *pScene,
+                                 IOSystem *pIOHandler) {
+  // Read file by istream
+  std::filebuf fb;
+  if (!fb.open(file, std::ios::in | std::ios::binary)) {
+    throw DeadlyImportError("Failed to open file " + file + ".");
+  }
 
-    std::istream fileStream( &fb );
+  std::istream fileStream(&fb);
 
-    // Get the file-size and validate it, throwing an exception when fails
-    fileStream.seekg(0, fileStream.end);
-    size_t fileSize = fileStream.tellg();
-    fileStream.seekg(0, fileStream.beg);
+  // Get the file-size and validate it, throwing an exception when fails
+  fileStream.seekg(0, fileStream.end);
+  size_t fileSize = fileStream.tellg();
+  fileStream.seekg(0, fileStream.beg);
 
-    if( fileSize < sizeof(pmx::PmxModel) ) {
-        throw DeadlyImportError( file + " is too small." );
-    }
+  if (fileSize < sizeof(pmx::PmxModel)) {
+    throw DeadlyImportError(file + " is too small.");
+  }
 
-    pmx::PmxModel model;
-    model.Read(&fileStream);
+  pmx::PmxModel model;
+  model.Read(&fileStream);
 
-    CreateDataFromImport(&model, pScene);
+  CreateDataFromImport(&model, pScene);
 }
 
 // ------------------------------------------------------------------------------------------------
-void MMDImporter::CreateDataFromImport(const pmx::PmxModel* pModel, aiScene* pScene)
-{
-    if( pModel == NULL ) {
-        return;
-    }
-
-    aiNode *pNode = new aiNode;
-    if ( !pModel->model_name.empty() ) {
-        pNode->mName.Set(pModel->model_name);
-    }
-    else {
-        ai_assert(false);
-    }
-    
-    pScene->mRootNode = pNode;
-    std::cout << pScene->mRootNode->mName.C_Str() << std::endl;
-    std::cout << pModel->index_count << std::endl;
-
+void MMDImporter::CreateDataFromImport(const pmx::PmxModel *pModel,
+                                       aiScene *pScene) {
+  if (pModel == NULL) {
+    return;
+  }
+
+  aiNode *pNode = new aiNode;
+  if (!pModel->model_name.empty()) {
+    pNode->mName.Set(pModel->model_name);
+  } else {
+    ai_assert(false);
+  }
+
+  pScene->mRootNode = pNode;
+  std::cout << pScene->mRootNode->mName.C_Str() << std::endl;
+  std::cout << pModel->index_count << std::endl;
+
+  /*
     pNode = new aiNode;
     pScene->mRootNode->addChildren(1, &pNode);
-    pScene->mRootNode->mNumChildren = 1;
-    pNode->mParent = pScene->mRootNode;
     pNode->mName.Set(string(pModel->model_name) + string("_mesh"));
 
     // split mesh by materials
     pNode->mNumMeshes = pModel->material_count;
     pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
-    for( unsigned int index = 0; index < pNode->mNumMeshes; index++ ) {
-        pNode->mMeshes[index] = index;
+    for (unsigned int index = 0; index < pNode->mNumMeshes; index++) {
+      pNode->mMeshes[index] = index;
     }
 
     pScene->mNumMeshes = pNode->mNumMeshes;
-    pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
-    for( unsigned int i = 0, indexStart = 0; i < pScene->mNumMeshes; i++ ) {
-        const int indexCount = pModel->materials[i].index_count;
-
-        std::cout << pModel->materials[i].material_name << std::endl;
-        std::cout << indexStart << " " << indexCount << std::endl;
+    pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
+    for (unsigned int i = 0, indexStart = 0; i < pScene->mNumMeshes; i++) {
+      const int indexCount = pModel->materials[i].index_count;
 
-        pScene->mMeshes[i] = CreateMesh(pModel,  indexStart, indexCount);
-        pScene->mMeshes[i]->mName = pModel->materials[i].material_name;
-        pScene->mMeshes[i]->mMaterialIndex = i;
-        indexStart += indexCount;
-    }
+      std::cout << pModel->materials[i].material_name << std::endl;
+      std::cout << indexStart << " " << indexCount << std::endl;
 
-    // create textures, may be dummy?
-    /*
-    pScene->mNumTextures = pModel->texture_count;
-    pScene->mTextures = new aiTexture*[pScene->mNumTextures];
-    for( unsigned int i = 0; i < pScene->mNumTextures; ++i) {
-        aiTexture *tex = new aiTexture;        
-        pScene->mTextures[i] = tex;
-        strcpy(tex->achFormatHint, "png");
-        tex->mHeight = 0;
-        ifstream file(pModel->textures[i], ios::binary | ios::ate);
-        streamsize size = file.tellg();
-        file.seekg(0, ios::beg);
-        char *buffer = new char[size];
-        file.read(buffer, size);
-        if(file.bad()) {
-            string err("PMX: Can't open texture file");
-            err.append(pModel->textures[i]);
-            throw DeadlyExportError(err);
-        }
-        tex->pcData = (aiTexel*)buffer; 
+      pScene->mMeshes[i] = CreateMesh(pModel, indexStart, indexCount);
+      pScene->mMeshes[i]->mName = pModel->materials[i].material_name;
+      pScene->mMeshes[i]->mMaterialIndex = i;
+      indexStart += indexCount;
     }
     */
 
+  // create bones
+  aiBone *pBone = new aiBone[pModel->bone_count];
+  for (auto i = 0; i < pModel->bone_count; i++) {
+    pBone[i].mName = pModel->bones[i].bone_name;
+  }
+
+  // create node hierarchy for bone position
+  auto bone_root_index = 0; // Default root: Bone 0 "Body" / "全ての親"
+  aiNode **ppNode = new aiNode *[pModel->bone_count];
+  for (auto i = 0; i < pModel->bone_count; i++) {
+    ppNode[i] = new aiNode(pModel->bones[i].bone_name);
+  }
+
+  for (auto i = 0; i < pModel->bone_count; i++) {
+    const pmx::PmxBone &bone = pModel->bones[i];
+    std::cout << "Bone " << i << ":" << std::endl;
+    std::cout << bone.bone_name << std::endl;
+    std::cout << bone.bone_english_name << std::endl;
+    std::cout << "position " << bone.position[0] << " " << bone.position[1]
+              << " " << bone.position[2] << std::endl;
+    std::cout << "parent_index " << bone.parent_index << std::endl;
+    std::cout << "level " << bone.level << std::endl;
+    std::cout << "bone_flag " << bone.bone_flag << std::endl;
+    std::cout << "offset " << bone.offset[0] << " " << bone.offset[1] << " "
+              << bone.offset[2] << std::endl;
+    std::cout << "target_index" << bone.target_index << std::endl;
+
+    if (bone.parent_index < 0) {
+      pScene->mRootNode->addChildren(1, ppNode + i);
+      bone_root_index = i;
+    } else {
+      ppNode[bone.parent_index]->addChildren(1, ppNode + i);
+
+      aiVector3D v3 = aiVector3D(
+          bone.position[0] - pModel->bones[bone.parent_index].position[0],
+          bone.position[1] - pModel->bones[bone.parent_index].position[1],
+          bone.position[2] - pModel->bones[bone.parent_index].position[2]);
+      aiMatrix4x4::Translation(v3, ppNode[i]->mTransformation);
+      std::cout << ppNode[i]->mTransformation.a1 << ' '
+                << ppNode[i]->mTransformation.a2 << ' '
+                << ppNode[i]->mTransformation.a3 << ' '
+                << ppNode[i]->mTransformation.a4 << ' '
+                << ppNode[i]->mTransformation.b1 << ' '
+                << ppNode[i]->mTransformation.b2 << ' '
+                << ppNode[i]->mTransformation.b3 << ' '
+                << ppNode[i]->mTransformation.b4 << ' '
+                << ppNode[i]->mTransformation.c1 << ' '
+                << ppNode[i]->mTransformation.c2 << ' '
+                << ppNode[i]->mTransformation.c3 << ' '
+                << ppNode[i]->mTransformation.c4 << ' '
+                << ppNode[i]->mTransformation.d1 << ' '
+                << ppNode[i]->mTransformation.d2 << ' '
+                << ppNode[i]->mTransformation.d3 << ' '
+                << ppNode[i]->mTransformation.d4 << ' ' << std::endl;
+    }
+  }
+
+  // use SkeletonMeshBuilder to generate bone vertices
+  SkeletonMeshBuilder dummyMeshbuild(pScene, ppNode[bone_root_index]);
+
+  // create textures, may be dummy?
+  /*
+  pScene->mNumTextures = pModel->texture_count;
+  pScene->mTextures = new aiTexture*[pScene->mNumTextures];
+  for( unsigned int i = 0; i < pScene->mNumTextures; ++i) {
+      aiTexture *tex = new aiTexture;
+      pScene->mTextures[i] = tex;
+      strcpy(tex->achFormatHint, "png");
+      tex->mHeight = 0;
+      ifstream file(pModel->textures[i], ios::binary | ios::ate);
+      streamsize size = file.tellg();
+      file.seekg(0, ios::beg);
+      char *buffer = new char[size];
+      file.read(buffer, size);
+      if(file.bad()) {
+          string err("PMX: Can't open texture file");
+          err.append(pModel->textures[i]);
+          throw DeadlyExportError(err);
+      }
+      tex->pcData = (aiTexel*)buffer;
+  }
+  */
+
+  /*
     // create materials
     pScene->mNumMaterials = pModel->material_count;
-    pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
-    for( unsigned int i = 0; i < pScene->mNumMaterials; i++ ) {
-        pScene->mMaterials[i] = CreateMaterial(&pModel->materials[i], pModel);
+    pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials];
+    for (unsigned int i = 0; i < pScene->mNumMaterials; i++) {
+      pScene->mMaterials[i] = CreateMaterial(&pModel->materials[i], pModel);
     }
 
-    // Convert everything to OpenGL space
-    MakeLeftHandedProcess convertProcess;
-    convertProcess.Execute(pScene);
+  // Convert everything to OpenGL space
+  MakeLeftHandedProcess convertProcess;
+  convertProcess.Execute(pScene);
 
-    FlipUVsProcess uvFlipper;
-    uvFlipper.Execute(pScene);
-
-    FlipWindingOrderProcess windingFlipper;
-    windingFlipper.Execute(pScene);
+  FlipUVsProcess uvFlipper;
+  uvFlipper.Execute(pScene);
 
+  FlipWindingOrderProcess windingFlipper;
+  windingFlipper.Execute(pScene);
+    */
 }
 
 // ------------------------------------------------------------------------------------------------
-aiMesh* MMDImporter::CreateMesh(const pmx::PmxModel* pModel, const int indexStart, const int indexCount)
-{
-    aiMesh *pMesh = new aiMesh;
-
-    pMesh->mNumVertices = indexCount;
-
-    pMesh->mNumFaces = indexCount / 3;
-    pMesh->mFaces = new aiFace[ pMesh->mNumFaces ];
-
-    for( unsigned int index = 0; index < pMesh->mNumFaces; index++ ) {
-        const int numIndices = 3; // trianglular face
-        pMesh->mFaces[index].mNumIndices = numIndices;
-        unsigned int *indices = new unsigned int[numIndices];
-        indices[0] = numIndices * index;
-        indices[1] = numIndices * index + 1;
-        indices[2] = numIndices * index + 2;
-        pMesh->mFaces[index].mIndices = indices;
-    }
-
-    pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ];
-    pMesh->mNormals = new aiVector3D[ pMesh->mNumVertices ];
-    pMesh->mTextureCoords[0] = new aiVector3D[ pMesh->mNumVertices ];
-    pMesh->mNumUVComponents[0] = 2;
-
-    // additional UVs
-    for( int i = 1; i <= pModel->setting.uv; i++ ) {
-        pMesh->mTextureCoords[i] = new aiVector3D[ pMesh->mNumVertices ];
-        pMesh->mNumUVComponents[i] = 4;
-    }
-
-    for( int index = 0; index < indexCount; index++ ) {
-        const pmx::PmxVertex *v = &pModel->vertices[pModel->indices[indexStart + index]];
-        const float* position = v->position;
-        pMesh->mVertices[index].Set(position[0], position[1], position[2]);
-        const float* normal = v->normal;
-        pMesh->mNormals[index].Set(normal[0], normal[1], normal[2]);
-        pMesh->mTextureCoords[0][index].x = v->uv[0];
-        pMesh->mTextureCoords[0][index].y = v->uv[1];
-        for( int i = 1; i <= pModel->setting.uv; i++ ) {
-            // TODO: wrong here? use quaternion transform?
-            pMesh->mTextureCoords[i][index].x = v->uva[i][0];
-            pMesh->mTextureCoords[i][index].y = v->uva[i][1];
-        }
+aiMesh *MMDImporter::CreateMesh(const pmx::PmxModel *pModel,
+                                const int indexStart, const int indexCount) {
+  aiMesh *pMesh = new aiMesh;
+
+  pMesh->mNumVertices = indexCount;
+
+  pMesh->mNumFaces = indexCount / 3;
+  pMesh->mFaces = new aiFace[pMesh->mNumFaces];
+
+  for (unsigned int index = 0; index < pMesh->mNumFaces; index++) {
+    const int numIndices = 3; // trianglular face
+    pMesh->mFaces[index].mNumIndices = numIndices;
+    unsigned int *indices = new unsigned int[numIndices];
+    indices[0] = numIndices * index;
+    indices[1] = numIndices * index + 1;
+    indices[2] = numIndices * index + 2;
+    pMesh->mFaces[index].mIndices = indices;
+  }
+
+  pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
+  pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
+  pMesh->mTextureCoords[0] = new aiVector3D[pMesh->mNumVertices];
+  pMesh->mNumUVComponents[0] = 2;
+
+  // additional UVs
+  for (int i = 1; i <= pModel->setting.uv; i++) {
+    pMesh->mTextureCoords[i] = new aiVector3D[pMesh->mNumVertices];
+    pMesh->mNumUVComponents[i] = 4;
+  }
+
+  for (int index = 0; index < indexCount; index++) {
+    const pmx::PmxVertex *v =
+        &pModel->vertices[pModel->indices[indexStart + index]];
+    const float *position = v->position;
+    pMesh->mVertices[index].Set(position[0], position[1], position[2]);
+    const float *normal = v->normal;
+    pMesh->mNormals[index].Set(normal[0], normal[1], normal[2]);
+    pMesh->mTextureCoords[0][index].x = v->uv[0];
+    pMesh->mTextureCoords[0][index].y = v->uv[1];
+    for (int i = 1; i <= pModel->setting.uv; i++) {
+      // TODO: wrong here? use quaternion transform?
+      pMesh->mTextureCoords[i][index].x = v->uva[i][0];
+      pMesh->mTextureCoords[i][index].y = v->uva[i][1];
     }
+  }
 
-    return pMesh;
+  return pMesh;
 }
 
 // ------------------------------------------------------------------------------------------------
-aiMaterial* MMDImporter::CreateMaterial(const pmx::PmxMaterial* pMat, const pmx::PmxModel* pModel)
-{
-    aiMaterial *mat = new aiMaterial();
-    aiString name(pMat->material_english_name);
-    mat->AddProperty(&name, AI_MATKEY_NAME);
-
-    aiColor3D diffuse(pMat->diffuse[0], pMat->diffuse[1], pMat->diffuse[2]);
-    mat->AddProperty(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
-    aiColor3D specular(pMat->specular[0], pMat->specular[1], pMat->specular[2]);
-    mat->AddProperty(&specular, 1, AI_MATKEY_COLOR_SPECULAR);
-    aiColor3D ambient(pMat->ambient[0], pMat->ambient[1], pMat->ambient[2]);
-    mat->AddProperty(&ambient, 1, AI_MATKEY_COLOR_AMBIENT);
-
-    float opacity = pMat->diffuse[3];
-    mat->AddProperty(&opacity, 1, AI_MATKEY_OPACITY);
-    float shininess = pMat->specularlity;
-    mat->AddProperty(&shininess, 1, AI_MATKEY_SHININESS_STRENGTH);
-    
-    aiString texture_path(pModel->textures[pMat->diffuse_texture_index]);
-    mat->AddProperty(&texture_path, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
-    int mapping_uvwsrc = 0;
-    mat->AddProperty(&mapping_uvwsrc, 1, AI_MATKEY_UVWSRC(aiTextureType_DIFFUSE, 0));
-
-    return mat;
+aiMaterial *MMDImporter::CreateMaterial(const pmx::PmxMaterial *pMat,
+                                        const pmx::PmxModel *pModel) {
+  aiMaterial *mat = new aiMaterial();
+  aiString name(pMat->material_english_name);
+  mat->AddProperty(&name, AI_MATKEY_NAME);
+
+  aiColor3D diffuse(pMat->diffuse[0], pMat->diffuse[1], pMat->diffuse[2]);
+  mat->AddProperty(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
+  aiColor3D specular(pMat->specular[0], pMat->specular[1], pMat->specular[2]);
+  mat->AddProperty(&specular, 1, AI_MATKEY_COLOR_SPECULAR);
+  aiColor3D ambient(pMat->ambient[0], pMat->ambient[1], pMat->ambient[2]);
+  mat->AddProperty(&ambient, 1, AI_MATKEY_COLOR_AMBIENT);
+
+  float opacity = pMat->diffuse[3];
+  mat->AddProperty(&opacity, 1, AI_MATKEY_OPACITY);
+  float shininess = pMat->specularlity;
+  mat->AddProperty(&shininess, 1, AI_MATKEY_SHININESS_STRENGTH);
+
+  aiString texture_path(pModel->textures[pMat->diffuse_texture_index]);
+  mat->AddProperty(&texture_path, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0));
+  int mapping_uvwsrc = 0;
+  mat->AddProperty(&mapping_uvwsrc, 1,
+                   AI_MATKEY_UVWSRC(aiTextureType_DIFFUSE, 0));
+
+  return mat;
 }
 
 // ------------------------------------------------------------------------------------------------
 
-}   // Namespace Assimp
+} // Namespace Assimp
 
 #endif // !! ASSIMP_BUILD_NO_MMD_IMPORTER