2015年6月23日火曜日

OpenGLでの描画

OpenGLでの描画

OpenGLを使って描画する。

三角形を例にします。
流れとしては頂点を設定して、描画って感じです。

頂点の設定

以下の手順で頂点を設定します。

Step1. 頂点の座標(X,Y,Z)を配列で定義する。

float[] vertices = {
  0.0f, 1.0f, 0.0f, //頂点0 (上)
  0.0f, 0.0f, 0.0f, //頂点1 (左下)
  1.0f, 1.0f, 0.0f, //頂点2 (右上)
};

Step2. バッファのメモリ確保

座標データ数x4倍のメモリを確保します。
※4倍しているのはfloatが4byte扱いの為。

ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);

Step3. ネイティブのエンディアン指定

nativeのエンディアンを取得し、設定します。

vbb.order(ByteOrder.nativeOrder());

Step4. ByteBuffer型のオブジェクトをFloatBufferに変換

FloatBuffer mVertexBuffer = vbb.asFloatBuffer();

Step5. Step4で変換されたFloatBufferに最初の頂点座標(float配列)をセット

mVertexBuffer.put(vertices);

Step6. 書き込み位置の調整
書き込みが発生するたびに次書き込むための位置が1進んでしまうため、それを戻す処理を行っています。

mVertexBuffer.position(0);

[参考]
http://librastudio.hatenablog.com/entry/2013/08/19/010615

描画の設定

Step1. 頂点配列を有効にする。

   glEnableClientState(int array)を使って、どの配列を使って、描画するかを指定します。
   今回の場合は、頂点を設定しているので引数は、GL_VERTEX_ARRAYとする。
   

変数 意味 参照
GL_COLOR_ARRAY カラー配列 glColorPointer()
GL_EDGE_FLAG_ARRAY エッジフラグ配列 glEdgeFlagPointer()
GL_INDEX_ARRAY 指標配列 glIndexPointer()
GL_NORMAL_ARRAY 法線配列 glNormalPointer()
GL_TEXTURE_COORD_ARRAY テクスチャ座標配列 glTexCoordPointer()
GL_VERTEX_ARRAY 頂点配列 glVertexPointer()

glEnableClientState(GL10.GL_VERTEX_ARRAY);

Step2. 頂点配列を定義する。

glVertexPointer((int size, int type, int stride,java.nio.Buffer pointer)

変数 意味 備考
size 頂点データのサイズ 2次元なら2,3次元なら3,Wを含めるなら4
type GL_SHORT、GL_INT、GL_FLOAT、GL_DOUBLE
stride 連続する頂点間でのバイト・オフセット 0 を指定すれば、頂点の情報が配列ないに隙間なく入っている
pointer 座標情報を含む配列へのポインタ

X,Y,Z座標を指定しているのでsizeは3。

glVertexPointer(3,GL10.GL_FLOAT,0,mVertexBuffer);

Step3. 法線ベクトルの追加

ここでいう法線ベクトルとは・・・  面に垂直な長さが1のベクトル。

1)p0→p1という向きのベクトルv1(= p1 - p0)の算出
2)同様に、p0→p2という向きのベクトルv2(= p2 - p0)の算出。
3)v2からv1への外積v2×v1の算出
4)外積の長さの算出
5)外積をその長さで割り、正規化する。  

※glEnable(GL_NORMALIZE)とすれば法線ベクトルを単位ベクトルにする必要はないようです。

今回の場合は、以下なので
0.0f, 1.0f, 0.0f, //頂点0 (上)
0.0f, 0.0f, 0.0f, //頂点1 (左下)
1.0f, 1.0f, 0.0f, //頂点2 (右上)

1) p1-p0 = 0.0f, -1.0f, 0.0f
2) p2-p0 = 1.0f, 0.0f, 0.0f
3)外積は以下で求めると、
 -1*0-0*0,0*1-0*0,0*0-(-1*1)=0.0f, 0.0f,1.0f
 となる。




なので、

4) 外積の長さは以下のようにすでに1なので、単位ベクトルになっている。

ので、

glNormal3f(0.0f, 0.0f, 1.0f)

※四角形の場合は三角形2つに分割して、その三角形2つの面法線ベクトルを平均化するらしい
※三角形の場合はなくても描画できました。

Step4. 描画

glDrawArrays(int mode,int first,int count)を使って描画します。
描画する面に対してglNormal, glDrawArraysをペアで設定する必要があります。
三角形の場合は1つでよいが立方体の場合は6面あるので、6ペア必要です。

変数 意味
mode 描画方法
first はじめに描画する頂点番号
count 描画する頂点数

今回の場合は三角形を塗りつぶしたいので、以下でいいようです。

glDrawArrays(GL10.GL_GL_TRIANGLES, 0, 3);

参考
http://sky.geocities.jp/freakish_osprey/opengl/opengl_normalvecotr.htm
http://opengl.softwarecarpenter.biz/?eid=1075451
http://atelier-yoka.com/dev_android/p_main.php?file=apigl10gldrawarrays

0 件のコメント :

コメントを投稿