AS3位图任意形变一步一步来

本文详细介绍了在Flash/ActionScript中实现位图任意形变的技术,通过使用3×3变换矩阵进行仿射变换。首先解释了基本的点变换原理,然后展示了如何计算变换矩阵,接着讲解如何将位图分割成三角形并进行形变,最后提到了形变过程中可能遇到的效率和精度问题。文章内容适合熟悉AS3和图形变换的读者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Flash/ActionScript中,只提供了仿射变换功能。仿射变换包括平移(x 和 y 重新定位)、旋转、缩放和倾斜,在进行这些形变时,平行线仍然会保持平行,因此没办法做到任意形变。

实现位图或者MC(MovieClip)的任意形变的一种方式就是把它们分割成三角行,然后对三角形进行相应的仿射变换。比较流行的PV3D(papervision3d)就是采用的这种方式。

一切从简单开始,我们先看看一个点在平面上的几个简单的基本变换。一般来说,我们都将平面上的一个点表示为一个1×2的矩阵,我们可以通过将改点乘以一个2×2的矩阵来对该点进行变换。以下是一些简单的示例:

由于平移变换不是线性的,因此不能表示为2×2的矩阵,通过与一个1×2的矩阵相加即可得到相应的平移变换位置。上图中的取镜像变换从某种意义上也可以看做是一种平移变换:

通过上面的一些基本变换方式,我们可以得到一些比较复杂的变换:

上面的这中变换就叫做仿射变换。对于这种仿射变换,它需要两个矩阵进行变换(一个2×2的矩阵用于旋转,一个1×2的矩阵用于平移),为了方便,我 们有一种替换方案,将整个变换存储于一个3×3的矩阵中。另外,还需要将点坐标由1×2扩充为1×3,组后一位通常补1,如以前的(2,1)就变为 [2,1,1]。下面的矩阵变换就是上图的复杂变换:

其变换矩阵的意义如下:

在Flash/ActionScript中,略有不同的是,Macromedia(现在应该叫Adobe了)把平移部分放到了第三列中,即是这样的:

请务必记住这一点不同! 通过这个3×3的矩阵,我们就可以进行任何仿射变换,但记住一点:经过任何反射变换,原来的直线还是直线,平行的直线依然还会平行!至于怎么实现“不平行”的变换,我们将在后面继续讲解。

 

AS3位图任意形变一步一步来(2)——计算变换矩阵

由于仿射变换时,平行的边依然平行,所以,我们无法对一个矩形的位图进行随意变换,比如我们无法拉伸一个角,也无法进行把它变成梯形等。在上文中,我们提到过一种思路,就是把矩形分割成两个三角形,这样变换时从表面上 看来就没有什么平行边了,这样我们就可以变换其中的一个或者多个角了。注意,我这里说的是从表面上看,这一点在后面的变换中要进行一定的处理的。

这样我们只需要对三个点进行平面变换,假设我们的三个点分别为(x1, y1)、(x2, y2)、(x3, y3),要变换的位置分别为(x1',y1')、(x2', y2')、(x3', y3')、现在,我们要做的就是计算其变换矩阵。假设其变换矩阵为:

注意,在Flash中,其对应的变换矩阵应该是这个(平移变换的位置略有不同):

根据上一篇文章 中提到的,点(x1, y1)变换为(x1', y1')时,有:

于是可以得到方程:

  • a*x1 + c * y1 + tx = x1'
  • b*x1 + d * y1 + ty = y1'

同理,我们还可以得到其他四个方程:

  • a*x2 + c * y2 + tx = x2'
  • b*x2 + d * y2 + ty = y2'
  • a*x3 + c * y3 + tx = x3'
  • b*x3 + d * y3 + ty = y3'

正好六个方程,六个未知数:a、b、c、d、tx、ty,解这六个方程就可以得到我们的变换矩阵。方程的解为:

这几个结果看起来够晕的,本来还想化简一下的,懒了,还怕弄错,谁有兴趣看看还能不能再简化一下,这个结果应该是没有错的。解这个方程够晕的,这篇就到这里为止吧,这几个结果留着后面用,下一篇讲讲如何把一个位图切割成三角形。

 

 

  AS3位图任意形变一步一步来(3)——切割位图

对不起,让大家久等了,继续写blog。

今天我们继续研究位图的任意形变,今天的主要目的就是从外部加载一张图片,然后分割成两个三角形。当然了,分割成两个三角形是远远不够的,这一点,我们在后面会讲到。

从外部加载一张图片很简单,使用Loader类就可以轻松完成了。不过要注意的是这里是Loader类,在包flash.display下,而不是 flash.net下的URLLoader类。这个类使用很简单,如下(为了简单,这就不写那些条条框框了,直接写在时间轴上了,所有的代码都在第一 帧):

参考代码: [复制代码]  [保存代码]
  1. // 这个是我们要load的图片
  2. var url:String = 'green.jpg' ;
  3. //这个是用来保存位图数据的
  4. var bmd:BitmapData = null;
  5. // load方法
  6. function Load():void {
  7.     var req:URLRequest = new URLRequest(url);
  8.     var loader:Loader = new Loader();
  9.     // 添加事件侦听
  10.     ConfigureListeners(loader.contentLoaderInfo);
  11.     try {
  12.         // 加载图片
  13.         loader.load(req);
  14.         // 如果你要在舞台上显示出来
  15.         // 可以添加下面的代码
  16.         // this.addChild(loader);
  17.     } catch (err:Error) {
  18.     }
  19. }
  20. function Con
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值