UNPKG

p2s

Version:

A JavaScript 2D physics engine.

118 lines (100 loc) 4.52 kB
<!DOCTYPE html> <html> <head> <title>Buoyancy demo - p2.js physics engine</title> <script src="../build/p2.js"></script> <script src="../build/p2.renderer.js"></script> <link href="css/demo.css" rel="stylesheet"/> <meta name="description" content="Buoyancy aka boat simulation"> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> </head> <body> <script> // Create demo application var app = new p2.WebGLRenderer(function(){ var world = new p2.World({ gravity : [0,-10] }); this.setWorld(world); // Create "water surface" var planeShape = new p2.Plane(); var plane = new p2.Body({ position:[0,0], collisionResponse: false }); plane.addShape(planeShape); world.addBody(plane); body = new p2.Body({ mass: 1, position: [0,2], angularVelocity: 0.5 }); body.addShape(new p2.Circle({ radius: 0.5 }), [0.5,0], 0); body.addShape(new p2.Circle({ radius: 0.5 }), [-0.5,0], 0); world.addBody(body); body2 = new p2.Body({ mass: 1, position: [-3,2], angularVelocity: 1 }); body2.addShape(new p2.Box({ width: 0.5, height: 2 }), [1,0], 0); body2.addShape(new p2.Box({ width: 0.5, height: 2 }), [0.5,0], 0); body2.addShape(new p2.Box({ width: 0.5, height: 2 }), [-0.5,0], 0); body2.addShape(new p2.Box({ width: 0.5, height: 2 }), [-1,0], 0); world.addBody(body2); // Add forces every step world.on('postStep', function(){ applyAABBBuoyancyForces(body, plane.position, k, c); applyAABBBuoyancyForces(body2, plane.position, k, c); }); var shapePosition = [0,0]; var centerOfBouyancy = [0,0]; var liftForce = [0,0]; var viscousForce = [0,0]; var shapeAngle = 0; var k = 100; // up force per submerged "volume" var c = 0.8; // viscosity var v = [0,0]; var aabb = new p2.AABB(); function applyAABBBuoyancyForces(body, planePosition, k, c){ for (var i = 0; i < body.shapes.length; i++) { var shape = body.shapes[i]; // Get shape world transform body.vectorToWorldFrame(shapePosition, shape.position); p2.vec2.add(shapePosition, shapePosition, body.position); shapeAngle = shape.angle + body.angle; // Get shape AABB shape.computeAABB(aabb, shapePosition, shapeAngle); var areaUnderWater; if(aabb.upperBound[1] < planePosition[1]){ // Fully submerged p2.vec2.copy(centerOfBouyancy,shapePosition); areaUnderWater = shape.area; } else if(aabb.lowerBound[1] < planePosition[1]){ // Partially submerged var width = aabb.upperBound[0] - aabb.lowerBound[0]; var height = 0 - aabb.lowerBound[1]; areaUnderWater = width * height; p2.vec2.set(centerOfBouyancy, aabb.lowerBound[0] + width / 2, aabb.lowerBound[1] + height / 2); } else { continue; } // Compute lift force p2.vec2.subtract(liftForce, planePosition, centerOfBouyancy); p2.vec2.scale(liftForce, liftForce, areaUnderWater * k); liftForce[0] = 0; // Make center of bouycancy relative to the body p2.vec2.subtract(centerOfBouyancy,centerOfBouyancy,body.position); // Viscous force body.getVelocityAtPoint(v, centerOfBouyancy); p2.vec2.scale(viscousForce, v, -c); // Apply forces body.applyForce(viscousForce,centerOfBouyancy); body.applyForce(liftForce,centerOfBouyancy); } } }); </script> </body> </html>