Giter Site home page Giter Site logo

p2.js's Introduction

p2.js

2D rigid body physics engine written in JavaScript. Includes collision detection, contacts, friction, restitution, motors, springs, advanced constraints and various shape types.

Demos | Examples | Documentation | Download | CDN | Wiki

Featured projects using p2.js

Demos

These demos use the p2 Demo framework, which provides rendering and interactivity. Use mouse/touch to throw or create objects. Use the right menu (or console!) to tweak parameters. Or just check the source to see how to programmatically build the current scene using p2.

Examples

Examples showing how to use p2.js with your favorite renderer.

Sample code

The following example uses the World, Circle, Body and Plane classes to set up a simple physics scene with a ball on a plane.

// Create a physics world, where bodies and constraints live
var world = new p2.World({
    gravity:[0, -9.82]
});

// Create an empty dynamic body
var circleBody = new p2.Body({
    mass: 5,
    position: [0, 10]
});

// Add a circle shape to the body
var circleShape = new p2.Circle({ radius: 1 });
circleBody.addShape(circleShape);

// ...and add the body to the world.
// If we don't add it to the world, it won't be simulated.
world.addBody(circleBody);

// Create an infinite ground plane body
var groundBody = new p2.Body({
    mass: 0 // Setting mass to 0 makes it static
});
var groundShape = new p2.Plane();
groundBody.addShape(groundShape);
world.addBody(groundBody);

// To animate the bodies, we must step the world forward in time, using a fixed time step size.
// The World will run substeps and interpolate automatically for us, to get smooth animation.
var fixedTimeStep = 1 / 60; // seconds
var maxSubSteps = 10; // Max sub steps to catch up with the wall clock
var lastTime;

// Animation loop
function animate(time){
	requestAnimationFrame(animate);

    // Compute elapsed time since last render frame
    var deltaTime = lastTime ? (time - lastTime) / 1000 : 0;

    // Move bodies forward in time
    world.step(fixedTimeStep, deltaTime, maxSubSteps);

    // Render the circle at the current interpolated position
    renderCircleAtPosition(circleBody.interpolatedPosition);

    lastTime = time;
}

// Start the animation loop
requestAnimationFrame(animate);

To interact with bodies, you need to do it after each internal step. Simply attach a "postStep" listener to the world, and make sure to use body.position here - body.interpolatedPosition is only for rendering.

world.on('postStep', function(event){
    // Add horizontal spring force
    circleBody.force[0] -= 100 * circleBody.position[0];
});

Install

Browser

Download either p2.js or the minified p2.min.js and include the script in your HTML:

<script src="p2.js" type="text/javascript"></script>

If you would like to use ordinary Array instead of Float32Array, define P2_ARRAY_TYPE globally before loading the library.

<script type="text/javascript">P2_ARRAY_TYPE = Array;</script>
<script src="p2.js" type="text/javascript"></script>
Node.js
npm install p2

Then require it like so:

var p2 = require('p2');

Supported collision pairs

Circle Plane Box Convex Particle Line Capsule Heightfield Ray
Circle Yes - - - - - - - -
Plane Yes - - - - - - - -
Box Yes Yes Yes - - - - - -
Convex Yes Yes Yes Yes - - - - -
Particle Yes Yes Yes Yes - - - - -
Line Yes Yes (todo) (todo) - - - - -
Capsule Yes Yes Yes Yes Yes (todo) Yes - -
Heightfield Yes - Yes Yes (todo) (todo) (todo) - -
Ray Yes Yes Yes Yes - Yes Yes Yes -

Note that concave polygon shapes can be created using Body.fromPolygon.

Install

Make sure you have git, Node.js, NPM and grunt installed.

git clone https://github.com/schteppe/p2.js.git;
cd p2.js;
npm install; # Install dependencies
grunt;

Grunt tasks

List all tasks using grunt --help.

grunt        # Run tests, build, minify
grunt dev    # Run tests, build
grunt test   # Run tests
grunt yuidoc # Build docs
grunt watch  # Watch for changes and run the "dev" task

