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 javax.print.attribute.standard.DateTimeAtCompleted; 20 21 import com.badlogic.gdx.Gdx; 22 import com.badlogic.gdx.graphics.Color; 23 import com.badlogic.gdx.graphics.VertexAttributes.Usage; 24 import com.badlogic.gdx.graphics.g3d.Material; 25 import com.badlogic.gdx.graphics.g3d.Model; 26 import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute; 27 import com.badlogic.gdx.math.Matrix4; 28 import com.badlogic.gdx.math.Vector3; 29 import com.badlogic.gdx.physics.bullet.collision.ContactCache; 30 import com.badlogic.gdx.physics.bullet.collision.ContactListener; 31 import com.badlogic.gdx.physics.bullet.collision.btBvhTriangleMeshShape; 32 import com.badlogic.gdx.physics.bullet.collision.btCollisionObject; 33 import com.badlogic.gdx.physics.bullet.collision.btPersistentManifold; 34 import com.badlogic.gdx.physics.bullet.collision.btSphereShape; 35 import com.badlogic.gdx.tests.bullet.ContactCallbackTest2.TestContactListener; 36 import com.badlogic.gdx.utils.Array; 37 38 public class ContactCacheTest extends BaseBulletTest { 39 public static class TestContactListener extends ContactListener { 40 public Array<BulletEntity> entities; 41 42 @Override onContactStarted(int userValue0, boolean match0, int userValue1, boolean match1)43 public void onContactStarted (int userValue0, boolean match0, int userValue1, boolean match1) { 44 if (match0) { 45 final BulletEntity e = (BulletEntity)(entities.get(userValue0)); 46 e.setColor(Color.RED); 47 Gdx.app.log(Float.toString(time), "Contact started " + userValue0); 48 } 49 if (match1) { 50 final BulletEntity e = (BulletEntity)(entities.get(userValue1)); 51 e.setColor(Color.RED); 52 Gdx.app.log(Float.toString(time), "Contact started " + userValue1); 53 } 54 } 55 56 @Override onContactEnded(int userValue0, boolean match0, int userValue1, boolean match1)57 public void onContactEnded (int userValue0, boolean match0, int userValue1, boolean match1) { 58 if (match0) { 59 final BulletEntity e = (BulletEntity)(entities.get(userValue0)); 60 e.setColor(Color.BLUE); 61 Gdx.app.log(Float.toString(time), "Contact ended " + userValue0); 62 } 63 if (match1) { 64 final BulletEntity e = (BulletEntity)(entities.get(userValue1)); 65 e.setColor(Color.BLUE); 66 Gdx.app.log(Float.toString(time), "Contact ended " + userValue1); 67 } 68 } 69 } 70 71 public static class TestContactCache extends ContactCache { 72 public Array<BulletEntity> entities; 73 74 @Override onContactStarted(btPersistentManifold manifold, boolean match0, boolean match1)75 public void onContactStarted (btPersistentManifold manifold, boolean match0, boolean match1) { 76 final int userValue0 = manifold.getBody0().getUserValue(); 77 final int userValue1 = manifold.getBody1().getUserValue(); 78 if (match0) { 79 final BulletEntity e = (BulletEntity)(entities.get(userValue0)); 80 e.setColor(Color.RED); 81 Gdx.app.log(Float.toString(time), "Contact started " + userValue0); 82 } 83 if (match1) { 84 final BulletEntity e = (BulletEntity)(entities.get(userValue1)); 85 e.setColor(Color.RED); 86 Gdx.app.log(Float.toString(time), "Contact started " + userValue1); 87 } 88 } 89 90 @Override onContactEnded(btCollisionObject colObj0, boolean match0, btCollisionObject colObj1, boolean match1)91 public void onContactEnded (btCollisionObject colObj0, boolean match0, btCollisionObject colObj1, boolean match1) { 92 final int userValue0 = colObj0.getUserValue(); 93 final int userValue1 = colObj1.getUserValue(); 94 if (match0) { 95 final BulletEntity e = (BulletEntity)(entities.get(userValue0)); 96 e.setColor(Color.BLUE); 97 Gdx.app.log(Float.toString(time), "Contact ended " + userValue0); 98 } 99 if (match1) { 100 final BulletEntity e = (BulletEntity)(entities.get(userValue1)); 101 e.setColor(Color.BLUE); 102 Gdx.app.log(Float.toString(time), "Contact ended " + userValue1); 103 } 104 } 105 } 106 107 final int SPHERECOUNT_X = 4; 108 final int SPHERECOUNT_Y = 1; 109 final int SPHERECOUNT_Z = 4; 110 111 final float SPHEREOFFSET_X = -2f; 112 final float SPHEREOFFSET_Y = 10f; 113 final float SPHEREOFFSET_Z = -2f; 114 115 final boolean USE_CONTACT_CACHE = true; 116 117 TestContactListener contactListener; 118 TestContactCache contactCache; 119 public static float time; 120 121 @Override create()122 public void create () { 123 super.create(); 124 125 final Model sphereModel = modelBuilder.createSphere(1f, 1f, 1f, 8, 8, 126 new Material(ColorAttribute.createDiffuse(Color.WHITE), ColorAttribute.createSpecular(Color.WHITE)), Usage.Position 127 | Usage.Normal); 128 disposables.add(sphereModel); 129 final BulletConstructor sphereConstructor = new BulletConstructor(sphereModel, 0.5f, new btSphereShape(0.5f)); 130 sphereConstructor.bodyInfo.setRestitution(1f); 131 world.addConstructor("sphere", sphereConstructor); 132 133 final Model sceneModel = objLoader.loadModel(Gdx.files.internal("data/scene.obj")); 134 disposables.add(sceneModel); 135 final BulletConstructor sceneConstructor = new BulletConstructor(sceneModel, 0f, new btBvhTriangleMeshShape( 136 sceneModel.meshParts)); 137 sceneConstructor.bodyInfo.setRestitution(0.25f); 138 world.addConstructor("scene", sceneConstructor); 139 140 final BulletEntity scene = world.add("scene", (new Matrix4()).setToTranslation(0f, 2f, 0f).rotate(Vector3.Y, -90)); 141 scene.setColor(0.25f + 0.5f * (float)Math.random(), 0.25f + 0.5f * (float)Math.random(), 142 0.25f + 0.5f * (float)Math.random(), 1f); 143 scene.body.setContactCallbackFlag(2); 144 145 world.add("ground", 0f, 0f, 0f).setColor(0.25f + 0.5f * (float)Math.random(), 0.25f + 0.5f * (float)Math.random(), 146 0.25f + 0.5f * (float)Math.random(), 1f); 147 148 for (int x = 0; x < SPHERECOUNT_X; x++) { 149 for (int y = 0; y < SPHERECOUNT_Y; y++) { 150 for (int z = 0; z < SPHERECOUNT_Z; z++) { 151 final BulletEntity e = (BulletEntity)world.add("sphere", SPHEREOFFSET_X + x * 3f, SPHEREOFFSET_Y + y * 3f, 152 SPHEREOFFSET_Z + z * 3f); 153 e.setColor(0.5f + 0.5f * (float)Math.random(), 0.5f + 0.5f * (float)Math.random(), 154 0.5f + 0.5f * (float)Math.random(), 1f); 155 156 e.body.setContactCallbackFilter(2); 157 } 158 } 159 } 160 161 if (USE_CONTACT_CACHE) { 162 contactCache = new TestContactCache(); 163 contactCache.entities = world.entities; 164 contactCache.setCacheTime(0.5f); 165 } else { 166 contactListener = new TestContactListener(); 167 contactListener.entities = world.entities; 168 } 169 time = 0; 170 } 171 172 @Override update()173 public void update () { 174 float delta = Gdx.graphics.getRawDeltaTime(); 175 time += delta; 176 super.update(); 177 if (contactCache != null) contactCache.update(delta); 178 } 179 180 @Override tap(float x, float y, int count, int button)181 public boolean tap (float x, float y, int count, int button) { 182 shoot(x, y); 183 return true; 184 } 185 186 @Override dispose()187 public void dispose () { 188 // Deleting the active contact listener, also disables that particular type of contact listener. 189 if (contactListener != null) contactListener.dispose(); 190 contactListener = null; 191 192 super.dispose(); 193 } 194 } 195