p2.js soft wheel vehicle tutorial

I recently made a demo for the p2.js physics engine with a truck and soft wheels, simulating traction. It’s a pretty interesting case, using a few different p2 constraint types. Perfect for a tutorial.

p2-softwheel

Open the JSFiddle!

World & Materials setup

The first thing we need is the simulation world.

var world = new p2.World({
  gravity : [0,-5]
});

Before starting with the vehicle, let’s set up materials. Experience tells me we’re going to need some extra friction for the wheels to get some traction against the ground. For this purpose, we create two Materials and a ContactMaterial. This way we can define a new friction coefficient between ground and wheels.

var groundMat = new p2.Material();
var wheelMat = new p2.Material();
var contactMat = new p2.ContactMaterial(groundMat, wheelMat, {
  friction: 30
});
world.addContactMaterial(contactMat);

We will use these two materials shortly, when creating geometry.

Chassis

The chassis is a single rigid body, with a few shapes in it. First, let’s create the Body:

var chassisBody = new p2.Body({
  mass: 1,
  position: [-0.3, 2.2]
});
world.addBody(chassisBody);

Next step is to add some geometry to it.

Chassis construction

// Capsule below the chassis
chassisBody.addShape(new p2.Capsule({
  length: 1.8,
  radius: 0.6
}), [0.5,-0.4], -0.1);

// First capsule above the trunk
chassisBody.addShape(new p2.Capsule({
  length: 1.8,
  radius: 0.1
}), [-0.4, 0.6], Math.PI/2);

// Second capsule above the trunk
chassisBody.addShape(new p2.Capsule({
  length: 1.8,
  radius: 0.1
}), [-0.2, 0.6], Math.PI/2);

// Inclined capsule above the trunk
chassisBody.addShape(new p2.Capsule({
  length: 1.8,
  radius: 0.1
}), [-1.4, 1], Math.PI/7);

// Main chassis shape
chassisBody.addShape(new p2.Convex({
  vertices: [
    [3.5, -0.6],
    [3.7, -0.4],
    [3.6, 0.5],
    [3.3, 0.6],
    [-3.5, 0.6],
    [-3.55, -0.1],
    [-3.4, -0.6]
  ],
  width: 7,
  height: 1.2
}));

// Top "window"
chassisBody.addShape(new p2.Convex({
  vertices: [
    [1, -0.5],
    [0.3, 0.5],
    [-1, 0.5],
    [-1.1, -0.5]
  ]
}), [1, 1.1], 0);

Wheels

For the soft wheel simulation, I chose an approach where the center of the wheel is a circular body, and the outer shell consists out of a number of “links”. The links are interconnected in a circle, and they are also constrained to the center circle so they must move when the inner wheel rotates. Finally the links have a spring connection to the center so they can flex radially.

wheel

Let’s break this down. First we create the center circle body.

var wheelBody = new p2.Body({
  mass: 1
});
wheelBody.addShape(new p2.Circle({ radius: 0.4 }));
world.addBody(wheelBody);

Let’s add a single link for starters. We use a Capsule shape.

var linkBody = new p2.Body({
  mass: 0.1,
  position: [0, 1],
  angle: Math.PI / 2
});
linkBody.addShape(new p2.Capsule({
  radius: 0.05,
  length: 0.4,
  material: wheelMat
}));
world.addBody(body);

First we need to make sure it can only move radially along an axis from the circle body’s center. For this, we use a PrismaticConstraint. We use the body centers as anchor points and define the slider axis locally in the center body.

var prismatic = new p2.PrismaticConstraint(wheelBody, linkBody, {
  localAnchorA: [0, 0],
  localAnchorB: [0, 0],
  localAxisA: [0, 1],
  disableRotationalLock: true,
  collideConnected: true
});
world.addConstraint(prismatic);

p2-softwheel-prismatic

To keep the links in a circle when the wheel is at rest, we add a DistanceConstraint between the center body and the link. To make the constraint soft, we set a small maxForce.

var distanceConstraint = new p2.DistanceConstraint(wheelBody, linkBody, {
  maxForce: 4
});
world.addConstraint(distanceConstraint);

p2-softwheel-prismatic-2

Now we will modify the “link” code so it runs in a for loop and adds more links. We will also make sure the loop adds RevoluteConstraints to connect the link ends to each other in a circular formation around the center body.

p2-softwheel-prismatic-3

// Create a chain of capsules around the center.
var lastBody, firstBody, N=16;
var linkLength = Math.sqrt(2 - 2*Math.cos(2 * Math.PI / N));
for(var i=0; i
  // Create a capsule body
  var angle = i / N * Math.PI * 2;
  var x = Math.cos(angle) - 2.2;
  var y = Math.sin(angle);
  var linkBody = new p2.Body({
    mass: 0.1,
    position: [x,y],
    angle: angle + Math.PI / 2
  });
  linkBody.addShape(new p2.Capsule({
    radius: 0.05,
    length: linkLength,
    material: wheelMat
  }));
  world.addBody(linkBody);

  // Constrain the capsule body to the center body.
  // A prismatic constraint lets it move radially from the center body along one axis
  var prismatic = new p2.PrismaticConstraint(wheelBody, linkBody, {
    localAnchorA: [0, 0],
    localAnchorB: [0, 0],
    localAxisA: [
      Math.cos(angle),
      Math.sin(angle)
    ],
    disableRotationalLock: true, // Let the capsule rotate around its own axis
    collideConnected: true
  });
  world.addConstraint(prismatic);

  // Make a "spring" that keeps the body from the center body at a given distance with some flexing
  world.addConstraint(new p2.DistanceConstraint(wheelBody, body, {
    maxForce: 4 // Allow flexing
  }));

  if(lastBody){
    // Constrain the capsule to the previous one.
    var c = new p2.RevoluteConstraint(linkBody, lastBody, {
      localPivotA: [-linkLength/2, 0],
      localPivotB: [linkLength/2, 0],
      collideConnected: false
    });
    world.addConstraint(c);
  } else {
    firstBody = linkBody;
  }

  lastBody = linkBody;
}

// Close the capsule circle
world.addConstraint(new p2.RevoluteConstraint(firstBody, lastBody, {
  localPivotA: [-linkLength/2, 0],
  localPivotB: [linkLength/2, 0],
  collideConnected: false
}));

Attach wheels to chassis

Now we will constrain the wheels to the chassis. We will let them move vertically and rotate freely using prismatic constraints. We set limits on the constraints so the wheels don’t slide too far away from (or too close to) the chassis.

p2-softwheel-suspension-1

var c1 = new p2.PrismaticConstraint(chassisBody,wheelBodyA,{
  localAnchorA : [
    wheelBodyA.position[0] - chassisBody.position[0],
    wheelBodyA.position[1] - chassisBody.position[1]
  ],
  localAnchorB: [0,0],
  localAxisA: [0,1],
  disableRotationalLock: true
});
var c2 = new p2.PrismaticConstraint(chassisBody,wheelBodyB,{
  localAnchorA: [
    wheelBodyB.position[0] - chassisBody.position[0],
    wheelBodyB.position[1] - chassisBody.position[1]
  ],
  localAnchorB: [0,0],
  localAxisA: [0,1],
  disableRotationalLock: true
});
c1.setLimits(-0.5, 0.4);
c2.setLimits(-0.5, 0.4);
world.addConstraint(c1);
world.addConstraint(c2);

Suspension

To get a suspension-like effect, we create soft distance constraints, that will let the wheels move up and down a bit. A distance constraint is by default very stiff, so we set its maxForce to something smaller to make it soft.

p2-softwheel-suspension-2

var suspensionA = new p2.DistanceConstraint(wheelBodyA, chassisBody, {
  maxForce: 6
});
world.addConstraint(suspensionA);
var suspensionB = new p2.DistanceConstraint(wheelBodyB, chassisBody, {
  maxForce: 6
});
world.addConstraint(suspensionB);

Ground plane

At last, we create a ground plane to let the vehicle drive on something. Optionally, we can add some obstacles.

var groundBody = new p2.Body({
  position: [0, -2]
});
groundBody.addShape(new p2.Plane({
  material: groundMat
}));
world.addBody(groundBody);

Applying engine torque

If you want to apply a torque to the wheels to make the vehicle move forward, it should be done after each physics step. Simply do something like this:

world.on("postStep",function(evt){
  wheelBodyA.angularForce += 30;
  wheelBodyB.angularForce += 30;
});