Release process

  1. Bump version number.
  2. Build and commit files in build/ and docs/.
  3. Tag the commit with the version number e.g. vX.Y.Z
  4. Add relase notes to github
  5. Publish to NPM

p2.js's People

Contributors

agilejoshua avatar andrewraycode avatar bkconrad avatar brollb avatar dasilvacontin avatar dgoemans avatar elisee avatar englercj avatar evilstreak avatar fishrock123 avatar flyover avatar georgiee avatar mccraveiro avatar nemosupremo avatar psalaets avatar rejemy avatar schteppe avatar stefanstarstable avatar thomasboyt avatar timrwood avatar wellcaffeinated avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

p2.js's Issues

Skip friction iterations

By skipping a number of FrictionEquation iterations, we can get faster convergence. Make this a property to GSSolver.

Turning off body rotation

Should be possible to fix the rotation of a body, keeping x and y dynamic. Maybe this should be a .motionState?

New Equation structure

Need a more general structure of Equation, so that it is simpler to make new constraint types without adding so much code.

.bodyA       // Participating bodies, renamed
.bodyB
.g           // constraint violation, position part
.GW          // constraint violation, velocity part
.GiMGt       // Currently equivalent to C-eps
.G           // Jacobian entry, linear+angular parts for bodies
.maxForce
.minForce
.stiffness
.relaxation
.a           // SPOOK parameters
.b
.h
.eps
.spookParamsNeedsUpdate // Flag
.lambda      // Constraint multiplier

There should be default methods for computing G, g, GW, GiMGt, that can be overridden by subclasses. Convenient if it is possible to rely on default methods, but it is also needed to be able to implement custom ones for motor equations, etc.

The Equation should also have an .update() function that will update all of the equation data.

Continuous collision detection (CCD)

Could be implemented by

  1. Extrapolating bounding spheres/boxes of the dynamic bodies and estimate time of impact (TOI)
  2. Root finding for a better estimate of the TOI and a point in time where the bodies actually intersect
  3. Extrapolate the body to the TOI and wait there until the timestep ends

This should be quite easy to implement for dynamic vs static bodies. Right now I think that dynamic vs dynamic should be okay too, but we'll see about that :)

Maybe trigger CCD only when body speed reaches a limit? Or always use it?

A question is still how constraints connected to the body will behave when using this.

Sizes

Hey guys, I am attempting to use this library as the physics portion of grapefruitjs/grapefruit.

How can I create a bounding box? I see there is a Plane shape, but it has no dimensions. I would rather not have to use bounding circles for things.

Thanks!

Expose contact shapes in "impact" event

This seems like a pretty basic feature, but I think it should be included the library. Having the shape exposed makes it easier to test for things like if a character should can jump or if a hit is a headshot or not.

Its my understanding all it requires is adding to world.js:

ev.bodyA = eq.bi;
ev.bodyB = eq.bj;
ev.shapeA = eq.shapeA;
ev.shapeB = eq.shapeB;

I would submit a PR, but I'm not thoroughly familiar with the codebase to know if those contact shapes are actually guaranteed (or if there is some other reason they are not exposed).

Vectors and Matrices should be refactored.

Is any reason for tVec2.create() vs new tVec2()?

Regardless, tVec.set(o, x, y) is kind if silly and we should make a prototype method for functions like it so that we can call (vec).set(x, y).

If in doubt, the old methods can be kept for internal use, and the new ones can be added for the API.

Cannot find module 'poly-decomp'

I've installed p2.js via GitHub into my node app. However when I run the app I receive an error telling me it can't find the module 'poly-decomp'.

I've traced the error to src/objects/Body.js line 2.

GearConstraint

Could be implemented with a RotationalVelocityEquation with a ratio specified in the GearConstraint.

Platformer - jump - requirements

Hello, I'm new to game development . Trying to start writing platformer. I tried to implement jump :

  1. Created body
    2 . Added 8 shapes ( rectangles)

123
4-5
678

3 . Added an event handler "impact"

Thinking when there is an impact on the shape 7 " I can jump". But I get only the first impact. And I can not know when I lost the ability to jump . How to get around these problems? May be necessary to do differently?

