ActionScript 3.0で始めるオブジェクト指向スクリプティング

第49回 テクスチャを立方体の4面に貼る

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

面の裏表の一方だけを描く―カリング

3次元空間における面の重ね順については,第38回z座標値に応じて重ね順を変えるでも考えた。もっとも,今回4面を描くインスタンス(mySprite)そのものはひとつなので,塗りの順序という方が正確だろう。塗る順番は,Graphics.drawTriangles()メソッドに渡す第2引数(indices)の3頂点番号の組で定まる。後の三角形が上塗りされる。

では,第38回と同じく「z座標値に応じて重ね順を変える⁠⁠,つまりGraphics.drawTriangles()メソッド第2引数のVectorエレメントに納める頂点番号の順序を換えればよいか。そういう手もある。しかし,今回はGraphics.drawTriangles()メソッドの第4引数を紹介したい。

前掲スクリプト1は,立方体が水平にのみ回る。そのため,見える面は多くてふたつだ。逆にいうと,後ろ側の裏返った面は消してしまってよい。そうすれば,重ね順を気にしなくてもよくなる。このように面の裏表の一方だけを描く処理は「カリング」と呼ばれる。描画が減らせる分,速さも稼げる。Graphics.drawTriangles()メソッドの第4引数は,TriangleCullingクラスの定数によりカリングを指定する。

カリングを決めるには,まず面の向きを確かめる。塗る三角形の頂点番号の順序の方向に右ネジを回すと捉えたとき,ネジの進む向きが面の正方向となる。つまり,頂点番号を時計回りに定めれば,z軸と同じ奥向きが面の正方向だ表2⁠。それに対して,今回のスクリプトで見せたいのは,手前に向いた面になる。つまり,負の側の面を描くと定めればよい。定数はTriangleCulling.NEGATIVEだ。

表2 TriangleCullingクラスのカリングを指定する定数

描画する面TriangleCullingクラスの定数時計回りの頂点番号で描画される面
正負両面NONE(デフォルト)両面
負の方向の面NEGATIVE手前向きの面
正の方向の面POSITIVE奥向きの面

頂点番号を時計回りに定めたとき

頂点番号を時計回りに定めたとき

スクリプト1にGraphics.drawTriangles()メソッドの第4引数を加えれば,取りあえず今回のテーマは完成だ。わずか1箇所の追加とはいえ,できあがりなのでスクリプト2として全文を掲げる。カリングで奥向きの裏返った面は消えるため,塗りの順序を変えなくても手前向きの面だけが表示される図4⁠。

図4 カリングによって手前向きの面だけが表示される

図4 カリングによって手前向きの面だけが表示される 図4 カリングによって手前向きの面だけが表示される

スクリプト2 3次元空間で回転させる立方体の4面にテクスチャマッピング(完成)

// フレームアクション
var nUnit:Number = 100 / 2;
var mySprite:Sprite = new Sprite();
var myTexture:BitmapData = new Image();
var vertices:Vector.<Number> = new Vector.<Number>();
var indices:Vector.<int> = new Vector.<int>();
var uvtData:Vector.<Number> = new Vector.<Number>();
var nDeceleration:Number = 0.3;
var myGraphics:Graphics = mySprite.graphics;
var myPerspective:PerspectiveProjection = transform.perspectiveProjection;
var worldMatrix3D:Matrix3D = new Matrix3D();
var viewMatrix3D:Matrix3D = myPerspective.toMatrix3D();
viewMatrix3D.prependTranslation(0, 0, myPerspective.focalLength);
mySprite.x = stage.stageWidth / 2;
mySprite.y = stage.stageHeight / 2;
vertices.push(-nUnit, -nUnit, -nUnit);
vertices.push(nUnit, -nUnit, -nUnit);
vertices.push(nUnit, nUnit, -nUnit);
vertices.push(-nUnit, nUnit, -nUnit);
vertices.push(-nUnit, -nUnit, nUnit);
vertices.push(nUnit, -nUnit, nUnit);
vertices.push(nUnit, nUnit, nUnit);
vertices.push(-nUnit, nUnit, nUnit);
vertices.push(-nUnit, -nUnit, -nUnit);
vertices.push(-nUnit, nUnit, -nUnit);
addRectangleIndices(0, 1, 2, 3);
addRectangleIndices(1, 5, 6, 2);
addRectangleIndices(5, 4, 7, 6);
addRectangleIndices(4, 8, 9, 7);
uvtData.push(0, 0, 0);
uvtData.push(1/4, 0, 0);
uvtData.push(1/4, 1, 0);
uvtData.push(0, 1, 0);
uvtData.push(3/4, 0, 0);
uvtData.push(2/4, 0, 0);
uvtData.push(2/4, 1, 0);
uvtData.push(3/4, 1, 0);
uvtData.push(1, 0, 0);
uvtData.push(1, 1, 0);
addChild(mySprite);
addEventListener(Event.ENTER_FRAME, xRotate);
function xRotate(eventObject:Event):void {
  var nRotationY:Number = mySprite.mouseX * nDeceleration;
  var vertices2D:Vector.<Number> = new Vector.<Number>();
  xTransform(vertices2D, nRotationY);
  xDraw(vertices2D);
}
function xTransform(vertices2D:Vector.<Number>, myRotation:Number):void {
  worldMatrix3D.prependRotation(myRotation, Vector3D.Y_AXIS);
  var myMatrix3D:Matrix3D = worldMatrix3D.clone();
  myMatrix3D.append(viewMatrix3D);
  Utils3D.projectVectors(myMatrix3D, vertices, vertices2D, uvtData);
}
function xDraw(vertices2D:Vector.<Number>):void {
  myGraphics.clear();
  myGraphics.beginBitmapFill(myTexture);
  // myGraphics.drawTriangles(vertices2D, indices, uvtData);
  myGraphics.drawTriangles(vertices2D, indices, uvtData, TriangleCulling.NEGATIVE);
  myGraphics.endFill();
}
function addRectangleIndices(n0:uint, n1:uint, n2:uint, n3:uint):void {
  indices.push(n0, n1, n3);
  indices.push(n1, n2, n3);
}

次回はこのスクリプト2に垂直の回転を加える。そうなると,後ろ側の裏返った面も消してしまう訳にはいかない。つまり,カリングで済ませることはできず※2⁠,塗りの順序を変えようということだ。

※2
立方体の6面すべてをテクスチャでくるんだ場合なら,内側の面つまり裏面は見えない(見えるのは手前の最大3面⁠⁠。したがって,カリングで済ませられる。次回は,あえて内側が見える立体を扱うことになる。

今回解説した次のサンプルファイルがダウンロードできます。

著者プロフィール

野中文雄(のなかふみお)

ソフトウェアトレーナー,テクニカルライター,オーサリングエンジニア。上智大学法学部卒,慶応義塾大学大学院経営管理研究科修士課程修了(MBA)。独立系パソコン販売会社で,総務・人事,企画,外資系企業担当営業などに携わる。その後,マルチメディアコンテンツ制作会社に転職。ソフトウェアトレーニング,コンテンツ制作などの業務を担当する。2001年11月に独立。Web制作者に向けた情報発信プロジェクトF-siteにも参加する。株式会社ロクナナ取締役(非常勤)。

URLhttp://www.FumioNonaka.com/

著書