När du har börjat arbeta med texturer vill du förmodligen också använda uvtData-parametern för
drawTriangles()
. Med den här parametern kan du ställa in UV-mappning för bitmappsfyllningar.
UV-mappning är en metod för att texturera objekt. Den utnyttjar två värden, ett U-vågrätt värde (x) och ett V-lodrätt värde (y). I stället för att baseras på pixelvärden, baseras de på procent. 0 U och 0 V innebär det övre vänstra hörnet i en bild och 1 U och 1 V det nedre högra hörnet:
Platserna UV 0 och 1 i en bitmappsbild
Vektorerna för en triangel kan tilldelas UV-koordinater om du vill koppla dem till respektive plats i en bild:
UV-koordinaterna i ett triangulärt område i en bitmappsbild
UV-värdena fortsätter att motsvara punkterna i triangeln:
Hörnen i triangeln flyttar och bitmappen förvrängs så att UV-värdena för de enskilda punkterna inte ändras
När ActionScript 3D-omformningarna används på triangeln som hör till bitmappen, används bitmappsbilden på triangeln utifrån UV-värdena. I stället för att använda matrisberäkningar, ska du ställa in eller justera UV-värdena om du vill skapa en tredimensionell effekt.
Metoden
Graphics.drawTriangles()
kan även innehålla ytterligare information för tredimensionella omformningar: T-värdet. T-värdet i uvtData representerar 3D-perspektivet, eller mer specifikt, skalfaktorn för det tillhörande hörnet. UVT-mappning tillför perspektivkorrigering i UV-mappningen. Exempel: om ett objekt placeras i 3D-ytan bort från vypunkten så att det verkar vara 50 % av den ursprungliga storleken, blir T-värdet för det objektet 0,5. Eftersom trianglarna ritas för att representera objekt i 3D-rymden, bestämmer deras placering utmed z-axeln deras T-värden. Följande ekvation bestämmer T-värdet:
T = focalLength/(focalLength + z);
I den här ekvationen representerar focalLength en brännvidd eller beräknad ”skärmplacering” som bestämmer hur mycket perspektiv som finns i bilden.
Brännvidd och z-värde
-
A.
-
vypunkt
-
B.
-
skärm
-
C.
-
3D-objekt
-
D.
-
värdet på focalLength
-
E.
-
z-värde
Värdet på T används för att skala enkla former så att de verkar vara längre bort. Det är vanligtvis detta värde som används för att konvertera 3D-punkter till 2D-punkter. När det gäller UVT-data används det också för att skala en bitmapp mellan punkterna i en triangel med perspektiv.
När du definierar UVT-värden följer T-värdet de UV-värden som har definierats för ett hörn. Med detta ”T” matchas vart tredje värde i
uvtData
-parametern (U, V och T) mot vartannat värde i
vertices
-parametern (x och y). Med enbart UV-värden blir uvtData.length == vertices.length. Om du tar med ett T-värde blir uvtData.length = 1.5*vertices.length.
I följande exempel visas ett plan som roteras i 3D-rymden med hjälp av UVT-data. I det här exemplet används en bild med namnet ocean.jpg och en hjälpklass, ImageLoader, för att läsa in bilden ocean.jpg så att den kan tilldelas BitmapData-objektet.
Här är ImageLoader-klasskällan (spara den här koden i en fil med namnet 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);
}
}
}
Och här är det ActionScript som använder trianglar, UV-mappning och T-värden för att göra så att bilden ser ut som om den krymper mot flyktpunkten och roterar. Spara den här koden i en fil med namnet 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);
}
}
}
Om du vill testa det här exemplet sparar du dessa två klassfiler i samma katalog som en bild med namnet ocean.jpg. Du ser hur den ursprungliga bitmappen omformas så att det verkar som om den försvinner med avståndet och roterar i 3D-rymden.