一个不错的3D引擎Sea3D
前几天心血来潮,研究了一下3d项目,有个朋友就给我推荐了sea3d,我试了一下还真不错,他有二种开发方式,一种是flash的away3d,一种three.js,简单的说他就是在away3d和three.js基础上做了2次开发。资源文件是在3dmax上装了一个插件,可以导出后缀名为sea的文件提供加载。
sea3d下载地址:https://github.com/sunag/sea3d
先贴demo,我先做了flash的版本,下面是地址,由于这个模型没有骨骼和动画,所以不会动(可以移动鼠标来控制镜头),换掉资源文件就可以动了。模型加载有点慢,可能需要等一会。
http://www.ajexoop.com/demo/3dDemo/Sea3DModelMananger.html
下面讲下做法,flash3d项目的通用修改参数是这样,首先再flash builder插入附加参数-swf-version=13
然后在index.template.html文件的第48行加入 params.wmode = "direct";
这样就可以运行3d项目了,然后倒入away3d与sea3d的类
准备工作完成,下面就是写代码了,我来贴一下代码,
package { import away3d.animators.SkeletonAnimationSet; import away3d.animators.SkeletonAnimator; import away3d.animators.states.AnimationStateBase; import away3d.animators.transitions.CrossfadeTransition; import away3d.containers.View3D; import away3d.debug.AwayStats; import away3d.entities.JointObject; import away3d.entities.Mesh; import away3d.events.AnimationStateEvent; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import flash.events.KeyboardEvent; import flash.events.MouseEvent; import flash.geom.Point; import flash.geom.Vector3D; import flash.net.URLRequest; import flash.ui.Keyboard; import sunag.events.SEAEvent; import sunag.sea3d.SEA3D; import sunag.sea3d.config.DefaultConfig; import sunag.utils.TimeStep; [SWF(backgroundColor="0x2f3032", frameRate="60")] public class Sea3DModelMananger extends Sprite { private var view:View3D; private var sea3d:SEA3D; private var keyState:Array = []; private var timeStep:TimeStep = new TimeStep(stage.frameRate); private var player:Mesh; private var animator:SkeletonAnimator; protected var position:Vector3D; private var roX:Number = 0; private var roY:Number = 0; private var len:Number = 0; private var modelItem:Mesh; public function Sea3DModelMananger() { /** * Basic config. * */ stage.stageFocusRect = false; stage.showDefaultContextMenu=false; stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; catalogue = Sea3DModelMananger.getCatalogue(stage.loaderInfo.url); view = new View3D(); view.backgroundColor = stage.color; view.antiAlias = 4; addChild(view); addChild(new AwayStats(view)); /** * Config * */ var config:DefaultConfig = new DefaultConfig(); /** * use cpu * */ //config.forceSkeletonCPU = true; /** * <sea3d.container> contains all elements loaded. * add objects in scene container * */ config.container = view.scene; /** * Init loader * */ sea3d = new SEA3D(config); sea3d.addEventListener(SEAEvent.COMPLETE, onComplete); sea3d.load(new URLRequest(Sea3DModelMananger.sourceTransition(".../ceshi08.sea"))); /** * Interactive * */ stage.addEventListener(MouseEvent.MOUSE_DOWN,mouseDownHandler); stage.addEventListener(MouseEvent.MOUSE_UP,mouseUpHandler); stage.addEventListener(MouseEvent.MOUSE_WHEEL,mouseWheelHandler); } private function onEnterFrame(e:Event):void { view.render(); } private function onComplete(e:SEAEvent):void { player = sea3d.getMesh("Player"); animator = player.animator as SkeletonAnimator; position = player.position; // modelItem = sea3d.getMesh("wuqi"); // // animator.play("run"); /** * <Camera001> Camera contained in MAX file. * <sea3d.get...> Using for get element. * */ view.camera = sea3d.getCamera("Camera001"); view.camera.x = 0; view.camera.y = 0; view.camera.rotationX = 0; view.camera.rotationY = 0; /** * Start render and update. * */ len = view.camera.z; stage.addEventListener(Event.ENTER_FRAME, onEnterFrame); } private var _currentPoint:Point = new Point(); private function mouseDownHandler(e:MouseEvent):void { _currentPoint.x = stage.mouseX; _currentPoint.y = stage.mouseY; this.addEventListener(Event.ENTER_FRAME,enterFrameHandler); } private function mouseUpHandler(e:MouseEvent):void { this.removeEventListener(Event.ENTER_FRAME,enterFrameHandler); } private function mouseWheelHandler(e:MouseEvent):void { if(e.delta > 0) { len += 20; } else { len -= 20; } if(len > 0) len = 0; changeModelHandler(); } private function enterFrameHandler(e:Event):void { var addX:Number = _currentPoint.x - stage.mouseX; var addY:Number = _currentPoint.y - stage.mouseY; _currentPoint.x = stage.mouseX; _currentPoint.y = stage.mouseY; roY = roY + addX; roX = roX + addY; if(roX > 90) { roX = 90; } else if(roX < -90) { roX = -90; } changeModelHandler(); } protected function changeModelHandler():void { var sin_rox:Number = Math.sin(Math.PI/180*(roX)) var cos_rox:Number = Math.cos(Math.PI/180*(roX)) var yy:Number = sin_rox * len; var zz:Number = cos_rox * len; view.camera.x = Math.sin(Math.PI/180*(-roY)) * zz; view.camera.y = yy; view.camera.z = Math.cos(Math.PI/180*(-roY)) * zz; view.camera.rotationX = -roX; view.camera.rotationY = -roY; } /** * 获取根目录地址 * @param source 地址 * @return 目录地址 * */ public static function getCatalogue(source:String):String { if(!source) return source; var str:String = source.split("?")[0]; var index:int = str.lastIndexOf("\\"); if(index == -1) { index = str.lastIndexOf("/"); } var contents:String = str.substring(0,index); return contents; } /** * 地址转换 加上“.../”后会对地址加上目录 * @param source 地址 * @return 转化后的地址 * */ protected static var catalogue:String; public static function sourceTransition(source:String):String { return source.replace("...",catalogue); } } } |
不知道away3d 或者说 sea3d有没有直接控制镜头跟随模型的类(现在国内外资料都不多),我直接自己写了个算法,好久没写算法,这算法也是写得我头疼。
demo的下载地址:http://pan.baidu.com/s/1o7G6QDk
之后我会放出js版的,可以用移动端看哦!
匿名
校长,我们来膜拜,