import com.badlogic.gdx.Application.ApplicationType;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.graphics.g3d.Environment;
import com.badlogic.gdx.graphics.g3d.Material;
import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.graphics.g3d.ModelBatch;
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
import com.badlogic.gdx.graphics.g3d.attributes.FloatAttribute;
import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
import com.badlogic.gdx.graphics.g3d.environment.DirectionalShadowLight;
import com.badlogic.gdx.graphics.g3d.loader.ObjLoader;
import com.badlogic.gdx.graphics.g3d.utils.DepthShaderProvider;
import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.math.collision.Ray;
import com.badlogic.gdx.physics.bullet.Bullet;
import com.badlogic.gdx.physics.bullet.dynamics.btRigidBody;
import com.badlogic.gdx.physics.bullet.linearmath.LinearMath;
import com.badlogic.gdx.physics.bullet.linearmath.btIDebugDraw.DebugDrawModes;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Disposable;
/** @author xoppa */
public class BaseBulletTest extends BulletTest {
// Set this to the path of the lib to use it on desktop instead of default lib.
private final static String customDesktopLib = null;//"D:\\Xoppa\\code\\libgdx\\extensions\\gdx-bullet\\jni\\vs\\gdxBullet\\x64\\Debug\\gdxBullet.dll";
private static boolean initialized = false;
public static boolean shadows = true;
public static void init () {
if (initialized) return;
// Need to initialize bullet before using it.
if (Gdx.app.getType() == ApplicationType.Desktop && customDesktopLib != null) {
System.load(customDesktopLib);
System.out.println("customDesktopLib loaded");// 没有执行这个if
} else{
Bullet.init();
System.out.println("Bullet initialised");// 执行的是这个else
}
Gdx.app.log("Bullet", "Version = " + LinearMath.btGetVersion());
initialized = true;
}
public Environment environment;
public DirectionalLight light;
public ModelBatch shadowBatch;
public BulletWorld world;
public ObjLoader objLoader = new ObjLoader();
public ModelBuilder modelBuilder = new ModelBuilder();
public ModelBatch modelBatch;
public Array<Disposable> disposables = new Array<Disposable>();
private int debugMode = DebugDrawModes.DBG_NoDebug;
protected final static Vector3 tmpV1 = new Vector3(), tmpV2 = new Vector3();
public BulletWorld createWorld () {
return new BulletWorld();
}
@Override
public void create () {
init();
environment = new Environment();
environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.3f, 0.3f, 0.3f, 1.f));
light = shadows ? new DirectionalShadowLight(1024, 1024, 20f, 20f, 1f, 300f) : new DirectionalLight();
light.set(0.8f, 0.8f, 0.8f, -0.5f, -1f, 0.7f);
environment.add(light);
if (shadows)
environment.shadowMap = (DirectionalShadowLight)light;
shadowBatch = new ModelBatch(new DepthShaderProvider());
modelBatch = new ModelBatch();
world = createWorld();
world.performanceCounter = performanceCounter;
final float width = Gdx.graphics.getWidth();
final float height = Gdx.graphics.getHeight();
if (width > height)
camera = new PerspectiveCamera(67f, 3f * width / height, 3f);
else
camera = new PerspectiveCamera(67f, 3f, 3f * height / width);
camera.position.set(10f, 10f, 10f);
camera.lookAt(0, 0, 0);
camera.update();
// Create some simple models
final Model groundModel = modelBuilder.createRect(
20f,
0f,
-20f,
-20f,
0f,
-20f,
-20f,
0f,
20f,
20f,
0f,
20f,
0,
1,
0,
new Material(ColorAttribute.createDiffuse(Color.WHITE), ColorAttribute.createSpecular(Color.WHITE), FloatAttribute
.createShininess(16f)), Usage.Position | Usage.Normal);
disposables.add(groundModel);
final Model boxModel = modelBuilder.createBox(1f, 1f, 1f, new Material(ColorAttribute.createDiffuse(Color.WHITE),
ColorAttribute.createSpecular(Color.WHITE), FloatAttribute.createShininess(64f)), Usage.Position | Usage.Normal);
disposables.add(boxModel);
// Add the constructors
world.addConstructor("ground", new BulletConstructor(groundModel, 0f)); // mass = 0: static body
world.addConstructor("box", new BulletConstructor(boxModel, 1f)); // mass = 1kg: dynamic body
world.addConstructor("staticbox", new BulletConstructor(boxModel, 0f)); // mass = 0: static body
}
@Override
public void dispose () {
world.dispose();
world = null;
for (Disposable disposable : disposables)
disposable.dispose();
disposables.clear();
modelBatch.dispose();
modelBatch = null;
shadowBatch.dispose();
shadowBatch = null;
if (shadows)
((DirectionalShadowLight)light).dispose();
light = null;
super.dispose();
}
@Override
public void render () {
render(true);
}
public void render (boolean update) {
fpsCounter.put(Gdx.graphics.getFramesPerSecond());
if (update) update();
beginRender(true);
renderWorld();
Gdx.gl.glDisable(GL20.GL_DEPTH_TEST);
if (debugMode != DebugDrawModes.DBG_NoDebug) world.setDebugMode(debugMode);
Gdx.gl.glEnable(GL20.GL_DEPTH_TEST);
performance.setLength(0);
performance.append("FPS: ").append(fpsCounter.value).append(", Bullet: ")
.append((int)(performanceCounter.load.value * 100f)).append("%");
}
protected void beginRender (boolean lighting) {
Gdx.gl.glViewport(0, 0, Gdx.graphics.getBackBufferWidth(), Gdx.graphics.getBackBufferHeight());
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
camera.update();
}
protected void renderWorld () {
if (shadows) {
((DirectionalShadowLight)light).begin(Vector3.Zero, camera.direction);
shadowBatch.begin(((DirectionalShadowLight)light).getCamera());
world.render(shadowBatch, null);
shadowBatch.end();
((DirectionalShadowLight)light).end();
}
modelBatch.begin(camera);
world.render(modelBatch, environment);
modelBatch.end();
}
public void update () {
world.update();
}
public BulletEntity shoot (final float x, final float y) {
return shoot(x, y, 30f);
}
public BulletEntity shoot (final float x, final float y, final float impulse) {
return shoot("box", x, y, impulse);
}
public BulletEntity shoot (final String what, final float x, final float y, final float impulse) {
// Shoot a box
Ray ray = camera.getPickRay(x, y);
BulletEntity entity = world.add(what, ray.origin.x, ray.origin.y, ray.origin.z);
entity.setColor(0.5f + 0.5f * (float)Math.random(), 0.5f + 0.5f * (float)Math.random(), 0.5f + 0.5f * (float)Math.random(),
1f);
((btRigidBody)entity.body).applyCentralImpulse(ray.direction.scl(impulse));
return entity;
}
public void setDebugMode (final int mode) {
world.setDebugMode(debugMode = mode);
}
public void toggleDebugMode () {
if (world.getDebugMode() == DebugDrawModes.DBG_NoDebug)
setDebugMode(DebugDrawModes.DBG_DrawWireframe | DebugDrawModes.DBG_DrawFeaturesText | DebugDrawModes.DBG_DrawText | DebugDrawModes.DBG_DrawContactPoints);
else if (world.renderMeshes)
world.renderMeshes = false;
else {
world.renderMeshes = true;
setDebugMode(DebugDrawModes.DBG_NoDebug);
}
}
@Override
public boolean longPress (float x, float y) {
toggleDebugMode();
return true;
}
@Override
public boolean keyUp (int keycode) {
if (keycode == Keys.ENTER) {
toggleDebugMode();
return true;
}
return super.keyUp(keycode);
}
}