Skip to content

Instantly share code, notes, and snippets.

@mucaho
Created May 10, 2015 15:32
Show Gist options
  • Save mucaho/fcbd9bfd1ce3111d518b to your computer and use it in GitHub Desktop.
Save mucaho/fcbd9bfd1ce3111d518b to your computer and use it in GitHub Desktop.
Calculate checksum for DominoTest using hopefully deterministic JBox2D - see https://github.com/jbox2d/jbox2d/issues/19
package org.jbox2d.checksum;
import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.common.Settings;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.*;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class ChecksumTest implements Runnable {
// DISABLE JBOX2D FAST MATH!!!
static {
Settings.FAST_ABS = false;
Settings.FAST_ATAN2 = false;
Settings.FAST_CEIL = false;
Settings.FAST_FLOOR = false;
Settings.FAST_POW = false;
Settings.FAST_ROUND = false;
Settings.SINCOS_LUT_ENABLED = false;
}
final float dwidth = .20f;
final float dheight = 1.0f;
float ddensity;// = 10f;
final float dfriction = 0.1f;
int baseCount = 25;
private World world;
private Body groundBody;
private Body bullet1;
private Body bullet2;
public void makeDomino(float x, float y, boolean horizontal, World world) {
PolygonShape sd = new PolygonShape();
sd.setAsBox(.5f * dwidth, .5f * dheight);
FixtureDef fd = new FixtureDef();
fd.shape = sd;
fd.density = ddensity;
BodyDef bd = new BodyDef();
bd.type = BodyType.DYNAMIC;
fd.friction = dfriction;
fd.restitution = 0.65f;
bd.position = new Vec2(x, y);
bd.angle = horizontal ? (float) (Math.PI / 2.0) : 0f;
Body myBody = world.createBody(bd);
myBody.createFixture(fd);
}
public void initWorld() {
Vec2 gravity = new Vec2(0, -10f);
world = new World(gravity);
world.setParticleGravityScale(0.4f);
world.setParticleDensity(1.2f);
BodyDef bodyDef = new BodyDef();
groundBody = world.createBody(bodyDef);
world.setAllowSleep(true);
world.setWarmStarting(true);
world.setSubStepping(false);
world.setContinuousPhysics(true);
}
public void initTest() {
{ // Floor
PolygonShape sd = new PolygonShape();
sd.setAsBox(50.0f, 10.0f);
BodyDef bd = new BodyDef();
bd.position = new Vec2(0.0f, -10.0f);
world.createBody(bd).createFixture(sd, 0f);
}
{
ddensity = 10f;
// Make bullet
PolygonShape sd = new PolygonShape();
sd.setAsBox(.7f, .7f);
FixtureDef fd = new FixtureDef();
fd.density = 35f;
BodyDef bd = new BodyDef();
bd.type = BodyType.DYNAMIC;
fd.shape = sd;
fd.friction = 0f;
fd.restitution = 0.85f;
bd.bullet = true;
// bd.addShape(sd);
bd.position = new Vec2(30f, 50f);
bullet1 = world.createBody(bd);
bullet1.createFixture(fd);
bullet1.setLinearVelocity(new Vec2(-25f, -25f));
bullet1.setAngularVelocity(6.7f);
fd.density = 25f;
bd.position = new Vec2(-30, 25f);
bullet2 = world.createBody(bd);
bullet2.createFixture(fd);
bullet2.setLinearVelocity(new Vec2(35f, -10f));
bullet2.setAngularVelocity(-8.3f);
}
{
float currX;
// Make base
for (int i = 0; i < baseCount; ++i) {
currX = i * 1.5f * dheight - (1.5f * dheight * baseCount / 2f);
makeDomino(currX, dheight / 2.0f, false, world);
makeDomino(currX, dheight + dwidth / 2.0f, true, world);
}
currX = baseCount * 1.5f * dheight - (1.5f * dheight * baseCount / 2f);
// Make 'I's
for (int j = 1; j < baseCount; ++j) {
if (j > 3)
ddensity *= .8f;
float currY = dheight * .5f + (dheight + 2f * dwidth) * .99f * j; // y at center of 'I'
// structure
for (int i = 0; i < baseCount - j; ++i) {
currX = i * 1.5f * dheight - (1.5f * dheight * (baseCount - j) / 2f);// +
// parent.random(-.05f,
// .05f);
ddensity *= 2.5f;
if (i == 0) {
makeDomino(currX - (1.25f * dheight) + .5f * dwidth, currY - dwidth, false, world);
}
if (i == baseCount - j - 1) {
// if (j != 1) //djm: why is this here? it makes it off balance
makeDomino(currX + (1.25f * dheight) - .5f * dwidth, currY - dwidth, false, world);
}
ddensity /= 2.5f;
makeDomino(currX, currY, false, world);
makeDomino(currX, currY + .5f * (dwidth + dheight), true, world);
makeDomino(currX, currY - .5f * (dwidth + dheight), true, world);
}
}
}
}
@Override
public void run() {
world.step(1f / 60f, 8, 3);
}
public int bodyCount() {
int count = 0;
Body body = world.getBodyList();
while (body != null) {
count++;
body = body.getNext();
}
return count;
}
public int checksum() {
int checkSum = 7;
Body body = world.getBodyList();
while (body != null) {
checkSum = 31 * checkSum + body.getPosition().hashCode();
checkSum = 31 * checkSum + body.getLinearVelocity().hashCode();
checkSum = 31 * checkSum + Float.floatToIntBits(body.getAngularVelocity());
body = body.getNext();
}
return checkSum;
}
public static void main (String[] args) throws InterruptedException {
final ChecksumTest test = new ChecksumTest();
test.initWorld();
test.initTest();
final AtomicInteger steps = new AtomicInteger(0);
final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
executor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
test.run();
steps.getAndIncrement();
if (steps.get() >= 1000)
executor.shutdown();
}
}, 0, 16, TimeUnit.MILLISECONDS);
executor.awaitTermination(1000 * 16 * 2, TimeUnit.MILLISECONDS);
System.out.println("Step count: " + steps.get());
System.out.println("Body count: " + test.bodyCount());
System.out.println("Bullet1 pos: " + test.bullet1.getPosition());
System.out.println("Bullet2 pos: " + test.bullet2.getPosition());
System.out.println("Checksum: " + test.checksum());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment