一旦开始处理纹理,您就要使用
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%,则该对象的 T 值为 0.5。因为在 3D 空间中是通过绘制三角形来表示对象的,所以对象在 z 轴上的位置确定对象的 T 值。用于确定 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 空间中旋转平面。本例使用了一幅名为 ocean.jpg 的图像和一个“帮助器”类 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 空间中消失于远处并不断旋转的效果。