Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shadow system - 2 / 6 #3474

Merged
merged 10 commits into from Oct 24, 2015
@@ -1,12 +1,12 @@
/*******************************************************************************
* 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.
@@ -24,7 +24,7 @@

/** Encapsulates an axis aligned bounding box represented by a minimum and a maximum Vector. Additionally you can query for the
* bounding box's center, dimensions and corner points.
*
*
* @author badlogicgames@gmail.com, Xoppa */
public class BoundingBox implements Serializable {
private static final long serialVersionUID = -1286036817192127343L;
@@ -123,30 +123,30 @@ public BoundingBox () {
}

/** Constructs a new bounding box from the given bounding box.
*
*
* @param bounds The bounding box to copy */
public BoundingBox (BoundingBox bounds) {
this.set(bounds);
}

/** Constructs the new bounding box using the given minimum and maximum vector.
*
*
* @param minimum The minimum vector
* @param maximum The maximum vector */
public BoundingBox (Vector3 minimum, Vector3 maximum) {
this.set(minimum, maximum);
}

/** Sets the given bounding box.
*
*
* @param bounds The bounds.
* @return This bounding box for chaining. */
public BoundingBox set (BoundingBox bounds) {
return this.set(bounds.min, bounds.max);
}

/** Sets the given minimum and maximum vector.
*
*
* @param minimum The minimum vector
* @param maximum The maximum vector
* @return This bounding box for chaining. */
@@ -161,7 +161,7 @@ public BoundingBox set (Vector3 minimum, Vector3 maximum) {
}

/** Sets the bounding box minimum and maximum vector from the given points.
*
*
* @param points The points.
* @return This bounding box for chaining. */
public BoundingBox set (Vector3[] points) {
@@ -172,7 +172,7 @@ public BoundingBox set (Vector3[] points) {
}

/** Sets the bounding box minimum and maximum vector from the given points.
*
*
* @param points The points.
* @return This bounding box for chaining. */
public BoundingBox set (List<Vector3> points) {
@@ -183,7 +183,7 @@ public BoundingBox set (List<Vector3> points) {
}

/** Sets the minimum and maximum vector to positive and negative infinity.
*
*
* @return This bounding box for chaining. */
public BoundingBox inf () {
min.set(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
@@ -214,16 +214,26 @@ public boolean isValid () {
}

/** Extends this bounding box by the given bounding box.
*
*
* @param a_bounds The bounding box
* @return This bounding box for chaining. */
public BoundingBox ext (BoundingBox a_bounds) {
return this.set(min.set(min(min.x, a_bounds.min.x), min(min.y, a_bounds.min.y), min(min.z, a_bounds.min.z)),
max.set(max(max.x, a_bounds.max.x), max(max.y, a_bounds.max.y), max(max.z, a_bounds.max.z)));
}

/** Extends this bounding box by the given sphere.
*
* @param center Sphere center
* @param radius Sphere radius
* @return This bounding box for chaining. */
public BoundingBox ext (Vector3 center, float radius) {
return this.set(min.set(min(min.x, center.x - radius), min(min.y, center.y - radius), min(min.z, center.z - radius)),
max.set(max(max.x, center.x + radius), max(max.y, center.y + radius), max(max.z, center.z + radius)));
}

/** Extends this bounding box by the given transformed bounding box.
*
*
* @param bounds The bounding box
* @param transform The transformation matrix to apply to bounds, before using it to extend this bounding box.
* @return This bounding box for chaining. */
@@ -241,7 +251,7 @@ public BoundingBox ext (BoundingBox bounds, Matrix4 transform) {

/** Multiplies the bounding box by the given matrix. This is achieved by multiplying the 8 corner points and then calculating
* the minimum and maximum vectors from the transformed points.
*
*
* @param transform The matrix
* @return This bounding box for chaining. */
public BoundingBox mul (Matrix4 transform) {
@@ -300,7 +310,7 @@ public String toString () {
}

/** Extends the bounding box by the given vector.
*
*
* @param x The x-coordinate
* @param y The y-coordinate
* @param z The z-coordinate
@@ -0,0 +1,126 @@
/*******************************************************************************
* 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 void analyze (BaseLight light, Camera camera, Iterable<RenderableProvider> 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 void getRenderables (Iterable<RenderableProvider> 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();
}
}
@@ -0,0 +1,30 @@
/*******************************************************************************
* 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.environment.BaseLight;

/** This Filter does not block lights. All lights are allowed.
* @author realitix */
public class AllLightFilter implements LightFilter {

@Override
public boolean filter (BaseLight light, Camera camera) {
return true;
}
}
@@ -0,0 +1,68 @@
/*******************************************************************************
* 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.environment.DirectionalLight;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.math.collision.BoundingBox;

/** Compute directional camera based on frustum bounding sphere.
* @author realitix */
public class BoundingSphereDirectionalAnalyzer implements DirectionalAnalyzer {
/** Objects used for computation */
protected BoundingBox bb = new BoundingBox();
protected Vector3 tmpV = new Vector3();
protected Vector3 tmpV2 = new Vector3();

@Override
public Camera analyze (DirectionalLight light, Camera out, Camera mainCamera) {
bb.inf();

// Create bounding box encompassing main camera frustum
for (int i = 0; i < mainCamera.frustum.planePoints.length; i++) {
bb.ext(mainCamera.frustum.planePoints[i]);
}

// Radius
float radius = bb.getDimensions(tmpV).len() * 0.5f;

// Center
bb.getCenter(tmpV);

// Move back from 1.5*radius
tmpV2.set(light.direction);
tmpV2.scl(radius * 1.5f);

// Position out camera
out.direction.set(light.direction);
out.position.set(tmpV.sub(tmpV2));

// Compute near and far
out.near = 0.5f * radius;
out.far = 2.5f * radius;

// Compute up vector
out.up.set(light.direction.y, light.direction.z, light.direction.x);

// Compute viewport (orthographic camera)
out.viewportWidth = radius;
out.viewportHeight = radius;

return out;
}
}
@@ -26,6 +26,7 @@
/** Compute the camera dimension based on directional light. Camera should be an orthographic camera.
* @param light Current directional light
* @param out Updated camera
* @return Camera Camera for chaining */
public Camera analyze (DirectionalLight light, Camera out);
* @param mainCamera Main Scene camera
* @return Camera Camera out for chaining */
public Camera analyze (DirectionalLight light, Camera out, Camera mainCamera);
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.