開始使用材質之後,您會希望使用
drawTriangles()
的 uvtData 參數。這個參數可以讓您設定用於點陣圖填色的 UV 對應。
UV 對應是一種為物件加上材質的方法,所仰賴的兩個值為 U 水平 (x) 值和 V 垂直 (y) 值 (以百分比為基礎,而非像素值)。0 U 和 0 V 是影像的左上角,而 1 U 和 1 V 則是影像的右下角:
點陣圖上 UV 0 和 1 的位置
您可以指定 UV 座標當做三角形的向量,將這些向量與影像上對應的位置產生關聯:
點陣圖影像上三角區域的 UV 座標
三角形各點的 UV 值都會保持一致:
三角形的各頂點會移動且點陣圖會扭曲,如此各點的 UV 值都保持不變
將 ActionScript 3D 變形套用至與點陣圖有關聯的三角形時,會根據 UV 值將點陣圖影像套用至三角形。因此,您不需要使用矩陣計算,只要設定或調整 UV 值,即可建立三維特效。
Graphics.drawTriangles()
方法也能接受三維變形的部分選擇性資訊:T 值。uvtData 中的 T 值表示 3D 透視,更具體來說,就是相關聯頂點的縮放比例係數。UVT 對應會將透視更正加入至 UV 對應。例如,如果將物件放在 3D 空間中遠離檢視者的位置,讓它看起來是原始大小的 50%,那麼,因為繪製三角形的目的是要表示 3D 空間中的物件,所以物件在 z 軸上的位置就會決定物件的 T 值。也就是說,物件的 T 值就是 0.5。決定 T 值的方程式如下:
T = focalLength/(focalLength + z);
在這個方程式中,focalLength 表示焦距或經過計算的「螢幕」位置,這個位置會規定檢視中所提供的透視量。
焦距和 z 值
-
A.
-
視點
-
B.
-
螢幕
-
C.
-
3D 物件
-
D.
-
focalLength 值
-
E.
-
z 值
T 的值是用於縮放基本的形狀,讓它們看起來似乎在遠方,離自己有一段距離。這個值通常用於將 3D 座標點轉換成 2D 座標點。如果是 UVT 資料,則通常會用於縮放具有透視特效之三角形內座標點間的點陣圖。
當您定義 UVT 值時,T 值會直接接在針對頂點所定義的 UV 值後面。得出 T 值之後,
uvtData
參數中的每三個值 (U、V 和 T) 都會符合
vertices
參數中的每兩個值 (x 和 y)。只有 UV 值時,uvtData.length == vertices.length。得出 T 值之後,uvtData.length = 1.5*vertices.length。
下列範例會顯示使用 UVT 資料在 3D 空間中旋轉的平面。在範例中,會使用「helper」類別 ImageLoader 載入名為 ocean.jpg 的影像,以便將影像指定給 BitmapData 物件。
以下為 ImageLoader 類別的原始碼 (請儲存下列程式碼,並命名為 ImageLoader.as):
package {
import flash.display.*
import flash.events.*;
import flash.net.URLRequest;
public class ImageLoader extends Sprite {
public var url:String;
public var bitmap:Bitmap;
public function ImageLoader(loc:String = null) {
if (loc != null){
url = loc;
loadImage();
}
}
public function loadImage():void{
if (url != null){
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIoError);
var req:URLRequest = new URLRequest(url);
loader.load(req);
}
}
private function onComplete(event:Event):void {
var loader:Loader = Loader(event.target.loader);
var info:LoaderInfo = LoaderInfo(loader.contentLoaderInfo);
this.bitmap = info.content as Bitmap;
this.dispatchEvent(new Event(Event.COMPLETE));
}
private function onIoError(event:IOErrorEvent):void {
trace("onIoError: " + event);
}
}
}
以下為 ActionScript,其中使用了三角形、UV 對應和 T 值,使影像看起來就像一邊旋轉並且朝著消失點縮小。請儲存下列程式碼,並命名為 Spinning3dOcean.as:
package {
import flash.display.*
import flash.events.*;
import flash.utils.getTimer;
public class Spinning3dOcean extends Sprite {
// plane vertex coordinates (and t values)
var x1:Number = -100, y1:Number = -100, z1:Number = 0, t1:Number = 0;
var x2:Number = 100, y2:Number = -100, z2:Number = 0, t2:Number = 0;
var x3:Number = 100, y3:Number = 100, z3:Number = 0, t3:Number = 0;
var x4:Number = -100, y4:Number = 100, z4:Number = 0, t4:Number = 0;
var focalLength:Number = 200;
// 2 triangles for 1 plane, indices will always be the same
var indices:Vector.<int>;
var container:Sprite;
var bitmapData:BitmapData; // texture
var imageLoader:ImageLoader;
public function Spinning3dOcean():void {
indices = new Vector.<int>();
indices.push(0,1,3, 1,2,3);
container = new Sprite(); // container to draw triangles in
container.x = 200;
container.y = 200;
addChild(container);
imageLoader = new ImageLoader("ocean.jpg");
imageLoader.addEventListener(Event.COMPLETE, onImageLoaded);
}
function onImageLoaded(event:Event):void {
bitmapData = imageLoader.bitmap.bitmapData;
// animate every frame
addEventListener(Event.ENTER_FRAME, rotatePlane);
}
function rotatePlane(event:Event):void {
// rotate vertices over time
var ticker = getTimer()/400;
z2 = z3 = -(z1 = z4 = 100*Math.sin(ticker));
x2 = x3 = -(x1 = x4 = 100*Math.cos(ticker));
// calculate t values
t1 = focalLength/(focalLength + z1);
t2 = focalLength/(focalLength + z2);
t3 = focalLength/(focalLength + z3);
t4 = focalLength/(focalLength + z4);
// determine triangle vertices based on t values
var vertices:Vector.<Number> = new Vector.<Number>();
vertices.push(x1*t1,y1*t1, x2*t2,y2*t2, x3*t3,y3*t3, x4*t4,y4*t4);
// set T values allowing perspective to change
// as each vertex moves around in z space
var uvtData:Vector.<Number> = new Vector.<Number>();
uvtData.push(0,0,t1, 1,0,t2, 1,1,t3, 0,1,t4);
// draw
container.graphics.clear();
container.graphics.beginBitmapFill(bitmapData);
container.graphics.drawTriangles(vertices, indices, uvtData);
}
}
}
若要測試這個範例,請將這兩個類別檔案儲存於「ocean.jpg」影像所在的目錄。您可以看到原始點陣圖的變形方式,看起來就像在 3D 空間中一邊旋轉,一邊朝著遠方消失。