ロクナナワークショップ NEWS & REPORT

フォローアップ「Try the ActionScript 3D 野中文雄のFlash CS4で学ぶ3次元表現」

この記事を読むのに必要な時間:およそ 13 分

Graphics.drawTriangles()メソッドの引数

前述のとおり,Graphics.drawTriangles()メソッドには,3つのVectorインスタンスを引数として指定する。

Graphicsインスタンス.drawTriangles(頂点座標, 頂点番号, uvtデータ) 

ここでGraphics.drawTriangles()メソッドを用いて,たとえば正方形の画像の右下隅を少し引き伸ばすとしよう図4)⁠簡単な変形なので,ビットマップはひとつの対角線でふたつの三角形に分ける。

図4 Graphics.drawTriangles()メソッドでビットマップを変形する

図4 Graphics.drawTriangles()メソッドでビットマップを変形する

Graphics.drawTriangles()メソッドの第1引数は,変形した三角形の頂点の座標だ。今回は下図5のように,4頂点でふたつの三角形を組合わせる。引数として渡すVectorインスタンスには,4頂点のxy座標で計8つの数値をエレメントとして納める。

図5 第1引数は変形した三角形の頂点のxy座標

図5 第1引数は変形した三角形の頂点のxy座標

Graphics.drawTriangles()メソッドの第3引数には,三角形にマッピングするテクスチャの頂点の座標を,第1引数の座標に対応する順序で指定する。ただし,座標値は左上隅が原点(0,0)で,右下隅を(1,1)とする比率で表す図6)⁠また,ふたつの値はuとvで示し,uv座標と呼ばれる。引数に渡すVectorインスタンスには,第1引数と同じ数の数値のエレメントが納められる。

図6 第3引数はマッピングするテクスチャの頂点のuv座標

図6 第3引数はマッピングするテクスチャの頂点のuv座標

ここで,三角形の頂点には,0から始まる整数の連番を頂点番号として下図7のように定めておく。すると,今回試そうとしているテクスチャマッピングでは,Graphics.drawTriangles()メソッドに下表1の座標値を,それぞれ第1引数と第3引数に指定すべきことになる。

図7 頂点に0から始まる整数の連番を定める

図7 頂点に0から始まる整数の連番を定める

表1 Graphics.drawTriangles()メソッドの第1引数/頂点座標と第3引数/uvtデータ

頂点番号第1引数/頂点座標第3引数/uvtデータ
0(0, 0)(0, 0)
1(100, 0)(1, 0)
2(0, 100)(0, 1)
3(110, 110)(1, 1)

もっとも,これらの値だけでは,どの頂点で三角形が構成されるのかわからない。そこで,Graphics.drawTriangles()メソッドの第2引数は,三角形の3つの頂点番号の組を,分割した三角形の数だけ指定する。今回は,ふたつに分けた三角形の左上半分の頂点(0,1,2)と,右下半分の頂点(1,2,3)の計6つの整数を,Vectorインスタンスに納めて引数とすることになる。

さて,以上のとおりVectorインスタンスの引数3つを指定して,Graphics.drawTriangles()メソッドによりテクスチャをマッピングするフレームアクションが以下のスクリプト1だ。Vectorインスタンスに納める値は,わかりやすいように座標あるいは頂点番号の組ごとに,Vector.push()メソッドで分けて加えている。[ムービープレビュー]を確かめると,テクスチャの右下隅が水平および垂直方向に10ピクセルずつ引き伸ばされてマッピングされる図8)⁠

スクリプト1 Graphics.drawTriangles()メソッドでテクスチャをマッピング

// タイムライン: メイン
// 第1フレームアクション
var mySprite:Sprite = new Sprite();
var myGraphics:Graphics = mySprite.graphics;
var myTexture:BitmapData = new Pen(0, 0);
// 頂点座標のVectorインスタンス生成
var vertices:Vector.<Number> = new Vector.<Number>();
// 頂点番号のVectorインスタンス生成
var indices:Vector.<int>= new Vector.<int>();
// uvtデータのVectorインスタンス生成
var uvtData:Vector.<Number> = new Vector.<Number>();
addChild(mySprite);
// 三角形の頂点座標を加える(第1引数)
vertices.push(0, 0);   // 頂点0
vertices.push(100, 0);   // 頂点1
vertices.push(0, 100);   // 頂点2
vertices.push(110, 110);   // 頂点3
// 三角形の頂点番号の組合わせを加える(第2引数)
indices.push(0, 1, 2);   // 左上半分: 頂点0-1-2
indices.push(1, 2, 3);   // 右下半分: 頂点1-2-3
// テクスチャマッピングのuv座標を加える(第3引数)
uvtData.push(0, 0);   // 頂点0
uvtData.push(1, 0);   // 頂点1
uvtData.push(0, 1);   // 頂点2
uvtData.push(1, 1);   // 頂点3
myGraphics.beginBitmapFill(myTexture);
myGraphics.drawTriangles(vertices, indices, uvtData); 

