package { //Flash AS3 imports import flash.display.Loader; import flash.display.Sprite; import flash.events.Event; import flash.events.KeyboardEvent; import flash.events.MouseEvent; import flash.net.URLLoader; import flash.net.URLLoaderDataFormat; import flash.net.URLRequest; //WOWEngine imports import fr.seraf.wow.core.data.WVector; import fr.seraf.wow.core.data.WVertex; import fr.seraf.wow.core.face.WPolygon; import fr.seraf.wow.core.WOWEngine; import fr.seraf.wow.events.WOWEvent; import fr.seraf.wow.primitive.WOWPolygon; import fr.seraf.wow.primitive.WSphere; //Papervision3D imports import org.papervision3d.cameras.Camera3D; import org.papervision3d.core.geom.renderables.Triangle3D; import org.papervision3d.core.geom.renderables.Vertex3D; import org.papervision3d.materials.ColorMaterial; import org.papervision3d.materials.utils.MaterialsList; import org.papervision3d.materials.WireframeMaterial; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.parsers.Collada; import org.papervision3d.objects.primitives.Cube; import org.papervision3d.objects.primitives.Sphere; import org.papervision3d.render.BasicRenderEngine; import org.papervision3d.scenes.Scene3D; import org.papervision3d.view.Viewport3D; /** * Simple exemple of WOWPolygon use from Papervision3D Collada file; * @author Henrion Thomas - www.badou.biz/blog */ public class Main extends Sprite { //Papervision private var _scene:Scene3D; private var _cam:Camera3D; private var _viewport:Viewport3D; private var _renderer:BasicRenderEngine; private var _rootNode:DisplayObject3D; //WOWEngine private var wowEngine:WOWEngine; //A URLLoader to load the Collada Datas private var levelLoader:URLLoader; //Array that'll contain all Particles (Render & Physics Particle); private var ParticlesArray:Array; //User const private static const num_Particles:uint = 10; private static const particles_radius:uint = 50; private static const radian_Ratio:Number = 180 / Math.PI; /** * CONSTRUCTOR */ public function Main() { //Make the Collada Loader , URLLoader and Data Text -> Collada is XML ; levelLoader = new URLLoader(); levelLoader.dataFormat = URLLoaderDataFormat.TEXT; levelLoader.addEventListener(Event.COMPLETE , onCompleteLoader); //Load the file levelLoader.load(new URLRequest("test23.dae")); } /** * When the loaded file is complete * @param e */ private function onCompleteLoader(e:Event):void { initPhysWorld(); initPv3dWorld(); initObjects(); initListeners(); loadText.x = 2500; } /** * Create the Physics World with WOWEngine */ private function initPhysWorld():void { wowEngine = new WOWEngine(.3); wowEngine.collisionResponseMode = wowEngine.SELECTIVE; //setup global force wowEngine.addMasslessForce(new WVector(0, 10, 0)); } /** * Create Papervision3d World */ private function initPv3dWorld():void { _viewport = new Viewport3D(550, 400, false, false); addChild(_viewport); _scene = new Scene3D(); _rootNode = new DisplayObject3D(); _scene.addChild(_rootNode); _cam = new Camera3D(); _cam.y = 0 , _cam.z = -2500 , _cam.localRotationX = 0; _renderer = new BasicRenderEngine(); } /** * Creates Objects ( Papervision & WOW ); */ private function initObjects():void { //Create the collada with the loaded data; var Levels:Collada = new Collada(XML(levelLoader.data) , new MaterialsList( { all:new WireframeMaterial(0xff00ff , 1 , 2) } ) ); _rootNode.addChild(Levels); //Retrieving the "ground" of the collada, it's called "pPlane1" in my .dae source; var ground:DisplayObject3D = Levels.getChildByName("pPlane1" , true); ground.material.doubleSided = true; //For each face of the ground; for (var i:int = 0; i < ground.geometry.faces.length; i++) { //store the currentface as Triangle3D; var tri:Triangle3D = ground.geometry.faces[i]; var VertArray:Array = new Array(); //for each vertice of the face; for (var u:int = 0; u < tri.vertices.length; u++) { //Store the currentVertice; var Vert:Vertex3D = tri.vertices[u]; //Convert it to a WOW Vertrex (invert axis); var VerticesNow:WVertex = new WVertex( -(ground.x + Vert.x) , -(ground.y + Vert.y) , -(ground.z + Vert.z)); //And push the WVertex to the VerticesArray; VertArray.push(VerticesNow); //Three following lines are optionnally , just display a cube in each WVertice to show you the differents between Papervision and WOW axis; var cub:Cube = new Cube(new MaterialsList( { all:new WireframeMaterial(0xff9900) } ) , 50, 50, 50); cub.x = VerticesNow.x , cub.y = VerticesNow.y , cub.z = VerticesNow.z; _rootNode.addChild(cub); } //Now create a WOWPolygon with VertArray; var Poly:WOWPolygon = new WOWPolygon(VertArray[2] , VertArray[1] , VertArray[0]); //Property of a WOWParticle Poly.fixed = true; Poly.collidable = true; Poly.elasticity = 0.5; Poly.friction = 0.02; //Add the Poly to the physical Engine; wowEngine.addParticle(Poly); //We can Add Collision Function if we need; //Poly.activCollisionEvent(Bouncing); } //Now Create some spherical Particles; ParticlesArray = new Array(); for (var Z:int = 0; Z < num_Particles; Z++) { //As tought on "http://seraf.mediabox.fr/wow-engine/as3-3d-physics-engine-wow-engine/" var Part_R:Sphere = new Sphere(new ColorMaterial(0x000000) , particles_radius ,8,8); Part_R.x = -1000 + Math.random() * 2000; Part_R.z = -1000 + Math.random() * 2000; Part_R.y = 200 + Math.random() * 600; //we must bind render and phys particle; var Part_P:WSphere = new WSphere( -Part_R.x , -Part_R.y , -Part_R.z , particles_radius , false , 5 * Math.random() , 0.3); //add the phys to the physical Engine; wowEngine.addParticle(Part_P); //and the render to the display list; _rootNode.addChild(Part_R); //push both in ParticlesArray; ParticlesArray.push(new Array(Part_R , Part_P)); } } /** * on Key down Handler * @param e */ private function onKeyDownHandler(e:KeyboardEvent):void { switch(e.keyCode) { case 37 : //trace("left"); _rootNode.localRotationY+=2; break; case 38 : //trace("up"); var angle:Number = _cam.localRotationX-=2; _cam.z = Math.cos(angle/radian_Ratio) * -2500; _cam.y = Math.sin(angle/radian_Ratio) * -2500; break; case 39 : //trace("right"); _rootNode.localRotationY-=2; break; case 40: //trace("down"); angle = _cam.localRotationX+=2; _cam.z = Math.cos(angle/radian_Ratio) * -2500; _cam.y = Math.sin(angle/radian_Ratio) * -2500; break; } } /** * on Mouse Click Handler * @param e */ private function onClickHandler(e:MouseEvent):void { //Randomize particules positions for (var i:int = 0; i < num_Particles; i++) { var PP:WSphere = ParticlesArray[i][1]; PP.px = 1000 - Math.random() * 2000; PP.pz = 1000 - Math.random() * 2000; PP.py = -200 - Math.random() * 600; } } /** * on EnterFrame Handler * @param e */ private function render(e:Event):void { //Run WOWEngine; wowEngine.step(); //Align render and Phys Particles AlingRenderObjects(); //Then Pv3D render; _renderer.renderScene(_scene , _cam , _viewport); } /** * Align particles (Pv3D - WOw); */ private function AlingRenderObjects():void { for (var i:int = 0; i < num_Particles; i++) { var PR:Sphere = ParticlesArray[i][0]; var PP:WSphere = ParticlesArray[i][1]; PR.x = -PP.px; PR.y = -PP.py; PR.z = -PP.pz; } } /** * Add listeners */ private function initListeners():void { addEventListener(Event.ENTER_FRAME , render); stage.addEventListener(MouseEvent.CLICK , onClickHandler); stage.addEventListener(KeyboardEvent.KEY_DOWN , onKeyDownHandler); } /** * If we need the collision Function * @param e */ private function Bouncing(e:WOWEvent):void { trace("collide between" + e.particuleA +" And " + e.particuleB ); } } }