The second question. When getting events "impact" I get the shapes, but it does not have an identifier. Only through event.bodyB.shapes.indexOf (event.shapeB); but I think it's a bad way.

Forgive for English. I don't know it. I am helped by Google Translate.

Provide handles on shapes to manipulate dimensions and orientation (with mouse or touch)

In the demos, we can already manipulate a body's position by dragging it. It would be nice to provide an option to show handles that can be used to modify, say, the radius of a circle or the width/height of a box. Similar handles should be given to modify the orientation (angle w.r.t. the horizontal axis). For an example, have a look at KDE Step.

Similar handles can be given to modify velocity of bodies and force values of objects like motors etc but this may be outside the scope of PixiDemo.js.

Web Worker Example

I saw in the Gruntfile that the application is suppose to run in a Web Worker. It would be awesome to see an example app running this as web worker!

RotationLockEquation

Need a more general approach for locking the angle between two bodies. Idea: define offset points locally in each body. Compute tangent vectors from these (include angle offset here!) and set the constraint violation to the dot product of these.

Backtrace Shape given ContactEquation

This might be needed in the future :)

Should not be too problematic to store the contact triggering Shape with each ContactEquation and FrictionEquation.

Keep track of colliding bodies of last step

To be able to check when two bodies impact each other for the first time (in contrast to a persistent contact), we need to keep track of their contact state from the last step. This can be done using a CollisionMatrix as done in Cannon.js, but I think it is better to use a .contactBodies property for each body, as well as .oldContactBodies (from the previous step).

(we could also scan the old contact equations array each time, but that is unnecessary)

Sensor Shapes

Is it possible to create a "sensor" shape? A shape that does not resolve collisions, but reports them?

Surface velocity

Should be possible to set surface velocity via a ContactMaterial. Implementation could simply be to set relative velocity to a FrictionEquation. Currently the friction equation tries to make relative velocity zero, but aiming for something else would produce surface velocity.

Save resulting constraint multiplier in Equation after solve

This is needed to be able to measure the resulting force from the equation. A suggestion is to add the constraint multiplier (lambda) as a property to Equation. Maybe also add methods for constructing the constraint force from this.

This is needed if someone wants to make "breakable" constraints, for instance. If the constraint force is over a limit, then the constraint is removed.

Shapes add to bodies with offset don't collide

I'm unsure if this is a bug, or if its intended behavior. If you add a shape to a body with an offset, that shape will not collide with other bodies.

From the asteroids example

shipShape = new p2.Circle(shipSize);
shipBody = new p2.Body({ mass:1, position:[0,0],angularVelocity:1 });
shipBody.addShape(shipShape, [.0001, .0001]);
shipShape.collisionGroup = SHIP;
shipShape.collisionMask = ASTEROID;
world.addBody(shipBody);

Use pixi.js for rendering

The demo renderer should use Pixi.js instead of 2D Three.js. This would be super.

Don't have time to do this myself at the moment but if someone else want to do it I'd be thankful.

Consider moving np.reset() to just before this.emit(this.postStepEvent)?

Alternatively: narrowphase.collidedLastStep in the postStep should return true for any body that collided just before the postStep

My proposed fix is just moving np.reset() The benefit that is gained from doing it this way is that narrowphase.collidedLastStep when executed in the postStep will now test if the bodies collided in the step that just executed instead of the one before it.

If you didn't get the explanation the diff looks like this:

449   // Narrowphase
450 - np.reset()
451   for(var i=0, Nresults=result.length; i!==Nresults; i+=2){
...
539   }
540 + np.reset()
541   this.emit(this.postStepEvent);

Why? Currently, there is no way using p2.js to tell if two objects are currently in contact. What this fix essentially does is ensure that for any body x and y that emitted an impact event, narrowphase.collidedLastStep(x,y) also returns true in the postStep event. Using this, a user can track what bodies are currently in contact by logging the contact in the impact event, then checking if the bodies had "collided" in each subsequent postStep event. If the bodies didn't collide in the postStep, then the bodies are no longer touching, if they did, then they are still touching.

