查看: 2678|回复: 1
打印 上一主题 下一主题

初步探索Flash 三维引擎

[复制链接]
.    

3797

主题

11

听众

5万

积分

首席设计师

Rank: 8Rank: 8

纳金币
32328
精华
41

活跃会员 优秀版主 荣誉管理 论坛元老

跳转到指定楼层
楼主
发表于 2012-10-18 21:34:56 |只看该作者 |倒序浏览
本文将介绍的是一个简单的实时3D引擎,并以此向大家阐明一种用Action Script在Flash二维的世界里表现三维对象的方法。



基本原理:我们所生活的世界是一个由x,y,z轴(也就是长宽高)组成的三维世界,要在一个二维平面上表现出三维的信息,我们首先必须要去掉三个坐标轴中的一个,z轴(表示物体深度的轴)。此外,我们还必须要选择一个视点,也就是代表观察者眼睛的一个点,和一个用于投影三维物体所有点的视平面,也就是我们所看见的那个面。然后,从三维物体上每个点到视点之间连线和视平面的交点就是该点在视平面上所应在位置。看了上面的一长串话是否有点头晕?没关系,请看看下面的那张图。

从图中我们可以看出当视点和物体AB位置不变,如果视平面S离物体AB越近,那么物体AB在视平面S上的投影A'B'(即我们所看到的对象)就越大。
实例:知道大致原理后,我们来看个三棱锥的例子。为了简单起见,我们假设视点,也就是眼睛的位置,是处于z轴之上的;另外,视平面S平行于x,y轴。
预备
新建一个Flash文件,并新建两个层,分别命名为actions和modal。新建一个图形元件(Graphic Symbol)并将之命名为line,在此元件中画一条沿45度角斜向右下方的直线并将之长宽皆设为100。
      
在actions层中插入9帧空白关键帧,并依次命名为modal info,init,start,loop,drawline,draw,rotx,roty和rotz。在modal层上插入4帧,然后将line元件从Library中拖到舞台上并将此实例命名为baseline。
一、 模型定义
使用某种编码方式将我们所要进行操作的三维对象表示出来的就是本步骤要做的。在这里,我们只建立简单的框架三维模型,所以只定义模型顶点以及点与点之间的线就够了。
1.1 定义点

在三维坐标系中的每个点都对应维一的一组x,y,z坐标量。因此,我们可以建立一个变量,比如叫points,并使用下面的编码方式来存放各点的坐标值:

其中代表第n个点的坐标,每个坐标值以三位数字来表示,即,12编码为012;1编码为001;点(33,1,0)编码为(033,001,000)。

然后,为了让每组坐标看起来清晰点,将每个点的坐标之间以一个字符R(其实随便什么都可以)来分隔。此外,还要定义一个变量,比如说叫totalpoints,来确定总的点数。
1.2 定义线
很早以前老师就告诉我们两点确定一条直线这个道理。根据这个老道理,我们只要确定两个端点的坐标值便能确定一条线段。所以,我们可以生成一个变量,比如叫lines,并使用跟上面定义点相类似的编码方式来存放各条线的定义:

其中代表第n条线段的两个端点坐标,每个端点以两位数字来表示。例如,从顶点1到顶点5的线段就被编码为0105。这里你可能会发现,这个简易3D引擎只能最多定义99个点。如果你需要添加点数的话其实也很简单,只要增加用以表示每个端点的数字的位数即可。

同样的,你得建立一个用来确定总线段数的变量,比如叫totallines。
1.3 其它的变量

定义完了点和线,我们还得告诉引擎眼睛的位置(比如说eyez)以及视平面所处的深度(zorder)。视点(eyez)离物体越远,物体的***效果就会越差。
1.4 构建三棱锥

用于构建模型的变量差不多都介绍完了,下面就在modal info帧中输入以下这段定义一个三棱锥模型的代码:
totalpoints=4;//四个顶点

points="010,010,000R090,000,000R090,090,090R000,090,000";//四个顶点的坐标

totallines=6;//六条边

lines="0102R0103R0104R0203R0204R0304";//六条边的定义

eyez=-500;//视点的位置

zorder=100;//视平面深度
二、 构建引擎
这一步是整个程序的核心,完成了引擎差不多就等于完成了全部。
2.1 初始化

在开始真正的引擎前我们先来做一些初始化的工作——将所定义模型的信息转存到一个个单独的变量中。在init帧中输入以下代码:

