BoxStack.java

The main class for building a World where boxes are dropping on a flat surface. A SimpleSpace is attached for collision detection. The things to be implemented are HashSpace, box-box and box-plane collisions, and a Dantzig LCP constraint solver.
package simulator;

import javax.vecmath.*;
import java.awt.event.*;
import com.brackeen.javagamebook.input.*;
import java.util.List;
import java.util.LinkedList;


public class BoxStack
extends Simulator {

private class MyObject {
Body
body; // the body

Geom
geom; // geometries representing this body
};

private static final int NUM = 10;
private static final double DENSITY = 5.0;
private static final int MAX_CONTACTS = 4; // maximum number of contact points per body

private static MyObject[] obj;
private static int num = 0;
private static int nextobj = 0;
private static boolean random_pos = true;
private static World world;
private static Geom floor;

private List contactgroup;

protected GameAction fire

=
new GameAction("fire", GameAction.DETECT_INITAL_PRESS_ONLY);

private class BoxStackCollision
extends Collision implements ContactConstants {

public void nearCallback(Geom g1, Geom g2) {

// exit without doing anything if the two bodies are connected by a joint

Body b1 = g1.getBody();
Body b2 = g2.getBody();
if (b1!=null && b2!=null &&
b1.isConnectedExcluding(b2,
"simulator.ContactJoint")) return;

Contact[] contact =
new Contact[MAX_CONTACTS]; // up to MAX_CONTACTS contacts per box-box

for (int i = 0; i < MAX_CONTACTS; i++) {
contact[i] =
new Contact();
contact[i].surface.mode = Bounce | SoftCFM;
contact[i].surface.mu = Double.POSITIVE_INFINITY;
contact[i].surface.mu2 =
0;
contact[i].surface.bounce =
0.1;
contact[i].surface.bounce_vel =
0.1;
contact[i].surface.soft_cfm =
0.01;
}
int numc = collide(g1, g2, MAX_CONTACTS, contact);
if (numc > 0) {
for (int i = 0; i < numc; i++) {
Joint c =
new ContactJoint(world, contact[i]);
c.attach(b1, b2);
}
}
}
}

public static void main(String[] args) {
new BoxStack().run();
}

public void start() {
inputManager.mapToKey(
fire, KeyEvent.VK_SPACE);
inputManager.mapToMouse(
fire, InputManager.MOUSE_BUTTON_1);

world =
new World();
//space = new SimpleSpace(null);

contactgroup = new LinkedList();
obj =
new MyObject[NUM];
for (int i = 0; i < NUM; i++) {
obj[i] =
new MyObject();
}

world.setGravity(
0, -0.5, 0);
world.setCFM(
1e-5);
world.setAutoDisableFlag(
true);
world.setContactMaxCorrectingVel(
0.1);
world.setContactSurfaceLayer(
0.001);

floor =
new Plane(space, 0, 1, 0, 0);
space.setCollision(
new BoxStackCollision());
}

public void step() {
//floor.setState(Geom.STATE_IDLE);

command();
space.collide();
world.step();
}

public void command() {
int i;
if (fire.isPressed()) {
if (num < NUM) {
i = num;
num++;
}
else {
i = nextobj;
nextobj++;
if (nextobj >= num) {
nextobj =
0;
}
}
obj[i].body =
new Body(world);
double[] sides = new double[3];
for (int k = 0; k < 3; k++) {
sides[k] = Math.random() *
50 + 10;
}

Matrix3d R =
new Matrix3d();
if (random_pos) {
obj[i].body.setPosition(Math.random() *
20 - 100,
Math.random() +
200,
Math.random() *
20 - 200);
R.set(
new AxisAngle4d(Math.random() * 2.0 - 1.0,
Math.random() *
2.0 - 1.0,
Math.random() *
2.0 - 1.0,
Math.random() *
10.0 - 5.0));
}
else {
double maxheight = 0;
for (int k = 0; k < num; k++) {
Vector3d pos = obj[k].body.getPosition();
if (pos.z > maxheight) {
maxheight = pos.z;
}
}
obj[i].body.setPosition(
0, maxheight + 1, 0);
R.set(
new AxisAngle4d(0, 1, 0, Math.random() * 10.0 - 5.0));
}
obj[i].body.setRotation(R);
//dBodySetData (obj[i].body,(void*) i);

Mass m =
new Mass();
m.setBox(DENSITY, sides[
0], sides[1], sides[2]);
obj[i].geom =
new Box(space, sides[0], sides[1], sides[2]);
obj[i].geom.setBody(obj[i].body);
obj[i].body.setMass(m);
}
}
}



Comments