Java port of Bullet

jezek2
Posts: 40
Joined: Fri Jan 11, 2008 8:33 am

Re: Java port of Bullet

Post by jezek2 »

New version available on JBullet homepage.

Changes in release 20101010:
- Added KinematicCharacterController, GhostObject and CharacterDemo
- Added DbvtBroadphase
- Added serialization of BVH
- Updated most classes to match Bullet 2.72
- Added CCD motion clamping fix from Bullet 2.74
- Removed usage of interface calls
- Added stackless traversal in OptimizedBvh
- Added jumping/gravity to KinematicCharacterController (contributed by Normen Hansen)
legendman3
Posts: 2
Joined: Tue Mar 08, 2011 12:17 am

Re: Java port of Bullet

Post by legendman3 »

So are you still updating this thing?
jezek2
Posts: 40
Joined: Fri Jan 11, 2008 8:33 am

Re: Java port of Bullet

Post by jezek2 »

legendman3 wrote:So are you still updating this thing?
Hi, yeah. I work on it from time to time, currently working on some features. Generally it's in a 'stable' state, that means we're all happily using it in our projects :) If you need something ported it's best to tell me so I can bring the functionality in, it can be often back ported even from newer versions of Bullet than JBullet is currently based on.
legendman3
Posts: 2
Joined: Tue Mar 08, 2011 12:17 am

Re: Java port of Bullet

Post by legendman3 »

Could you post a download for your jStackAlloc library? Im making a project and i need that library for it. It wont compile without that library.
jezek2
Posts: 40
Joined: Fri Jan 11, 2008 8:33 am

Re: Java port of Bullet

Post by jezek2 »

legendman3 wrote:Could you post a download for your jStackAlloc library? Im making a project and i need that library for it. It wont compile without that library.
You can download the sources and binary here. You have to run the bytecode instrumentation task after compiling (from Ant script). It's recommended to just use the already compiled 'jbullet.jar' (in the 'dist' subdirectory of sources) instead of compiling yourself. Note that you can just copy out the demos and compile them without the need of bytecode modification nor JStackAlloc.

The next version of JBullet (no date set yet) will make bytecode instrumentation optional (more details here).
PepeLui
Posts: 2
Joined: Wed Jan 26, 2011 2:45 pm

Re: Java port of Bullet

Post by PepeLui »

It will be cool if you can port the Spring Constraint!

Awesome job dude!
MMazur
Posts: 6
Joined: Sun Mar 20, 2011 6:22 pm

Re: Java port of Bullet

Post by MMazur »

Hi,
could anyone post a snippet of a code on how to use TriangleMesh in JBullet? From what I see it's a lot different than original Bullet. I'm just trying to construct a simple static terrain mesh. I have no idea how to do that - ConvexHull works, but of course terribly slow ( terrain has something like 60 000 vertices ). Here's the code that I tried:

Code: Select all

        IndexedMesh mesh = new IndexedMesh();
        ByteBuffer verts = ByteBuffer.allocate(model.vertexsets.size() * 3 * (Float.SIZE/8) );
        ByteBuffer polys = ByteBuffer.allocate(model.faces.size() * 3 * (Integer.SIZE/8) );
        
        for(int i = 0; i < model.vertexsets.size(); i++)
        {
        	float tempx = ((float[]) model.vertexsets.get(i))[0]; // this is correct data loaded from an OBJ file
	float tempy = ((float[]) model.vertexsets.get(i))[1];
	float tempz = ((float[]) model.vertexsets.get(i))[2];
        	verts.putFloat( tempx );
        	verts.putFloat( tempy );
        	verts.putFloat( tempz );
        }
        
        for(int i = 0; i < model.faces.size(); i++)
        {
        	int tempx = ((int[]) model.faces.get(i))[0]; // this is correct data loaded from an OBJ file
        	int tempy = ((int[]) model.faces.get(i))[1];
        	int tempz = ((int[]) model.faces.get(i))[2];
        	polys.putInt( tempx );
        	polys.putInt( tempy );
        	polys.putInt( tempz );
        }

        mesh.numTriangles = model.numpolygons();
        mesh.numVertices = model.vertexsets.size();
        mesh.vertexBase = verts;
        mesh.triangleIndexBase = polys;
        mesh.triangleIndexStride = Integer.SIZE/8;
        mesh.vertexStride = (Float.SIZE/8)*3;
        
        TriangleIndexVertexArray vertexarray = new TriangleIndexVertexArray();
        vertexarray.addIndexedMesh(mesh);
        BvhTriangleMeshShape terrainshape = new BvhTriangleMeshShape(vertexarray, true);
