Alternativa3D demo系列 -- 渲染+物理引擎测试

   对Alternativa3D渲染引擎和AlternativaPhysics物理引擎做了下测试。

   在上个demo的基础上做了下修改,引入了物理引擎的测试。

   DEMO地址:http://peony3d.com/3DScene/PhysicsWorld/

 在IE下感觉蛮卡的,可能是因为IE没有显卡加速的缘故,在chrome/firefox下运行良好。

 WSAD为方向健,鼠标可以拖拽方向。

 

 关于AlternativaPhysics,个人感觉physics3dintegration用着实在是比较别扭。所以自己实现了二个类重新封装了物体显示和物理刚体。

 Alternativa3D中对贴图的处理没有加入共享贴图的概念,有时相同的物体得让GPU创建几次贴图,所以对这个也做了下优化。

 具体就不多说了,贴代码 可能会更为直观一点。

 

 PhysicsObject: 自然物体,包含显示及物理刚体概念。未完成,只写了个大概的样子。

public class PhysicsObject
    {
        
        private static var _matrix:Matrix4 = new Matrix4();
        
        public function PhysicsObject()
        {
            createRender();
            createBody();
        }
        
        protected var _render:Object3D;
        public function get render():Object3D{
            return _render;
        }
        
        public function set render(value:Object3D):void{
            _render = value;
            updateTransform();
        }
        
        //物理刚体
        protected var _body:Body;
        //碰撞体
        private var _collision:CollisionPrimitive;
        public function get body():Body{
            return _body;
        }
        //创建body
        protected function createBody():void{
            _body = new Body();
        }
        
        protected function createRender():void{
            
        }
        
        protected var _transform:Matrix4 = Matrix4.IDENTITY;
        public function set transform(value:Matrix4):void{
            _transform.copy(value);
            updateRendertransform(value);
            if(_body){
                _body.transform = value;
            }
        }
        
        public function get transform():Matrix4{
            return _transform;
        }
        
        //设置位置
        public function setPosition(x:Number,y:Number,z:Number):void{
            _transform.setPositionXYZ(x,y,z);
            transform = _transform;
        }
        
        public function setVelocity(x:Number,y:Number,z:Number):void{
            if(_body){
                _body.setVelocityXYZ(x,y,z);
            }
        }
        
        public function setRotation(x:Number,y:Number,z:Number):void{
            if(_body){
                _render.rotationX = x;
                _render.rotationY = y;
                _render.rotationZ = z;
            }
        }
        
        //加物理碰撞处理。
        public function addPhysicsPrimitive(primitive:PhysicsPrimitive):void{
            _collision = primitive.primitive;
            _body.addPhysicsPrimitive(primitive,null);
            _collision.calcDerivedData(localTransform);
            _body.aabb.addBoundBox(_collision.aabb);
        }
        
        //
        public function update(t:Number):void{
            
            if(_body && _body.movable){
                _body.interpolateToMatrixSLERP(t,_matrix);
                //更新矩阵
                updateRendertransform(_matrix);
            }
        }
        
        
        //transform setter getter
        protected var localTransform:Matrix4 = new Matrix4();
        //将render的位置 更新到矩阵中去。
        protected function updateTransform():void{
            if(!_render){
                return;
            }
            
            this.localTransform.setMatrix(_render.x,  _render.y,  _render.z,
                _render.rotationX, _render.rotationY, _render.rotationZ);
            var scale:Number = _render.scaleX;
            this.localTransform.m00 *= scale;
            this.localTransform.m10 *= scale;
            this.localTransform.m20 *= scale;
            scale = _render.scaleY;
            this.localTransform.m01 *= scale;
            this.localTransform.m11 *= scale;
            this.localTransform.m21 *= scale;
            scale = _render.scaleZ;
            this.localTransform.m02 *= scale;
            this.localTransform.m12 *= scale;
            this.localTransform.m22 *= scale;
        }
        
        protected static var m4:Matrix4 = new Matrix4();
        protected static var xAxis:Vector3 = new Vector3(), yAxis:Vector3 = new Vector3(), zAxis:Vector3 = new Vector3();
        protected function updateRendertransform(value:Matrix4):void{
            if(!_render){
                return;
            }
            
            m4.copy(localTransform);
            m4.append(value);
            
            _render.x = m4.m03;
            _render.y = m4.m13;
            _render.z = m4.m23;
            
            m4.getAxis(0, xAxis);
            m4.getAxis(1, yAxis);
            m4.getAxis(2, zAxis);
            var scale:Number = xAxis.length();
            _render.scaleX = scale;
            xAxis.scale(1.0 / scale);
            scale = yAxis.length();
            _render.scaleY = scale;
            yAxis.scale(1.0 / scale);
            scale = zAxis.length();
            _render.scaleZ = scale;
            zAxis.scale(1.0 / scale);
            m4.setAxes(xAxis, yAxis, zAxis, xAxis);
            m4.getEulerAngles(xAxis);
            _render.rotationX = xAxis.x;
            _render.rotationY = xAxis.y;
            _render.rotationZ = xAxis.z;
        }
    }

 

