`

[转] AS3 制作3D位图方法

阅读更多
http://bbs.9ria.com/viewthread.php?tid=82221&extra=page%3D1%26amp%3Borderby%3Ddateline%26amp%3Bfilter%3D2592000


当一张位图在空间中移动或旋转时,它在屏幕上的投影可能是任意的不规则的四边形。我们利用透视计算计算出投影到屏幕上的四边形的四个顶点的在屏幕上的坐标,用Graphics.beginBitmapFill(sourceBitmapData)、Graphics.moveTo和Graphics.lineTo,不能在不规则四边形内填充到完整的位图,这时我们会试着设置Graphics.beginBitmapFill()方法的第二个Matrix类参数,但是还是不能够填充得到完整的位图。虽然这样,但是不难发现,我们不能得到完整的位图填充,但是通过调整Graphics.beginBitmapFill()的Matrix参数,我们可以准确获得一半的位图。两个一半就是一了,而位图的一半就是一个三角形。任意的四边形都可以分成两个三角形,那么我们先画一个三角形填充一半的位图,再画另一个三角形填充另一半的位图,我们就能填充到完整的位图。向下面这样:

var triangle_a:Sprite=new Sprite

var triangle_b:Sprite=new Sprite

addChild(triangle_a)

addChild(triangle_b)



//drawTriangle 函数是用来为Sprite对象画三角形的

drawTriangle(triangle_a,sourceBitmapData, A,B,C)

drawTriangle(triangle_b,sourceBitmapData,D,E,F)



function drawTriangle(_target:Sprite,_sourceBitmapData:BitmapData,Aopint,Boint,Coint):void

{

  var _matrix:Matrix=new Matrix

  //……………………

  //Matrix的计算后面再说

  _target.graphics.clear()

  //为了看得清楚,可以加上下面这句

  //_target.graphics.lineStyle(1)

  _target.graphics.beginBitmapFill(_sourceBitmapData,_matrix)

  _target.graphics.moveTo(A.x,A.y)

  _target.graphics.lineTo(B.x,B.y)

  _target.graphics.lineTo(C.x,C.y)

  _target.graphics.lineTo(A.x,A.y)

}

Graphics.beginBitmapFill()方法中的Matrix类参数,是位图填充方式的关键。而Matrix类参数有a,b,c,d,tx,ty六个属性,我们要做的就是要把这六个属性的值计算出来。我们并不需要知道这六个参数各自的作用,我们只需要知道这六个属性组成了这样一个矩阵:

[ a,b,tx,

c,d,ty,

0,0,1]

Matrix类有这样的一个方法Matrix.transformPoint(_point:Point):Point{//….},先说说它是怎么工作的。根据我的理解,它函数代码大体上是这样的:



public function transformPoint(_point:Point):Point

{

var _x:Number=a * _point.x + c * _point.y + tx

var _y:Number=b * _point.x + d * _point.y + ty



return new Point(_x,_y)

}

我为什么要把这个方法写出来呢?细想一下,屏幕平面上的直角三角形形通过空间旋转和移动后,它在屏幕上的投影变成了非直角三角形,那么是否存在这样一个矩阵,使得屏幕平面上的直角三角形的三个顶点分别乘以该矩阵后,则使用矩阵的上述方法赋值后(则 _point=_matrix.transformPoint(_point)),与此直角三角形经过空间旋转和移动后在屏幕上的投影(非直角三角形)的三个顶点分别对应相等?由此问题我们可以列出两组三元一次方程。如下:

设屏幕平面上的直角三角形的三个顶点分别为:A(x1,y1),B(x2,y2),C(x3,y3), 此直角三角形经过空间旋转和移动后在屏幕上的投影(非直角三角形)的三个顶点分别为:_A(_x1,_y1),_B(_x2,_y2),_C(_x3,_y3)



综上所述有:



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 * 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、c、tx和b、d、ty。跑题太远了吧!这个矩阵与我们上面说到的位图填充有什么关系么?!Graphics.beginBitmapFill()方法的第二个参数是矩阵Matrix类型吧~。Graphics.beginBitmapFill()方法的第二个Matrix类的参数与我们上面计算出来的矩阵有什么联系么?当然有联系,上面计算出来的矩阵就是我们所要的矩阵,它就是我们能够完整填充三角形的关键!还是不太明白,为什么通过上面方程组计算出来的矩阵就可以做到完整的位图填充?

那我就依我理解简要说说吧。当你使用Graphics.beginBitmapFill(sourceBitmapData,matrix)进行位图填充时,位图上每一个像素的坐标都作出了相应的改变,而这种改变与使用matrix.transformPoint()方法后的效果一样。假定Point类p是为图上一个像素的坐标,改变Graphics.beginBitmapFill()的Matrix类参数为matrix,p的坐标变为q,而q就是使用matrix.transformPoint(p)方法赋值后的坐标,则q=matrix.transformPoint(p)。那么我们只要令改变后的坐标等于三角形的顶点就可以了。这就是两个方程组提出的依据,也是为什么我要提到Matrix.transformPoint()方法的原因。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics