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); } } }

浙公网安备 33010602011771号