Flash Player 10 和更高版本,Adobe AIR 1.5 和更高版本

在 ActionScript 中,使用Graphics.drawTriangles()方法执行位图转换,因为 3D 模型由空间中的一系列三角形表示。(但是,Flash Player 和 AIR 不支持深度缓冲,因此显示对象在本质上仍然是平面的,即 2D。这一点在了解 Flash Player 和 AIR 运行时中的 3D 显示对象中进行了说明。)Graphics.drawTriangles()方法通过一组坐标来绘制三角形路径,它与Graphics.drawPath()方法类似。

若要熟悉Graphics.drawPath()方法的使用,请参阅绘制路径

Graphics.drawTriangles()方法使用 Vector.<Number> 来指定三角形路径的点位置:

  1. drawTriangles(vertices:Vector.<Number>, indices:Vector.<int> = null, uvtData:Vector.<Number> = null, culling:String = "none"):void

drawTriangles()的第一个参数是唯一的必需参数:vertices参数。该参数是由定义坐标的数字组成的矢量,通过该矢量即可绘制三角形。每三组坐标(六个数字)表示一个三角形路径。如果没有indices参数,矢量的长度应始终为六的倍数,因为每个三角形都需要三个坐标对(三组 x/y 值对)。例如:

  1. graphics.beginFill(0xFF8000);
  2. graphics.drawTriangles(
  3. Vector.<Number>([
  4. 10,10, 100,10, 10,100,
  5. 110,10, 110,100, 20,100]));

这些三角形不共享任何点,但是如果有共享点,就可以使用第二个drawTriangles()参数indices来对多个三角形重复使用vertices矢量中的值。

使用indices参数时,请注意,indices值是点索引,而不是直接与vertices数组元素相关的索引。也就是说,vertices矢量中由indices定义的索引实际上是除以 2 后的实际索引。例如,对于vertices矢量的第三个点,即使该点的第一个数值从矢量索引 4 开始,也使用indices值 2。

例如,使用indices参数合并两个三角形使二者共享对边:

  1. graphics.beginFill(0xFF8000);
  2. graphics.drawTriangles(
  3. Vector.<Number>([10,10, 100,10, 10,100, 100,100]),
  4. Vector.<int>([0,1,2, 1,3,2]));

请注意,尽管正方形现在是通过两个三角形绘制的,但在vertices矢量中只指定了四个点。通过使用indices,两个三角形共享的两点将由每个三角形重复使用。这样可以将顶点总数从 6(12 个数字)减少为 4(8 个数字):

使用 vertices 参数通过两个三角形绘制的正方形

对于较大的三角形网格,这种方法非常有用,因为这种情况下大多数点由多个三角形共享。

所有填充方式都可应用于三角形。填充应用于三角形网格的方式与应用于其他形状的方式是相同的。

转换位图

位图转换可在三维对象上提供透视视觉效果或“纹理”。具体而言,您可以朝消失点的方向扭曲位图,这样图像在朝消失点方向移动时会出现收缩效果。或者,您可以使用二维位图为三维对象创建表面,从而提供纹理视觉效果或将三维对象“包裹”起来。

使用消失点的二维表面和用位图包裹的三维对象。

UV 映射

一旦开始处理纹理,您就要使用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 值的等式为:

  1. 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 的文件中):

  1. package {
  2. import flash.display.*
  3. import flash.events.*;
  4. import flash.net.URLRequest;
  5. public class ImageLoader extends Sprite {
  6. public var url:String;
  7. public var bitmap:Bitmap;
  8. public function ImageLoader(loc:String = null) {
  9. if (loc != null){
  10. url = loc;
  11. loadImage();
  12. }
  13. }
  14. public function loadImage():void{
  15. if (url != null){
  16. var loader:Loader = new Loader();
  17. loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
  18. loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIoError);
  19.  
  20. var req:URLRequest = new URLRequest(url);
  21. loader.load(req);
  22. }
  23. }
  24.  
  25. private function onComplete(event:Event):void {
  26. var loader:Loader = Loader(event.target.loader);
  27. var info:LoaderInfo = LoaderInfo(loader.contentLoaderInfo);
  28. this.bitmap = info.content as Bitmap;
  29. this.dispatchEvent(new Event(Event.COMPLETE));
  30. }
  31.  
  32. private function onIoError(event:IOErrorEvent):void {
  33. trace("onIoError: " + event);
  34. }
  35. }
  36. }

