忍者ブログ


[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。



[ 2018/12/20 00:47 | ]
Android課題開発2
バイト三昧な期間も終わり、ようやく宿題に手をつけられるように。

提出日は8日、あと3日しかない!!
(こーなったら手抜きすっか。)
ワイヤーフレームが使えない!?
前回の参考文献に示したサンプルコードのお陰で、前回の時点で図形(ポリゴン)の描画はできる状態になりました。

ということで、さっそく正立方体をワイヤーフレームで描画してみることに。
描画処理はサンプルでいうと、GLTutorialBaseを継承したクラスの「drawFrame(GL10)」(オーバーライド)に書いていきます。

FloatBufferに座標値を入れて、glVertexPointer()で登録、glEnableClientState()で登録したものを有効にし、glDrawArrays(GL_LINE_LOOP)で描くだけ!

おおお!!!マインスイーパーに最低限必要な正立方体が描けましたー!
この中にハタとかハテナとか数字が出てくるんですねー。(完成すればね。orz)

さて、次はこの立方体を移動したり回転させてみます。
さっきの描画処理の前後に、glPushMatrix()とglPopMatrix()を加え、回転や移動をして描画した後の他の描画処理に影響が出ないようにします。
今回は1.5だけ右に移動させ、その座標系で45度左+下回転させます。
glRotatef(45.0f, 1, 1, 0)で、左(第2)+下(第3引数)回転45度(第1引数)に回転
glTranslatef(1.5f, 0, 0)で右(+x方向)に1.5進ませます。

この順番をglTranslatef -> glRotatefとすると、回転してから移動してしまいます。
おそらく回転・移動行列の計算順の関係で、プログラムに書いたものと逆になってしまうのだと思います。

さて、実行!!

うん、ちゃんと回転移動できてま・・・あれ?
。。。画面外に出るとダメなようです。

今回実装した立方体の描画は、「前面」「後面」「その他の柱4つ」の順で描画しており、それぞれGL_LINE_LOOP、GL_LINE_LOOP、GL_LINE_STRIP(x4つ)をglDrawArrays()に渡し、ワイヤーフレームとして描画しています。(下図)


GL_LINE_LOOPは、頂点を全て結び、最後と最初の頂点も結ぶ、
GL_LINE_STRIPは、同じく全て結ぶが、最後と最初の頂点は結ばない。
画面外にでると、この最後と最初をうまく結べないらしいです。

やっぱり手抜きは不可能なようですw
諦めて透過色を持ったテクスチャを使います。

テクスチャを貼る
どうでもいいんですが、今回参考にしているサンプル、参考にしている僕が言うのは大変失礼だけど、単純なミスが多すぎ。
立方体にテクスチャを貼るとき、テクスチャの座標を「左下(0, 0)」として上下逆さまに貼付けちゃったり、画像の読み込みの際、符号付き8bit変数であるbyte型で0〜255のRGB値を読み込んでしまったり。
でも完全なサンプルだと、修正箇所が見当たらない故に勉強にはならないんでしょうね。

さて、テクスチャを使ってみようと思います。
まず予備知識から。
 ・画像サイズは縦横2n
 ・とりあえずpngとbmpが読み込める(他の形式は調べていない)
 ・透過色が使える

さっき作ったワイヤーフレームの箱を、テクスチャで作ります。
使用するテクスチャは以下のものです。

わかりやすいように、透過色を黒で塗りました。が、背景が白だからやっぱり見にくいですね。。。

このファイルをテクスチャとして読み込む処理ですが、今回はそんなこと考えている時間はないので、サンプルを(修正しつつ)そのまま使っちゃいます。
GLTutorialBaseクラスのloadTexture(GL10, Bitmap, boolean)をコピーします。

修正箇所は、変数alphaとredとgreenとblueの型をbyteからintに変更し、
その下にあるib.put()の引数を
(red<<24) + (green<<16) + (blue<<8) + alpha
とします。
これで透過色とRGB色の値が正しいテクスチャ画像を作成できます。

テクスチャの利用の仕方は、サンプル内のGLTutorialNine.javaに全部書いてあるんですが、一応メモ。

<画像をロード>
・Bitmap bmp = BitmapFactory.decodeResource(Context, 画像)
(Contextを使う ∴ コンストラクタ上で上記文を実行する)
<画像からテクスチャ作成>
・int tex = loadTexture(GL10, bmp, false)
(オーバーライドのinit()などから呼び出す)
<描画時にテクスチャを適用(テクスチャの切り替えができる)>
・glBindTexture(GL_TEXTURE_2D, tex)
・glActiveTexture(tex)
(drawFrame()内で使用、切り替えしない場合は必要なし)

描画の際は、透過色の先が見えるように、奥行きの比較をしないようにします。
・glDisable(GL_DEPTH_TEST)
あとは、透過色を有効にします。
・glEnable(GL_BLEND)
・glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
テクスチャを有効にします。
・glEnable(GL_TEXTURE_2D)

テクスチャを貼り付ける際、張り付けられる側の座標に「UV座標」を設定しなければならないので、これを設定します。
UV座標は簡単に言うと、貼り付ける縦横の開始・終了位置です。
この設定値は、0〜1の範囲で指定します(画像サイズの割合)。
頂点座標(xyz)1つに対し、UV座標(uv)1つ設定する必要があります。

本項の最初に言った「上下逆さまに貼り付け」とは、テクスチャ画像の座標(x, y)は左上を中心(0, 0)とし、右下方向へ「+」となる一方で、頂点の座標は左・上・手前の方向へ「+」の値となるため、テクスチャ画像の座標を3D座標系のxとyと見てしまうと、上下が逆になる、ということです。

以上で前準備は完了、描画をします。
glVertexPointer()で頂点座標を、glTexCoordPointer()でUV座標を設定します。
そしてglEnableClientState()で、GL_VERTEX_ARRAYとGL_TEXTURE_COORD_ARRAYを有効にし、glDrawArrays(GL_TRIANGLE_STRIP)で描いてあげると・・・

できた!!
奥の描画物が手前に上書き描画されてしまっているのは、奥行きの比較をなくしてしまったためです。
試しに比較を有効にしてみると・・・

後ろのフレームが見えません。

今回のような完全な透明部分と、完全な不透明部分とが存在する場合は、Zソート法を使うとよいらしいですが、面倒なので時間がある時に考えてみます。

拍手[0回]

PR



[ 2010/01/05 02:46 | Comments(0) | TrackBack(0) | プログラム ]

トラックバック

トラックバックURL:

コメントを投稿する






<< Android課題開発3  |  ホーム  |  Android課題開発1 >>