i'm encountering a strange problem.
The boxes in the example get sucked into the Bhv mesh.
I dont know how to explain it.
You may try it out. THe terrain is in the attachment.
Press L for debug mode.
- Code: Select all
public class Demolation extends Game {
SpriteBatch batch;
BitmapFont font;
public void create() {
batch = new SpriteBatch();
font = new BitmapFont();
this.setScreen(new MainMenuScreen(this));
}
public void render() {
super.render();
}
public void dispose() {
batch.dispose();
font.dispose();
}
}
- Code: Select all
public class MainMenuScreen implements Screen {
final Demolation game;
OrthographicCamera camera;
public MainMenuScreen(final Demolation demolation) {
game = demolation;
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
game.batch.setProjectionMatrix(camera.combined);
game.font.setScale(2f);
game.batch.begin();
game.font.draw(game.batch, "Welcome", 100, 150);
game.font.draw(game.batch, "Tap anywhere to begin!", 100, 100);
game.batch.end();
if (Gdx.input.isTouched()) {
game.setScreen(new Phys(game));
dispose();
}
}
@Override
public void resize(int width, int height) {
}
@Override
public void show() {
}
@Override
public void hide() {
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void dispose() {
}
}
- Code: Select all
public class Phys implements Screen {
Demolation game;
final static short GROUND_FLAG = 1 << 8;
final static short OBJECT_FLAG = 1 << 9;
final static short ALL_FLAG = -1;
PerspectiveCamera cam;
CameraInputController camController;
ModelBatch modelBatch;
Environment environment;
Model model, model2, rad, rahmen;
Array<GameObject> instances;
ArrayMap<String, GameObject.Constructor> constructors;
float spawnTimer;
btCollisionConfiguration collisionConfig;
btDispatcher dispatcher;
MyContactListener contactListener;
btBroadphaseInterface broadphase;
btDynamicsWorld dynamicsWorld;
btConstraintSolver constraintSolver;
PointLight plight;
DirectionalLight light;
int visibleCount;
protected Stage stage;
protected Label label;
protected BitmapFont font;
protected StringBuilder stringBuilder;
Vector3 position;
AssetManager assets;
boolean loading;
DebugDrawer debugDrawer;
boolean debug = false;
public Phys(Demolation gam) {
this.game = gam;
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
position = new Vector3();
stage = new Stage();
font = new BitmapFont();
label = new Label(" ", new Label.LabelStyle(font, Color.WHITE));
stage.addActor(label);
stringBuilder = new StringBuilder();
Bullet.init();
modelBatch = new ModelBatch();
environment = new Environment();
environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.1f, 0.1f, 0.1f, 1f));
light = new DirectionalLight();
light.set(Color.WHITE, -90, -90, 90);
environment.add(light);
plight = new PointLight();
plight.set(Color.RED, -5f, 5f, -3f, 15f);
environment.add(plight);
cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
cam.position.set(3f, 60f, 10f);
cam.lookAt(0, 40f, 0);
cam.near = 1f;
cam.far = 300f;
cam.update();
camController = new CameraInputController(cam);
Gdx.input.setInputProcessor(camController);
ModelBuilder mb = new ModelBuilder();
mb.begin();
mb.node().id = "ground";
mb.part("ground", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal,
new Material(ColorAttribute.createDiffuse(Color.PINK))).box(50f,
1f, 50f);
mb.node().id = "sphere";
mb.part("sphere", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal,
new Material(ColorAttribute.createDiffuse(Color.GREEN)))
.sphere(6f, 6f, 6f, 10, 10);
mb.node().id = "box";
mb.part("box", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal,
new Material(ColorAttribute.createDiffuse(Color.BLUE))).box(2f,
2f, 2f);
model = mb.end();
constructors = new ArrayMap<String, GameObject.Constructor>(
String.class, GameObject.Constructor.class);
constructors.put("ground", new GameObject.Constructor(model, "ground",
new btBoxShape(new Vector3(25f, 0.5f, 25f)), 0f));
constructors.put("sphere", new GameObject.Constructor(model, "sphere",
new btSphereShape(3f), 100f));
constructors.put("box", new GameObject.Constructor(model, "box",
new btBoxShape(new Vector3(1f, 1f, 1f)), 1f));
assets = new AssetManager();
assets.load("model/test.g3db", Model.class);
while (!assets.update()) {}
collisionConfig = new btDefaultCollisionConfiguration();
dispatcher = new btCollisionDispatcher(collisionConfig);
broadphase = new btDbvtBroadphase();
constraintSolver = new btSequentialImpulseConstraintSolver();
dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, constraintSolver, collisionConfig);
dynamicsWorld.setGravity(new Vector3(0, -10f, 0));
contactListener = new MyContactListener();
instances = new Array<GameObject>();
terrain();
debugDrawer = new DebugDrawer();
debugDrawer.setDebugMode(btIDebugDraw.DebugDrawModes.DBG_MAX_DEBUG_DRAW_MODE);
dynamicsWorld.setDebugDrawer(debugDrawer);
// GameObject object = constructors.get("ground").construct();
// object.body.setCollisionFlags(object.body.getCollisionFlags() | btCollisionObject.CollisionFlags.CF_KINEMATIC_OBJECT);
// instances.add(object);
// dynamicsWorld.addRigidBody(object.body);
// object.body.setContactCallbackFlag(GROUND_FLAG);
// object.body.setContactCallbackFilter(0);
// object.body.setActivationState(Collision.DISABLE_DEACTIVATION);
}
btBvhTriangleMeshShape terrainbhv;
Model terrain;
GameObject terrainGO;
private void terrain() {
terrain = assets.get("model/test.g3db", Model.class);
terrain.meshes.first().scale(97f, 97f, 97f);
String terrainStr = terrain.nodes.first().id;
terrainbhv = (btBvhTriangleMeshShape) Bullet.obtainStaticNodeShape(terrain.nodes);
terrainbhv.setMargin(0.2f);
constructors.put(terrainStr, new GameObject.Constructor(terrain, terrainStr,terrainbhv, 0.0f));
terrainGO = constructors.get(terrainStr).construct();
terrainGO.transform.setFromEulerAngles(0,0,0);
terrainGO.transform.trn(-210,0,-210);
terrainGO.body.proceedToTransform(terrainGO.transform);
terrainGO.body.setUserValue(instances.size);
terrainGO.body.setCollisionFlags(terrainGO.body.getCollisionFlags()
| btCollisionObject.CollisionFlags.CF_KINEMATIC_OBJECT);
terrainGO.body.setContactCallbackFlag(GROUND_FLAG);
terrainGO.body.setContactCallbackFilter(0);
terrainGO.body.setActivationState(Collision.DISABLE_DEACTIVATION);
dynamicsWorld.addRigidBody(terrainGO.body);
instances.add(terrainGO);
}
public void spawn() {
GameObject obj = constructors.values[1 + MathUtils.random(constructors.size - 3)].construct();
obj.transform.setFromEulerAngles(MathUtils.random(360f),MathUtils.random(360f), MathUtils.random(360f));
obj.transform.trn(-1.2f, 50f,2.6f);
obj.body.proceedToTransform(obj.transform);
obj.body.setUserValue(instances.size);
obj.body.setCollisionFlags(obj.body.getCollisionFlags() | btCollisionObject.CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
instances.add(obj);
dynamicsWorld.addRigidBody(obj.body);
obj.body.setContactCallbackFlag(OBJECT_FLAG);
obj.body.setContactCallbackFilter(GROUND_FLAG);
}
protected boolean isVisible(Camera cam1, GameObject instance) {
instance.transform.getTranslation(position);
position.add(instance.center);
return cam1.frustum.sphereInFrustum(position, instance.radius);
}
float angle, speed = 90f;
@Override
public void render(float delta) {
//if (loading && assets.update()) geladen();
final float deltaa = Math.min(1f / 30f, Gdx.graphics.getDeltaTime());
angle = (angle + deltaa * speed) % 360f;
dynamicsWorld.stepSimulation(delta, 10, 1f / 120f);
if ((spawnTimer -= delta) < 0) {
spawn();
spawnTimer = 0.5f;
}
camController.update();
Gdx.gl.glClearColor(0, 0, 0, 1.f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
if (!debug) {
modelBatch.begin(cam);
visibleCount = 0;
for (final GameObject instance : instances) {
if (isVisible(cam, instance)) {
modelBatch.render(instance, environment);
visibleCount++;
}
}
modelBatch.end();
} else {
debugDrawer.begin(cam);
dynamicsWorld.debugDrawWorld();
debugDrawer.end();
}
stringBuilder.setLength(0);
stringBuilder.append(" FPS: ").append(Gdx.graphics.getFramesPerSecond());
stringBuilder.append(" Visible: ").append(visibleCount);
label.setText(stringBuilder);
stage.draw();
if (Gdx.input.isKeyJustPressed(Keys.L)) {
debug = !debug;
}
}
@Override
public void dispose() {
debugDrawer.dispose();
for (GameObject obj : instances)
obj.dispose();
instances.clear();
for (GameObject.Constructor ctor : constructors.values())
ctor.dispose();
constructors.clear();
dynamicsWorld.dispose();
constraintSolver.dispose();
broadphase.dispose();
dispatcher.dispose();
collisionConfig.dispose();
contactListener.dispose();
modelBatch.dispose();
model.dispose();
assets.dispose();
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void resize(int width, int height) {
stage.getViewport().update(width, height, true);
}
@Override
public void show() {
}
@Override
public void hide() {
}
class MyContactListener extends ContactListener {
@Override
public boolean onContactAdded(int userValue0, int partId0, int index0,
boolean match0, int userValue1, int partId1, int index1,
boolean match1) {
// if (match0)
// ((ColorAttribute) instances.get(userValue0).materials.get(0)
// .get(ColorAttribute.Diffuse)).color.set(Color.WHITE);
// if (match1)
// ((ColorAttribute) instances.get(userValue1).materials.get(0)
// .get(ColorAttribute.Diffuse)).color.set(Color.WHITE);
return true;
}
}
static class MyMotionState extends btMotionState {
Matrix4 transform;
@Override
public void getWorldTransform(Matrix4 worldTrans) {
worldTrans.set(transform);
}
@Override
public void setWorldTransform(Matrix4 worldTrans) {
transform.set(worldTrans);
}
}
static class GameObject extends ModelInstance implements Disposable {
public Vector3 center = new Vector3();
public Vector3 dimensions = new Vector3();
public float radius;
private BoundingBox bounds = new BoundingBox();
public final btRigidBody body;
public final MyMotionState motionState;
public GameObject(Model model1, String node, btRigidBody.btRigidBodyConstructionInfo constructionInfo) {
super(model1, node);
calculateBoundingBox(bounds);
center.set(bounds.getCenter());
dimensions.set(bounds.getDimensions());
radius = dimensions.len() / 2f;
motionState = new MyMotionState();
motionState.transform = transform;
body = new btRigidBody(constructionInfo);
body.setMotionState(motionState);
}
@Override
public void dispose() {
body.dispose();
motionState.dispose();
}
static class Constructor implements Disposable {
public final Model model;
public final String node;
public final btCollisionShape shape;
public final btRigidBody.btRigidBodyConstructionInfo constructionInfo;
private static Vector3 localInertia = new Vector3();
public Constructor(Model model, String node, btCollisionShape shape, float mass) {
this.model = model;
this.node = node;
this.shape = shape;
if (mass > 0f)
shape.calculateLocalInertia(mass, localInertia);
else
localInertia.set(0, 0, 0);
this.constructionInfo = new btRigidBody.btRigidBodyConstructionInfo(
mass, null, shape, localInertia);
}
public GameObject construct() {
return new GameObject(model, node, constructionInfo);
}
@Override
public void dispose() {
shape.dispose();
constructionInfo.dispose();
}
}
}
}
The g3db terrain file :
It looks like a fundamental bug.
How have you solved this problem ?