下面的 ActionScript 用三角形、UV 映射和 T 值使图像获得这样的显示效果:图像朝着消失点逐渐收缩并不断旋转。将此代码保存到命名为 Spinning3dOcean.as 的文件中:

  1. package {
  2. import flash.display.*
  3. import flash.events.*;
  4. import flash.utils.getTimer;
  5.  
  6. public class Spinning3dOcean extends Sprite {
  7. // plane vertex coordinates (and t values)
  8. var x1:Number = -100, y1:Number = -100, z1:Number = 0, t1:Number = 0;
  9. var x2:Number = 100, y2:Number = -100, z2:Number = 0, t2:Number = 0;
  10. var x3:Number = 100, y3:Number = 100, z3:Number = 0, t3:Number = 0;
  11. var x4:Number = -100, y4:Number = 100, z4:Number = 0, t4:Number = 0;
  12. var focalLength:Number = 200;
  13. // 2 triangles for 1 plane, indices will always be the same
  14. var indices:Vector.<int>;
  15.  
  16. var container:Sprite;
  17.  
  18. var bitmapData:BitmapData; // texture
  19. var imageLoader:ImageLoader;
  20. public function Spinning3dOcean():void {
  21. indices = new Vector.<int>();
  22. indices.push(0,1,3, 1,2,3);
  23.  
  24. container = new Sprite(); // container to draw triangles in
  25. container.x = 200;
  26. container.y = 200;
  27. addChild(container);
  28.  
  29. imageLoader = new ImageLoader("ocean.jpg");
  30. imageLoader.addEventListener(Event.COMPLETE, onImageLoaded);
  31. }
  32. function onImageLoaded(event:Event):void {
  33. bitmapData = imageLoader.bitmap.bitmapData;
  34. // animate every frame
  35. addEventListener(Event.ENTER_FRAME, rotatePlane);
  36. }
  37. function rotatePlane(event:Event):void {
  38. // rotate vertices over time
  39. var ticker = getTimer()/400;
  40. z2 = z3 = -(z1 = z4 = 100*Math.sin(ticker));
  41. x2 = x3 = -(x1 = x4 = 100*Math.cos(ticker));
  42.  
  43. // calculate t values
  44. t1 = focalLength/(focalLength + z1);
  45. t2 = focalLength/(focalLength + z2);
  46. t3 = focalLength/(focalLength + z3);
  47. t4 = focalLength/(focalLength + z4);
  48.  
  49. // determine triangle vertices based on t values
  50. var vertices:Vector.<Number> = new Vector.<Number>();
  51. vertices.push(x1*t1,y1*t1, x2*t2,y2*t2, x3*t3,y3*t3, x4*t4,y4*t4);
  52. // set T values allowing perspective to change
  53. // as each vertex moves around in z space
  54. var uvtData:Vector.<Number> = new Vector.<Number>();
  55. uvtData.push(0,0,t1, 1,0,t2, 1,1,t3, 0,1,t4);
  56.  
  57. // draw
  58. container.graphics.clear();
  59. container.graphics.beginBitmapFill(bitmapData);
  60. container.graphics.drawTriangles(vertices, indices, uvtData);
  61. }
  62. }
  63. }

若要测试此示例,请在名为“ocean.jpg”的图像所在的目录中保存这两个类文件。您可以看到原始位图如何转换为在 3D 空间中消失于远处并不断旋转的效果。

剔除

剔除是一个过程,用于确定三维对象的哪些表面因对当前视点不可见而不应被渲染器所呈示。在 3D 空间中,三维对象“背面”的表面对视点不可见:
3D 对象的背面对视点不可见。
A.视点  B.3D 对象   C.三维对象的背面
 
从本质上讲,不管三角形的大小、形状或位置如何,所有三角形都会始终呈示。剔除能确保 Flash Player 或 AIR 正确呈示 3D 对象。此外,为了减少呈示周期,有时您会希望渲染器跳过某些三角形。考虑在空间中旋转的立方体。在任何给定时间,您看到的立方体的面数不会超过三个面,这是因为不可见的面朝向立方体背面的其他方向。因为这些面不可见,所以渲染器不应绘制它们。如果不用剔除,Flash Player 或 AIR 就既要绘制正面也要绘制背面。
立方体的某些面对当前视点不可见

因此,Graphics.drawTriangles()方法采用第四个参数来建立剔除值:

  1. public function drawTriangles(vertices:Vector.<Number>, indices:Vector.<int> = null, uvtData:Vector.<Number> = null, culling:String = "none"):void

该剔除参数是来自TriangleCulling枚举类的值:TriangleCulling.NONE、TriangleCulling.POSITIVE和TriangleCulling.NEGATIVE。这些值与定义对象表面的三角形路径的方向有关。用于确定剔除的 ActionScript API 假设 3D 形状的所有外向三角形都是以同一路径方向绘制的。一旦三角形面经过旋转后,其路径方向也会改变。此时可以剔除(不呈示)该三角形。

因此,如果TriangleCulling值为POSITIVE,则会移除正向路径方向(顺时针)的三角形。如果TriangleCulling值为NEGATIVE,则会移除负向路径方向(逆时针)的三角形。对于立方体,朝前的表面具有正向路径方向,而朝后的表面具有负向路径方向:

“展开”的立方体,用以显示路径方向。当立方体“恢复原状”后,背面路径方向变为相反方向。

若要了解剔除的工作原理,请从前面 UV 映射中的示例开始,将drawTriangles()方法的剔除参数设置为TriangleCulling.NEGATIVE:

  1. container.graphics.drawTriangles(vertices, indices, uvtData, TriangleCulling.NEGATIVE);

请注意,在对象旋转时,未呈现图像的“背面”。

