roadProgram的专栏

一个程序员的路

转 第十六章 3D 线条与填充(1) (as3.0)

 第十五章我们介绍了 3D,但只是将物体置于 3D 空间中,设置大小与位置。物体实际
上还是 2D 的。这就像老的 3D 游戏中,我们可以绕着某个物体或人物走,这些对象会转
过来面对我们。这些物体或人物并不是真正的会转过来 —— 只是看上去是这样的,因为它
们都是 2D 物体,那是我们看到它唯一的一个视角。
    本章,我们将真正地在 Flash 中创建 3D 模型。具体说来有创建并使用 3D 点,线条,
填充以及立体图形。学习完本章,大家就可以任意在三维空间中创建各种形状,并对它们执
行移动和旋转。
创建点和线条
    如果只在 3D 中创建点而不创建线条的话是没有任何意义的。因为理论上讲,一个点
是没有维度并且不可见的。开始时,我们还将使用 Ball3D 类,给一个非常小的半径,只要
能看到点在哪就够了。这样,只需要再创建几条线将这些小球连起来就行了。相当简单。我
们前面做过这样的例子,不过这次要在小球上添加透视,将它们放入 3D 空间。
    可以将点的实例设为黑色,10 像素宽。创建一些点的实例,根据鼠标的位置对它们进
行旋转(如前一章最后所讲的一样)然后在点间绘制一些线条。代码与上一章的 RotateXY.as
文件几乎相同。主要的区别在 onEnterFrame 的最后一块儿,从第一个点循环绘制线条到剩
下所有的点。同时,我还删除了 sortZ 方法,因为在这里有没有都一样。以下是 Lines3D1.as
的全部代码。

运行结果如图 16-1 所示。

转 <wbr>第十六章 <wbr>3D <wbr>线条与填充(1) <wbr>(as3.0)
         图 16-1 3D 点与线


     实际来说,没有太多可改的地方。如果要转为立体 3D 模型,就要舍弃所有的这些黑
点。第一个尝试非常简单。只要在创建时将每个 Ball3D 实例的半径设置为 0 即可,如下:
    var ball:Ball3D = new Ball3D(0);


运行结果如图 16-2 所示。

转 <wbr>第十六章 <wbr>3D <wbr>线条与填充(1) <wbr>(as3.0)

图 16-2 3D 线条,点不可见
     回过头再看看先前的代码,   这时我们发现有很多地方是多余的。比如,scaleX, scaleY 以
及 visible 对于一个看不到的点来说完全没有用的。没有可见的或可缩放的对象。根据这条
线索,更深层地思考认识一下这个继承自 Sprite 类的一般类,现在它实际上只是五个变量
的容器:xpos, ypos, zpos, x, y。实在有些过分。一个影片有许多功能——发送事件,绘图,
容纳其它 sprite 影片等等 —— 并且占用了大量资源。如此使用一个 sprite 影片就像开着
坦克到市区里捡一块面包。
    如果只需要存储变量的话,不如让我们创建一个只用于存储这些变量作为属性的类。事
实上, 如果再将透视和坐标旋转再放入这个类中,比单纯只存储几个属性更有意义。  女士们、
先生们,现在我把这个 Point3D 类送与各位:

package {
 public class Point3D {
  public var fl:Number = 250;
  private var vpX:Number = 0;
  private var vpY:Number = 0;
  private var cX:Number = 0;
  private var cY:Number = 0;
  private var cZ:Number = 0;
  public var x:Number = 0;
  public var y:Number = 0;
  public var z:Number = 0;
public function Point3D(x:Number=0, y:Number=0, z:Number=0) {
  this.x = x;
  this.y = y;
  this.z = z;
}
public function setVanishingPoint(vpX:Number, vpY:Number):void {
  this.vpX = vpX;
  this.vpY = vpY;
}
public function setCenter(cX:Number,cY:Number,cZ:Number=0):void {
  this.cX = cX;
  this.cY = cY;
  this.cZ = cZ;
}
public function get screenX():Number {
  var scale:Number = fl / (fl + z + cZ);
  return vpX + cX + x * scale;
}
public function get screenY():Number {
  var scale:Number = fl / (fl + z + cZ);
  return vpY + cY + y * scale;
}
public function rotateX(angleX:Number):void {
  var cosX:Number = Math.cos(angleX);
  var sinX:Number = Math.sin(angleX);
  var y1:Number = y * cosX - z * sinX;
  var z1:Number = z * cosX + y * sinX;
  y = y1;
  z = z1;
    }
    public function rotateY(angleY:Number):void {
      var cosY:Number = Math.cos(angleY);
      var sinY:Number = Math.sin(angleY);
      var x1:Number = x * cosY - z * sinY;
      var z1:Number = z * cosY + x * sinY;
      x = x1;
      z = z1;
    }
    public function rotateZ(angleZ:Number):void {
      var cosZ:Number = Math.cos(angleZ);
      var sinZ:Number = Math.sin(angleZ);
      var x1:Number = x * cosZ - y * sinZ;
      var y1:Number = y * cosZ + x * sinZ;
      x = x1;
      y = y1;
    }
  }
}
       现在,在使用这个类创建 3D 点时,可以传入 x, y, z 坐标,或者使用公共的 x, y, z 属
