1 /******************************************************************************* 2 * Copyright 2011 See AUTHORS file. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 ******************************************************************************/ 16 17 package com.badlogic.gdx.tests.bullet; 18 19 import com.badlogic.gdx.Gdx; 20 import com.badlogic.gdx.graphics.Color; 21 import com.badlogic.gdx.graphics.Mesh; 22 import com.badlogic.gdx.graphics.g3d.Model; 23 import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute; 24 import com.badlogic.gdx.graphics.glutils.ShapeRenderer; 25 import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType; 26 import com.badlogic.gdx.math.Vector3; 27 import com.badlogic.gdx.physics.bullet.collision.Collision; 28 import com.badlogic.gdx.physics.bullet.collision.btCollisionDispatcher; 29 import com.badlogic.gdx.physics.bullet.collision.btCollisionObject; 30 import com.badlogic.gdx.physics.bullet.collision.btCollisionObjectWrapper; 31 import com.badlogic.gdx.physics.bullet.collision.btCollisionWorld; 32 import com.badlogic.gdx.physics.bullet.collision.ContactResultCallback; 33 import com.badlogic.gdx.physics.bullet.collision.btConvexHullShape; 34 import com.badlogic.gdx.physics.bullet.collision.btDbvtBroadphase; 35 import com.badlogic.gdx.physics.bullet.collision.btDefaultCollisionConfiguration; 36 import com.badlogic.gdx.physics.bullet.collision.btManifoldPoint; 37 import com.badlogic.gdx.physics.bullet.collision.btShapeHull; 38 import com.badlogic.gdx.physics.bullet.linearmath.btVector3; 39 40 /** @author xoppa, didum */ 41 public class ConvexHullDistanceTest extends BaseBulletTest { 42 private ConvexHullDistance distance; 43 private ShapeRenderer shapeRenderer; 44 45 @Override create()46 public void create () { 47 super.create(); 48 49 final Model carModel = objLoader.loadModel(Gdx.files.internal("data/car.obj")); 50 disposables.add(carModel); 51 carModel.materials.get(0).clear(); 52 carModel.materials.get(0).set(ColorAttribute.createDiffuse(Color.WHITE), ColorAttribute.createSpecular(Color.WHITE)); 53 world.addConstructor("car", new BulletConstructor(carModel, 5f, createConvexHullShape(carModel, true))); 54 55 // Create the entities 56 world.add("ground", 0f, 0f, 0f).setColor(0.25f + 0.5f * (float)Math.random(), 0.25f + 0.5f * (float)Math.random(), 57 0.25f + 0.5f * (float)Math.random(), 1f); 58 59 for (float y = 10f; y < 50f; y += 5f) 60 world.add("car", -2f + (float)Math.random() * 4f, y, -2f + (float)Math.random() * 4f).setColor( 61 0.25f + 0.5f * (float)Math.random(), 0.25f + 0.5f * (float)Math.random(), 0.25f + 0.5f * (float)Math.random(), 1f); 62 distance = new ConvexHullDistance(); 63 shapeRenderer = new ShapeRenderer(); 64 } 65 66 @Override tap(float x, float y, int count, int button)67 public boolean tap (float x, float y, int count, int button) { 68 shoot(x, y); 69 return true; 70 } 71 72 @Override render()73 public void render () { 74 super.render(); 75 76 // Draw the lines of the distances 77 78 camera.update(); 79 shapeRenderer.setProjectionMatrix(camera.combined); 80 shapeRenderer.begin(ShapeType.Line); 81 shapeRenderer.setColor(1, 1, 0, 1); 82 83 for (int i = 0; i < world.entities.size; i++) { 84 btCollisionObject collisionObject0 = world.entities.get(i).body; 85 86 for (int j = 0; j < world.entities.size; j++) { 87 88 if (i != j) { 89 btCollisionObject collisionObject1 = world.entities.get(j).body; 90 distance.calculateDistance(collisionObject0, collisionObject1); 91 shapeRenderer.line(distance.getVector3()[0], distance.getVector3()[1]); 92 } 93 } 94 } 95 96 shapeRenderer.end(); 97 } 98 createConvexHullShape(final Model model, boolean optimize)99 public static btConvexHullShape createConvexHullShape (final Model model, boolean optimize) { 100 final Mesh mesh = model.meshes.get(0); 101 final btConvexHullShape shape = new btConvexHullShape(mesh.getVerticesBuffer(), mesh.getNumVertices(), mesh.getVertexSize()); 102 if (!optimize) return shape; 103 // now optimize the shape 104 final btShapeHull hull = new btShapeHull(shape); 105 hull.buildHull(shape.getMargin()); 106 final btConvexHullShape result = new btConvexHullShape(hull); 107 // delete the temporary shape 108 shape.dispose(); 109 hull.dispose(); 110 return result; 111 } 112 113 private class ConvexHullDistance { 114 private btDefaultCollisionConfiguration collisionConfiguration; 115 private btCollisionDispatcher dispatcher; 116 private btDbvtBroadphase pairCache; 117 private btCollisionWorld collisionWorld; 118 Vector3[] vectors = new Vector3[]{new Vector3(), new Vector3()}; 119 ConvexHullDistance()120 public ConvexHullDistance () { 121 collisionConfiguration = new btDefaultCollisionConfiguration(); 122 dispatcher = new btCollisionDispatcher(collisionConfiguration); 123 pairCache = new btDbvtBroadphase(); 124 collisionWorld = new btCollisionWorld(dispatcher, pairCache, collisionConfiguration); 125 } 126 getVector3()127 public Vector3[] getVector3 () { 128 return vectors; 129 } 130 calculateDistance(btCollisionObject colObjA, btCollisionObject colObjB)131 public void calculateDistance (btCollisionObject colObjA, btCollisionObject colObjB) { 132 DistanceInternalResultCallback result = new DistanceInternalResultCallback(); 133 134 Collision.setGContactBreakingThreshold(100f); 135 collisionWorld.contactPairTest(colObjA, colObjB, result); 136 Collision.setGContactBreakingThreshold(0.02f); 137 } 138 139 private class DistanceInternalResultCallback extends ContactResultCallback { DistanceInternalResultCallback()140 public DistanceInternalResultCallback () { 141 142 } 143 144 @Override addSingleResult(btManifoldPoint cp, btCollisionObjectWrapper colObj0Wrap, int partId0, int index0, btCollisionObjectWrapper colObj1Wrap, int partId1, int index1)145 public float addSingleResult (btManifoldPoint cp, btCollisionObjectWrapper colObj0Wrap, int partId0, int index0, 146 btCollisionObjectWrapper colObj1Wrap, int partId1, int index1) { 147 148 cp.getPositionWorldOnA(vectors[0]); 149 cp.getPositionWorldOnB(vectors[1]); 150 151 return 1.f; 152 } 153 } 154 } 155 } 156