• 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.Application.ApplicationType;
20 import com.badlogic.gdx.Gdx;
21 import com.badlogic.gdx.Input.Keys;
22 import com.badlogic.gdx.graphics.Color;
23 import com.badlogic.gdx.graphics.GL20;
24 import com.badlogic.gdx.graphics.PerspectiveCamera;
25 import com.badlogic.gdx.graphics.VertexAttributes.Usage;
26 import com.badlogic.gdx.graphics.g3d.Environment;
27 import com.badlogic.gdx.graphics.g3d.Material;
28 import com.badlogic.gdx.graphics.g3d.Model;
29 import com.badlogic.gdx.graphics.g3d.ModelBatch;
30 import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
31 import com.badlogic.gdx.graphics.g3d.attributes.FloatAttribute;
32 import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
33 import com.badlogic.gdx.graphics.g3d.environment.DirectionalShadowLight;
34 import com.badlogic.gdx.graphics.g3d.loader.ObjLoader;
35 import com.badlogic.gdx.graphics.g3d.utils.DepthShaderProvider;
36 import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
37 import com.badlogic.gdx.math.Vector3;
38 import com.badlogic.gdx.math.collision.Ray;
39 import com.badlogic.gdx.physics.bullet.Bullet;
40 import com.badlogic.gdx.physics.bullet.dynamics.btRigidBody;
41 import com.badlogic.gdx.physics.bullet.linearmath.LinearMath;
42 import com.badlogic.gdx.physics.bullet.linearmath.btIDebugDraw.DebugDrawModes;
43 import com.badlogic.gdx.utils.Array;
44 import com.badlogic.gdx.utils.Disposable;
45 
46 /** @author xoppa */
47 public class BaseBulletTest extends BulletTest {
48 	// Set this to the path of the lib to use it on desktop instead of default lib.
49 	private final static String customDesktopLib = null;//"D:\\Xoppa\\code\\libgdx\\extensions\\gdx-bullet\\jni\\vs\\gdxBullet\\x64\\Debug\\gdxBullet.dll";
50 
51 	private static boolean initialized = false;
52 
53 	public static boolean shadows = true;
54 
init()55 	public static void init () {
56 		if (initialized) return;
57 		// Need to initialize bullet before using it.
58 		if (Gdx.app.getType() == ApplicationType.Desktop && customDesktopLib != null) {
59 			System.load(customDesktopLib);
60 		} else
61 			Bullet.init();
62 		Gdx.app.log("Bullet", "Version = " + LinearMath.btGetVersion());
63 		initialized = true;
64 	}
65 
66 	public Environment environment;
67 	public DirectionalLight light;
68 	public ModelBatch shadowBatch;
69 
70 	public BulletWorld world;
71 	public ObjLoader objLoader = new ObjLoader();
72 	public ModelBuilder modelBuilder = new ModelBuilder();
73 	public ModelBatch modelBatch;
74 	public Array<Disposable> disposables = new Array<Disposable>();
75 	private int debugMode = DebugDrawModes.DBG_NoDebug;
76 
77 	protected final static Vector3 tmpV1 = new Vector3(), tmpV2 = new Vector3();
78 
createWorld()79 	public BulletWorld createWorld () {
80 		return new BulletWorld();
81 	}
82 
83 	@Override
create()84 	public void create () {
85 		init();
86 		environment = new Environment();
87 		environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.3f, 0.3f, 0.3f, 1.f));
88 		light = shadows ? new DirectionalShadowLight(1024, 1024, 20f, 20f, 1f, 300f) : new DirectionalLight();
89 		light.set(0.8f, 0.8f, 0.8f, -0.5f, -1f, 0.7f);
90 		environment.add(light);
91 		if (shadows)
92 			environment.shadowMap = (DirectionalShadowLight)light;
93 		shadowBatch = new ModelBatch(new DepthShaderProvider());
94 
95 		modelBatch = new ModelBatch();
96 
97 		world = createWorld();
98 		world.performanceCounter = performanceCounter;
99 
100 		final float width = Gdx.graphics.getWidth();
101 		final float height = Gdx.graphics.getHeight();
102 		if (width > height)
103 			camera = new PerspectiveCamera(67f, 3f * width / height, 3f);
104 		else
105 			camera = new PerspectiveCamera(67f, 3f, 3f * height / width);
106 		camera.position.set(10f, 10f, 10f);
107 		camera.lookAt(0, 0, 0);
108 		camera.update();
109 
110 		// Create some simple models
111 		final Model groundModel = modelBuilder.createRect(
112 			20f,
113 			0f,
114 			-20f,
115 			-20f,
116 			0f,
117 			-20f,
118 			-20f,
119 			0f,
120 			20f,
121 			20f,
122 			0f,
123 			20f,
124 			0,
125 			1,
126 			0,
127 			new Material(ColorAttribute.createDiffuse(Color.WHITE), ColorAttribute.createSpecular(Color.WHITE), FloatAttribute
128 				.createShininess(16f)), Usage.Position | Usage.Normal);
129 		disposables.add(groundModel);
130 		final Model boxModel = modelBuilder.createBox(1f, 1f, 1f, new Material(ColorAttribute.createDiffuse(Color.WHITE),
131 			ColorAttribute.createSpecular(Color.WHITE), FloatAttribute.createShininess(64f)), Usage.Position | Usage.Normal);
132 		disposables.add(boxModel);
133 
134 		// Add the constructors
135 		world.addConstructor("ground", new BulletConstructor(groundModel, 0f)); // mass = 0: static body
136 		world.addConstructor("box", new BulletConstructor(boxModel, 1f)); // mass = 1kg: dynamic body
137 		world.addConstructor("staticbox", new BulletConstructor(boxModel, 0f)); // mass = 0: static body
138 	}
139 
140 	@Override
dispose()141 	public void dispose () {
142 		world.dispose();
143 		world = null;
144 
145 		for (Disposable disposable : disposables)
146 			disposable.dispose();
147 		disposables.clear();
148 
149 		modelBatch.dispose();
150 		modelBatch = null;
151 
152 		shadowBatch.dispose();
153 		shadowBatch = null;
154 
155 		if (shadows)
156 			((DirectionalShadowLight)light).dispose();
157 		light = null;
158 
159 		super.dispose();
160 	}
161 
162 	@Override
render()163 	public void render () {
164 		render(true);
165 	}
166 
render(boolean update)167 	public void render (boolean update) {
168 		fpsCounter.put(Gdx.graphics.getFramesPerSecond());
169 
170 		if (update) update();
171 
172 		beginRender(true);
173 
174 		renderWorld();
175 
176 		Gdx.gl.glDisable(GL20.GL_DEPTH_TEST);
177 		if (debugMode != DebugDrawModes.DBG_NoDebug) world.setDebugMode(debugMode);
178 		Gdx.gl.glEnable(GL20.GL_DEPTH_TEST);
179 
180 		performance.setLength(0);
181 		performance.append("FPS: ").append(fpsCounter.value).append(", Bullet: ")
182 			.append((int)(performanceCounter.load.value * 100f)).append("%");
183 	}
184 
beginRender(boolean lighting)185 	protected void beginRender (boolean lighting) {
186 		Gdx.gl.glViewport(0, 0, Gdx.graphics.getBackBufferWidth(), Gdx.graphics.getBackBufferHeight());
187 		Gdx.gl.glClearColor(0, 0, 0, 0);
188 		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
189 		camera.update();
190 	}
191 
renderWorld()192 	protected void renderWorld () {
193 		if (shadows) {
194 			((DirectionalShadowLight)light).begin(Vector3.Zero, camera.direction);
195 			shadowBatch.begin(((DirectionalShadowLight)light).getCamera());
196 			world.render(shadowBatch, null);
197 			shadowBatch.end();
198 			((DirectionalShadowLight)light).end();
199 		}
200 
201 		modelBatch.begin(camera);
202 		world.render(modelBatch, environment);
203 		modelBatch.end();
204 	}
205 
update()206 	public void update () {
207 		world.update();
208 	}
209 
shoot(final float x, final float y)210 	public BulletEntity shoot (final float x, final float y) {
211 		return shoot(x, y, 30f);
212 	}
213 
shoot(final float x, final float y, final float impulse)214 	public BulletEntity shoot (final float x, final float y, final float impulse) {
215 		return shoot("box", x, y, impulse);
216 	}
217 
shoot(final String what, final float x, final float y, final float impulse)218 	public BulletEntity shoot (final String what, final float x, final float y, final float impulse) {
219 		// Shoot a box
220 		Ray ray = camera.getPickRay(x, y);
221 		BulletEntity entity = world.add(what, ray.origin.x, ray.origin.y, ray.origin.z);
222 		entity.setColor(0.5f + 0.5f * (float)Math.random(), 0.5f + 0.5f * (float)Math.random(), 0.5f + 0.5f * (float)Math.random(),
223 			1f);
224 		((btRigidBody)entity.body).applyCentralImpulse(ray.direction.scl(impulse));
225 		return entity;
226 	}
227 
setDebugMode(final int mode)228 	public void setDebugMode (final int mode) {
229 		world.setDebugMode(debugMode = mode);
230 	}
231 
toggleDebugMode()232 	public void toggleDebugMode () {
233 		if (world.getDebugMode() == DebugDrawModes.DBG_NoDebug)
234 			setDebugMode(DebugDrawModes.DBG_DrawWireframe | DebugDrawModes.DBG_DrawFeaturesText | DebugDrawModes.DBG_DrawText | DebugDrawModes.DBG_DrawContactPoints);
235 		else if (world.renderMeshes)
236 			world.renderMeshes = false;
237 		else {
238 			world.renderMeshes = true;
239 			setDebugMode(DebugDrawModes.DBG_NoDebug);
240 		}
241 	}
242 
243 	@Override
longPress(float x, float y)244 	public boolean longPress (float x, float y) {
245 		toggleDebugMode();
246 		return true;
247 	}
248 
249 	@Override
keyUp(int keycode)250 	public boolean keyUp (int keycode) {
251 		if (keycode == Keys.ENTER) {
252 			toggleDebugMode();
253 			return true;
254 		}
255 		return super.keyUp(keycode);
256 	}
257 }
258