/******************************************************************************* * 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.shadows.utils; import com.badlogic.gdx.graphics.Camera; import com.badlogic.gdx.graphics.g3d.Renderable; import com.badlogic.gdx.graphics.g3d.RenderableProvider; import com.badlogic.gdx.graphics.g3d.environment.BaseLight; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.math.collision.BoundingBox; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Pool; /** Compute near and far plane based on renderable providers passed in constructor. Renderable providers array should contains only * renderable in camera frustum. * @author realitix */ public class AABBNearFarAnalyzer implements NearFarAnalyzer { /** Near and far initialization before computation. You should put the same values as the main camera */ public static float CAMERA_NEAR = 1; public static float CAMERA_FAR = 100; // @TODO Merge renderable pools (ModelBatch) protected static class RenderablePool extends Pool<Renderable> { protected Array<Renderable> obtained = new Array<Renderable>(); @Override protected Renderable newObject () { return new Renderable(); } @Override public Renderable obtain () { Renderable renderable = super.obtain(); renderable.environment = null; renderable.material = null; renderable.meshPart.set("", null, 0, 0, 0); renderable.shader = null; obtained.add(renderable); return renderable; } public void flush () { super.freeAll(obtained); obtained.clear(); } } protected final RenderablePool renderablesPool = new RenderablePool(); /** list of Renderables to be rendered in the current batch **/ protected final Array<Renderable> renderables = new Array<Renderable>(); /** Objects used for computation */ protected BoundingBox bb1 = new BoundingBox(); protected Vector3 tmpV = new Vector3(); @Override public <T extends RenderableProvider> void analyze (BaseLight light, Camera camera, Iterable<T> renderableProviders) { getRenderables(renderableProviders); prepareCamera(camera); bb1.inf(); for (Renderable renderable : renderables) { renderable.worldTransform.getTranslation(tmpV); tmpV.add(renderable.meshPart.center); if (camera.frustum.sphereInFrustum(tmpV, renderable.meshPart.radius)) { bb1.ext(tmpV, renderable.meshPart.radius); } } computeResult(bb1, camera); renderablesPool.flush(); renderables.clear(); } protected <T extends RenderableProvider> void getRenderables (Iterable<T> renderableProviders) { for (RenderableProvider renderableProvider : renderableProviders) { renderableProvider.getRenderables(renderables, renderablesPool); } } /** Initialize camera before computation. * @param camera Camera to compute. */ protected void prepareCamera (Camera camera) { camera.near = AABBNearFarAnalyzer.CAMERA_NEAR; camera.far = AABBNearFarAnalyzer.CAMERA_FAR; camera.update(); } /** Compute final result. * @param bb BoundingBox encompassing instances * @param camera Camera to compute */ protected void computeResult (BoundingBox bb, Camera camera) { // Radius float radius = bb1.getDimensions(tmpV).len() * 0.5f; // Center bb1.getCenter(tmpV); // Computation float distance = tmpV.dst(camera.position); float near = distance - radius; float far = distance + radius; if (near <= 0) near = CAMERA_NEAR; if (far <= 0) far = CAMERA_FAR; camera.near = near; camera.far = far; camera.update(); } }