查看: 2882|回复: 0
打印 上一主题 下一主题

Flash 3D - Away 3D

[复制链接]

435

主题

2

听众

6371

积分

高级设计师

Rank: 6Rank: 6

纳金币
6372
精华
0

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

跳转到指定楼层
楼主
发表于 2012-8-31 10:25:09 |只看该作者 |倒序浏览
Flash Player 9实现了许多新的功能,3D就是其中之一。本篇教程将演示如何建立一个逼真的虚拟互动地球,还包括太阳和星空。很难吗?不会,用Away3D来实现很容易!
近来,关于3D的讨论风靡Flash社区。不少3D引擎,各有优缺点。Carlos Pinho为我们列出一张很好的3D引擎清单。本文中,我们将会使用Away3D来实现一个漂亮的场景。






下面是最终完成的效果。试试用鼠标点击或拖动。






很明显这个场景并不是完全精确,但是对于演示flash 3d程序来说已经足够了。



第一步:下载软件
在本地建立一个文件夹"Earth3D"。从Away 3D官方网站下载软件包http://away3d.com/downloads/。本教程使用2.0版,"away3d_2_0_0.zip"。但应该也同样适用于更新的版本。



将软件包保存在"Earth3D"文件夹中,解压。完成后,会得到一个新的子文件夹,"away3d_2_0_0"。其中有两个文件夹,"away3d"及"nochump"。将这两个文件夹移至"Earth3D",并删除"away3d_2_0_0"。



打开Flash,新建一个Flash文件 (Actionscript 3),保存在"Earth3D"文件夹中,命名为"earth3D.fla". 将背景设为暗色。至此完成了准备工作。



第二步: 预备
如果你对Actionscript3不熟悉的话,这些代码可能对你有些陌生。我假定学习本教程的设计师们只有有限的AS3编程经验。所以,如果你是一位高手可以跳过类似下面这样的解释。



使用Away3D时,我们需要告诉Flash需要调用3D引擎的哪些部分。这时需要"import"语句。这里需要调用几个功能包,所以需要多个"import"语句。你大概可以从它们的名字中猜出是做什么用的。



点击时间线上的第一帧,按F9打开AS编程窗口。把下面这段代码拷过去。



// import the required parts of Away3Dimport away3d.containers.*;import away3d.core.base.*;import away3d.primitives.*;import away3d.materials.*;import away3d.core.utils.Cast;import away3d.cameras.*;// import some filters we'll use laterimport flash.filters.BitmapFilter;import flash.filters.BitmapFilterQuality;import flash.filters.BitmapFilterType;import flash.filters.GlowFilter;定义一些变量来保存旋转,鼠标动作等信息。把下面这些代码也拷进Flash中,放在刚才的Import语句下面。



// variablesvar move:Boolean = false;var lastPanAngle:Number;var lastTiltAngle:Number;var lastMouseX:Number;var lastMouseY:Number;var skies:Sphere;



第三步: 设置3D环境
就象在Flash中一样,Away3D也有一个供你绘制场景的舞台。我们将其称为Scene3D。既然是3D立体场景,我们就可以浏览3D物体之间。所以我们需要一个摄像机来观看场景。Away3D中提供了3种摄像机:



Camera3D - 在3D空间内自由移动。
TargetCamera3D - 指向一个物体。
HoverCamera3D - 在一个物体上盘旋。
既然准备在地球上空盘旋,就用使用HoverCamera3D好了。这也是初学者试验时最容易掌握的模式。下面的代码中,用到了放大比例zoom和焦距focus来设定相机,就和设定真正的相机是一样的。



另外,我们还需要定义一个视点(View3D)。把下面这段代码粘贴到现有代码的下面。



// Set the scenevar scene:Scene3D = new Scene3D();// Create and set up the cameravar camera:HoverCamera3D = new HoverCamera3D({zoom:2, focus:200, distance:400});camera.targetpanangle = camera.panangle = -180;camera.targettiltangle = camera.tiltangle = 15;camera.yfactor = 1;var view:View3D = new View3D({scene:scene, camera:camera});// Add viewport to the Flash display list so it's visibleaddChild(view);// Adjust viewview.x = 230;view.y = 200;