World: APP的封装及场景初始化,帧循环等的处理。

public class World
    {
        public function World(stage:Stage,callBack:Function)
        {
            _stage = stage;
            _call = callBack;
            init();
        }
        
        public static var context:Context3D;
        private var _call:Function;
        private var _stage3D:Stage3D;
        private var _context:Context3D;
        private var _root:Object3D;
        private var _stage:Stage;
        private var _camera:Camera3D;
        private var _objects:Vector.<PhysicsObject>;
        private var _cameraController:PhysicsObjectController;
        
        private var physicsScene:PhysicsScene;
        public var physicsStep:int = 60;
        
        //初始化stage
        private function init():void{
            _stage3D = _stage.stage3Ds[0];
            _stage3D.addEventListener(Event.CONTEXT3D_CREATE, onContext3dCreate);
            _stage3D.requestContext3D(Context3DRenderMode.AUTO);
            
        }
        //创建stage3d
        private function onContext3dCreate(event:Event):void{
            _stage3D.removeEventListener(Event.CONTEXT3D_CREATE, onContext3dCreate);
            _context = _stage3D.context3D;
            trace(_context.driverInfo);
            context = _context;
            initScene();
        }
        
        
        //初始化3D场景
        private function initScene():void{
            
            _root = new Object3D();
            _root.addEventListener(Event3D.ADDED, addObject);
            _root.addEventListener(Event3D.REMOVED, removeObject);
            _objects = new Vector.<PhysicsObject>();
            
            physicsScene = PhysicsConfiguration.MINIMAL.getPhysicsScene();
            
            //
            _camera = new Camera3D(1,10000);
            var view:View = new View(_stage.stageWidth,_stage.stageHeight);
            view.antiAlias = 2;
            //设置viewport.
            _camera.view = view;
            _root.addChild(_camera);
            view.hideLogo();
            
            //进行回调。
            _call.apply(null);
            _stage.addEventListener(Event.ENTER_FRAME, step);
        }
        
        //添加物体。上传资源
        private function addObject(event:Event):void{
            if (_context != null) {
                var obj:Object3D = event.target as Object3D;
                var res:Resource;
                //上传本身 及子组件的所有资源。
                for each (res in obj.getResources(true)) {
                    res.upload(_context);
                }
            }
        }
        //删除 物体
        private function removeObject(event:Event):void{
            var obj:Object3D = event.target as Object3D;
            for each (var res:Resource in obj.getResources(true)) {
                res.dispose();
            }
        }
        
        public function set cameraController(value:PhysicsObjectController):void{
            _cameraController = value;
        }
        
        public function get camera():Camera3D{
            return _camera;
        }
        
        public function createCamera():Camera3D{
            var result:Camera3D = new Camera3D(1,10000);
            var view:View = new View(_stage.stageWidth,_stage.stageHeight);
            view.antiAlias = 2;
            //设置viewport.
            result.view = view;
            view.hideLogo();
            
            return result;
        }
        
        
        public function addCamera(camera:Camera3D):void{
            
        }
        
        public function addTestObject(obj:Object3D):void{
            _root.addChild(obj);
        }
        
        
        public function addLight(light:Light3D):void{
            _root.addChild(light);
        }
    
        //add child
        public function addChild(node:PhysicsObject):void{
            var render:Object3D = node.render;
            if(render && !_root.contains(render)){
                _root.addChild(render);
                physicsScene.add(node.body);
                _objects.push(node);
            }
        }
        
        public function removeChild(node:PhysicsObject):void{
            var render:Object3D = node.render;
            if(render && _root.contains(render)){
                _root.removeChild(render);
                physicsScene.remove(node.body);
                var index:int = _objects.indexOf(node);
                _objects.splice(index,1);
            }
        }
        
        private function step(event:Event):void{
            var t:Number;
            if (!_pause) {
                var now:int = getTimer();
                while (physicsScene.time < now) {
                    physicsScene.update(physicsStep);
                }
                t = 1 + (now - physicsScene.time)/physicsStep;
            } else {
                t = 1;
            }
            
            var obj:PhysicsObject;
            for each(obj in _objects){
                obj.update(t);
            }
            
            if(_cameraController){
                _cameraController.update();
            }
            
            _camera.startTimer();
            _camera.render(_stage3D);
            _camera.stopTimer();
        }
        
        private var _pause:Boolean = false;
        public function set pause(value:Boolean):void {
            if (value) {
                _pause = true;
            } else {
                physicsScene.time = getTimer();
                _pause = false;
            }
        }
        
        public function get pause():Boolean {
            return _pause;
        }

PhysicsWorld: mainApp

[SWF(width="800",height="600",frameRate="60",backgroundColor="0x000000")]
    public class PhysicsWorld extends Sprite
    {
        [Embed("caodi.3DS",mimeType="application/octet-stream")]   
        static private const SceneMesh:Class;
        ///////////////////////models//////////////////////////////////////////
        [Embed("scene.a3d",mimeType="application/octet-stream")]   
        static private const SceneData:Class;
        
        public function PhysicsWorld()
        {
            stage.scaleMode =  StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            TextureManager.initTextures();
            world = new World(stage,createScene);
            
        }
        
        private var world:World;
        private function createScene():void{
            
            var camera:Camera3D = world.camera;
            this.addChild(camera.view);
            this.addChild(camera.diagram);
            
            //添加光照
            var light:Light3D = new OmniLight(0xFFFFFF, 1, 10000);
            light.x = 100;
            light.y = 100;
            light.z = 1000;
            light.intensity = 1;
            world.addLight(light);
            light = new AmbientLight(0xFFFFFF);
            light.intensity = 0.3;
            world.addLight(light);
            
            createCaodi();
            
            for(var i:int = 0; i<30; i++){
                var box:BoxView = new BoxView();
                box.setPosition(-200+i*22,0,i*20+60);
                world.addChild(box);
            }
            
            var sphere:Player = new Player();
            sphere.setPosition(30,-100,0);
            world.addChild(sphere);
            
            sphere.render.addChild(camera);
            
            //设置控制器
            var _cameraController:PhysicsObjectController = new PhysicsObjectController(stage, sphere,50);
            _cameraController.maxPitch = 0.9;
            _cameraController.minPitch = -0.7;
            _cameraController.setCameraPosition(camera,0,-60,100);
            _cameraController.cameraLookAt(camera,0,0,0);
            world.cameraController = _cameraController;
        }
        
        private function createCaodi():void{
            var parser:Parser3DS = new Parser3DS();
            parser.parse(new SceneMesh()); //parse the first 3D object
            
            var obj:Object3D;
            for each(obj in parser.objects){
                if(obj is Mesh){
                    obj.z = -150;
                    
                    (obj as Mesh).setMaterialToAllSurfaces(new VertexLightTextureMaterial(TextureManager.airRes));
                    var plane:PhysicsObject = new PhysicsObject();
                    plane.render = obj;
                    var t:CollisionTriangleMesh = new CollisionTriangleMesh(MeshUtils.createGeometryMeshFromMesh3d( obj as Mesh),CollisionType.STATIC);
                    plane.body.movable = false;
                    plane.addPhysicsPrimitive(new PhysicsPrimitive(t));
                    
                    world.addChild(plane);
                }
            }
        }

 


  

posted @ 2012-05-15 18:45  peony3d  阅读(689)  评论(0)    收藏  举报