Papervision3D and the Wow Physics Engine

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