创建了场景、相机和视点之后,设置一些初始属性。除非你修改设定,HoverCamer会始终指向舞台的中心。我们用平移角度(panangle) 和倾斜角度(tiltangle)两个属性来围绕这个中心点旋转。最后只剩下画出些东西,好让我们去看了。我们绘制一个基本的球体来做为起点。把下面的代 码粘贴到后面。



var globe:Sphere = new Sphere({material:"blue#white",radius:150,segmentsH:18, segmentsW:26});view.scene.addChild(globe);view.render();



上面的代码中,我们通过几个参数控制新建球体的函数:材质、半径和三角型面数。后面我们还会用到更复杂的纹理贴图。这里暂时使用白线框的蓝色材质。半径的作用很明显了。segmentsH和segmentsW用于控制球体网格的精细度。



编了半天,现在可以大致看一下效果了。按CTRL+Enter (苹果上按Apple-Enter)预览。你可以用调整平移角度panangle, 和倾斜角度tiltangle, 放大倍数zoom, 焦距focus以及距离distance参数, 来试验HoverCamera3D的工作方式。







第四步: 互动操作
只是看着球体还不够酷,我们还要自己盘旋浏览。编写这个功能,我们需要读取当鼠标按下时的坐标位置。把下面的代码粘贴到Flash编程窗口。



