• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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