libgdx crash example
Single file example to reproduce android crash.
See https://github.com/libgdx/libgdx/issues/2083
C1.java
—
Java source code,
6 kB (7127 bytes)
File contents
package com.dahetral.C1; import com.badlogic.gdx.ApplicationListener; import com.badlogic.gdx.Gdx; 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.*; import com.badlogic.gdx.graphics.g3d.attributes.BlendingAttribute; import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute; import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight; import com.badlogic.gdx.graphics.g3d.utils.CameraInputController; import com.badlogic.gdx.graphics.g3d.utils.MeshPartBuilder; import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.physics.bullet.Bullet; import com.badlogic.gdx.physics.bullet.collision.*; import com.badlogic.gdx.physics.bullet.dynamics.btRigidBody; import com.badlogic.gdx.utils.Disposable; /* Simple bouncing ball inside a translucent sphere, elastic collsions and no external forces (gravity) based on http://blog.xoppa.com/using-the-libgdx-3d-physics-bullet-wrapper-part1 */ public class C1 implements ApplicationListener { final static short GROUND_FLAG = 1<<8; final static short OBJECT_FLAG = 1<<9; final static short ALL_FLAG = -1; class MyContactListener extends ContactListener { @Override public boolean onContactAdded (btManifoldPoint p, btCollisionObject colObj0, int partId0, int index0, btCollisionObject colObj1, int partId1, int index1) { // *** crashes on android, see issue 2083 *** float vec[] = p.getNormalWorldOnB().getFloats(); // float vec[] = new float[] {0, 1f, 0}; // works Vector3 bN = new Vector3(vec); mMove.trn(bN); return true; } } PerspectiveCamera cam; CameraInputController camController; ModelBatch modelBatch; Environment environment; btCollisionConfiguration collisionConfig; btDispatcher dispatcher; MyContactListener contactListener; btBroadphaseInterface broadphase; btCollisionWorld collisionWorld; @Override public void create () { Bullet.init(); modelBatch = new ModelBatch(); environment = new Environment(); environment.set( new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f)); environment.add( new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f)); cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); cam.position.set(3f, 7f, 10f); cam.lookAt(0, 0f, 0); cam.near = 1f; cam.far = 300f; cam.update(); camController = new CameraInputController(cam); Gdx.input.setInputProcessor(camController); collisionConfig = new btDefaultCollisionConfiguration(); dispatcher = new btCollisionDispatcher(collisionConfig); broadphase = new btDbvtBroadphase(); collisionWorld = new btCollisionWorld(dispatcher, broadphase, collisionConfig); contactListener = new MyContactListener(); createMove(); createDome(); } ModelBuilder mb = new ModelBuilder(); RigidObjectX mMove; private void createMove() { mb.begin(); mb.node().id = "move1"; mb.part("sphere", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.RED))) .sphere(1f, 1f, 1f, 16, 16); Model m = mb.end(); btCollisionShape b = new btSphereShape(0.5f); mMove = new RigidObjectX(m, "move1", b, 1f); mMove.translate(0f, 0f, 0f); // place object mMove.setVelocity(0f, -.1f, 0f, .1f); // set velocity vector mMove.body.setCollisionFlags(mMove.body.getCollisionFlags() | btCollisionObject.CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK); collisionWorld.addCollisionObject(mMove.body, OBJECT_FLAG, GROUND_FLAG); } RigidObjectX mDome; private void createDome() { mb.begin(); mb.node().id = "Dome"; Material mat = new Material(); mat.set(new ColorAttribute(ColorAttribute.Diffuse, Color.WHITE)); mat.set(new BlendingAttribute(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, .3f)); MeshPartBuilder mpb = mb.part("dome", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, mat); mpb.sphere(10f, 10f, 10f, 32, 32); Model m = mb.end(); btCollisionShape b = Bullet.obtainStaticNodeShape(m.nodes); mDome = new RigidObjectX(m, "Dome", b, 0f); collisionWorld.addCollisionObject(mDome.body, GROUND_FLAG, ALL_FLAG); } @Override public void render () { mMove.trn(); collisionWorld.performDiscreteCollisionDetection(); camController.update(); Gdx.gl.glClearColor(0.2f, 0.2f, 0.2f, 1.f); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT); modelBatch.begin(cam); modelBatch.render(mMove, environment); modelBatch.render(mDome, environment); modelBatch.end(); } @Override public void dispose () { mMove.dispose(); mDome.dispose(); collisionWorld.dispose(); broadphase.dispose(); dispatcher.dispose(); collisionConfig.dispose(); contactListener.dispose(); modelBatch.dispose(); } @Override public void pause () { } @Override public void resume () { } @Override public void resize (int width, int height) { } class RigidObjectX extends ModelInstance implements Disposable { public final btRigidBody body; public Vector3 localI = new Vector3(); public float velocityscale = .1f; public Vector3 velocity = new Vector3(); public RigidObjectX(Model model, String node, btCollisionShape shape, float mass) { super(model, node); if (mass > 0f) shape.calculateLocalInertia(mass, localI); else localI.set(0, 0, 0); body = new btRigidBody( new btRigidBody.btRigidBodyConstructionInfo(mass, null, shape, localI) ); } public void setVelocity(float x, float y, float z, float scale) { velocity.set(x, y, z); velocityscale = scale; } // translate object based on velocity and update collision location public void trn() { this.transform.trn(velocity); this.body.setWorldTransform(this.transform); } // reposition object and update collision location public void translate(float x, float y, float z) { this.transform.translate(x, y, z); this.body.setWorldTransform(this.transform); } // update velocity and translate public void trn(Vector3 collisionNormal) { collisionNormal.scl(this.velocityscale); this.velocity.set(collisionNormal); this.trn(); } @Override public void dispose() { body.dispose(); } } }