以前作ったPlaneを使ってて思ったこと
手直ししてみよう。
package { import alternativa.engine3d.core.Object3D; import alternativa.engine3d.core.VertexAttributes; import alternativa.engine3d.materials.Material; import alternativa.engine3d.objects.Mesh; import alternativa.engine3d.resources.Geometry; /** * ... * @author 9ballsyndrome * @see http://9ballsyndrome.blog.fc2.com/ * @version 1.1 * @date 07/09/2011 */ public class Plane extends Mesh { private var _h:uint; private var _w:uint; private var _segW:uint; private var _segH:uint; private var _material:Material; private var _doubleSided:Boolean; private var _uvt:Vector.<Number>; public function Plane(width:Number = 100, height:Number = 100, widthSegments:uint = 1, heightSegments:uint = 1, doubleSided:Boolean = false, material:Material = null){ this._w = width; this._h = height; this._segW = widthSegments; this._segH = heightSegments; this._doubleSided = doubleSided; this._material = material; setPlane(); } private function setPlane():void { //set parameter var numW:uint = _segW + 1; var numH:uint = _segH + 1; var numVertex:uint = numW * numH; var numTiles:uint = _segW * _segH; var numTriangles:uint = (_doubleSided) ? numTiles * 4 : numTiles * 2; // var attributes:Array = new Array(); attributes[0] = VertexAttributes.POSITION; attributes[1] = VertexAttributes.POSITION; attributes[2] = VertexAttributes.POSITION; attributes[3] = VertexAttributes.TEXCOORDS[0]; attributes[4] = VertexAttributes.TEXCOORDS[0]; var geometry:Geometry = new Geometry(); geometry.addVertexStream(attributes); geometry.numVertices = numVertex; var i:uint; var j:uint; var n:uint; //uv var offsetW:Number = 1 / _segW; var offsetH:Number = -1 / _segH; _uvt = new Vector.<Number>(numVertex * 2); for (i = 0; i < numVertex; i++){ n = i << 1; _uvt[n] = offsetW * (i / numH >> 0); _uvt[uint(n + 1)] = 1 + offsetH * (i % numH); } //xyz var biasW:Number = -_w / 2; var biasH:Number = -_h / 2; offsetW = _w / _segW; offsetH = _h / _segH; var vertices:Vector.<Number> = new Vector.<Number>(numVertex * 3); for (i = 0; i < numVertex; i++){ n = i * 3; vertices[n] = biasW + offsetW * (i / numH >> 0); vertices[uint(n + 1)] = biasH + offsetH * (i % numH); vertices[uint(n + 2)] = 0; } //indices var vec_indices:Vector.<uint> = new Vector.<uint>(numTriangles * 3); for (i = 0; i < numTiles; i++){ j = (i / _segH >> 0) + i; n = i * 6; vec_indices[n] = j; vec_indices[uint(n + 1)] = j + numH; vec_indices[uint(n + 2)] = j + 1 + numH; vec_indices[uint(n + 3)] = j; vec_indices[uint(n + 4)] = j + 1 + numH; vec_indices[uint(n + 5)] = j + 1; } if (_doubleSided){ for (i = 0; i < numTiles; i++){ j = i * 6; n = j + numTiles * 6; vec_indices[n] = vec_indices[j]; vec_indices[uint(n + 1)] = vec_indices[uint(j + 2)]; vec_indices[uint(n + 2)] = vec_indices[uint(j + 1)]; vec_indices[uint(n + 3)] = vec_indices[uint(j + 3)]; vec_indices[uint(n + 4)] = vec_indices[uint(j + 5)]; vec_indices[uint(n + 5)] = vec_indices[uint(j + 4)]; } } geometry.setAttributeValues(VertexAttributes.POSITION, vertices); geometry.setAttributeValues(VertexAttributes.TEXCOORDS[0], _uvt); geometry.indices = vec_indices; this.geometry = geometry; if (_doubleSided){ var half:uint = numTriangles >> 1; this.addSurface(_material, 0, half); this.addSurface(_material, half * 3, half); } else { this.addSurface(_material, 0, numTriangles); } this.calculateBoundBox(); } public function setUV(uStart:Number, uEnd:Number, vStart:Number, vEnd:Number):void { var perW:Number = uEnd - uStart; var perH:Number = vEnd - vStart; var numVertex:uint = geometry.numVertices; var uvt:Vector.<Number> = new Vector.<Number>(numVertex); var n:uint; for (var i:uint = 0; i < numVertex; i++){ n = i << 1; uvt[n] = uStart + _uvt[n] * perW; uvt[uint(n + 1)] = vStart + _uvt[uint(n + 1)] * perH; } geometry.setAttributeValues(VertexAttributes.TEXCOORDS[0], uvt); } override public function clone():Object3D { return new Plane(_w, _h, _segW, _segH, _doubleSided, _material); } } }
Alternativa3D 8のuv座標は画像の左上が原点っぽい。
以前大嘘書いちゃったぽい。
最低限の修正で直したいので頂点の位置と順番はそのまま、uv座標のvのみを0と1が反転するようなコードにした。
また、引数のuv座標の割合指定をやめ、メソッド化するのでsetPlane内のuv指定で使っていた割合の部分を元に戻し、必ず0~1になるようにした。
Alternativa3D 8のポリゴンを結ぶ3点の指定は見える側から見て反時計回りっぽい。また大嘘だったわ。
これも最低限で済むように全部の三角形の2番目と3番目を入れ替えるだけにした。
両面に違う画像を張りたくなったので、Surfaeceを分けることにする。
Plane二枚張り合わせりゃいいじゃんって思うけど、ポリゴン数は変わらなくても頂点数倍になっちゃうもん。
そしてuv座標だけど、1枚のテクスチャから複数のPlaneを作り、すこしづつずらしたい、という使い方をしたいと思ったので割合を指定するだけじゃ足りなくなった。
Planeの開始u座標(一番左の点のu座標),終了u座標(一番右の点のu座標),開始v座標(一番上の点のv座標),終了v座標(一番下の点のv座標)
を引数にしてPlaneの全頂点のuv座標を書き換えるsetUV()メソッドを作った。
setUV(0 , 1 , 0 , 1)が普通の状態(デフォルト)にあたる。
テクスチャの左上1/4だけ使いたいときはsetUV(0 , 0.5 , 0 , 0.5)、
左下1/4だけ使いたいときはsetUV(0 , 0.5 , 0.5 , 1)
と、開始点と終了点をそれぞれ指定することでVertexAttributes.TEXCOORDS[0]を書き換える。
やってることは全頂点についてスケーリングして底上げするだけ。
動的に変更することも可能だがその時はgeometryのupload()を忘れずに。
新しいuvを絶対値で指定するためにuv座標を保存してある初期_uvtがインスタンス変数になったけどまあこれくらいはいいよね。
このPlaneを使って画像のトランジション効果のようなものを作ろう。
Author:9ballsyn
ActionScriptについて
最近はMolehill