Cool! What now?

Play around with the JSFiddle to see the full code. See if you can add some more cool stuff to the vehicle!

Please leave a comment, star p2.js on Github, tweet or if you think this tutorial is useful!

TinyGoon – TowerFall clone in WebGL

I made this game together with and at Goo.

TinyGoon

It’s a kill ’em all multiplayer game with support for up to 4 players. We used the Gamepad API directly, which means that it doesn’t work perfect in all browsers.

The game uses a new SpriteSystem that I made for Goo Create and the physics is from p2.js.

Here’s the Goo team playing the game when we first presented it. It was buggy but fun! It was the longest presentation of the day since we didn’t want to stop playing.

tinygoon-playing

I made the tile graphics. Should probably start a career as a 2D pixel graphics artist!

tinygoon-editing

Launch the game.

PhysicsToy – halfway there…

Recently, I’ve been working on a 2D physics editor called PhysicsToy. It makes it possible to create these kinds of simulations, without coding:

Cogwheels

Silly car

Before I get bored and want to start a new cool hobby project, I wanted to report the current status of the web app.

Frontend: Angular.js and Pixi.js

I used the p2.js debug renderer and polished it up a bit. Then I added some Angular.js magic. I’ve wanted to learn Angular for a while, and PhysicsToy was a great project to use it in. I hooked up Angular and connected it to a simple list-like menu. Then added some code for updating the p2.js world as the angular data changes. Viola, PhysicsToy was born.

Backend: Node.js and Postgres on Heroku

Another thing I wanted to try was Postgres. I’ve been using MySQL in other projects, but why not try something new, and at the same time choose open source.
Postgres didn’t let me down. It offered a JSON data type, which is convenient for my Angular scene data. Postgres seems more consistent and in general more thought through than MySQL, even though they are based on the same SQL language.

Before pushing the data to Postgres, I do some validation using JSON-schema. I use an interesting solution for version handling of the JSON: I store the scene data as it is and never upgrade it in the database, but I do on-the-fly upgrading when serving to the clients. The benefits of this solution are that the original scenes can be in all servers forever. And it’s ideal when the app is under development, with a constantly changing data model. The only bad part is that the upgrading takes some server juice.

Had a fun time coding this, I hope that it will grow to something big!

How much garbage is my JavaScript producing?

While reading this article about garbage collection in JavaScript, a question popped up in my head… How can I test how much garbage a piece of code is producing?

I’ve written a small snippet that can measure this for you. What you need is a recent version of Google Chrome.

To be able to measure the memory heap size, we need to enable it in Chrome. Chrome can give you access to the state of the JavaScript heap (the memory allocated to JavaScript objects), but to get it to work you’ll need to start it with the –enable-precise-memory-info flag:

chrome --enable-precise-memory-info

Or, on OSX:

open -a "Google Chrome" --args --enable-precise-memory-info

Now, create an HTML file containing the following code.

This will write the number of bytes allocated between "// Start" and "// End" to console every 10th of a second.

My current version of Chrome (40.0.2214.115) is producing 40 bytes to run this function, that is why I remove 40 bytes from the output number. You may need to change this depending on your Chrome version and settings.

If you run this script, you will notice that the first output numbers are

2424
728
0
0
0
...

The first numbers are there probably because of initialization garbage. After a little while, the initialization garbage is gone and we see that the number of allocated bytes in the loop is 0.

Now, let's allocate something in the loop and see what happens. If I, for example, allocate a plain object inside the above loop, like this,

setInterval(function(){
    var before = window.performance.memory.usedJSHeapSize;
    var obj = new Object();
    var diff = window.performance.memory.usedJSHeapSize - before;
    console.log(diff-40);
}, 100);

then the output is

3360
752
56
56
56
56
...

We conclude that a plain JavaScript object takes 56 bytes to allocate.

You can use this code snippet to measure how much GC load different pieces of code allocates in your game loop. Why not try this JSFiddle here to get started? Good luck!

p2.js – 2D JavaScript physics

I recently started on a small 2D physics engine project that I for now call p2.js. It contains just the basics, spheres, particles, planes. They can interact either through frictionless contacts or spring forces.

p2_2