I'm not asking anyone to fix my code. I just need an example on how to construct a static terrain geometry and add it to the world.

edit: At: ( I have no idea if these strides should mean one point, or a set of 3 points. It doesn't work either way. )

Code: Select all

mesh.triangleIndexStride = (Integer.SIZE/8) * 3;
mesh.vertexStride = (Float.SIZE/8) * 3;
MMazur
Posts: 6
Joined: Sun Mar 20, 2011 6:22 pm

Re: Java port of Bullet

Post by MMazur »

Ok, i got it working triangle stride should be 3 points, and vert stride 1 point. But I have another problem - simulation works as ConvexHullShape and also BvhTriangleMeshShape, but both are EXTREMELY SLOW. I reduced my mesh to 15682 polygons, and 7983 vertices, which is absolutely unacceptable, and still one simulation steps takes ~1 second to calculate ( only physics ).
What's the proper way to construct static mesh geometry?
JumperBR
Posts: 1
Joined: Mon Mar 14, 2011 5:06 pm

Re: Java port of Bullet

Post by JumperBR »

Hi jezek2,
I see you are doing an excellent job with Jbullet, keep the good work!
But, I've been trying to use your jbullet to implement a space game into scale and I'm having some dificulties with big numbers (well, space is huge)...
Looks like jbullet doesn't have a good precision when dealing with positions bigger than 100000000.

I've changed the VehicleDemo.java to show this problem, in the code below I add a big number to the initial position and I keep getting some weird results, you should look at it...
So, is there any way to improve precision? Any help is appreciated. Maybe changing from float to double...
If not, anyone recommend a good physics engine for a space game?

thx in advance.

Code: Select all

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import com.bulletphysics.collision.broadphase.BroadphaseInterface;
import com.bulletphysics.collision.broadphase.DbvtBroadphase;
import com.bulletphysics.collision.dispatch.CollisionDispatcher;
import com.bulletphysics.collision.dispatch.CollisionObject;
import com.bulletphysics.collision.dispatch.DefaultCollisionConfiguration;
import com.bulletphysics.collision.shapes.BoxShape;
import com.bulletphysics.collision.shapes.BvhTriangleMeshShape;
import com.bulletphysics.collision.shapes.CollisionShape;
import com.bulletphysics.collision.shapes.CompoundShape;
import com.bulletphysics.collision.shapes.CylinderShapeX;
import com.bulletphysics.collision.shapes.TriangleIndexVertexArray;
import com.bulletphysics.demos.opengl.GLDebugDrawer;
import com.bulletphysics.demos.opengl.GLShapeDrawer;
import com.bulletphysics.demos.opengl.IGL;
import com.bulletphysics.dynamics.DiscreteDynamicsWorld;
import com.bulletphysics.dynamics.RigidBody;
import com.bulletphysics.dynamics.constraintsolver.ConstraintSolver;
import com.bulletphysics.dynamics.constraintsolver.SequentialImpulseConstraintSolver;
import com.bulletphysics.dynamics.vehicle.DefaultVehicleRaycaster;
import com.bulletphysics.dynamics.vehicle.RaycastVehicle;
import com.bulletphysics.dynamics.vehicle.VehicleRaycaster;
import com.bulletphysics.dynamics.vehicle.VehicleTuning;
import com.bulletphysics.dynamics.vehicle.WheelInfo;
import com.bulletphysics.linearmath.Transform;
import com.bulletphysics.util.ObjectArrayList;
import javax.vecmath.Vector3f;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;

/**
 * VehicleDemo shows how to setup and use the built-in raycast vehicle.
 * 
 * @author jezek2
 */
public class VehicleDemo extends DemoApplication {

//Change the following variable to move the entire scene to a different position...
	float ix=100000000;
	private static final int rightIndex = 0;
	private static final int upIndex = 1;
	private static final int forwardIndex = 2;
	private static final Vector3f wheelDirectionCS0 = new Vector3f(0,-1,0);
	private static final Vector3f wheelAxleCS = new Vector3f(-1,0,0);
	//#endif
	
	private static final int maxProxies = 32766;
	private static final int maxOverlap = 65535;

	// RaycastVehicle is the interface for the constraint that implements the raycast vehicle
	// notice that for higher-quality slow-moving vehicles, another approach might be better
	// implementing explicit hinged-wheel constraints with cylinder collision, rather then raycasts
	private static float gEngineForce = 0.f;
	private static float gBreakingForce = 0.f;

	private static float maxEngineForce = 1000.f;//this should be engine/velocity dependent
	private static float maxBreakingForce = 100.f;

	private static float gVehicleSteering = 0.f;
	private static float steeringIncrement = 0.04f;
	private static float steeringClamp = 0.3f;
	private static float wheelRadius = 0.5f;
	private static float wheelWidth = 0.4f;
	private static float wheelFriction = 1000;//1e30f;
	private static float suspensionStiffness = 20.f;
	private static float suspensionDamping = 2.3f;
	private static float suspensionCompression = 4.4f;
	private static float rollInfluence = 0.1f;//1.0f;

	private static final float suspensionRestLength = 0.6f;

	private static final int CUBE_HALF_EXTENTS = 1;
	
	////////////////////////////////////////////////////////////////////////////
	
	public RigidBody carChassis;
	public ObjectArrayList<CollisionShape> collisionShapes = new ObjectArrayList<CollisionShape>();
	public BroadphaseInterface overlappingPairCache;
	public CollisionDispatcher dispatcher;
	public ConstraintSolver constraintSolver;
	public DefaultCollisionConfiguration collisionConfiguration;
	public TriangleIndexVertexArray indexVertexArrays;

	public ByteBuffer vertices;

	public VehicleTuning tuning = new VehicleTuning();
	public VehicleRaycaster vehicleRayCaster;
	public RaycastVehicle vehicle;

	public float cameraHeight;

	public float minCameraDistance;
	public float maxCameraDistance;

	public VehicleDemo(IGL gl) {
		super(gl);
		carChassis = null;
		cameraHeight = 4f;
		minCameraDistance = 3f;
		maxCameraDistance = 10f;
		indexVertexArrays = null;
		vertices = null;
		vehicle = null;
		cameraPosition.set(30, 30, 30);
	}

	public void initPhysics() {
		//#ifdef FORCE_ZAXIS_UP
		//m_cameraUp = btVector3(0,0,1);
		//m_forwardAxis = 1;
		//#endif

		CollisionShape groundShape = new BoxShape(new Vector3f(50, 3, 50));
		collisionShapes.add(groundShape);
		collisionConfiguration = new DefaultCollisionConfiguration();
		dispatcher = new CollisionDispatcher(collisionConfiguration);
		Vector3f worldMin = new Vector3f(-1000, -1000, -1000);
		Vector3f worldMax = new Vector3f(1000, 1000, 1000);
		//overlappingPairCache = new AxisSweep3(worldMin, worldMax);
		//overlappingPairCache = new SimpleBroadphase();
		overlappingPairCache = new DbvtBroadphase();
		constraintSolver = new SequentialImpulseConstraintSolver();
		dynamicsWorld = new DiscreteDynamicsWorld(dispatcher, overlappingPairCache, constraintSolver, collisionConfiguration);
		//#ifdef FORCE_ZAXIS_UP
		//dynamicsWorld.setGravity(new Vector3f(0, 0, -10));
		//#endif 

		//m_dynamicsWorld->setGravity(btVector3(0,0,0));
		Transform tr = new Transform();
		
		tr.setIdentity();

		// either use heightfield or triangle mesh
		//#define  USE_TRIMESH_GROUND 1
		//#ifdef USE_TRIMESH_GROUND

		final float TRIANGLE_SIZE = 20f;

		// create a triangle-mesh ground
		int vertStride = 4 * 3 /* sizeof(btVector3) */;
		int indexStride = 3 * 4 /* 3*sizeof(int) */;

		final int NUM_VERTS_X = 20;
		final int NUM_VERTS_Y = 20;
		final int totalVerts = NUM_VERTS_X * NUM_VERTS_Y;

		final int totalTriangles = 2 * (NUM_VERTS_X - 1) * (NUM_VERTS_Y - 1);

		vertices = ByteBuffer.allocateDirect(totalVerts * vertStride).order(ByteOrder.nativeOrder());
		ByteBuffer gIndices = ByteBuffer.allocateDirect(totalTriangles * 3 * 4).order(ByteOrder.nativeOrder());

		Vector3f tmp = new Vector3f();
		for (int i = 0; i < NUM_VERTS_X; i++) {
			for (int j = 0; j < NUM_VERTS_Y; j++) {
				float wl = 0.2f;
				// height set to zero, but can also use curved landscape, just uncomment out the code
				float height = 0f;//(float)Math.random()*10-10;//20f * (float)Math.sin(i * wl) * (float)Math.cos(j * wl);
				
				//#ifdef FORCE_ZAXIS_UP
				//m_vertices[i+j*NUM_VERTS_X].setValue(
				//	(i-NUM_VERTS_X*0.5f)*TRIANGLE_SIZE,
				//	(j-NUM_VERTS_Y*0.5f)*TRIANGLE_SIZE,
				//	height
				//	);
				//#else
				tmp.set(
						(i - NUM_VERTS_X * 0.5f) * TRIANGLE_SIZE,
						height,
						(j - NUM_VERTS_Y * 0.5f) * TRIANGLE_SIZE);

				int index = i + j * NUM_VERTS_X;
				vertices.putFloat((index * 3 + 0) * 4, tmp.x);
				vertices.putFloat((index * 3 + 1) * 4, tmp.y);
				vertices.putFloat((index * 3 + 2) * 4, tmp.z);
				//#endif
			}
		}

		//int index=0;
		gIndices.clear();
		for (int i = 0; i < NUM_VERTS_X - 1; i++) {
			for (int j = 0; j < NUM_VERTS_Y - 1; j++) {
				gIndices.putInt(j * NUM_VERTS_X + i);
				gIndices.putInt(j * NUM_VERTS_X + i + 1);
				gIndices.putInt((j + 1) * NUM_VERTS_X + i + 1);

				gIndices.putInt(j * NUM_VERTS_X + i);
				gIndices.putInt((j + 1) * NUM_VERTS_X + i + 1);
				gIndices.putInt((j + 1) * NUM_VERTS_X + i);
			}
		}
		gIndices.flip();

		indexVertexArrays = new TriangleIndexVertexArray(totalTriangles,
				gIndices,
				indexStride,
				totalVerts, vertices, vertStride);

		boolean useQuantizedAabbCompression = true;
		groundShape = new BvhTriangleMeshShape(indexVertexArrays, useQuantizedAabbCompression);

		tr.origin.set(ix+0, -4.5f, 0);

		//#else
//		//testing btHeightfieldTerrainShape
//		int width=128;
//		int length=128;
//		unsigned char* heightfieldData = new unsigned char[width*length];
//		{
//			for (int i=0;i<width*length;i++)
//			{
//				heightfieldData[i]=0;
//			}
//		}
//
//		char*	filename="heightfield128x128.raw";
//		FILE* heightfieldFile = fopen(filename,"r");
//		if (!heightfieldFile)
//		{
//			filename="../../heightfield128x128.raw";
//			heightfieldFile = fopen(filename,"r");
//		}
//		if (heightfieldFile)
//		{
//			int numBytes =fread(heightfieldData,1,width*length,heightfieldFile);
//			//btAssert(numBytes);
//			if (!numBytes)
//			{
//				printf("couldn't read heightfield at %s\n",filename);
//			}
//			fclose (heightfieldFile);
//		}
//
//
//		btScalar maxHeight = 20000.f;
//
//		bool useFloatDatam=false;
//		bool flipQuadEdges=false;
//
//		btHeightfieldTerrainShape* heightFieldShape = new btHeightfieldTerrainShape(width,length,heightfieldData,maxHeight,upIndex,useFloatDatam,flipQuadEdges);;
//		groundShape = heightFieldShape;
//
//		heightFieldShape->setUseDiamondSubdivision(true);
//
//		btVector3 localScaling(20,20,20);
//		localScaling[upIndex]=1.f;
//		groundShape->setLocalScaling(localScaling);
//
//		tr.setOrigin(btVector3(0,-64.5f,0));
//
		//#endif

		collisionShapes.add(groundShape);

		// create ground object
		localCreateRigidBody(0, tr, groundShape);

		//#ifdef FORCE_ZAXIS_UP
		//	//   indexRightAxis = 0; 
		//	//   indexUpAxis = 2; 
		//	//   indexForwardAxis = 1; 
		//btCollisionShape* chassisShape = new btBoxShape(btVector3(1.f,2.f, 0.5f));
		//btCompoundShape* compound = new btCompoundShape();
		//btTransform localTrans;
		//localTrans.setIdentity();
		// //localTrans effectively shifts the center of mass with respect to the chassis
		//localTrans.setOrigin(btVector3(0,0,1));
		//#else
		CollisionShape chassisShape = new BoxShape(new Vector3f(1.0f, 0.5f, 2.0f));
		collisionShapes.add(chassisShape);

		CompoundShape compound = new CompoundShape();
		collisionShapes.add(compound);
		Transform localTrans = new Transform();
		localTrans.setIdentity();
		// localTrans effectively shifts the center of mass with respect to the chassis
		localTrans.origin.set(0, 1, 0);
		//#endif

		compound.addChildShape(localTrans, chassisShape);

		tr.origin.set(0, 0, 0);

		
		
	/*	Transform startTransform = new Transform();
		startTransform.setIdentity();
		Vector3f camPos = new Vector3f(ix,-10,0);
		startTransform.origin.set(new Vector3f(ix,-10,0));*/
		
		
		
		carChassis = localCreateRigidBody(800, tr, compound); //chassisShape);
		//m_carChassis->setDamping(0.2,0.2);

		
		clientResetScene();
		//tr.origin.set(0, -40, 0);
		// create vehicle
		{
			vehicleRayCaster = new DefaultVehicleRaycaster(dynamicsWorld);
			vehicle = new RaycastVehicle(tuning, carChassis, vehicleRayCaster);

			// never deactivate the vehicle
			carChassis.setActivationState(CollisionObject.DISABLE_DEACTIVATION);

			dynamicsWorld.addVehicle(vehicle);

			float connectionHeight = 1.2f;

			boolean isFrontWheel = true;

			// choose coordinate system
			vehicle.setCoordinateSystem(rightIndex, upIndex, forwardIndex);

			//#ifdef FORCE_ZAXIS_UP
			//btVector3 connectionPointCS0(CUBE_HALF_EXTENTS-(0.3*wheelWidth),2*CUBE_HALF_EXTENTS-wheelRadius, connectionHeight);
			//#else
			Vector3f connectionPointCS0 = new Vector3f(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, 2f * CUBE_HALF_EXTENTS - wheelRadius);
			//#endif

			vehicle.addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel);
			//#ifdef FORCE_ZAXIS_UP
			//connectionPointCS0 = btVector3(-CUBE_HALF_EXTENTS+(0.3*wheelWidth),2*CUBE_HALF_EXTENTS-wheelRadius, connectionHeight);
			//#else
			connectionPointCS0.set(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, 2f * CUBE_HALF_EXTENTS - wheelRadius);
			//#endif

			vehicle.addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel);
			//#ifdef FORCE_ZAXIS_UP
			//connectionPointCS0 = btVector3(-CUBE_HALF_EXTENTS+(0.3*wheelWidth),-2*CUBE_HALF_EXTENTS+wheelRadius, connectionHeight);
			//#else
			connectionPointCS0.set(-CUBE_HALF_EXTENTS + (0.3f * wheelWidth), connectionHeight, -2f * CUBE_HALF_EXTENTS + wheelRadius);
			//#endif //FORCE_ZAXIS_UP
			isFrontWheel = false;
			vehicle.addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel);
			//#ifdef FORCE_ZAXIS_UP
			//connectionPointCS0 = btVector3(CUBE_HALF_EXTENTS-(0.3*wheelWidth),-2*CUBE_HALF_EXTENTS+wheelRadius, connectionHeight);
			//#else
			connectionPointCS0.set(CUBE_HALF_EXTENTS - (0.3f * wheelWidth), connectionHeight, -2f * CUBE_HALF_EXTENTS + wheelRadius);
			//#endif
			vehicle.addWheel(connectionPointCS0, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, wheelRadius, tuning, isFrontWheel);

			for (int i = 0; i < vehicle.getNumWheels(); i++) {
				WheelInfo wheel = vehicle.getWheelInfo(i);
				wheel.suspensionStiffness = suspensionStiffness;
				wheel.wheelsDampingRelaxation = suspensionDamping;
				wheel.wheelsDampingCompression = suspensionCompression;
				wheel.frictionSlip = wheelFriction;
				wheel.rollInfluence = rollInfluence;
			}
		}
		
		
		
		

		setCameraDistance(26.f);
	}
	
	// to be implemented by the demo
	@Override
	public void renderme() {
		updateCamera();

		CylinderShapeX wheelShape = new CylinderShapeX(new Vector3f(wheelWidth, wheelRadius, wheelRadius));
		Vector3f wheelColor = new Vector3f(1, 0, 0);

		for (int i = 0; i < vehicle.getNumWheels(); i++) {
			// synchronize the wheels with the (interpolated) chassis worldtransform
			vehicle.updateWheelTransform(i, true);
			// draw wheels (cylinders)
			Transform trans = vehicle.getWheelInfo(i).worldTransform;
			GLShapeDrawer.drawOpenGL(gl, trans, wheelShape, wheelColor, getDebugMode());
		}

		super.renderme();
	}
	
	@Override
	public void clientMoveAndDisplay() {
		gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT); 

		{			
			int wheelIndex = 2;
			vehicle.applyEngineForce(gEngineForce,wheelIndex);
			vehicle.setBrake(gBreakingForce,wheelIndex);
			wheelIndex = 3;
			vehicle.applyEngineForce(gEngineForce,wheelIndex);
			vehicle.setBrake(gBreakingForce,wheelIndex);

			wheelIndex = 0;
			vehicle.setSteeringValue(gVehicleSteering,wheelIndex);
			wheelIndex = 1;
			vehicle.setSteeringValue(gVehicleSteering,wheelIndex);
		}

		float dt = getDeltaTimeMicroseconds() * 0.000001f;
		
		if (dynamicsWorld != null)
		{
			// during idle mode, just run 1 simulation step maximum
			int maxSimSubSteps = idle ? 1 : 2;
			if (idle)
				dt = 1f/420f;

			int numSimSteps = dynamicsWorld.stepSimulation(dt,maxSimSubSteps);

			//#define VERBOSE_FEEDBACK
			//#ifdef VERBOSE_FEEDBACK
			//if (!numSimSteps)
			//	printf("Interpolated transforms\n");
			//else
			//{
			//	if (numSimSteps > maxSimSubSteps)
			//	{
			//		//detect dropping frames
			//		printf("Dropped (%i) simulation steps out of %i\n",numSimSteps - maxSimSubSteps,numSimSteps);
			//	} else
			//	{
			//		printf("Simulated (%i) steps\n",numSimSteps);
			//	}
			//}
			//#endif //VERBOSE_FEEDBACK
		}

		//#ifdef USE_QUICKPROF 
		//btProfiler::beginBlock("render"); 
		//#endif //USE_QUICKPROF 

		renderme(); 
		
		// optional but useful: debug drawing
		if (dynamicsWorld != null) {
			dynamicsWorld.debugDrawWorld();
		}

		//#ifdef USE_QUICKPROF 
		//btProfiler::endBlock("render"); 
		//#endif 
	}

	@Override
	public void displayCallback() {
		gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT);

		renderme();
		
		// optional but useful: debug drawing
		if (dynamicsWorld != null) {
			dynamicsWorld.debugDrawWorld();
		}
	}

	@Override
	public void clientResetScene() {
		gVehicleSteering = 0f;
		Transform tr = new Transform();
		tr.setIdentity();
		tr.origin.set(new Vector3f(ix,10,0));
		carChassis.setCenterOfMassTransform(tr);
		carChassis.setLinearVelocity(new Vector3f(0, 0, 0));
		carChassis.setAngularVelocity(new Vector3f(0, 0, 0));
		dynamicsWorld.getBroadphase().getOverlappingPairCache().cleanProxyFromPairs(carChassis.getBroadphaseHandle(), getDynamicsWorld().getDispatcher());
		if (vehicle != null) {
			vehicle.resetSuspension();
			for (int i = 0; i < vehicle.getNumWheels(); i++) {
				// synchronize the wheels with the (interpolated) chassis worldtransform
				vehicle.updateWheelTransform(i, true);
			}
		}
	}

	@Override
	public void specialKeyboardUp(int key, int x, int y, int modifiers) {
		switch (key) {
			case Keyboard.KEY_UP: {
				gEngineForce = 0f;
				break;
			}
			case Keyboard.KEY_DOWN: {
				gBreakingForce = 0f;
				break;
			}
			default:
				super.specialKeyboardUp(key, x, y, modifiers);
				break;
		}
	}

	@Override
	public void specialKeyboard(int key, int x, int y, int modifiers) {
		//	printf("key = %i x=%i y=%i\n",key,x,y);

		switch (key) {
			case Keyboard.KEY_LEFT: {
				gVehicleSteering += steeringIncrement;
				if (gVehicleSteering > steeringClamp) {
					gVehicleSteering = steeringClamp;
				}
				break;
			}
			case Keyboard.KEY_RIGHT: {
				gVehicleSteering -= steeringIncrement;
				if (gVehicleSteering < -steeringClamp) {
					gVehicleSteering = -steeringClamp;
				}
				break;
			}
			case Keyboard.KEY_UP: {
				gEngineForce = maxEngineForce;
				gBreakingForce = 0.f;
				break;
			}
			case Keyboard.KEY_DOWN: {
				gBreakingForce = maxBreakingForce;
				gEngineForce = 0.f;
				break;
			}
			default:
				super.specialKeyboard(key, x, y, modifiers);
				break;
		}

		//glutPostRedisplay();
	}

	@Override
	public void updateCamera()
	{

		// //#define DISABLE_CAMERA 1
		//#ifdef DISABLE_CAMERA
		//DemoApplication::updateCamera();
		//return;
		//#endif //DISABLE_CAMERA

		gl.glMatrixMode(gl.GL_PROJECTION);
		gl.glLoadIdentity();

		Transform chassisWorldTrans = new Transform();

		// look at the vehicle
		carChassis.getMotionState().getWorldTransform(chassisWorldTrans);
		cameraTargetPosition.set(chassisWorldTrans.origin);

		
		// interpolate the camera height
		//#ifdef FORCE_ZAXIS_UP
		//m_cameraPosition[2] = (15.0*m_cameraPosition[2] + m_cameraTargetPosition[2] + m_cameraHeight)/16.0;
		//#else
		cameraPosition.y = (15.0f*cameraPosition.y + cameraTargetPosition.y + cameraHeight) / 16.0f;
		//#endif

		System.out.println("Position:"+cameraPosition);
		Vector3f camToObject = new Vector3f();
		camToObject.sub(cameraTargetPosition, cameraPosition);

		// keep distance between min and max distance
		float cameraDistance = camToObject.length();
		float correctionFactor = 0f;
		if (cameraDistance < minCameraDistance)
		{
			correctionFactor = 0.15f*(minCameraDistance-cameraDistance)/cameraDistance;
		}
		if (cameraDistance > maxCameraDistance)
		{
			correctionFactor = 0.15f*(maxCameraDistance-cameraDistance)/cameraDistance;
		}
		Vector3f tmp = new Vector3f();
		tmp.scale(correctionFactor, camToObject);
		cameraPosition.sub(tmp);

		// update OpenGL camera settings
		gl.glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 10000.0);

		gl.glMatrixMode(IGL.GL_MODELVIEW);
		gl.glLoadIdentity();
		
		gl.gluLookAt(cameraPosition.x,cameraPosition.y,cameraPosition.z,
				  cameraTargetPosition.x,cameraTargetPosition.y, cameraTargetPosition.z,
				  cameraUp.x,cameraUp.y,cameraUp.z);
	}
	
	public static void main(String[] args) throws LWJGLException {
		VehicleDemo vehicleDemo = new VehicleDemo(LWJGL.getGL());
		vehicleDemo.initPhysics();
		vehicleDemo.getDynamicsWorld().setDebugDrawer(new GLDebugDrawer(LWJGL.getGL()));

		LWJGL.main(args, 800, 600, "Bullet Vehicle Demo", vehicleDemo);
	}
	
}
MMazur
Posts: 6
Joined: Sun Mar 20, 2011 6:22 pm

