/******************************************************************************* * 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.g3d; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Buttons; import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.graphics.Camera; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.g3d.Environment; import com.badlogic.gdx.graphics.g3d.Model; import com.badlogic.gdx.graphics.g3d.ModelBatch; import com.badlogic.gdx.graphics.g3d.ModelInstance; import com.badlogic.gdx.graphics.g3d.Renderable; import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute; import com.badlogic.gdx.graphics.g3d.attributes.DirectionalLightsAttribute; import com.badlogic.gdx.graphics.g3d.attributes.PointLightsAttribute; import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight; import com.badlogic.gdx.graphics.g3d.environment.PointLight; import com.badlogic.gdx.graphics.g3d.model.Animation; import com.badlogic.gdx.graphics.g3d.shaders.DefaultShader; import com.badlogic.gdx.graphics.g3d.shaders.DefaultShader.Config; import com.badlogic.gdx.graphics.g3d.utils.AnimationController; import com.badlogic.gdx.graphics.g3d.utils.DefaultShaderProvider; import com.badlogic.gdx.graphics.g3d.utils.ShaderProvider; import com.badlogic.gdx.graphics.profiling.GLProfiler; import com.badlogic.gdx.graphics.profiling.GL20Profiler; import com.badlogic.gdx.graphics.profiling.GL30Profiler; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Matrix4; import com.badlogic.gdx.math.Quaternion; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.math.collision.BoundingBox; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.ui.CheckBox; import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener.ChangeEvent; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.StringBuilder; /** @author Daniel Holderbaum */ public class Benchmark3DTest extends BaseG3dHudTest { protected Environment environment; protected Label vertexCountLabel, textureBindsLabel, shaderSwitchesLabel, drawCallsLabel, glCallsLabel, lightsLabel; protected CheckBox lightingCheckBox, lightsCheckBox; protected boolean lighting; @Override public void create () { super.create(); GLProfiler.enable(); randomizeLights(); cam.position.set(10, 10, 10); cam.lookAt(0, 0, 0); cam.update(); showAxes = true; lighting = true; vertexCountLabel = new Label("Vertices: 999", skin); vertexCountLabel.setPosition(0, fpsLabel.getTop()); hud.addActor(vertexCountLabel); textureBindsLabel = new Label("Texture bindings: 999", skin); textureBindsLabel.setPosition(0, vertexCountLabel.getTop()); hud.addActor(textureBindsLabel); shaderSwitchesLabel = new Label("Shader switches: 999", skin); shaderSwitchesLabel.setPosition(0, textureBindsLabel.getTop()); hud.addActor(shaderSwitchesLabel); drawCallsLabel = new Label("Draw calls: 999", skin); drawCallsLabel.setPosition(0, shaderSwitchesLabel.getTop()); hud.addActor(drawCallsLabel); glCallsLabel = new Label("GL calls: 999", skin); glCallsLabel.setPosition(0, drawCallsLabel.getTop()); hud.addActor(glCallsLabel); lightsLabel = new Label("Lights: 999", skin); lightsLabel.setPosition(0, glCallsLabel.getTop()); hud.addActor(lightsLabel); lightingCheckBox = new CheckBox("Lighting", skin); lightingCheckBox.setChecked(lighting); lightingCheckBox.addListener(new ChangeListener() { @Override public void changed (ChangeEvent event, Actor actor) { lighting = lightingCheckBox.isChecked(); } }); lightingCheckBox.setPosition(hudWidth - lightingCheckBox.getWidth(), gridCheckBox.getTop()); hud.addActor(lightingCheckBox); lightsCheckBox = new CheckBox("Randomize lights", skin); lightsCheckBox.setChecked(false); lightsCheckBox.addListener(new ChangeListener() { @Override public void changed (ChangeEvent event, Actor actor) { lightsCheckBox.setChecked(false); randomizeLights(); } }); lightsCheckBox.setPosition(hudWidth - lightsCheckBox.getWidth(), lightingCheckBox.getTop()); hud.addActor(lightsCheckBox); moveCheckBox.remove(); rotateCheckBox.remove(); } protected void randomizeLights () { int pointLights = MathUtils.random(5); int directionalLights = MathUtils.random(5); DefaultShader.Config config = new Config(); config.numDirectionalLights = directionalLights; config.numPointLights = pointLights; config.numSpotLights = 0; modelBatch.dispose(); modelBatch = new ModelBatch(new DefaultShaderProvider(config)); environment = new Environment(); environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1.f)); for (int i = 0; i < pointLights; i++) { environment.add(new PointLight().set(randomColor(), randomPosition(), MathUtils.random(10f))); } for (int i = 0; i < directionalLights; i++) { environment.add(new DirectionalLight().set(randomColor(), randomPosition())); } } protected Color randomColor () { return new Color(MathUtils.random(1.0f), MathUtils.random(1.0f), MathUtils.random(1.0f), MathUtils.random(1.0f)); } protected Vector3 randomPosition () { return new Vector3(MathUtils.random(-10f, 10f), MathUtils.random(-10f, 10f), MathUtils.random(-10f, 10f)); } private final Vector3 tmpV = new Vector3(); private final Quaternion tmpQ = new Quaternion(); private final BoundingBox bounds = new BoundingBox(); protected void getStatus (final StringBuilder stringBuilder) { stringBuilder.setLength(0); stringBuilder.append("GL calls: "); stringBuilder.append(GLProfiler.calls); glCallsLabel.setText(stringBuilder); stringBuilder.setLength(0); stringBuilder.append("Draw calls: "); stringBuilder.append(GLProfiler.drawCalls); drawCallsLabel.setText(stringBuilder); stringBuilder.setLength(0); stringBuilder.append("Shader switches: "); stringBuilder.append(GLProfiler.shaderSwitches); shaderSwitchesLabel.setText(stringBuilder); stringBuilder.setLength(0); stringBuilder.append("Texture bindings: "); stringBuilder.append(GLProfiler.textureBindings); textureBindsLabel.setText(stringBuilder); stringBuilder.setLength(0); stringBuilder.append("Vertices: "); stringBuilder.append(GLProfiler.vertexCount.total); vertexCountLabel.setText(stringBuilder); DirectionalLightsAttribute dirLights = (DirectionalLightsAttribute)environment.get(DirectionalLightsAttribute.Type); PointLightsAttribute pointLights = (PointLightsAttribute)environment.get(PointLightsAttribute.Type); stringBuilder.setLength(0); stringBuilder.append("Lights: "); stringBuilder.append((dirLights == null ? 0 : dirLights.lights.size) + (pointLights == null ? 0 : pointLights.lights.size)); stringBuilder.append(", Directional: "); stringBuilder.append(dirLights == null ? 0 : dirLights.lights.size); stringBuilder.append(", Point: "); stringBuilder.append(pointLights == null ? 0 : pointLights.lights.size); lightsLabel.setText(stringBuilder); GLProfiler.reset(); stringBuilder.setLength(0); super.getStatus(stringBuilder); } @Override protected void render (ModelBatch batch, Array<ModelInstance> instances) { if (lighting) { batch.render(instances, environment); } else { batch.render(instances); } } protected String currentlyLoading; @Override protected void onModelClicked (final String name) { if (name == null) return; currentlyLoading = "data/" + name; assets.load(currentlyLoading, Model.class); loading = true; } @Override protected void onLoaded () { if (currentlyLoading == null || currentlyLoading.length() == 0) return; final ModelInstance instance = new ModelInstance(assets.get(currentlyLoading, Model.class)); instance.transform = new Matrix4().idt(); instance.transform.setToTranslation(MathUtils.random(-10, 10), MathUtils.random(-10, 10), MathUtils.random(-10, 10)); instance.transform.rotate(Vector3.X, MathUtils.random(-180, 180)); instance.transform.rotate(Vector3.Y, MathUtils.random(-180, 180)); instance.transform.rotate(Vector3.Z, MathUtils.random(-180, 180)); instances.add(instance); } @Override public boolean keyUp (int keycode) { if (keycode == Keys.SPACE || keycode == Keys.MENU) { onLoaded(); } return super.keyUp(keycode); } @Override public boolean touchUp (int screenX, int screenY, int pointer, int button) { onModelClicked(models[MathUtils.random(models.length-1)]); return false; } @Override public void dispose () { super.dispose(); GLProfiler.disable(); } }