I'm not fully sure what problems this might cause (the only difference here is that np.reset() is not called the very first time the narrowphase loop runs), but I think its a good idea to have narrowphase.collidedLastStep return true for bodies that collided in that step.

LICENSE?

do you plan on putting an open source license on this?

Shape density (introduce fixtures?)

Body now accepts a "mass" argument, but it would be more convenient if the default would be density. Density could be set for each Shape, for example:

body.addShape(shape,{ offset:[1,0], angle:1, density:1 });

or perhaps set it directly on the shape?

shape.density = 1;

I think the latter is uglier. A shape is to me a mathematical shape, without physics properties (note: we already set shape.material and collision groups/masks which is also ugly). Setting the shape-specific physics properties via .addShape() seems more neat to me.

Another note: box2d uses a Fixture class to solve this. From the manual: "A fixture binds a shape to a body and adds material properties such as density, friction, and restitution". The "fixture" is for us the options object.

Restitution support

I notice that restitution is defined in ContactMaterial but it doesn't seems to be used by the calculation. The objects behave the same regardless of the restitution parameter.

Did I miss something or is it not supported yet?

Support for Universal gravitation

To create the simulation of earth's rotation around the Sun, I need universal gravitation which needs to be applied for each PAIR of bodies. Unlike springs, this can be controlled by just a boolean property of the world. The center of gravity can be assumed to be the geometric center of the shape.

It might also be a good idea to provide coulomb force, if electrical charges of two bodies are known.

Adaptive number of iterations for IslandSolver

This is needed for more dynamic scenes, for example where the user can add bodies interactively. If the user adds a pile of 100 bodies, we have to use more iterations to solve that pile properly.

A suggestion is to add a function that computes the number of iterations needed for an Island in the IslandSolver. We also need to keep the IslandSolver open for other subsolver types (not just GSSolver). We cannot assume that all solvers do iterations.

var solver = new IslandSolver(subsolver);
// Update the max iterations parameter before solving
solver.on("beforeSolveIsland",function(evt){
  subsolver.iterations = evt.island.equations.length * 5;
});

For less advanced users, one could add an "adaptiveIterations" parameter to the IslandSolver, that adds an event listener automatically using a "good" approximation for iterations. This would of course throw an error if the subsolver is not a GSSolver.

var solver = new IslandSolver(subsolver,{
  adaptiveIterations: true,
});

Frame rate independence

By keeping an internal clock for the physics, and interpolate positions, angles, velocities etc., we can get a physics frame rate independent of the rendering frame rate. So, if the rendering is lagging, the physics will still be correct.

This is sort of how I would like it to work: http://bulletphysics.org/mediawiki-1.5.8/index.php/Stepping_The_World

One problem is that we must store both the internal step positions & velocities, as well as the interpolated values, in each body. It would be great if the user could switch between interpolated physics and non-interpolated physics seamlessly and not having to read other properties from the Body, for example.

Suggested stepping API:

var fixedTimeStep = 1/60;

// No interpolation
world.step(fixedTimeStep);

// Here, the position of the body is not interpolated.
renderObject(body.position[0],body.position[1]);

// With interpolation. Here, "timeStep" is the
// elapsed time since the last .step().
// maxSubSteps is the max fixed time
// steps to take in one call
world.step(fixedTimeStep,timeStep,maxSubSteps);

// Here, the position of the body IS interpolated,
// though the user does not notice.
renderObject(body.position[0],body.position[1]);

If interpolation is enabled, we could in the beginning of World.prototype.step swap the fixed step states with the interpolated ones, and swap back at the end.

Bounding box support

It would be handy to have a method Shape.prototype.computeAABB(aabb,position,angle) for each shape type. Body.prototype.updateAABB() could be added to Body, and this updates the AABB whenever the body changed (each step).

An own AABB class would be great!

Soup Up the PubSub?

I have a bit of a souped up pubsub implementation in PhysicsJS that could be easily coerced to take on the same syntax as your current implementation.
https://github.com/wellcaffeinated/PhysicsJS/blob/feature/pubsub/src/util/pubsub.js

