/*
*
* (c)2010 Lein-Mathisen Digital
* http://lmdig.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
package com.kristianlm.robotanks.box2dbridge.jnibox2d;
import org.jbox2d.collision.AABB;
import org.jbox2d.collision.Segment;
import org.jbox2d.common.RaycastResult;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.BodyDef;
import com.kristianlm.robotanks.box2dbridge.IBody;
import com.kristianlm.robotanks.box2dbridge.IJoint;
import com.kristianlm.robotanks.box2dbridge.IShape;
import com.kristianlm.robotanks.box2dbridge.IWorld;
public class JNIBox2DWorld implements IWorld {
JNIBox2DBody groundBody;
public boolean testJNI() throws UnsatisfiedLinkError {
// this is our plan:
// make a test call to native library. it may throw unsatisfiedlink exception,
// but then we catch it and use the JBox2d
try {
int result = nTestLib(13);
System.out.println("jni test result: " + result);
}
catch (Exception e) {
return false;
}
return true;
}
@Override
public int create(AABB worldAABB, Vec2 gravity, boolean doSleep) {
if(!isJniOK()) {
// our loadlibrary function failed (native lib not found)
return -1;
}
nCreateWorld( worldAABB.lowerBound.x, worldAABB.lowerBound.y,
worldAABB.upperBound.x, worldAABB.upperBound.y, gravity.x,
gravity.y, doSleep);
groundBody = new JNIBox2DBody(0);
return 0;
}
@Override
public IBody createBody(BodyDef def) {
int id = nCreateBody(def.position.x, def.position.y);
JNIBox2DBody jb = new JNIBox2DBody(id);
jb.setUserData(def.userData);
return jb;
}
@Override
public IBody getGroundBody() {
return groundBody;
}
@Override
public IShape[] query(AABB aabb, int maxCount) {
JNIBox2DShape[] shapeList = new JNIBox2DShape[maxCount];
nShapeQuery(aabb.lowerBound.x, aabb.lowerBound.y,
aabb.upperBound.x, aabb.upperBound.y, maxCount, shapeList);
/*
* IShape [] is = new JNIBox2DShape [bodies] ; for(int i = 0 ; i <
* bodies ; i++) { is[i] = new JNIBox2DShape(bodyList[i]); }
*/
// System.out.println("Found " + bodies + " bodies in query.");
return shapeList;
}
public IJoint createRevoluteJoint(IBody body1, IBody body2, float anchorX, float anchorY) {
JNIBox2DBody b1 = null, b2 = null;
if (body1 instanceof JNIBox2DBody)
b1 = (JNIBox2DBody) body1;
else
return null;
if (body2 instanceof JNIBox2DBody)
b2 = (JNIBox2DBody) body2;
else
return null;
int jID = nCreateRevoluteJoint(b1.bodyID, b2.bodyID, anchorX, anchorY);
if(jID < 0) {
System.out.println("native could not create joint");
return null;
}
return new JNIBox2DJoint(jID);
}
@Override
public void destroyJoint(IJoint j) {
if (!(j instanceof JNIBox2DJoint)) {
System.out
.println("Cannot destroy IJoint of type other than JNIBox2DJoint");
return;
}
JNIBox2DJoint jj = (JNIBox2DJoint) j;
nDestroyJoint(jj.jointID);
}
@Override
public IShape raycastOne(Segment s, RaycastResult rr, boolean solidShapes,
Object userData) {
JNIBox2DShape shape = nRaycastOne(s.p1.x, s.p1.y, s.p2.x, s.p2.y, rr,
solidShapes, userData);
return shape;
// return null;
}
@Override
public void destroyBody(IBody body) {
if (body instanceof JNIBox2DBody) {
JNIBox2DBody jnibody = (JNIBox2DBody) body;
nDestroyBody(jnibody.bodyID);
} else
System.out
.println("WARNING JNI world destroybody: no jnibody instance provided");
}
@Override
public void destroy() {
nDestroy();
}
@Override
public void sync() {
nUpdateAllPositions();
}
// implemented in C/C++
// automatically dynamically linked at run-time
// JVM looks for .so/.dll files in java.library.path
native private void nUpdateAllPositions();
private static boolean jniOk = false;
public static boolean isJniOK() { return jniOk; }
static {
try {
System.loadLibrary("box2d");
jniOk = true;
} catch (java.lang.UnsatisfiedLinkError e) {
jniOk = false;
}
}
native private int nTestLib(int k);
native public int nCreateWorld(float x1, float y1, float x2, float y2,
float gravity_x, float gravity_y, boolean canSleep);
// fills shapeList with IDs of shapes
native private int nShapeQuery(float x1, float y1, float x2, float y2,
int maxCount, Object[] shapeList);
native public void step(float dt, int iterations);
native public void nDestroy();
native public int nCreateBody(float x, float y);
native public void nDestroyBody(int bodyID);
native public int nCreateRevoluteJoint(int body1, int body2, float x,
float y);
native public void nDestroyJoint(int jointID);
native private JNIBox2DShape nRaycastOne(float p1x, float p1y, float p2x,
float p2y, RaycastResult rr, boolean solidShapes, Object userData);
native private void nUpdateAllPosditions();
}