前回は、Graphics.drawTriangles()メソッドにより、三角形に分けた領域をビットマップで塗った。今回は、このいわゆる「テクスチャマッピング」について、さらに解説を加える。このメソッドの使い方は奥深い。その練習も兼ねよう。
矩形のビットマップを任意の四角形に変形する
まずは、前回のおさらいから入る。Graphics.drawTriangles()メソッドを使えば、正方形のビットマップも自由な四角形に変形できる。たとえば、100×100ピクセルのビットマップを、以下のような四角形に塗るとしよう。なお、位置合わせがしやすいように、Shapeインスタンスはステージの真ん中におく。したがって、基準点(0, 0)は中央になる。各頂点には、わかりやすいように整数の頂点番号(0~3)を添えた。
Graphics.drawTriangles()メソッドは、第1引数のVectorオブジェクト(Numberベース型)で三角形の頂点座標を順に納め、第3引数のVectorオブジェクト(Numberベース型)にはビットマップの対応するuv座標を定めて渡した。フレームアクションは、つぎのスクリプト1のようになるだろう。
[ムービープレビュー]を確かめると、指定した四角形にビットマップが変形して塗られる(図2)。結果はまったく問題ない。しかし、スクリプト1を見ると、四角形の頂点は4つなのに、Graphics.drawTriangles()メソッドに渡した第1引数と第3引数のVectorオブジェクト(頂点座標とuv座標)にはそれぞれ6組、つまり12の数値エレメントが加えられている。ふたつの三角形に頂点1と2が重複しているからだ(前掲図1参照)。
テクスチャマッピングは、面を細かな三角形に分けてビットマップを貼っていく手法である。三角形の数が多くなると、頂点の重複もそれに伴って増えてしまう。Graphics.drawTriangles()メソッドの第2引数を使えば、座標の重複は避けることができる。
三角形の頂点の組を定める - Graphics.drawTriangles()メソッドの第2引数
前掲スクリプト1のGraphics.drawTriangles()メソッドに渡す引数の指定を変えよう。第1引数(vertices)の頂点座標は、重複しない4組つまり8つの数値エレメントのみVectorオブジェクトに加える。対応する第3引数(uvData)のVectorオブジェクトも、同じく8つの数値エレメントを納めることになる。しかし、これではどの3頂点で三角形をつくるのかがわからない。その3頂点の組合わせを決めるのが第2引数だ。
Graphics.drawTriangles()メソッドの第2引数はintベース型のVectorオブジェクトで、三角形の3頂点番号の組を納める。頂点番号は0から始まる整数で、第1引数に納めた座標の順序にしたがう。3頂点番号がひと組になるので、スクリプト1の例なら三角形ふたつで、6つの整数を加えればよい。その手直しをしたのが、つぎのスクリプト2だ。
Graphics.drawTriangles()メソッドに渡す第1引数のVectorオブジェクト(Numberベース型)には、重複のない4頂点の座標を納めた。その順序は前掲図1の頂点番号に合わせている。第3引数のVectorオブジェクト(Numberベース型)にも、もちろん第1引数に対応するuv座標を4組加えた。
そして、第2引数のintベース型Vectorオブジェクト(indices)には、ふたつの三角形の3頂点番号の組を定めた。3頂点番号の順序は、今のところ気にしなくとも構わない。ただ、後のちのため、本連載では時計回りに決める[1]。
[ムービープレビュー]を確かめると、描かれるビットマップは前掲スクリプト1と変わらない(前掲図2)。しかし、座標の数が減ると、内部的な負荷は軽くなる[2]。また、座標と三角形の指定を分けることで、スクリプトも扱いやすくなる。
描画する三角形の座標をマウスクリックで動かす
今回の最後は、テクスチャマッピングに簡単なインタラクションを加える。下図3のように正方形を4つの三角形に分け、インスタンス上をマウスクリックしたとき中央の座標をその位置に動かしてみる。ちょっとしたモーフィング効果だ。
Shapeインスタンスはマウスクリックを受け取れない。そこで、Spriteインスタンスに替えてビットマップを塗ることにする。あとは初めの描画については、三角形が4つに増えたこと以外、前掲スクリプト2と考え方は同じだ[3]。マウスクリックで動かす頂点座標は、頂点番号0に設定している。
Spriteインスタンスをマウスクリック(InteractiveObject.mouseDownイベント)したときのリスナー関数(xDraw())は、クリック位置のxy座標でVectorオブジェクト(vertices)の頂点0の数値エレメントを書替えたうえで、Graphics.drawTriangles()メソッドに渡して再描画している。クリック時のSpriteインスタンスの基準点から見たマウスポインタのxy座標は、MouseEventオブジェクトのMouseEvent.localX/MouseEvent.localYプロパティで得られる。
[ムービープレビュー]でSpriteインスタンスをクリックすると、その位置がテクスチャの中心になるように変形して描かれる(図4)。テクスチャの中心になっている頂点0の座標は、前掲図3のとおり4つの三角形すべてに共通している。もし、Graphics.drawTriangles()メソッドの第2引数で頂点番号の組を定めなければ、頂点0の座標が4つ重複し、マウスクリックのリスナー関数(xDraw())でも第1引数のVectorエレメントを4座標分書き替えなければならなかったはずだ。第2引数を用いたことにより、その書替えがひと組のxy座標で済んだのである。
ようやく次回から、3次元空間座標を2次元平面に透視投影したうえで、その面にテクスチャマッピングする方法の解説に入る。