This is a little Hello World app using Papervision3D, and the Wow Physics Engine, written in AS3.
The useful parts of the source code used in the hello World app is down below. Basically you start by setting up the physics world, then the 3d. The Enterframe loop is used to update the rendering part to show what the objects in the physics world are doing.
Initialize the physics world and its objects:
private function initPhysics():void { //keep the objects in an array, so we can access them later on wowBalls = new Array(); wowAnchorPoints = new Array(); wowConstraints = new Array(); // init wow basics wow=new WOWEngine(); wow.collisionResponseMode = wow.SELECTIVE; //add some gravity wow.addMasslessForce(new WVector(0,gravity,0)); var wowBall:WSphere; var wowAnchorPoint1:WSphere; var wowAnchorPoint2:WSphere; var constraint:WSpringConstraint; var x:int = 0; var y:int = -ballHeight/2; var z:int = 0; var fixed:Boolean = false; //make the physics representation of the balls for(var i:uint=0; i < NUM_OF_BALLS; i++) { //add the ball fixed = false; wowBall = new WSphere(1+((i-center)*ballSpacing),y,z,ballRadius,fixed,ballMass,ballElasticity,ballFriction); wowBalls.push(wowBall); wow.addParticle(wowBall); //add the first anchorpoint 'holding' the ball fixed = true; wowAnchorPoint1 = new WSphere(x+((i-center)*ballSpacing),y+ballHeight,z-150,ballRadius,fixed); wowAnchorPoints.push(wowAnchorPoint1); wow.addParticle(wowAnchorPoint1); //add the second anchorpoint 'holding' the ball wowAnchorPoint2 = new WSphere(x+((i-center)*ballSpacing),y+ballHeight,z+150,ballRadius,fixed); wowAnchorPoints.push(wowAnchorPoint2); wow.addParticle(wowAnchorPoint2); //build the 'holding' mechanism by using constraints constraint = new WSpringConstraint(wowBall, wowAnchorPoint1,stiffness); wowConstraints.push(constraint); wow.addConstraint(constraint); constraint = new WSpringConstraint(wowBall, wowAnchorPoint2,stiffness); wowConstraints.push(constraint); wow.addConstraint(constraint); }
Now create the Papervision 3D world:
private function init3D():void { pv3dBalls = new Array(); pv3dAnchorPoints = new Array(); pv3dMirrorBalls = new Array(); // init papervision basics view = new BasicView(stage.stageWidth, stage.stageHeight, true, true); view.camera.zoom = 10; view.camera.focus = 150; addChild(view); //use interactive 3dmouse vMouse = view.viewport.interactiveSceneManager.virtualMouse; mouse3D = view.viewport.interactiveSceneManager.mouse3D; Mouse3D.enabled = true; //create lines obj representing constraints between anchorpoints and balls pv3dLinesArray = new Array(); pv3dLines = new Lines3D(new LineMaterial(0x666666,1)); view.scene.addChild(pv3dLines); // create materials var shadowData = new glasTexture() as Bitmap; var mp:BitmapMaterial = new BitmapMaterial(shadowData.bitmapData); var ballData = new ballTexture() as Bitmap; var ballMirrorMaterial:BitmapMaterial = new BitmapMaterial(ballData.bitmapData); light = new PointLight3D(false,false); envMaterial = new EnvMapMaterial(light, ballData.bitmapData,ballData.bitmapData,1); //create the glas "table" var glasPane:Plane = new Plane(mp,600,400); glasPane.rotationX = 270; glasPane.y = -120; view.scene.addChild(glasPane, "glasPane"); var dragPlane:Plane = new Plane(new ColorMaterial(0xFF0000, 0), 1000,1000, 6, 6); dragPlane.material.interactive = true; dragPlane.material.doubleSided = true; dragPlane.z = 50; view.scene.addChild(dragPlane, "dragPlane"); var pv3dBall:Sphere; var pv3dMirrorBall:Sphere; var pv3dAnchorPoint1:Sphere; var pv3dAnchorPoint2:Sphere; //create the 3d representation of the balls for(var i:uint=0; i < NUM_OF_BALLS; i++) { //add the shiny little ball pv3dBall = new Sphere(envMaterial,ballRadius+2,16,16); //(new WireframeMaterial(0xaf8554),ballRadius+5,10,10); pv3dBall.material.interactive = true; pv3dBall.name = "pv3dBall"+i; pv3dBall.scale *=-1; view.scene.addChild(pv3dBall, "pv3dBall"+i); pv3dBalls.push(pv3dBall); //add the mirror ball pv3dMirrorBall = new Sphere(ballMirrorMaterial,ballRadius+2,10,10); view.scene.addChild(pv3dMirrorBall, "pv3dMirrorBall"+i); pv3dMirrorBalls.push(pv3dMirrorBall); //add the first anchorpoint 'holding' the ball pv3dAnchorPoint1 = new Sphere(new ColorMaterial(0x999999,0.5),1); view.scene.addChild(pv3dAnchorPoint1, "pv3dAnchorPoint1"+i); pv3dAnchorPoints.push(pv3dAnchorPoint1); //add the second anchorpoint 'holding' the ball pv3dAnchorPoint2 = new Sphere(new ColorMaterial(0x999999,0.5),1); view.scene.addChild(pv3dAnchorPoint2, "pv3dAnchorPoint2"+i); pv3dAnchorPoints.push(pv3dAnchorPoint2); //add lines from ball to both anchorpoints, coordinates are done later... pv3dLinesArray.push(new Line3D(pv3dLines,new LineMaterial(0x999999,0.1),1, new Vertex3D(0,0,0), new Vertex3D(0,0,0) )); pv3dLines.addLine(pv3dLinesArray[i*2]); pv3dLinesArray.push(new Line3D(pv3dLines,new LineMaterial(0x999999,0.1),1, new Vertex3D(0,0,0), new Vertex3D(0,0,0) )); pv3dLines.addLine(pv3dLinesArray[i*2+1]); }
Now get the Loop going:
private function loop( event : Event ):void { //do the physics stuff wow.step(); //set viewable stuff to physics stuff syncRenderingToPhysics(); light.copyPosition(view.camera); //do some camera movement Camera3D(view.camera).hover(0, view.viewport.containerSprite.mouseX*0.003, (view.viewport.containerSprite.mouseY-400)*0.002); //do the 3d rendering stuff view.singleRender(); }
This part will update the graphics part to show what the physics objects are doing:
private function syncRenderingToPhysics():void { if(_dragging) { wowBalls[_actualDragObjID].px = mouse3D.x; wowBalls[_actualDragObjID].py = mouse3D.y; } //just reposition the moving parts... for(var i:uint=0; i < NUM_OF_BALLS; i++) { pv3dBalls[i].x = wowBalls[i].px; pv3dBalls[i].y = wowBalls[i].py; pv3dBalls[i].z = wowBalls[i].pz; pv3dMirrorBalls[i].copyPosition(pv3dBalls[i]); pv3dMirrorBalls[i].y = (pv3dMirrorBalls[i].y*-1)-250; .... } }