Inaccurate Collisions when using Bullet.obtainStaticNodeShape()
See original GitHub issueOk, so I’ve recently been trying to create collision shapes using models that I’ve exported from Blender. I am using the Bullet Physics engine and libGDX 1.9.2. Whenever I run this test with a collision shape that is created as a btBoxShape, everything works as it should. Whenever I use the Bullet.obtainStaticNodeShape() with the nodes of my model, which is a cube, I can see that the shape is generated properly through the Debug Drawer. The physics of the object only seem to work in a small area located in the center of the shape, everywhere else, objects simply fall through. The model is Blender’s default cube with a scale of 24 on the X and Y axes, and a scale of 0.3 on the Z axis. I export as a fbx with a scale of .01 and -Z being Forward and Y Being Up in the export settings. I then use fbx-conv to generate a .g3db file.
Here is the class for the simple test that I’ve created that shows the issue.
package com.imackshun.tests.customcollisionshape;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.g3d.Model;
import com.badlogic.gdx.graphics.g3d.loader.G3dModelLoader;
import com.badlogic.gdx.graphics.g3d.utils.CameraInputController;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.physics.bullet.Bullet;
import com.badlogic.gdx.physics.bullet.DebugDrawer;
import com.badlogic.gdx.physics.bullet.collision.btBoxShape;
import com.badlogic.gdx.physics.bullet.collision.btBroadphaseInterface;
import com.badlogic.gdx.physics.bullet.collision.btCollisionConfiguration;
import com.badlogic.gdx.physics.bullet.collision.btCollisionDispatcher;
import com.badlogic.gdx.physics.bullet.collision.btCollisionObject;
import com.badlogic.gdx.physics.bullet.collision.btCollisionShape;
import com.badlogic.gdx.physics.bullet.collision.btDbvtBroadphase;
import com.badlogic.gdx.physics.bullet.collision.btDefaultCollisionConfiguration;
import com.badlogic.gdx.physics.bullet.collision.btDispatcher;
import com.badlogic.gdx.physics.bullet.dynamics.btConstraintSolver;
import com.badlogic.gdx.physics.bullet.dynamics.btDiscreteDynamicsWorld;
import com.badlogic.gdx.physics.bullet.dynamics.btDynamicsWorld;
import com.badlogic.gdx.physics.bullet.dynamics.btSequentialImpulseConstraintSolver;
import com.badlogic.gdx.physics.bullet.linearmath.btIDebugDraw;
import com.badlogic.gdx.utils.UBJsonReader;
public class CustomCollisionShape extends ApplicationAdapter {
public PerspectiveCamera cam;
// For the ground collision... The player shouldn't fall through the ground.
private btCollisionShape groundShape;
private btCollisionObject groundCollision;
private Model collisionModel;
//Objects to fall
private btCollisionShape boxShape;
private Object boxCollision1;
private Object boxCollision2;
private Object boxCollision3;
private Object boxCollision4;
private Object boxCollision5;
// Used for collisions.
private btCollisionConfiguration collisionConfig;
private btDispatcher dispatcher;
private btBroadphaseInterface broadphase;
private btDynamicsWorld dynamicsWorld;
private btConstraintSolver constraintSolver;
private DebugDrawer debugDrawer;
//For controlling the camera.
public CameraInputController camController;
@Override
public void create() {
//Initialize the camera...
cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
cam.position.set(0f, 25f, 30f);
cam.lookAt(0, 0, 0);
cam.near = 1f;
cam.far = 300f;
cam.update();
//Camera controller.
camController = new CameraInputController(cam);
Gdx.input.setInputProcessor(camController);
// Initialize the physics engine!
Bullet.init();
//Physics Stuff
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, -30f, 0));
debugDrawer = new DebugDrawer();
debugDrawer.setDebugMode(btIDebugDraw.DebugDrawModes.DBG_MAX_DEBUG_DRAW_MODE);
dynamicsWorld.setDebugDrawer(debugDrawer);
//Load the model.
UBJsonReader jsonReader = new UBJsonReader();
G3dModelLoader modelLoader = new G3dModelLoader(jsonReader);
//collisionModel = modelLoader.loadModel(Gdx.files.internal("ArenaCollisionCube.g3db"));
//This works just fine.
groundShape = new btBoxShape(new Vector3(20f, 1f, 20f));
//This is inaccurate everywhere but the center.
//groundShape = Bullet.obtainStaticNodeShape(collisionModel.nodes);
groundCollision = new btCollisionObject();
groundCollision.setCollisionShape(groundShape);
groundCollision.setUserValue(0);
groundCollision.setCollisionFlags(groundCollision.getCollisionFlags() | btCollisionObject.CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
dynamicsWorld.addCollisionObject(groundCollision);
//Boxes
boxShape = new btBoxShape(new Vector3(2f, 2f, 2f));
// Initialize the Rigidbodies.
boxCollision1 = new Object(new Vector3(0f, 10f, 0f), boxShape, dynamicsWorld, 1);
boxCollision2 = new Object(new Vector3(-18f, 10f, 0f), boxShape, dynamicsWorld, 2);
boxCollision3 = new Object(new Vector3(18f, 10f, 0f), boxShape, dynamicsWorld, 3);
boxCollision4 = new Object(new Vector3(0f, 10f, -18f), boxShape, dynamicsWorld, 4);
boxCollision5 = new Object(new Vector3(0f, 10f, 18f), boxShape, dynamicsWorld, 5);
}
@Override
public void render() {
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
//Update the camera controller!
camController.update();
// Update the physics engine!
final float delta2 = Math.min(1f / 30f, Gdx.graphics.getDeltaTime());
dynamicsWorld.stepSimulation(delta2, 5, 1f / 60f);
// Physics debugging.
debugDrawer.begin(cam);
dynamicsWorld.debugDrawWorld();
debugDrawer.end();
}
}
Here is the Object.class file. Just to make it easier to create the rigidbodies.
package com.imackshun.tests.customcollisionshape;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.physics.bullet.collision.btCollisionObject;
import com.badlogic.gdx.physics.bullet.collision.btCollisionShape;
import com.badlogic.gdx.physics.bullet.dynamics.btDynamicsWorld;
import com.badlogic.gdx.physics.bullet.dynamics.btRigidBody;
public class Object {
private float Mass;
// The actual collision objects...
public btRigidBody rbody;
// Used to construct a rigidbody.
public btRigidBody.btRigidBodyConstructionInfo constructionInfo;
// Uh...Hmmm. IDK lol? Takes in mass... Like...Resistance?
private static Vector3 localInertia = new Vector3();
// Constructor
public Object(Vector3 Position, btCollisionShape CollisionShape, btDynamicsWorld dynamicsWorld, int userValue) {
Mass = 10;
if (Mass > 0f) {
CollisionShape.calculateLocalInertia(Mass, localInertia);
} else {
localInertia.set(0, 0, 0);
}
this.constructionInfo = new btRigidBody.btRigidBodyConstructionInfo(Mass, null, CollisionShape, localInertia);
constructionInfo.setFriction(10f);
rbody = new btRigidBody(constructionInfo);
rbody.setCollisionShape(CollisionShape);
rbody.setLinearFactor(new Vector3(1f, 1f, 0f));
rbody.setUserValue(userValue);
// Determines how this object ineracts with other objects.
rbody.setCollisionFlags(rbody.getCollisionFlags() | btCollisionObject.CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
// Add the collision objects to za warudo.
rbody.translate(new Vector3(Position.x, Position.y, Position.z));
dynamicsWorld.addRigidBody(rbody);
}
}
Here is a link to the exact model that I am using.
https://www.dropbox.com/s/696dk3gk2etge4t/ArenaCollisionCube.blend?dl=0
Issue Analytics
- State:
- Created 6 years ago
- Comments:10
Top GitHub Comments
I had a similar issue:
btCollisionShape mapShape = new btBvhTriangleMeshShape(model.meshParts);
the mesh did collide, but it was too small and weirdly rotatedbtCollisionShape mapShape = Bullet.obtainStaticNodeShape(model.nodes);
the collision mesh looked right in debug draw, but the player fell throughRemoving transforms and setting object scales in edit mode didn’t work for me. According to the following discussion: https://pybullet.org/Bullet/phpBB3/viewtopic.php?t=10104 there is a problem with too big polygons not being properly used by bullet. We solved the problem by applying a SubdivisionSurface modifier in Blender (simple mode) in order to get smaller polys.
To solve this problem you should
In addition, you can export your object via .obj and then convert it via https://asneakyfox.github.io/libgdx-fbxconv-gui/ . There’re no problems with Scaling.