ofMeshの基礎

           
##始めに
今回はopenFrameworksでよく使われるofMesh及びofVboMeshに関しての記事です.
内容的には、まだopenFrameworksを始めたばかりでofMeshをこれから使ってみたいと思っている人向けだと思います.
ofSpherePrimitiveやofBoxPrimitiveなんかも内部ではofMeshを使って描画しています.
サンプルコード→[meshSample](https://github.com/SakuragiYoshimasa/meshSample)
今回のサンプルでは[前回の記事](http://qiita.com/Yoshimasa/items/330507633f3eff6e144a)のSceneElementとSceneManagerも用いています.

##ofMeshと頂点の繋ぎ方
ofMeshとはポリゴンを構成する頂点の座標とその色やテクスチャ座標の集合であり, またその頂点の描画順を持つことが出来ます. 描画順に関しては特に必ず必要という訳ではありませんが知っておいて損はないでしょう.

今回は簡単な四角形を書いてみます
こんな感じのイメージで頂点を４つ追加します.
<img width="300" alt="FPS_45_5791.png" src="https://qiita-image-store.s3.amazonaws.com/0/68570/197ee272-0880-bbb1-bd27-366691cda43f.png">

```cpp:SquereSample.h

#include "SceneElement.cpp"
class SquereSample : public SceneElement {
    ....
    ofMesh mesh;
}
```

```cpp:SquareSample.cpp
void SquereSample::init(){
    mesh.addVertex(ofVec3f(100,100,0));
    mesh.addVertex(ofVec3f(100,200,0));
    mesh.addVertex(ofVec3f(200,200,0));
    mesh.addVertex(ofVec3f(200,100,0));
}

void SquereSample::draw(){
    mesh.draw(); 
    ofTranslate(200, 0);
    mesh.drawWireframe(); //線のみ表示
}
```

しかしこれを実行しても…
<img width="411" alt="FPS_45_5791.png" src="https://qiita-image-store.s3.amazonaws.com/0/68570/836761a5-a99f-064b-7b7b-30e113b637b2.png">
三角形一個しかできないですね.これはopenGLにはポリゴンの頂点の繋ぎ方が定められていて、デフォルトではGL_TRIANGLESという設定になっているからです。この繋ぎ方では最初の頂点から順に３つづつ頂点を組み合わせて三角形を描画します.ですので四角形を書こうと思うと以下のように合計6個の頂点を追加しなければなりません.

```cpp:SquareSample.cpp
void SquereSample::init(){
    mesh.addVertex(ofVec3f(100,100,0));
    mesh.addVertex(ofVec3f(100,200,0));
    mesh.addVertex(ofVec3f(200,200,0));
    mesh.addVertex(ofVec3f(100,100,0));
    mesh.addVertex(ofVec3f(200,100,0));
    mesh.addVertex(ofVec3f(200,200,0));
}
```
こうすると以下のように四角形を描くことができます.
<img width="398" alt="FPS_59_4061.png" src="https://qiita-image-store.s3.amazonaws.com/0/68570/bdf2ac3b-a792-0e47-8939-8882062af470.png">

しかしこれでは同じ頂点を繰り返し用いるのにも関わらず追加する必要がありますので色々と都合が悪いです.ここで先に記述した頂点の描画順を指定することで再利用していきます.
init()内を以下のように書き換えindexを利用することでも上記の四角形を描くことが可能です.
基本的には頂点を幾つかの三角形で常に共有したい場合は以下のようにindexを用いると良いと思いますが、最後に掲載した動画のように個々の三角形として扱いたい場合はindexは使わずにいた方が良いです.


```cpp:SquareSample.cpp
void SquereSample::init(){
    mesh.addVertex(ofVec3f(100,100,0));
    mesh.addVertex(ofVec3f(100,200,0));
    mesh.addVertex(ofVec3f(200,200,0));
    mesh.addVertex(ofVec3f(200,100,0));

    mesh.useIndices = true;
    mesh.addIndex(0);
    mesh.addIndex(1);
    mesh.addIndex(2);
    mesh.addIndex(0);
    mesh.addIndex(3);
    mesh.addIndex(2);
}
```

今回は頂点の繋ぎ方でGL_TRIANGLESを例にしましたが他にも以下の繋ぎ方があります。
・GL_POINTS
・GL_LINES
・GL_LINE_STRIP
・GL_LINE_LOOP
・GL_TRIANGLE_STRIP
・GL_TRIANGLE_FAN
・GL_QUAD_STRIP
・GL_POLYGON

それぞれの繋ぎ方に関してはこちらを参考にしてください→[Document](http://openframeworks.jp/documentation/3d/ofMesh.html)

例えばGL_LINESにして四角形を書こうと思うと以下のように書けます.

```cpp:SquareSample.cpp
void SquereSample::init(){
    
    mesh.addVertex(ofVec3f(100,100,0));
    mesh.addVertex(ofVec3f(100,200,0));
    mesh.addVertex(ofVec3f(200,200,0));
    mesh.addVertex(ofVec3f(200,100,0));

    mesh.setMode(OF_PRIMITIVE_LINES);
    mesh.addIndex(0);
    mesh.addIndex(1);
    mesh.addIndex(1);
    mesh.addIndex(2);
    mesh.addIndex(2);
    mesh.addIndex(3);
    mesh.addIndex(3);
    mesh.addIndex(0);
}
```

しかしこの場合、面という概念が存在しないので上図のように塗りつぶされることはありません.



また更に頂点の色を指定することができます.
頂点の繋ぎ方はGL_TRIANGLESとして説明していきます.
Meshには頂点と同じように以下のように頂点の色を指定します.

```cpp:SquareSample.cpp
void SquereSample::init(){
    
    ...

    mesh.addColor(ofColor(255,0,0));
    mesh.addColor(ofColor(0,255,0));
    mesh.addColor(ofColor(0,0,255));
    mesh.addColor(ofColor(0,0,0));
}

```
これで各頂点に色を付ける事が出来ました.
<img width="391" alt="FPS_45_4799.png" src="https://qiita-image-store.s3.amazonaws.com/0/68570/1f0125af-5350-2823-d622-7ff893ffadc3.png">

以上の原理さえわかっていれば色んな図形を描く事ができますね.
他にもcolorを指定せずにMeshに画像のデータを貼り付けることもできたり、頂点の順番によって法線が決まることとその影響等もありますが今回は省略します.要望があれば追記したいと思います.


##終わりに
以上がofMeshについての基本的な内容でした.oFで3Dモデルを読み込んだりちょっと変わった図形を描きたい時にも使えるので深く押さえておきたいところです.今回書いた内容を用いれば下に貼り付けたデモのようなガラスが割れるような表現も出来ますし, よくあるPointCloudなんかもできちゃいますね.
Meshをもっと使い倒していきたいところです.

[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/icTsxBk62xo/0.jpg)](http://www.youtube.com/watch?v=icTsxBk62xo)