図8 変形した三角形にマッピングされたテクスチャ

図8 イ変形した三角形にマッピングされたテクスチャ

ドラッグで変形した任意の四角形にテクスチャマッピング

Graphics.drawTriangles()メソッドの使い方が確かめられたので,簡単な応用例を紹介しよう。矩形のインスタンスの4隅にドラッグできるポイントを置き,それらの位置に合わせて変形した四角形にテクスチャをマッピングする図9)⁠

図9 ドラッグした4隅のポイントに合わせて変形した四角形にテクスチャマッピング

図9 ドラッグした4隅のポイントに合わせて変形した四角形にテクスチャマッピング

準備として,矩形のインスタンスの4隅に置くシンボルには,ドラッグできるようにフレームアクションを記述しておく。その中で,ドラッグしている間,メインタイムラインの関数xTransform()を呼出すようにする図10※2]。メインタイムラインに定義する関数xTransform()の本体で,ドラッグした4隅のインスタンスの位置に合わせてテクスチャマッピングしようという訳だ。

図10 ドラッグするシンボルに記述したフレームアクション

図10 ドラッグするシンボルに記述したフレームアクション

4隅のドラッグにより変わる値は,Graphics.drawTriangles()メソッドの第1引数であるマッピング対象の座標だけだ。第2および第3引数の値は,そのままでよい。すると,関数xTransform()では,第1引数のVectorインスタンスを作成し,それを渡してGraphics.drawTriangles()メソッドを呼出すことになる。なお,ドラッグする4隅のインスタンスには,矩形インスタンスの頂点座標に合わせて,point0_mc~point3_mcと名前をつけた。また,Graphics.drawTriangles()メソッドに渡す第2引数と第3引数のVectorインスタンスは,それぞれ変数indicesおよびuvtDataに設定されているものとする。

function xTransform():void {
  // 三角形の頂点座標(第1引数)
  var vertices:Vector. = new Vector.();
  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.beginBitmapFill(myTexture);
  myGraphics.drawTriangles(vertices, indices, uvtData);
}

Spriteインスタンスの生成や,Graphics.drawTriangles()メソッドに渡す第2引数と第3引数のVectorインスタンスの初期化については,前掲スクリプト001と基本的に同じでよさそうだ。したがって,ドラッグで変形した任意の四角形にテクスチャマッピングするフレームアクションは,つぎのスクリプト2のようになる。

スクリプト2 ドラッグで変形した任意の四角形にテクスチャマッピングするフレームアクション

// タイムライン: メイン
// 第1フレームアクション
var mySprite:Sprite = new Sprite();
var myGraphics:Graphics = mySprite.graphics;
var myTexture:BitmapData = new Pen(0,0);
var indices:Vector. = new Vector.();
var uvtData:Vector. = new Vector.();
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. = new Vector.();
  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);
}

新たに加えた処理が3つある。第1は,関数xTransform()の本体で,ビットマップの塗りを設定するGraphics.beginBitmapFill()メソッドの)前にGraphics.clear()メソッドで前の描画を消したことだ。この処理がないと,前の塗りが残ってしまう図11)⁠

図11 Grphics.clear()メソッドを呼出さないと前の描画が残る

図11 Grphics.clear()メソッドを呼出さないと前の描画が残る

第2に,SpriteインスタンスをDisplayObjectContainer.addChildAt()メソッドでタイムラインの表示リストに加えた。今回は,4隅のインスタンスを予めタイムラインに配置してある。DisplayObjectContainer.addChild()メソッドでSpriteインスタンスを加えると,それらの前面に表示されてしまう。そこで,DisplayObjectContainer.addChildAt()メソッドの第2引数にインデックスとして0を渡すことにより,4隅のインスタンスの背面にSpriteインスタンスを配置した。

そして第3は,このフレームアクションからxTransform()関数を呼出したことだ。関数xTransform()は,4隅のインスタンスのいずれかをドラッグしなければ実行されない。つまり,そのままでは,ドラッグするまでタイムラインにビットマップが表示されなくなってしまうからだ。

[※2]
シンボルのフレームアクションは本題からそれるので,これ以上の説明は省く。具体的な内容は,サンプルファイルを見てほしい。

著者プロフィール

ロクナナワークショップ(ロクナナワークショップ)

アドビ認定トレーニングセンター ロクナナワークショップでは,Web業界の第一線で活躍中の講師陣による,実践的な講座を開講しています。全ての講座は最大6名・1日6時間で完結する,PCを操作しながらの集中トレーニングです。

また,各方面で活躍中のクリエイターをお迎えし,最新技術やアイデアをご紹介いただくイベントも開催しています。学生割引もありますので,是非一度参加してみてください。

URL:https://67.org/ws/

コメント

コメントの記入