It has some nice features like binding callbacks to different scopes, event listener priority management, and is very similar to jQuery's .on(), .off(), .one() syntax where you can bind to multiple events at once.

It is 30% slower than your current implementation... but what that really means is that the implementation can emit
~10^6 events per frame... so I don't think it's a performance concern :)

I could implement it quickly if you're interested

Limits for PrismaticConstraint

Should have the following properties:

.lowerLimitEnabled
.upperLimitEnabled
.lowerLimit
.upperLimit

The implementation can be done by adding ContactEquations when the limits are exceeded, similar to as it is done in the RevoluteConstraint.

SpookParams class?

Both Equation and GSSolver are using SPOOK parameters. Making an own class to bundle them up in objects could save some code.

Or maybe it is better to remove the solver parameters, and only use Equation parameters. To set things globally, one could call a method in World. That would set all parameters in all constraint equations (and materials).

Strict serializer

Use of a JSON validator that does strict validation (no allowed fields except the specified ones). I see this as the only way to get a rock solid serializer.
This will catch most errors that may slip in during file format upgrade.

Also, the serializer should allow full version specification "a.b.c" since it will always be backwards compatible anyway.

z-schema could be used for validation. Another option is json-validator, but I find it less useful for strict formats.

The serializer should probably not be included in the default p2.js bundle.

Async API - needed for parallelism

I've had some progress with parallel JS / webworkers lately, and I think making some parts of p2 parallel is a good idea, especially the solver which is most computationally heavy.

One of the problems with this is that p2 will need an asynchronous API. For the users, the main problem will be the World.step() call. Parallel implementations will force this call to be async.
A typical world stepping / rendering loop will probably look something like this after making World.step async (see my blog entry):

function render(){
    requestAnimationFrame(animloop);
    renderer.render();
}
function animloop(){
    world.step(1/60,render); // asynchronous
}
animloop(); // Start chained loop

We will need to redesign the API for the components we may want to make parallel in the future. For the solver, I guess only the .solve() method needs to be async.

I've not thought about how to restructure the code in World.step(), any ideas are welcome :)

Control Bodies

I noticed #28 which seems to imply that CCD (or swept collisions) is not yet implemented. Currently I am using Chipmunk-js and for seting velocity of bodies without causing teleportation, tunneling, or other weird stuff I need to use control bodies joined by a specific pivot joint.

Will CCD be implemented soon, or will I have to use the same methodology here?

Sorry for the questions I've been posting lately! I am evaluating p2.js for my game engine, and being able to directly control bodies will reduce complexity significantly.

p2.Body not required by certain modules

On the current master/dev branch p2 fails because Broadphase and Narrowphase don't require('../objects/Body') causing it to crash.

Let me know if this is wrong, I don't do a lot of JS development.

Can we expect the master/dev branch to be mostly stable? I've decided to use it for the .fixedRotation property.

Heightfield

Could be implemented as a Shape that takes points as constructor argument. Implement Circle/Heightfield collision response to begin with.

Separate Event

I see there is a collision (impact) event, is there no event to report a separation?

Equation sorting function for solver

It would be a nice feature to be able to sort the solver equations before each solve. The function could be given as an option to the solver constructor.

var solver = new Solver({
  equationSortFunction : function(eqA,eqB){
     // Sort by ascending y-position of body i
     return eqA.bi.position[1] - eqB.bi.position[1];
  }
});

The sorting can be handy in many cases. Examples:

  • a pile of bodies, and the user want to solve from bottom and up
  • a rope, the user wants to solve from top to bottom
  • etc.

It would also be nice to be able to shuffle the equations before each solve. Sorting by a random number is inefficient and should be done differently though.

Friction

To enable friction, we need to implement FrictionEquation and then add some mechanisms to the World class to add then when needed.

See CANNON.World and CANNON.FrictionEquation.

We could start off with a global friction value, but a Material class would be needed later to get more fine-grained control over it.

Body sleeping

Should be implemented as in Cannon.js (see the Particle and World classes)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.