中級
本テーマの前回「三角形分割によるテクスチャマッピング − Graphics.drawTriangles メソッド Part 1」は、Graphics.drawTriangles メソッドに渡す3つの引数について、基本的な指定の仕方をご説明しました。今回のPart 2では、簡単なサンプルを作成して、Graphics.drawTriangles メソッドによりテクスチャを動的にマッピングしてみます 図001 。
![]() |
→ | ![]() |
![]() |
![]() |
ドラッグするポイントをMovieClipシンボルでつくり、ビットマップ画像の4隅の位置に合わせてタイムラインに配置する。
インスタンスをドラッグするための処理は、MovieClipシンボルにフレームアクションとして記述しておきます スクリプト001 。マウスイベントの扱いは、本稿のテーマから外れますので、説明を省きます[*1]。ここで確かめておきたいのは、インスタンスをドラッグしている間、DisplayObject.enterFrameイベント 定数Event.ENTER_FRAME のリスナー関数xUpdate が呼出され、その関数本体からはメインタイムラインのxTransform という関数が実行されるということです[*2]。
// MovieClip: ドラッグするポイント
// 第1フレームアクション
buttonMode = true;
addEventListener(MouseEvent.MOUSE_DOWN, xPress);
function xPress(eventObject:MouseEvent):void {
startDrag();
addEventListener(MouseEvent.MOUSE_UP, xRelease);
stage.addEventListener(MouseEvent.MOUSE_UP, xRelease);
addEventListener(Event.ENTER_FRAME, xUpdate);
}
function xRelease(eventObject:MouseEvent):void {
stopDrag();
removeEventListener(MouseEvent.MOUSE_UP, xRelease);
stage.removeEventListener(MouseEvent.MOUSE_UP, xRelease);
removeEventListener(Event.ENTER_FRAME, xUpdate);
}
function xUpdate(eventObject:Event):void { // ドラッグ中に呼出されるリスナー関数
MovieClip(root).xTransform(); // メインタイムラインの関数xTransform()を呼出す
}
そこで、メインタイムラインに関数xTransform()を定義し、つぎのように確認用のtrace()関数を加えたうえで、[ムービープレビュー]してみます。
function xTransform():void {
trace("called!");
}
ポイントのインスタンスをドラッグすると、メインタイムラインに定義したxTransform 関数が呼出されて、[出力]パネルに確認用の文字列が表示されます 図003 。これで準備はできました。あとは、メインタイムラインのフレームアクションで、関数xTransform にテクスチャマッピングの処理を定義すればよいでしょう。
![]() |
![]() |
ポイントのインスタンスをドラッグすると、メインタイムラインに定義したxTransform 関数が呼出される。この関数に、テクスチャマッピングの処理を加える。
[*1] マウスイベントの扱いについては、F-siteセミナー「イベントを制する者、ActionScript 3.0を制す」および「マウスイベント」をお読みください。
[*2] メインタイムラインに定義した関数にDisplayObject.rootプロパティを参照してアクセスする場合、プロパティはMovieClipクラスでキャストする必要があります 「rootプロパティでメインタイムラインの関数にアクセスできない」参照 。
ポイントのインスタンスをドラッグしている間、メインタイムラインの関数xTransform が呼出されます。ですから、そのたびに新たなテクスチャマッピングを行えばよいということです。処理内容を簡単にするため、今回も正方形のビットマップを対角線でふたつに分けます。頂点番号は、Z状に0から3までの整数とします 図004 。
このとき、Graphics.drawTriangles メソッドの第2引数に渡す頂点番号の組と第3引数のuvtデータの座標は、毎回とくに変わることはありません。したがって、各頂点のxy座標だけを、xTransform 関数で指定し直せばよいでしょう。以下のフレームアクション スクリプト002 の前半は、Part 1でご紹介したスクリプト004と基本的に変わりません。後半に定義した関数xTransform で、各ポイントのインスタンスからxy座標を調べ、Graphics.drawTriangles メソッドの第1引数として指定しています。
// タイムライン: メイン
// 第1フレームアクション
var mySprite:Sprite = new Sprite();
var myGraphics:Graphics = mySprite.graphics;
var myTexture:BitmapData = new Pen(0,0);
var indices:Vector.<int> = new Vector.<int>();
var uvtData:Vector.<Number> = new Vector.<Number>();
addChildAt(mySprite, 0);
// 三角形の頂点番号の組合わせ(第2引数)
indices.push(0,1,2);
indices.push(1,3,2);
// テクスチャマッピングのuv座標(第3引数)
uvtData.push(0,0);
uvtData.push(1,0);
uvtData.push(0,1);
uvtData.push(1,1);
xTransform(); // ドラッグ前にテクスチャを初期位置にマッピング
function xTransform():void {
// 三角形の頂点座標(第1引数)
var vertices:Vector.<Number> = new Vector.<Number>();
vertices.push(point0_mc.x, point0_mc.y);
vertices.push(point1_mc.x, point1_mc.y);
vertices.push(point2_mc.x, point2_mc.y);
vertices.push(point3_mc.x, point3_mc.y);
myGraphics.clear(); // 描画を一旦消す
myGraphics.beginBitmapFill(myTexture);
myGraphics.drawTriangles(vertices, indices, uvtData);
}
関数xTransform の本体で頂点座標 vertices を取得し、Graphics.drawTriangles メソッドの第1引数に指定していることがおわかりになれば、あとはPart 1の解説で処理内容は理解できるでしょう。ふたつだけ補足しておきます。
ひとつは、xTransform 関数定義の直前に、フレームアクションから関数を呼出していることです。このステートメントがないと、ポイントのインスタンスをドラッグするまでxTransform 関数が呼出されず、初期位置にテクスチャがマッピングされないからです。
もうひとつは、Grphics.clear メソッドの呼出しです。これを行わないと、以前の描画は残ったままテクスチャが重ね塗りされてしまいます。ですから、新たにマッピングする前に、毎回このメソッドで描画を消去しておく必要があるのです。 図005
[ムービープレビュー]で4隅のポイントをドラッグすると、その位置座標に合わせて、動的にテクスチャがマッピングされます 図006 。
左上と右下のポイントとで、ドラッグした方の三角形を前面に描画するようスクリプトを修正してみましょう。まず、ドラッグされているインスタンスがわからなければなりません。そのため、ドラッグするMovieClipシンボルのフレームアクションを書替え、xTransform()関数の引数に自分自身の参照(this)を渡して呼出すことにします。(図008)
図008■xTransform()関数の呼出しに自身の参照を引数として渡す
関数xTransform()を定義するメインタイムラインのフレームアクションでは、4つのポイントごとに頂点番号のVectorインスタンスを用意しておき、各ポイントのインスタンス名からそのうちのひとつを取出す仕組みにしましょう。そのために新たにindicesをObject型の変数として宣言し、各インスタンス名のプロパティにそれぞれのVectorインスタンスを設定します。フレームアクションには、つぎのような関数xGetIndices()の定義を加えます[*3]。
var indices:Object = xGetIndices();
function xGetIndices() {
var oIndices:Object = new Object();
// point1_mc〜point3_mcまでの頂点番号をプロパティとして設定
var myIndices:Vector.<int> = new Vector.<int>();
myIndices.push(0,1,2); // 左上の三角形
myIndices.push(1,3,2); // 右下の三角形
oIndices.point1_mc = oIndices.point2_mc = oIndices.point3_mc = myIndices;
// point0_mcの頂点番号をプロパティとして設定
myIndices = new Vector.<int>();
myIndices.push(1,3,2); // 右下の三角形
myIndices.push(0,1,2); // 左上の三角形
oIndices.point0_mc = myIndices;
return oIndices;
}
関数xGetIndices()の返すObjectインスタンスには、4つのポイントのインスタンス名をプロパティ名とする頂点番号のVectorインスタンスが納められています。したがって、ポイントのインスタンスが変数my_mcに入っているなら、そのポイントに対応した頂点番号のVectorインスタンスをつぎのようにして取出すことができます。
indices[my_mc.name]
以上の修正を加えたメインタイムラインのフレームアクションは、以下のスクリプト003のとおりです。ポイントのインスタンスから呼出されるxTransform 関数にインスタンスの参照が渡されますので、そのインスタンス名によりGraphics.drawTriangles メソッドに指定する第2引数のVectorインスタンスを取出しています。これで、左上のポイントのインスタンスをドラッグすれば、左上半分の三角形が手前に描画されるようになりました 図009 。
// タイムライン: メイン
// 第1フレームアクション
var mySprite:Sprite = new Sprite();
var myGraphics:Graphics = mySprite.graphics;
var myTexture:BitmapData = new Pen(0,0);
var indices:Object = xGetIndices();
var uvtData:Vector.<Number> = new Vector.<Number>();
addChildAt(mySprite, 0);
uvtData.push(0,0);
uvtData.push(1,0);
uvtData.push(0,1);
uvtData.push(1,1);
xTransform(point0_mc);
function xGetIndices() {
var oIndices:Object = new Object();
var myIndices:Vector.<int> = new Vector.<int>();
myIndices.push(0,1,2);
myIndices.push(1,3,2);
oIndices.point1_mc = oIndices.point2_mc = oIndices.point3_mc = myIndices;
myIndices = new Vector.<int>();
myIndices.push(1,3,2);
myIndices.push(0,1,2);
oIndices.point0_mc = myIndices;
return oIndices;
}
function xTransform(my_mc:MovieClip):void {
var vertices:Vector.<Number> = new Vector.<Number>();
vertices.push(point0_mc.x, point0_mc.y);
vertices.push(point1_mc.x, point1_mc.y);
vertices.push(point2_mc.x, point2_mc.y);
vertices.push(point3_mc.x, point3_mc.y);
myGraphics.clear();
myGraphics.beginBitmapFill(myTexture);
myGraphics.drawTriangles(vertices, indices[my_mc.name], uvtData);
}
図009■左上のポイントをドラッグすると左上半分の三角形が手前に描画される
[*3] テクスチャは対角線でふたつに分けられているだけですので、左上半分と右下半分の三角形のどちらを前面にするかが問題です。つまり、重ね順が問われるのは左上と右下のポイントです。右上と左下のポイントは2分割した対角線になるため、一方を他方の手前に描画することはできません。