function MouseDown(event:MouseEvent):void{    lastPanAngle = camera.targetpanangle;    lastTiltAngle = camera.targettiltangle;    lastMouseX = stage.mouseX;    lastMouseY = stage.mouseY;    move = ***e;}function MouseUp(event:MouseEvent):void{    move = false;}function onEnterFrame(e:Event):void{    // rerender viewport    var cameraSpeed:Number = 0.3; // Approximately same speed as mouse movement.    if (move) {        camera.targetpanangle = cameraSpeed*(stage.mouseX - lastMouseX) + lastPanAngle;        camera.targettiltangle = cameraSpeed*(stage.mouseY - lastMouseY) + lastTiltAngle;    }    camera.hover();      view.render();}addEventListener(Event.ENTER_FRAME, onEnterFrame);stage.addEventListener(MouseEvent.MOUSE_DOWN, MouseDown);stage.addEventListener(MouseEvent.MOUSE_UP, MouseUp);



当使用者点击鼠标的时候,会执行第一个函数(function )。我们设置了接受鼠标点击函数(MouseEvent)来实现这个功能。代码最后用addEventListener把这个函数加入舞台。点击鼠标时, 程序记录相机和鼠标的位置值。然后把move变量设为有效(***e),允许旋转。第二个函数的原理相同,负责关掉move变量。



最后一个函数会在每一帧执行。当按下鼠标时(move变量为***e),程序会基于当前鼠标位置和之前的鼠标位置来更新旋转。这一步是这个程序中最复杂的部分。后面的步骤都很有意思。ctrl+回车输出SWF,转转这个小球吧!







第五步: 加入纹理贴图
搜索合适的地球贴图的时候,我偶然进到JHT的Planetary Pixel Emporium。这里有地球和其他太阳系行星的高质量贴图。所有公用资源都可以免费使用。这个站点同时还提供超高分辨率贴图收费下载。我对一些贴图进行了修改,点击这里下载ZIP文件,然后解压到工作目录中。



回到Flash中,选择文件->导入->导入到库,然后选择"earthmap1k.jpg"。导入后打开文件库面板(窗口-> 文件库),右键点击图片从下拉菜单中选择"链接"(Linkage)。选中"导出到Actionscript”(Export for Actionscript)复选框。









这样就可以在Away3D中,就可以使用以下代码直接调用图片了。



globe.material = new BitmapMaterial(Cast.bitmap("earthmap1k.jpg"));再次输出SWF,看看地球全貌。







第六笔: 增加天空云层
地球看起来不错,但有些单调吧?看看下面怎么来改进。 地球周围有大气云层环绕,如果实现这点,就有深度的感觉了。Away3D可以用Flash支持的各种位图来作为纹理。用一张PNG透明图片来模拟云层,我 们透过云层看到下面的大地。我们还可以通过单独控制天空旋转强化景深效果。



将"earthcloudmap.png"导入文件库。同样设置链接"Linkage",以备AS程序调用。这样图片是由两张JHR网站上下载的图片合成的。加入以下代码。



skies = new Sphere({material:"earthcloudmap.png",radius:153,segmentsH:18, segmentsW:26});view.scene.addChild(skies);









输出动画后,有些问题?这是因为Away3D默认设置中,同时渲染两个球体时有问题。找到建立view的那行代码,将其改为以下语句:(译者注:我在Away3D 2.1.0中渲染场景,没有出现上述问题。)



var view:View3D = new View3D({scene:scene, camera:camera, renderer:Renderer.CORRECT_Z_ORDER});最后的那个参数是使3D引擎以正确方式来处理Z轴排列(Z-sort)。要使用这个参数,我们还需要在代码开始处引入新的类库。



import away3d.core.render.*;这行代码导入了必要的渲染器。现在效果好了,但速度也稍慢了些。



下面加入些云层飘动的效果如何?



在onEnterFrame 函数中加入两行代码:



function onEnterFrame(e:Event):void{    // rerender viewport    var cameraSpeed:Number = 0.3; // Approximately same speed as mouse movement.    if (move) {        camera.targetpanangle = cameraSpeed*(stage.mouseX - lastMouseX) + lastPanAngle;        camera.targettiltangle = cameraSpeed*(stage.mouseY - lastMouseY) + lastTiltAngle;    }    camera.hover();      view.render();    if(skies)        skies.rotationY += .015;}只改了最后两行。涵义为,如何skies存在,就让他沿Y轴慢慢转(0.015 度每帧)。这样看起来更加真实。自己试一下吧!



(译者又注:Sonic在这里改了一下。首先修改旋转方向,观察云层形状,改为逆时针方向更为真实。其次以开始毫秒数除-1500来实现旋转。可以通过修改除数大小来控制速度。)



skies.rotationY = getTimer() / -1500; //rotating clouds



第七步: 加入星空
在太空中看到地球,应该是在星空的环绕之下。当我寻找星空的贴图的时候,我找到了这篇教程。虽然不是专门为创建星空贴图而写的,但生成的图片和我们需要的效果很类似。因为这篇带有演示草图的文章发布在教育资源中,我想我们使用"star_map_small.jpg"这张图片来做这个教程应该是合法的。(敬佩一下老外的版权意识,差距很大啊。)



相机放在距场景中心400units远的地方。所以建造一下比400 units大一些的球体,就可以把相机放在球体里面,展示球体的内部。我们来试一下:



var heavens:Sphere = new Sphere({material:"star_map_small.jpg",radius:1200,x:0,y:0,segmentsH:9, segmentsW:9});view.scene.addChild(heavens);



当你把这段代码加进去的时候,你看不到星空。这是因为如果以双面方式来渲染3D网络,计算量会增加一倍。3D引擎会省掉一切可能的运算负担,来达到最佳的速度。当然你也可以打开双面渲染,同时你也需要翻转材质方向,就象这样:



heavens.invertFaces();



把这句代码加上后,星空就出现了。另外请注意因为星空用了很暗的贴图,基本看不到细节,所以我们用了一个精度很低的球体。(segmentsH:9, segmentsW:9) - 9x9 segments







第八步:加入太阳



导入"sunmap.jpg",在链接选项中打开“为Actionscript导出”。这和前面步骤中处理材质的方法一样。



var sun = new Sphere({material:"sunmap.jpg",radius:50,x:150,y:100,z:600,segmentsH:6, segmentsW:6});view.scene.addChild(sun);



添加一个新的球体,并赋予太阳材质。这个球体很小,在地球的右(x轴)上(y轴)方。离地球有一段距离(深度,z轴)。再次测试场景,可以看到初始场景中,太阳在地球后面。移动场景时,太阳也会单独移动。











第九步: 优化
到这里开始出现问题了。即便太阳只有6x6 segments的精度,场景已经开始变慢了。想要顺畅运行动画,我们需要做些优化工作。减少场景中三角型的数量是目前的主要问题。为了表现云层,地球外 面附加的球体多边型数量很多,而且需要修正Z轴(Z-sorting),占用了过多的资源。(译者注,是我的机器配置比较好吗?我没觉得慢,不过下面优化 的办法还是很值得学习的。



另一个附加云层的办法是把地球贴图和天空结合在一起(有时称为“预烘烤贴图”)。在现实中,天空和地球表面是很接近的,所以这样做还能增加真实感(至少可以拿这个说法当借口)。先把创建天空的两行代码注释掉(在代码前加两个斜杠//)。



// skies = new Sphere({material:"earthcloudmap.png",radius:153,segmentsH:18, segmentsW:26});// scene.addChild(skies);



下面导入"earthmap1k.png",我用photoshop把两张图片结合在了一起。象前面一样设置为Actionscript导出图片。在后面加上这行代码:



globe.material = new BitmapMaterial(Cast.bitmap("earthmap1k.png"));



同时,把相机设置恢复成普通渲染模式,不再强制物体Z轴顺序。将设定View3D的代码替换为这样:



var view:View3D = new View3D({scene:scene, camera:camera, renderer:Renderer.BASIC});这两招可以大大加快运行速度。







第十步: 夜景
烘培贴图的技巧还可以有别的用处。在Photoshop中处理一下,把夜景照片结合到贴图中。导入"earthmap1k_night_day.png",设定图片为Actionscript导出。加入下面的代码。



var newMaterial:BitmapMaterial = new BitmapMaterial(Cast.bitmap("earthmap1k_night_day.png"));globe.material = newMaterial;



效果好多了,是吧?看到夜景中闪烁的灯光了吗?







第十一步: 大气层
最后一步。设置"ownCanvas"属性。在Away3D中,所有的物体都可以使用标准Flash滤镜。加入以下代码,本篇教程到此结束。



var myFilter1:Array = new Array()myFilter1.push(new GlowFilter(0xFFFFAA, 1, 25, 25, 3, 1, false, false));sun.ownCanvas=***e;sun.filters=myFilter1;var myFilter2:Array = new Array()myFilter2.push(new GlowFilter(0xFFFFFF, 0.4, 15, 15, 2, 1, false, false));globe.ownCanvas=***e;globe.filters=myFilter2;



结束语
这篇教程只是一个开始。为什么不把整个太阳系都做出来呢?所需的所有贴图在JHR的网站上都有。或者加上变焦功能?再或者让相机自由移动?(太空船?)加上镜头反光的效果?一切皆有可能。



虽然Away3D使用简单,但现在还存在着文档不足的问题。这个问题可能会逐渐解决。(译者注:在我翻译本文时,已经看到了一些3D引擎分析对比的 文章指出,Away3D在提供文档方面做的是比较出色的了,对比分析的文章我后面会翻译放出。)Away3D的开发小组在官方网站上列出了一些学习资源。 最佳的学习方法就是直接看看别人的代码。我写这篇教程的时候,在Away3D开发者之一Rob Bateman写的这篇教程 (英文,尚未翻译)中学到了很多东西。教程中讲解了一些Away3D中材质和阴影的技巧。在这里你可以下载本教程的FLA源文件。



开始创建你自己的3D世界之前,别忘了Flash Player也有它的局限。3D Flash目前还很幼小。Adobe已经开始在Flash Player 10中增加更多的3D功能支持,到时候性能肯定会大大增强。但是目前为止我们还只能限制我们的3D项目规模。我还知道Adobe已经在直接与 Papervision3D和Away3D的开发团队进行沟通。确保这些引擎可以在Flash Player 10发布后,短时间内开始支持新的功能。所以现在我们可以先玩玩,在现有功能中尽情发挥。


分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

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

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

GMT+8, 2025-1-27 05:54 , Processed in 0.066196 second(s), 29 queries .

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

© 2008-2019 Narkii Inc.

回顶部