性 进 行 设 置 。 类 中 包 涵 了 一 个 默 认 的 fl 属 性 以 及 用 于 存 放 消 失 点 的 属 性 , 可通过setVanishingPoint() 方法进行设置。使用三种旋转方法,可以绕着某一轴的中心点进行旋转。
还可以用 setCenter 方法改变中心点。大家马上会看到这些应用。最后,它还可以为我们处
理所有的透视。当我们已经旋转或设置了点的位置时,只需要用 screenX 和 screenY 即可
获得透视的点在屏幕上的位置。
     这个类会让我们后面两章的程序变得简单许多。
     使用这个新的类重新编写上面线条旋转的程序将会惊人的简单,如 Lines3D2.as 所示:
转 <wbr>第十六章 <wbr>3D <wbr>线条与填充(1) <wbr>(as3.0)

图 16-3 3D 空间中的正方形坐标
     注意,所有的 z 值都相同。这是一个平面上的正方形。将一个正方形放在平面上的最
简单的办法就是让所有的点在某个轴上的位置都相同(这里我选择了 z 轴),还要定义正方
形的其它两个轴(x 和 y 轴)。以下代码将代替循环随机创建的点:
points[0] = new Point3D(-100, -100, 100);
points[1] = new Point3D( 100, -100, 100);
points[2] = new Point3D( 100, 100, 100);
points[3] = new Point3D(-100, 100, 100);
我们还要手动设置每个点的消失点。在循环中做是再简单不过的了:
for (var i:uint = 0; i < numPoints; i++) {
  points[i].setVanishingPoint(vpX, vpY);
}
因为现在有四个点,我们将不得不把 numPoints 改为 4。剩下的代码还可以正常工作,但
是我们还要多做一步:绘制一条连接最后一个点与第一个点的线,用于将图形封闭。以下是
全部代码,可见 Square3D.as(运行结果如图 16-4 所示):


转 <wbr>第十六章 <wbr>3D <wbr>线条与填充(1) <wbr>(as3.0)
图 16-4 3D 旋转正方形
     太奇妙了——一个旋转的正方形!现在我们应该可以创建出任何的平面图形了。我通常
都预先将所有的这些点在方格纸上标出(如图 16-5 所示) ,用来帮助作图。

转 <wbr>第十六章 <wbr>3D <wbr>线条与填充(1) <wbr>(as3.0)
图 16-5 使用方格纸标出所有的点
     通过这个草稿,可以用来帮助创建所需的这些点:
points[0] = new Point3D(-150, -250, 100);
points[1] = new Point3D( 150, -250, 100);
points[2] = new Point3D( 150, -150, 100);
points[3] = new Point3D( -50, -150, 100);
points[4] = new Point3D( -50, -50, 100);
points[5] = new Point3D( 50, -50, 100);
points[6] = new Point3D( 50, 50, 100);
points[7] = new Point3D( -50, 50, 100);
points[8] = new Point3D( -50, 150, 100);
points[9] = new Point3D( 150, 150, 100);
points[10] = new Point3D( 150, 250, 100);
points[11] = new Point3D(-150, 250, 100);
这样就完成了 SpinningE.as 中的旋转字母 E 的效果,运行结果如图 16-6 所示。不要忘记
将 numPoints 改为 12。稍后我们要使用 points.length 让这个值可以动态改变。

转 <wbr>第十六章 <wbr>3D <wbr>线条与填充(1) <wbr>(as3.0)

图 16-6 3D 旋转字母 E

 

      执行后我们注意到当字母 E 向我们旋转过来时,某些点会变得非常近,并且与第一个
3D 例子一样会发生倒置。您也许首先会想到增加所有点的 z 值,但这实际上会让效果变
得更糟。例如,假设将 z 设为 500。旋转的时候,z 将从 500 到 -500,甚至会让有些点
运动到观察点更往后的位置,会让事情更糟糕。不过我们可以使用 setCenter 方法将所有点
向 z 轴推移,如下:
for (var i:uint = 0; i < numPoints; i++) {
  points[i].setVanishingPoint(vpX, vpY);
  points[i].setCenter(0, 0, 200);
}
打开 Point3D 类,我们会看到 scale 的计算方法为:
     var scale:Number = fl / (fl + z + cZ);
这样就将整个系统推移了 200 像素,包括旋转系统。原来 z 的值保持不变,只是因为计算
透视的值更高了,那么所有物体都将呈现在观察着的前面。试用其它的值进行替换,观察运
动效果。稍后,我们会让这个图形在其它的轴上也能运动起来。

(如果要转载请注明出处http://blog.sina.com.cn/jooi,谢谢)

阅读更多
个人分类: Flash Flex
想对作者说点什么? 我来说一句

用纹理填充线条.rar

2010年07月02日 44KB 下载

flash as3.0颜色填充demo

2013年03月20日 7KB 下载

C# 绘制用纹理填充线条

2009年04月23日 12KB 下载

图片填充文字线条

2012年02月29日 49KB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