CDR6275

Michio SHIRAISHI Official Site


OpenGL 4.1とOpenGL ES SL 1.0で学ぶ3次元コンピュータグラフィックス

東邦大学理学部情報科学科 白石路雄
最終更新: 2014年2月20日

4. モデリング変換

4.1 モデルを読み込む

 モデリング変換について学ぶ前に、3次元の形状モデルを読み込んでみましょう。三角形などを座標変換してもいいのですけれど、おもしろくないですからね。

 使用するデータは、MikuMikuDanceに含まれている3次元モデルを使います。3次元モデルにはさまざまなフォーマットがありますが、MikuMikuDanceで用いられているのはpmd(pmx)と呼ばれるフォーマットです。そのフォーマットのファイルを読み込むライブラリとして、MeshIOがありますので、これを利用します。

 ファイルを読み込む部分は以下のようになっています。

  char* modelFilePath = nullptr;
  if(strlen(modelSearchPath) == 0){
    modelFilePath = new char[strlen("miku.pmd")+1];
    strcpy(modelFilePath, "miku.pmd");
  }
  else{
    modelFilePath = new char[strlen(modelSearchPath)+strlen("miku.pmd")+2];
    strcpy(modelFilePath, modelSearchPath);
    strcat(modelFilePath, "/");
    strcat(modelFilePath, "miku.pmd");
  }
    
  meshio::pmd::IO io;
  io.read(modelFilePath);
  numVertices = (int)io.vertices.size();
  float* vertexCoordinates = new float[numVertices*3];
  std::vector<meshio::pmd::Vertex>::iterator vertexIter = io.vertices.begin();
  int i=0;
  while(vertexIter!=io.vertices.end()){
    meshio::pmd::Vertex vertex = *vertexIter;
    vertexCoordinates[3*i+0] = 0.07f*vertex.pos.x;
    vertexCoordinates[3*i+1] = 0.07f*vertex.pos.y;
    vertexCoordinates[3*i+2] = 0.07f*vertex.pos.z;
    i++;
    vertexIter++;
  }
  numFaces = (int)io.indices.size()/3;
  faceVertexIndices = new unsigned int[numFaces*3];
  std::vector<unsigned short>::iterator faceIter = io.indices.begin();
  i=0;
  unsigned int max = 0;
  while(faceIter!=io.indices.end()){
    faceVertexIndices[i++] = *faceIter;
    if(max < *faceIter) max = *faceIter;
    faceIter++;
  }
  delete modelFilePath;

 最初にmodelFilePathを作成しています。環境の違いを吸収するために、modelSearchPathが設定されている場合は、modelSearchPathの後ろにmiku.pmdを追加した文字列が設定されます。

 これ以降は、MeshIOの使い方にもなるのですが、io.readとするとファイルを読み込みます。いったん読み込むと、io.vertices.size()として頂点の数を読み込むことができます。その後に、

  float* vertexCoordinates = new float[numVertices*3];

として、頂点数を3倍した数の配列vertexCoordinatesを確保します。次に、MeshIOで定義されているイテレータを使って、vertexCoordinatesに値を入れていきます。ここで、初音ミクのモデルで定義されている座標が大きいために、0.07倍してから代入しています。

 面を構成する頂点インデックスも同様にすると読み込むことができます。

 実行結果は次のようになります。

model-load

 お気づきの通り、このモデルでは原点を足元として、yが正の領域に定義されていることが分かります。はみ出ていますが、後で調整していきます。