There are a few reasons why I wanted to roll my own engine, however, the most important one for now was the question about using typed arrays or not. Now I’ve got the answer to that.
I followed Brandon Jones simple instructions on how to use the typed arrays correctly, and as one of his slides implies, I was indeed barfing rainbows when seeing the results. Okay, maybe not barfing rainbows, but I must agree that I was a bit surprised.

In total I get a performance gain of about 30% when using Float32Array instead of vector objects such as {x:2,y:1}. This number, 30%, is just a very rough estimate, because it depends on a lot of different parameters. However, my implementation made it relatively easy to switch between these. Another thing that I noticed was that switching between ordinary Arrays and Float32Array didn’t affect performance much at all, though there are a few other advantages of using the latter.

The key to using Float32Arrays is to avoid creating new ones. In the physics engine case this can get a bit tricky since there are things added and removed to the simulation in every timestep. A good example is the contacts. When two geometries collide I need a new ConactEquation instance in the engine. This is basically a holder for a number of vectors, so making a new instance every time it is needed is a no go. To solve this I made sure these objects are reused in between every timestep, and if there are excess objects, I store them for later use.

The scene you see in the image above is a simulation of 900 circles trapped in container consisting of 3 planes. The number of solver iterations is 10. I can get reasonable results by using fewer iterations too. Rendering is made in a small 2D demo renderer I built with Three.js.

I’m going to make a demo page for the engine soon, though for now only the code is available.

The split solver in Cannon.js

As I had recently implemented some graph traversing code, I was keen on using it in Cannon.js. You may think, why use graph algorithms in a physics engine? The idea is a bit tricky but I’ll try to explain.

In the usual contact solving case, we iterate over all contacts in the system. For each iteration, we transfer impulses from one body to another. In the example case of stacked boxes, iterating like this will make the top box “feel” impulses from the bottom box as the impulse travel through the stack (this depends on how many times we iterate over the system and what iteration order we use, though that’s another problem).

Many solvers have a “tolerance” parameter and it is used to check when to stop iterating. If the total error (read: contact overlap) is small, then the solution is good enough and we can stop. The tolerance is compared to the *sum* of all errors in the system.

Say we have one stack of boxes on a static plane and a sphere on the same plane. The total error will include both the errors from the stack and from the sphere. We will stop iterating over all the contacts when the total error is below the tolerance limit. Say we reach M iterations. This means we compute stuff M times on each of the N contacts in the system (a total of N*M computations).

sphere-boxes

Now what if we split the system into two independent systems, one for the stack+plane and one for the sphere+plane, and run the solver once for each of the two systems? The stack will probably still need M iterations, but the interesting thing is that the sphere will only need one. Why? Because the case of a single contact does not need to propagate impulses, and it can directly report the exact solution.

graphs

So, in the big system we need M*N computations and in the split system we need M*(N-1). That’s great! And this strategy works for many other systems too. In most cases, we can get away cheaper by using a split solver.

But what about the graph algorithm, you may say. It is used to find the independent sets in the system. Yes, it will add some complexity. However, that computation needed is not as hard as the solve part, and it has linear complexity (with respect to the number of contacts and bodies). The solving complexity depends on the number of contacts times the number of iterations. The number of iterations should be linearly dependent on the number of contacts to be able to propagate all impulses across the system, and so we end up with a quadratic solving complexity.

There is another advantage with the split solver: the subsystems can be solved in parallel. But that is another story!

The CANNON.SplitSolver class is available in the cannon.js/dev branch, and here is a live demo where you can toggle split for a scene.

Recent Node.js development

Code frequency plot

Recently I’ve been working a lot on the Node.js version of friendship-bracelets.net. Here’s a quick status report.

Code reduction

I’ve reduced the code to less than half its size by abstracting key parts of the code and compressing a few static JS files. I really love JavaScript – abstracting code has never been easier (and dirtier).
One interesting abstraction I made was an “edit resource” page. For each resource I have a Schema class instance that can help create an HTML form and then validate input from the client.

Nginx

Other news is that I’ve started using Nginx to serve static files and proxy to Node. It was really easy to set up so I will probably continue using Nginx. The only drawback is that I really want PHPMyAdmin for administrating my database, so I still have to run an instance of Apache… Perhaps I’ll find a solution to this later on. I will post instructions about my setup when it’s stable.