Re: Java port of Bullet

Post by MMazur »

@JumperBR
Well, you could just scale your world down. Quite simple.
hughperkins
Posts: 1
Joined: Mon May 09, 2011 7:22 am

Re: Java port of Bullet

Post by hughperkins »

Please could you post a list of the features that are working, and just as important, the features that are not working?
affogato
Posts: 2
Joined: Fri Jul 29, 2011 3:33 am

Java port of Bullet - added spring (Generic6DofSpringConstra

Post by affogato »

If anyone in the community is interested in using Translational Motors, the Spring Constraint (Generic6DofSpringConstraint) and the ConstraintDemo in JBullet, you can pull my fork of JBullet from:
https://github.com/affogato/JBullet-QIntBio-Fork

This was added for use in a cellular simulation project called QIntBio.

The spring constraint was added to Bullet _after_ the major refactoring of the constraint solver in revision 1542 involving SIMD support. The translational motor and the way the spring constraint uses it to simulate the effect of a spring, is written for the newer software design (with getInfo() functions and optimised SIMD functions).
Therefore, there was no code to solve the linear spring constraint, that can be ported in a straightforward manner.

New code was written following the old template.

Hope it is useful  :)
osbeorn
Posts: 1
Joined: Wed Dec 07, 2011 3:31 pm

Re: Java port of Bullet

Post by osbeorn »

I am trying to run the JBullet demos in eclipse with no luck. I keep getting the

Code: Select all

Exception in thread "main" java.lang.Error: not instrumented
at cz.advel.stack.Stack.alloc(Stack.java:122)
error. I have no idea how to solve this problem so im asking here for help. I tried building with Ant and also with no success as i dont really know how to do that.
Thanks in advance.
xexuxjy
Posts: 225
Joined: Wed Jan 07, 2009 11:43 am
Location: London

Re: Java port of Bullet

Post by xexuxjy »

If you've built the JBullet.jar via ant then that should be in dist/jbullet.jar . If you add this to your project libraries, and then in order & export make sure that jbullet.jar is above the JBullet/src folder then it should correctly pick up the instrumented version.
gmfreaky
Posts: 1
Joined: Fri Feb 17, 2012 1:28 pm

Re: Java port of Bullet

Post by gmfreaky »

Is the HeightfieldTerrainShape class ported for JBullet? Is there an alternative available?
Post Reply