/******************************************************************************* * Copyright 2011 See AUTHORS file. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.badlogic.gdx.tests.bullet; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.g3d.Environment; import com.badlogic.gdx.graphics.g3d.ModelBatch; import com.badlogic.gdx.math.Matrix4; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.math.WindowedMean; import com.badlogic.gdx.physics.bullet.DebugDrawer; 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.btCollisionWorld; import com.badlogic.gdx.physics.bullet.collision.btDbvtBroadphase; import com.badlogic.gdx.physics.bullet.collision.btDefaultCollisionConfiguration; 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.btRigidBody; import com.badlogic.gdx.physics.bullet.dynamics.btSequentialImpulseConstraintSolver; import com.badlogic.gdx.physics.bullet.linearmath.btIDebugDraw; import com.badlogic.gdx.utils.PerformanceCounter; /** @author xoppa Bullet physics world that holds all bullet entities and constructors. */ public class BulletWorld extends BaseWorld<BulletEntity> { public DebugDrawer debugDrawer = null; public boolean renderMeshes = true; public final btCollisionConfiguration collisionConfiguration; public final btCollisionDispatcher dispatcher; public final btBroadphaseInterface broadphase; public final btConstraintSolver solver; public final btCollisionWorld collisionWorld; public PerformanceCounter performanceCounter; public final Vector3 gravity; public int maxSubSteps = 5; public float fixedTimeStep = 1f / 60f; public BulletWorld (final btCollisionConfiguration collisionConfiguration, final btCollisionDispatcher dispatcher, final btBroadphaseInterface broadphase, final btConstraintSolver solver, final btCollisionWorld world, final Vector3 gravity) { this.collisionConfiguration = collisionConfiguration; this.dispatcher = dispatcher; this.broadphase = broadphase; this.solver = solver; this.collisionWorld = world; if (world instanceof btDynamicsWorld) ((btDynamicsWorld)this.collisionWorld).setGravity(gravity); this.gravity = gravity; } public BulletWorld (final btCollisionConfiguration collisionConfiguration, final btCollisionDispatcher dispatcher, final btBroadphaseInterface broadphase, final btConstraintSolver solver, final btCollisionWorld world) { this(collisionConfiguration, dispatcher, broadphase, solver, world, new Vector3(0, -10, 0)); } public BulletWorld (final Vector3 gravity) { collisionConfiguration = new btDefaultCollisionConfiguration(); dispatcher = new btCollisionDispatcher(collisionConfiguration); broadphase = new btDbvtBroadphase(); solver = new btSequentialImpulseConstraintSolver(); collisionWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration); ((btDynamicsWorld)collisionWorld).setGravity(gravity); this.gravity = gravity; } public BulletWorld () { this(new Vector3(0, -10, 0)); } @Override public void add (final BulletEntity entity) { super.add(entity); if (entity.body != null) { if (entity.body instanceof btRigidBody) ((btDiscreteDynamicsWorld)collisionWorld).addRigidBody((btRigidBody)entity.body); else collisionWorld.addCollisionObject(entity.body); // Store the index of the entity in the collision object. entity.body.setUserValue(entities.size - 1); } } @Override public void update () { if (performanceCounter != null) { performanceCounter.tick(); performanceCounter.start(); } if (collisionWorld instanceof btDynamicsWorld) ((btDynamicsWorld)collisionWorld).stepSimulation(Gdx.graphics.getDeltaTime(), maxSubSteps, fixedTimeStep); if (performanceCounter != null) performanceCounter.stop(); } @Override public void render (ModelBatch batch, Environment lights, Iterable<BulletEntity> entities) { if (renderMeshes) super.render(batch, lights, entities); if (debugDrawer != null && debugDrawer.getDebugMode() > 0) { batch.flush(); debugDrawer.begin(batch.getCamera()); collisionWorld.debugDrawWorld(); debugDrawer.end(); } } @Override public void dispose () { for (int i = 0; i < entities.size; i++) { btCollisionObject body = entities.get(i).body; if (body != null) { if (body instanceof btRigidBody) ((btDynamicsWorld)collisionWorld).removeRigidBody((btRigidBody)body); else collisionWorld.removeCollisionObject(body); } } super.dispose(); collisionWorld.dispose(); if (solver != null) solver.dispose(); if (broadphase != null) broadphase.dispose(); if (dispatcher != null) dispatcher.dispose(); if (collisionConfiguration != null) collisionConfiguration.dispose(); } public void setDebugMode (final int mode) { if (mode == btIDebugDraw.DebugDrawModes.DBG_NoDebug && debugDrawer == null) return; if (debugDrawer == null) collisionWorld.setDebugDrawer(debugDrawer = new DebugDrawer()); debugDrawer.setDebugMode(mode); } public int getDebugMode () { return (debugDrawer == null) ? 0 : debugDrawer.getDebugMode(); } }