原文地址:http://help.adobe.com/zh_CN/as3/dev/WS84753F1C-5ABE-40b1-A2E4-07D7349976C4.html#WS509D19BB-239B-4489-B965-844DDA611AE7

[ActionScript 3.0] 通过三角形获得 3D 效果的更多相关文章

  1. 2D图形如何运动模拟出3D效果

    一.先看看实现效果图 (左边的2d图片如何运动出右边3d的效果)                                      引言: 对于这个题目,真的很尴尬,不知道取啥,就想了这个题目 ...

  2. 60.自己定义View练习(五)高仿小米时钟 - 使用Camera和Matrix实现3D效果

    *本篇文章已授权微信公众号 guolin_blog (郭霖)独家公布 本文出自:猴菇先生的博客 http://blog.csdn.net/qq_31715429/article/details/546 ...

  3. ActionScript 3.0入门:Hello World、文件读写、数据存储(SharedObject)、与JS互调

    近期项目中可能要用到Flash存取数据,并与JS互调,所以就看了一下ActionScript 3.0,现把学习结果分享一下,希望对新手有帮助. 目录 ActionScript 3.0简介 Hello ...

  4. 3d效果的图片轮播

    CSS3的3d变换 CSS3给我们提供了一个新的功能,那就是3d变换.3d变换和2d变换的基本API函数类似,只不过多了些在Z轴上的操作,不难使用. 但是,为了让元素拥有3d变换的功能,我们需要给他的 ...

  5. CSS3 文本3D效果

    代码如下: <!DOCTYPE html> <html> <head> <style> h1 { color: #3D3D3D; font-size: ...

  6. [转]ActionScript 3.0入门:Hello World、文件读写、数据存储(SharedObject)、与JS互调

    本文转自:http://www.cnblogs.com/artwl/p/3396330.html 近期项目中可能要用到Flash存取数据,并与JS互调,所以就看了一下ActionScript 3.0, ...

  7. 网页3D效果库Three.js初窥

    网页3D效果库Three.js初窥 背景 一直想研究下web页面的3D效果,最后选择了一个比较的成熟的框架Three.js下手 ThreeJs官网 ThreeJs-github; 接下来我会陆续翻译 ...

  8. 视频特效制作:如何给视频添加边框、水印、动画以及3D效果

    2014-12-08 09:47 编辑: suiling 分类:iOS开发 来源:叶孤城的blog 招聘信息: iOS手机软件开发工程师 iOS工程师 Web后端高级开发工程师 iOS软件工程师 ja ...

  9. 图片设置3D效果

    /** * 图片绘制3d效果 * @param srcImage * @param radius * @param border * @param padding * @return * @throw ...

随机推荐

  1. svg中改变class调用的线条颜色

    <style type="text/css"><![CDATA[ .kV220 {stroke:rgb(255,0,0);fill:none} .kV22 {st ...

  2. Netflix Zuul 了解

    Zuul 是提供动态路由,监控,弹性,安全等的边缘服务.Zuul 相当于是设备和 Netflix 流应用的 Web 网站后端所有请求的前门.Zuul 可以适当的对多个 Amazon Auto Scal ...

  3. 无法在web服务器上启动调试。Microsoft Visual Studio 远程调试监视器(MSVSMON.EXE)似乎没有在远程计算机上运行,VS2012调试错误

    1.重启(无用) 2.关闭防火墙(无用) 3.开启文件与打印机共享(无用) 4.无远程调试权限,改为本地调试.或者是IIS中此项目没有启动.或者没有在IIS中新建此项目.

  4. ant脚本编写

    使用ant脚本前的准备 1.下载一个ant安装包.如:apache-ant-1.8.4-bin.zip.解压到E盘. 2.配置环境变量.新增ANT_HOME:E:\apache-ant-1.8.4:P ...

  5. maven设置---Dmaven.multiModuleProjectDirectory system propery is not set.

    设置maven 环境变量: MAVEN_HOME:D:\Java\apache-maven-3.3.3 M2_HOME:D:\Java\apache-maven-3.3.3 path:%MAVEN_H ...

  6. Cannot find class for bean with name service

    Cannot find class [com.jx.p2p.service.impl.LazyInvestServiceImpl] for bean with name 'service' defin ...

  7. ORA-27101:shared memory realm does not exist的问题

    ORA-27101:shared memory realm does not exist的问题 登陆SQLPlus时出现: ORA-01034:ORACLE not avaiable ORA-2710 ...

  8. 股票自用指标 boll 菜刀

    BI:=(H+L+O+C)/; BOL:EMA(BI,N); UPPER:BOLL+N1*STD(CLOSE,N); LOWER:BOLL-N1*STD(CLOSE,N); MA1:MA(CLOSE, ...

  9. 为什么要用VisualSVN Server,而不用Subversion?

    为什么要用VisualSVN Server,而不用Subversion? [SVN 服务器的选择] - 摘自网络 http://www.cnblogs.com/haoliansheng/archive ...

  10. perl中的grep函数介绍

    grep函数 (如果你是个的新手,你可以先跳过下面的两段,直接到 Grep vs.loops 样例这一部分,放心,在后面你还会遇到它) <pre>grep BLOCK LISTgrep E ...