Chat using Server-Sent Events

Another thing I’ve done is a chat client. I was really excited while doing this because it is a whole new concept to the site. This way we can get even closer interaction with the users.
The tech behind the real-time chat is server-sent events, or more specifically, EventEmitter in HTML5. Earlier I was determined to use WebSocket, but since server-sent events is more well supported (on both client and server) and good enough for the purpose, I went that way.

Caching of Express views

I’ve probably mentioned how to do this earlier, but now I’ve tried it. When starting the Express app with the environment variable NODE_ENV set to “production”, I simply run
app.configure("production",function(){
  app.enable("view cache");
});
This makes Express cache the templates inside the app, and it makes the app faster. By also relieving the app from serving static files (using Nginx), this makes the web app perform really well. It almost feels like running the app locally when it in reality it’s on a virtual machine in a datacenter somewhere else.

Mobile app thoughts

I’ve already started using jQuery mobile for the mobile site, but it will probably only make it more difficult for me to maintain the site. Using that will need different HTML for the layout, which duplicates that amount of code. I’m starting to think maybe it’s better to just add some CSS when on mobile instead.

Express: multi-language site

A question from a user came in, and he asked if the site could be translated into russian (he even offered help). Making an Express app support multiple languages is easy using e.g. i18n-node. However, making friendship-bracelets.net in multiple languages is probably not that easy. As I see it, we have 3 options for multi-language implementation.

  1. Just translating the menu buttons and some of the text. This will encourage people comment in their own language (if the site is in your language, you will probably write text in your own language). I think it would be really confusing if everyone posted stuff in mixed languages.
  2. Separating the languages into own sites with separate content. One site will have its own set of content and the other won’t have it. Not really cool and not really a good option in this case.
  3. Let’s say we have two sites of different language, A and B, and they share all content. Should all content in A also be visible for users in B? For some content, yes. What if you post content in your own language site A (english) and get a comment on it in site B (russian)? It gets more complicated than this when you think about it, and there will be special rules for just about everything.

Discussing this with the mods lead to a decision to do nothing about the multi-language question. However, It would be really cool to try out i18n in the future (I never tried it before).

Server-side pattern rendering

I’m getting closer to the core of friendship-bracelets.net… Pattern rendering. It is the most vital part. This is what almost all users go to the site for. I’m going to make it as good as I can.

One advantage with doing this in Node.js and JavaScript is that if there is a need for client side rendering, the same code could be used. An example could be to change the colors in the pattern interactively, to check whether a set of colors are good looking together or not.

Many things are falling into place now. I want to launch a beta testing site soon but before that I need generators and server-side rendering for all types of patterns… And probably a lot of other stuff that has nothing to do with patterns at all. I hope you can wait.

Comment boxes

The comment boxes on friendship-bracelets.net are like small web browsers. They load stuff dynamically from other places and view only what you need. You can post your comment and a script will save it on the server for you.

The code from the old version needed to be rewritten for various reasons. The first is that the code was a monster… Second is that it did not load things comments from the server on the desired format.

Need to get some sleep now… Over and out.

HTML5 Generators

The generators are the most important things on Friendship-Bracelets.net. Users use them to make their own pattern, either of type Normal, Alpha, Kumihimo or simple name patterns.

There has been a lot of problems with the generators since the site started. The first normal generator was written in pure PHP, and the users had to interact with it by writing “pattern code”. This code looked somewhat like this:

DDDD
ddd
RRRR
rrr

Each letter in this code was representing a knot, and each row represented a row in the pattern. D meant “forward knot”, d was backward knot, R backward-forward knot, and r forward-backward knot. Can you imagine writing a pattern this way?

Another drawback with a PHP generator was that the server had to do all the rendering and send back the results to the user every time he/she updated the code. This was very heavy for the server.

Later on, I made the generator in Flash. I really hated Flash (I still do) but it was the only reasonable way to make an interactive generator at that time.

By that time the site had the same generator code written in both Flash and PHP, which doubled the code maintenance time for me. And I had no experience in unit testing, which made everything a whole mess.

Now everything is going to be written in JavaScript, and all the code is going to be unit tested. I’m really excited that the site finally is getting simpler to maintain.