setProperty ("/baseline", _x, 1000);//隐藏原来的那条线

//下面的循环转存所有点的信息

for (i=1; i<=totalpoints; i++) {

set ("x" add i, substring(points, Number((i-1)*12+1), 3));

set ("y" add i, substring(points, Number((i-1)*12+5), 3));

set ("z" add i, substring(points, Number((i-1)*12+9), 3));

}

//下面的循环转存所有线的信息

for (i=1; i<=totallines;i++) {

set ("pt1" add i, substring(lines, Number((i-1)*5+1), 2));

set ("pt2" add i, substring(lines, Number((i-1)*5+3), 2));

}

//下面两个变量分别表示显示中心点的x和y

centerx=190;

centery=215;
2.2 创建基本循环
完成了初始化,下面我们来建立程序中最基本的循环。选中loop帧,并在其中输入:

gotoAndPlay ("start");
2.3 绘制模型
绘制模型的过程可分为两个部分,第一部分将三维物体的各点坐标值转换为投影到视平面S上的相应二维坐标;第二部分根据转换完毕的二维坐标在视平面S上绘制出图像。在这个例子里我们在帧draw里面进行三维坐标的二维化,然后使用帧drawline来进行绘制工作。所以,在帧draw里输入以下的代码:
//下面的循环根据公式进行三维坐标的二维化

for (i=1; i<=totalpoints; i++) {

u = (zorder-eyez)/(eval("z" add i)-eyez);//二维化公式

if (i<=9) {

set ("2Dx0" add i, u*eval("x" add i)+centerx);

set ("2Dy0" add i, u*eval("y" add i)+centery);

} else {

set ("2Dx" add i, u*eval("x" add i)+centerx);

set ("2Dy" add i, u*eval("y" add i)+centery);

}

}

//下面的循环负责复制线段并将之显示出来

for(i=1;i<=totallines;i++){

duplicateMovieClip("/baseline","line" add i,i);

call("drawline");

}

在帧drawline里输入以下的代码:

pt1 = eval("pt1" add i);

pt2 = eval("pt2" add i);

setProperty ("line" add i, _x, eval("2Dx" add pt1));

setProperty ("line" add i, _y, eval("2Dy" add pt1));

setProperty ("line" add i, _xscale, eval("2Dx" add pt2) - eval("2Dx" add pt1));

setProperty ("line" add i, _yscale, eval("2Dy" add pt2) - eval("2Dy" add pt1));
至此绘制模型的工作大致就做完了,在start帧中输入:

call("draw");

按Ctrl+Enter后就可以看到你所定义的模型的模样了。
2.4 旋转
旋转其实也很简单,只要将坐标根据不同旋转角度重新映射一次就可以了,下面是一组用于旋转计算的公式:
沿x轴旋转:

沿y轴旋转:

沿z轴旋转:

由于篇幅有限,这里就只介绍一种旋转方式——沿x轴旋转。
根据上面的这些公式,我们还需要设置一些变量来满足要求。在init帧中追加以下的代码:

basecos=0.9848; //cos10的值

basesin=0.1736; //sin10的值

cos=basecos;

sin=basesin;
axis="x";//沿哪个轴旋转,这里是x也就是说沿x轴旋转

在rotx中输入如下的代码:

//根据不同的角度值重新计算二维坐标

for (i=1; i<=totalpoints; i++) {

set ("tmp", (sin*eval("y" add i))+(cos*eval("z" add i)));

set ("y" add i, (cos*eval("y" add i))-(sin*eval("z" add i)));

set ("z" add i, tmp);

}

接下来只要在start帧中call("draw");的上面插入一句

call("rot" add axis);//根据axis的值调用不同类型的旋转
这样,整个引擎基本上就可以算是完工了。另外两帧roty 和rotz大家只要参照相应的公式填一下应该是没什么大问题的。
如开头所说,这个引擎在功能上其实是相当简陋的,甚至是有相当多BUG的。但本文只是想抛砖引玉,向各位展示一种思路,引擎的完善与实用化留待各位有兴趣的朋友自己慢慢研究了。



更多精彩教程,尽在web3D纳金网http://www.narkii.com/college/
文章来源互联网
分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

0

主题

1

听众

2458

积分

中级设计师

Rank: 5Rank: 5

纳金币
0
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

沙发
发表于 2014-2-22 18:14:41 |只看该作者
Thanks for sharing
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2024-12-4 04:45 , Processed in 0.090033 second(s), 30 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部