shader-nodes-enhancement
parent
824e99c96e
commit
83aef82d92
@ -1,214 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (c) 2009-2015 jMonkeyEngine |
|
||||||
* All rights reserved. |
|
||||||
* |
|
||||||
* Redistribution and use in source and binary forms, with or without |
|
||||||
* modification, are permitted provided that the following conditions are |
|
||||||
* met: |
|
||||||
* |
|
||||||
* * Redistributions of source code must retain the above copyright |
|
||||||
* notice, this list of conditions and the following disclaimer. |
|
||||||
* |
|
||||||
* * Redistributions in binary form must reproduce the above copyright |
|
||||||
* notice, this list of conditions and the following disclaimer in the |
|
||||||
* documentation and/or other materials provided with the distribution. |
|
||||||
* |
|
||||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
|
||||||
* may be used to endorse or promote products derived from this software |
|
||||||
* without specific prior written permission. |
|
||||||
* |
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
||||||
*/ |
|
||||||
package com.jme3.light; |
|
||||||
|
|
||||||
import com.jme3.bounding.BoundingSphere; |
|
||||||
import com.jme3.post.SceneProcessor; |
|
||||||
import com.jme3.profile.AppProfiler; |
|
||||||
import com.jme3.renderer.RenderManager; |
|
||||||
import com.jme3.renderer.ViewPort; |
|
||||||
import com.jme3.renderer.queue.RenderQueue; |
|
||||||
import com.jme3.scene.Spatial; |
|
||||||
import com.jme3.texture.FrameBuffer; |
|
||||||
import com.jme3.util.TempVars; |
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.Collections; |
|
||||||
import java.util.List; |
|
||||||
|
|
||||||
/** |
|
||||||
* this processor allows to blend several light probes maps together according to a Point of Interest. |
|
||||||
* This is all based on this article by Sebastien lagarde |
|
||||||
* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
|
|
||||||
* @author Nehon |
|
||||||
*/ |
|
||||||
public class LightProbeBlendingProcessor implements SceneProcessor { |
|
||||||
|
|
||||||
private ViewPort viewPort; |
|
||||||
private LightFilter prevFilter; |
|
||||||
private RenderManager renderManager; |
|
||||||
private LightProbe probe = new LightProbe(); |
|
||||||
private Spatial poi; |
|
||||||
private AppProfiler prof; |
|
||||||
|
|
||||||
public LightProbeBlendingProcessor(Spatial poi) { |
|
||||||
this.poi = poi; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void initialize(RenderManager rm, ViewPort vp) { |
|
||||||
viewPort = vp; |
|
||||||
renderManager = rm; |
|
||||||
prevFilter = rm.getLightFilter(); |
|
||||||
rm.setLightFilter(new PoiLightProbeLightFilter(this)); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void reshape(ViewPort vp, int w, int h) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public boolean isInitialized() { |
|
||||||
return viewPort != null; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void preFrame(float tpf) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
/** 1. For POI take a spatial in the constructor and make all calculation against its world pos |
|
||||||
* - Alternatively compute an arbitrary POI by casting rays from the camera |
|
||||||
* (one in the center and one for each corner and take the median point) |
|
||||||
* 2. Take the 4 most weighted probes for default. Maybe allow the user to change this |
|
||||||
* 3. For the inner influence radius take half of the radius for a start we'll see then how to change this. |
|
||||||
* |
|
||||||
*/ |
|
||||||
@Override |
|
||||||
public void postQueue(RenderQueue rq) { |
|
||||||
List<BlendFactor> blendFactors = new ArrayList<BlendFactor>(); |
|
||||||
float sumBlendFactors = computeBlendFactors(blendFactors); |
|
||||||
|
|
||||||
//Sort blend factors according to their weight
|
|
||||||
Collections.sort(blendFactors); |
|
||||||
|
|
||||||
//normalize blend factors;
|
|
||||||
float normalizer = 1f / sumBlendFactors; |
|
||||||
for (BlendFactor blendFactor : blendFactors) { |
|
||||||
blendFactor.ndf *= normalizer; |
|
||||||
// System.err.println(blendFactor);
|
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
//for now just pick the first probe.
|
|
||||||
if(!blendFactors.isEmpty()){ |
|
||||||
probe = blendFactors.get(0).lightProbe; |
|
||||||
}else{ |
|
||||||
probe = null; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private float computeBlendFactors(List<BlendFactor> blendFactors) { |
|
||||||
float sumBlendFactors = 0; |
|
||||||
for (Spatial scene : viewPort.getScenes()) { |
|
||||||
for (Light light : scene.getWorldLightList()) { |
|
||||||
if(light.getType() == Light.Type.Probe){ |
|
||||||
LightProbe p = (LightProbe)light; |
|
||||||
TempVars vars = TempVars.get(); |
|
||||||
boolean intersect = p.intersectsFrustum(viewPort.getCamera(), vars); |
|
||||||
vars.release(); |
|
||||||
//check if the probe is inside the camera frustum
|
|
||||||
if(intersect){ |
|
||||||
|
|
||||||
//is the poi inside the bounds of this probe
|
|
||||||
if(poi.getWorldBound().intersects(p.getBounds())){ |
|
||||||
|
|
||||||
//computing the distance as we need it to check if th epoi in in the inner radius and later to compute the weight
|
|
||||||
float outerRadius = ((BoundingSphere)p.getBounds()).getRadius(); |
|
||||||
float innerRadius = outerRadius * 0.5f; |
|
||||||
float distance = p.getBounds().getCenter().distance(poi.getWorldTranslation()); |
|
||||||
|
|
||||||
// if the poi in inside the inner range of this probe, then this probe is the only one that matters.
|
|
||||||
if( distance < innerRadius ){ |
|
||||||
blendFactors.clear(); |
|
||||||
blendFactors.add(new BlendFactor(p, 1.0f)); |
|
||||||
return 1.0f; |
|
||||||
} |
|
||||||
//else we need to compute the weight of this probe and collect it for blending
|
|
||||||
float ndf = (distance - innerRadius) / (outerRadius - innerRadius); |
|
||||||
sumBlendFactors += ndf; |
|
||||||
blendFactors.add(new BlendFactor(p, ndf)); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return sumBlendFactors; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void postFrame(FrameBuffer out) { |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void cleanup() { |
|
||||||
viewPort = null; |
|
||||||
renderManager.setLightFilter(prevFilter); |
|
||||||
} |
|
||||||
|
|
||||||
public void populateProbe(LightList lightList){ |
|
||||||
if(probe != null && probe.isReady()){ |
|
||||||
lightList.add(probe); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public Spatial getPoi() { |
|
||||||
return poi; |
|
||||||
} |
|
||||||
|
|
||||||
public void setPoi(Spatial poi) { |
|
||||||
this.poi = poi; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void setProfiler(AppProfiler profiler) { |
|
||||||
this.prof = profiler; |
|
||||||
} |
|
||||||
|
|
||||||
private class BlendFactor implements Comparable<BlendFactor>{ |
|
||||||
|
|
||||||
LightProbe lightProbe; |
|
||||||
float ndf; |
|
||||||
|
|
||||||
public BlendFactor(LightProbe lightProbe, float ndf) { |
|
||||||
this.lightProbe = lightProbe; |
|
||||||
this.ndf = ndf; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String toString() { |
|
||||||
return "BlendFactor{" + "lightProbe=" + lightProbe + ", ndf=" + ndf + '}'; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public int compareTo(BlendFactor o) { |
|
||||||
if(o.ndf > ndf){ |
|
||||||
return -1; |
|
||||||
}else if(o.ndf < ndf){ |
|
||||||
return 1; |
|
||||||
} |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,249 @@ |
|||||||
|
package com.jme3.light; |
||||||
|
|
||||||
|
import com.jme3.bounding.BoundingBox; |
||||||
|
import com.jme3.bounding.BoundingSphere; |
||||||
|
import com.jme3.export.*; |
||||||
|
import com.jme3.math.*; |
||||||
|
import com.jme3.renderer.Camera; |
||||||
|
import com.jme3.util.TempVars; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
public class OrientedBoxProbeArea implements ProbeArea { |
||||||
|
private Transform transform = new Transform(); |
||||||
|
|
||||||
|
/** |
||||||
|
* @see LightProbe#getUniformMatrix() |
||||||
|
* for this Area type, the matrix is updated when the probe is transformed, |
||||||
|
* and its data is used for bound checks in the light culling process. |
||||||
|
*/ |
||||||
|
private Matrix4f uniformMatrix = new Matrix4f(); |
||||||
|
|
||||||
|
public OrientedBoxProbeArea() { |
||||||
|
} |
||||||
|
|
||||||
|
public OrientedBoxProbeArea(Transform transform) { |
||||||
|
transform.set(transform); |
||||||
|
updateMatrix(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean intersectsBox(BoundingBox box, TempVars vars) { |
||||||
|
|
||||||
|
Vector3f axis1 = getScaledAxis(0, vars.vect1); |
||||||
|
Vector3f axis2 = getScaledAxis(1, vars.vect2); |
||||||
|
Vector3f axis3 = getScaledAxis(2, vars.vect3); |
||||||
|
|
||||||
|
Vector3f tn = vars.vect4; |
||||||
|
Plane p = vars.plane; |
||||||
|
Vector3f c = box.getCenter(); |
||||||
|
|
||||||
|
p.setNormal(0, 0, -1); |
||||||
|
p.setConstant(-(c.z + box.getZExtent())); |
||||||
|
if (!insidePlane(p, axis1, axis2, axis3, tn)) return false; |
||||||
|
|
||||||
|
p.setNormal(0, 0, 1); |
||||||
|
p.setConstant(c.z - box.getZExtent()); |
||||||
|
if (!insidePlane(p, axis1, axis2, axis3, tn)) return false; |
||||||
|
|
||||||
|
|
||||||
|
p.setNormal(0, -1, 0); |
||||||
|
p.setConstant(-(c.y + box.getYExtent())); |
||||||
|
if (!insidePlane(p, axis1, axis2, axis3, tn)) return false; |
||||||
|
|
||||||
|
p.setNormal(0, 1, 0); |
||||||
|
p.setConstant(c.y - box.getYExtent()); |
||||||
|
if (!insidePlane(p, axis1, axis2, axis3, tn)) return false; |
||||||
|
|
||||||
|
p.setNormal(-1, 0, 0); |
||||||
|
p.setConstant(-(c.x + box.getXExtent())); |
||||||
|
if (!insidePlane(p, axis1, axis2, axis3, tn)) return false; |
||||||
|
|
||||||
|
p.setNormal(1, 0, 0); |
||||||
|
p.setConstant(c.x - box.getXExtent()); |
||||||
|
if (!insidePlane(p, axis1, axis2, axis3, tn)) return false; |
||||||
|
|
||||||
|
return true; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public float getRadius() { |
||||||
|
return Math.max(Math.max(transform.getScale().x, transform.getScale().y), transform.getScale().z); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) { |
||||||
|
|
||||||
|
Vector3f closestPoint = getClosestPoint(vars, sphere.getCenter()); |
||||||
|
// check if the point intersects with the sphere bound
|
||||||
|
if (sphere.intersects(closestPoint)) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean intersectsFrustum(Camera camera, TempVars vars) { |
||||||
|
|
||||||
|
// extract the scaled axis
|
||||||
|
// this allows a small optimization.
|
||||||
|
Vector3f axis1 = getScaledAxis(0, vars.vect1); |
||||||
|
Vector3f axis2 = getScaledAxis(1, vars.vect2); |
||||||
|
Vector3f axis3 = getScaledAxis(2, vars.vect3); |
||||||
|
|
||||||
|
Vector3f tn = vars.vect4; |
||||||
|
|
||||||
|
for (int i = 5; i >= 0; i--) { |
||||||
|
Plane p = camera.getWorldPlane(i); |
||||||
|
if (!insidePlane(p, axis1, axis2, axis3, tn)) return false; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
private Vector3f getScaledAxis(int index, Vector3f store) { |
||||||
|
Matrix4f u = uniformMatrix; |
||||||
|
float x = 0, y = 0, z = 0, s = 1; |
||||||
|
switch (index) { |
||||||
|
case 0: |
||||||
|
x = u.m00; |
||||||
|
y = u.m10; |
||||||
|
z = u.m20; |
||||||
|
s = u.m30; |
||||||
|
break; |
||||||
|
case 1: |
||||||
|
x = u.m01; |
||||||
|
y = u.m11; |
||||||
|
z = u.m21; |
||||||
|
s = u.m31; |
||||||
|
break; |
||||||
|
case 2: |
||||||
|
x = u.m02; |
||||||
|
y = u.m12; |
||||||
|
z = u.m22; |
||||||
|
s = u.m32; |
||||||
|
} |
||||||
|
return store.set(x, y, z).multLocal(s); |
||||||
|
} |
||||||
|
|
||||||
|
private boolean insidePlane(Plane p, Vector3f axis1, Vector3f axis2, Vector3f axis3, Vector3f tn) { |
||||||
|
// transform the plane normal in the box local space.
|
||||||
|
tn.set(axis1.dot(p.getNormal()), axis2.dot(p.getNormal()), axis3.dot(p.getNormal())); |
||||||
|
|
||||||
|
// distance check
|
||||||
|
float radius = FastMath.abs(tn.x) + |
||||||
|
FastMath.abs(tn.y) + |
||||||
|
FastMath.abs(tn.z); |
||||||
|
|
||||||
|
float distance = p.pseudoDistance(transform.getTranslation()); |
||||||
|
|
||||||
|
if (distance < -radius) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
private Vector3f getClosestPoint(TempVars vars, Vector3f point) { |
||||||
|
// non normalized direction
|
||||||
|
Vector3f dir = vars.vect2.set(point).subtractLocal(transform.getTranslation()); |
||||||
|
// initialize the closest point with box center
|
||||||
|
Vector3f closestPoint = vars.vect3.set(transform.getTranslation()); |
||||||
|
|
||||||
|
//store extent in an array
|
||||||
|
float[] r = vars.fWdU; |
||||||
|
r[0] = transform.getScale().x; |
||||||
|
r[1] = transform.getScale().y; |
||||||
|
r[2] = transform.getScale().z; |
||||||
|
|
||||||
|
// computing closest point to sphere center
|
||||||
|
for (int i = 0; i < 3; i++) { |
||||||
|
// extract the axis from the 3x3 matrix
|
||||||
|
Vector3f axis = getScaledAxis(i, vars.vect1); |
||||||
|
// nomalize (here we just divide by the extent
|
||||||
|
axis.divideLocal(r[i]); |
||||||
|
// distance to the closest point on this axis.
|
||||||
|
float d = FastMath.clamp(dir.dot(axis), -r[i], r[i]); |
||||||
|
closestPoint.addLocal(vars.vect4.set(axis).multLocal(d)); |
||||||
|
} |
||||||
|
return closestPoint; |
||||||
|
} |
||||||
|
|
||||||
|
private void updateMatrix() { |
||||||
|
TempVars vars = TempVars.get(); |
||||||
|
Matrix3f r = vars.tempMat3; |
||||||
|
Matrix4f u = uniformMatrix; |
||||||
|
transform.getRotation().toRotationMatrix(r); |
||||||
|
|
||||||
|
u.m00 = r.get(0,0); |
||||||
|
u.m10 = r.get(1,0); |
||||||
|
u.m20 = r.get(2,0); |
||||||
|
u.m01 = r.get(0,1); |
||||||
|
u.m11 = r.get(1,1); |
||||||
|
u.m21 = r.get(2,1); |
||||||
|
u.m02 = r.get(0,2); |
||||||
|
u.m12 = r.get(1,2); |
||||||
|
u.m22 = r.get(2,2); |
||||||
|
|
||||||
|
//scale
|
||||||
|
u.m30 = transform.getScale().x; |
||||||
|
u.m31 = transform.getScale().y; |
||||||
|
u.m32 = transform.getScale().z; |
||||||
|
|
||||||
|
//position
|
||||||
|
u.m03 = transform.getTranslation().x; |
||||||
|
u.m13 = transform.getTranslation().y; |
||||||
|
u.m23 = transform.getTranslation().z; |
||||||
|
|
||||||
|
vars.release(); |
||||||
|
} |
||||||
|
|
||||||
|
public Matrix4f getUniformMatrix() { |
||||||
|
return uniformMatrix; |
||||||
|
} |
||||||
|
|
||||||
|
public Vector3f getExtent() { |
||||||
|
return transform.getScale(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setExtent(Vector3f extent) { |
||||||
|
transform.setScale(extent); |
||||||
|
updateMatrix(); |
||||||
|
} |
||||||
|
|
||||||
|
public Vector3f getCenter() { |
||||||
|
return transform.getTranslation(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setCenter(Vector3f center) { |
||||||
|
transform.setTranslation(center); |
||||||
|
updateMatrix(); |
||||||
|
} |
||||||
|
|
||||||
|
public Quaternion getRotation() { |
||||||
|
return transform.getRotation(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setRotation(Quaternion rotation) { |
||||||
|
transform.setRotation(rotation); |
||||||
|
updateMatrix(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected OrientedBoxProbeArea clone() throws CloneNotSupportedException { |
||||||
|
return new OrientedBoxProbeArea(transform); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void write(JmeExporter e) throws IOException { |
||||||
|
OutputCapsule oc = e.getCapsule(this); |
||||||
|
oc.write(transform, "transform", new Transform()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void read(JmeImporter i) throws IOException { |
||||||
|
InputCapsule ic = i.getCapsule(this); |
||||||
|
transform = (Transform) ic.readSavable("transform", new Transform()); |
||||||
|
updateMatrix(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -1,107 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (c) 2009-2015 jMonkeyEngine |
|
||||||
* All rights reserved. |
|
||||||
* |
|
||||||
* Redistribution and use in source and binary forms, with or without |
|
||||||
* modification, are permitted provided that the following conditions are |
|
||||||
* met: |
|
||||||
* |
|
||||||
* * Redistributions of source code must retain the above copyright |
|
||||||
* notice, this list of conditions and the following disclaimer. |
|
||||||
* |
|
||||||
* * Redistributions in binary form must reproduce the above copyright |
|
||||||
* notice, this list of conditions and the following disclaimer in the |
|
||||||
* documentation and/or other materials provided with the distribution. |
|
||||||
* |
|
||||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
|
||||||
* may be used to endorse or promote products derived from this software |
|
||||||
* without specific prior written permission. |
|
||||||
* |
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
||||||
*/ |
|
||||||
package com.jme3.light; |
|
||||||
|
|
||||||
import com.jme3.bounding.BoundingBox; |
|
||||||
import com.jme3.bounding.BoundingSphere; |
|
||||||
import com.jme3.bounding.BoundingVolume; |
|
||||||
import com.jme3.renderer.Camera; |
|
||||||
import com.jme3.scene.Geometry; |
|
||||||
import com.jme3.util.TempVars; |
|
||||||
import java.util.HashSet; |
|
||||||
|
|
||||||
public final class PoiLightProbeLightFilter implements LightFilter { |
|
||||||
|
|
||||||
private Camera camera; |
|
||||||
private final HashSet<Light> processedLights = new HashSet<Light>(); |
|
||||||
private final LightProbeBlendingProcessor processor; |
|
||||||
|
|
||||||
public PoiLightProbeLightFilter(LightProbeBlendingProcessor processor) { |
|
||||||
this.processor = processor; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void setCamera(Camera camera) { |
|
||||||
this.camera = camera; |
|
||||||
for (Light light : processedLights) { |
|
||||||
light.frustumCheckNeeded = true; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void filterLights(Geometry geometry, LightList filteredLightList) { |
|
||||||
TempVars vars = TempVars.get(); |
|
||||||
try { |
|
||||||
LightList worldLights = geometry.getWorldLightList(); |
|
||||||
|
|
||||||
for (int i = 0; i < worldLights.size(); i++) { |
|
||||||
Light light = worldLights.get(i); |
|
||||||
|
|
||||||
if (light.getType() == Light.Type.Probe) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
if (light.frustumCheckNeeded) { |
|
||||||
processedLights.add(light); |
|
||||||
light.frustumCheckNeeded = false; |
|
||||||
light.intersectsFrustum = light.intersectsFrustum(camera, vars); |
|
||||||
} |
|
||||||
|
|
||||||
if (!light.intersectsFrustum) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
BoundingVolume bv = geometry.getWorldBound(); |
|
||||||
|
|
||||||
if (bv instanceof BoundingBox) { |
|
||||||
if (!light.intersectsBox((BoundingBox) bv, vars)) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
} else if (bv instanceof BoundingSphere) { |
|
||||||
if (!Float.isInfinite(((BoundingSphere) bv).getRadius())) { |
|
||||||
if (!light.intersectsSphere((BoundingSphere) bv, vars)) { |
|
||||||
continue; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
filteredLightList.add(light); |
|
||||||
} |
|
||||||
|
|
||||||
processor.populateProbe(filteredLightList); |
|
||||||
|
|
||||||
} finally { |
|
||||||
vars.release(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -0,0 +1,33 @@ |
|||||||
|
package com.jme3.light; |
||||||
|
|
||||||
|
import com.jme3.bounding.BoundingBox; |
||||||
|
import com.jme3.bounding.BoundingSphere; |
||||||
|
import com.jme3.export.Savable; |
||||||
|
import com.jme3.math.Matrix4f; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.renderer.Camera; |
||||||
|
import com.jme3.util.TempVars; |
||||||
|
|
||||||
|
public interface ProbeArea extends Savable, Cloneable{ |
||||||
|
|
||||||
|
public void setCenter(Vector3f center); |
||||||
|
|
||||||
|
public float getRadius(); |
||||||
|
|
||||||
|
public Matrix4f getUniformMatrix(); |
||||||
|
|
||||||
|
/** |
||||||
|
* @see Light#intersectsBox(BoundingBox, TempVars) |
||||||
|
*/ |
||||||
|
public boolean intersectsBox(BoundingBox box, TempVars vars); |
||||||
|
|
||||||
|
/** |
||||||
|
* @see Light#intersectsSphere(BoundingSphere, TempVars) |
||||||
|
*/ |
||||||
|
public boolean intersectsSphere(BoundingSphere sphere, TempVars vars); |
||||||
|
|
||||||
|
/** |
||||||
|
* @see Light#intersectsFrustum(Camera, TempVars) |
||||||
|
*/ |
||||||
|
public abstract boolean intersectsFrustum(Camera camera, TempVars vars); |
||||||
|
} |
@ -0,0 +1,102 @@ |
|||||||
|
package com.jme3.light; |
||||||
|
|
||||||
|
import com.jme3.bounding.*; |
||||||
|
import com.jme3.export.*; |
||||||
|
import com.jme3.math.Matrix4f; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.renderer.Camera; |
||||||
|
import com.jme3.util.TempVars; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.logging.Level; |
||||||
|
|
||||||
|
public class SphereProbeArea implements ProbeArea { |
||||||
|
|
||||||
|
private Vector3f center = new Vector3f(); |
||||||
|
private float radius = 1; |
||||||
|
private Matrix4f uniformMatrix = new Matrix4f(); |
||||||
|
|
||||||
|
public SphereProbeArea() { |
||||||
|
} |
||||||
|
|
||||||
|
public SphereProbeArea(Vector3f center, float radius) { |
||||||
|
this.center.set(center); |
||||||
|
this.radius = radius; |
||||||
|
updateMatrix(); |
||||||
|
} |
||||||
|
|
||||||
|
public Vector3f getCenter() { |
||||||
|
return center; |
||||||
|
} |
||||||
|
|
||||||
|
public void setCenter(Vector3f center) { |
||||||
|
this.center.set(center); |
||||||
|
updateMatrix(); |
||||||
|
} |
||||||
|
|
||||||
|
public float getRadius() { |
||||||
|
return radius; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRadius(float radius) { |
||||||
|
this.radius = radius; |
||||||
|
updateMatrix(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Matrix4f getUniformMatrix() { |
||||||
|
return uniformMatrix; |
||||||
|
} |
||||||
|
|
||||||
|
private void updateMatrix(){ |
||||||
|
//position
|
||||||
|
uniformMatrix.m03 = center.x; |
||||||
|
uniformMatrix.m13 = center.y; |
||||||
|
uniformMatrix.m23 = center.z; |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean intersectsBox(BoundingBox box, TempVars vars) { |
||||||
|
return Intersection.intersect(box, center, radius); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) { |
||||||
|
return Intersection.intersect(sphere, center, radius); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean intersectsFrustum(Camera camera, TempVars vars) { |
||||||
|
return Intersection.intersect(camera, center, radius); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String toString() { |
||||||
|
return "SphereProbeArea{" + |
||||||
|
"center=" + center + |
||||||
|
", radius=" + radius + |
||||||
|
'}'; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected SphereProbeArea clone() throws CloneNotSupportedException { |
||||||
|
return new SphereProbeArea(center, radius); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void write(JmeExporter e) throws IOException { |
||||||
|
OutputCapsule oc = e.getCapsule(this); |
||||||
|
oc.write(center, "center", new Vector3f()); |
||||||
|
oc.write(radius, "radius", 1); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void read(JmeImporter i) throws IOException { |
||||||
|
InputCapsule ic = i.getCapsule(this); |
||||||
|
center = (Vector3f) ic.readSavable("center", new Vector3f()); |
||||||
|
radius = ic.readFloat("radius", 1); |
||||||
|
updateMatrix(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,77 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2015 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.light; |
||||||
|
|
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* This strategy returns the 3 closest probe from the rendered object. |
||||||
|
* <p> |
||||||
|
* Image based lighting will be blended between those probes in the shader according to their distance and range. |
||||||
|
* |
||||||
|
* @author Nehon |
||||||
|
*/ |
||||||
|
public class WeightedProbeBlendingStrategy implements LightProbeBlendingStrategy { |
||||||
|
|
||||||
|
private final static int MAX_PROBES = 3; |
||||||
|
List<LightProbe> lightProbes = new ArrayList<LightProbe>(); |
||||||
|
|
||||||
|
@Override |
||||||
|
public void registerProbe(LightProbe probe) { |
||||||
|
lightProbes.add(probe); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void populateProbes(Geometry g, LightList lightList) { |
||||||
|
if (!lightProbes.isEmpty()) { |
||||||
|
//The 3 first probes are the closest to the geometry since the
|
||||||
|
//light list is sorted according to the distance to the geom.
|
||||||
|
int addedProbes = 0; |
||||||
|
for (LightProbe p : lightProbes) { |
||||||
|
if (p.isReady() && p.isEnabled()) { |
||||||
|
lightList.add(p); |
||||||
|
addedProbes ++; |
||||||
|
} |
||||||
|
if (addedProbes == MAX_PROBES) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//clearing the list for next pass.
|
||||||
|
lightProbes.clear(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,301 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2012 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package jme3test.light; |
||||||
|
|
||||||
|
import com.jme3.app.ChaseCameraAppState; |
||||||
|
import com.jme3.app.SimpleApplication; |
||||||
|
import com.jme3.bounding.BoundingBox; |
||||||
|
import com.jme3.bounding.BoundingSphere; |
||||||
|
import com.jme3.export.binary.BinaryExporter; |
||||||
|
import com.jme3.input.KeyInput; |
||||||
|
import com.jme3.input.MouseInput; |
||||||
|
import com.jme3.input.controls.*; |
||||||
|
import com.jme3.light.*; |
||||||
|
import com.jme3.material.Material; |
||||||
|
import com.jme3.math.*; |
||||||
|
import com.jme3.renderer.Camera; |
||||||
|
import com.jme3.scene.*; |
||||||
|
import com.jme3.scene.debug.Grid; |
||||||
|
import com.jme3.scene.debug.WireFrustum; |
||||||
|
import com.jme3.scene.shape.*; |
||||||
|
import com.jme3.shadow.ShadowUtil; |
||||||
|
import com.jme3.util.TempVars; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
public class TestObbVsBounds extends SimpleApplication { |
||||||
|
|
||||||
|
private Node ln; |
||||||
|
private BoundingBox aabb = new BoundingBox(); |
||||||
|
private BoundingSphere sphere = new BoundingSphere(10, new Vector3f(-30, 0, -60)); |
||||||
|
|
||||||
|
private final static float MOVE_SPEED = 60; |
||||||
|
private Vector3f tmp = new Vector3f(); |
||||||
|
private Quaternion tmpQuat = new Quaternion(); |
||||||
|
private boolean moving, shift; |
||||||
|
private boolean panning; |
||||||
|
|
||||||
|
private OrientedBoxProbeArea area = new OrientedBoxProbeArea(); |
||||||
|
private Camera frustumCam; |
||||||
|
|
||||||
|
private Geometry areaGeom; |
||||||
|
private Geometry frustumGeom; |
||||||
|
private Geometry aabbGeom; |
||||||
|
private Geometry sphereGeom; |
||||||
|
|
||||||
|
public static void main(String[] args) { |
||||||
|
TestObbVsBounds app = new TestObbVsBounds(); |
||||||
|
app.start(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void simpleInitApp() { |
||||||
|
viewPort.setBackgroundColor(ColorRGBA.DarkGray); |
||||||
|
frustumCam = cam.clone(); |
||||||
|
frustumCam.setFrustumFar(25); |
||||||
|
makeCamFrustum(); |
||||||
|
aabb.setCenter(20, 10, -60); |
||||||
|
aabb.setXExtent(10); |
||||||
|
aabb.setYExtent(5); |
||||||
|
aabb.setZExtent(3); |
||||||
|
makeBoxWire(aabb); |
||||||
|
makeSphereWire(sphere); |
||||||
|
|
||||||
|
rootNode.addLight(new DirectionalLight()); |
||||||
|
AmbientLight al = new AmbientLight(); |
||||||
|
al.setColor(ColorRGBA.White.mult(0.2f)); |
||||||
|
rootNode.addLight(al); |
||||||
|
|
||||||
|
Grid grid = new Grid(50, 50, 5); |
||||||
|
Geometry gridGeom = new Geometry("grid", grid); |
||||||
|
gridGeom.setMaterial(new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md")); |
||||||
|
gridGeom.getMaterial().setColor("Color", ColorRGBA.Gray); |
||||||
|
rootNode.attachChild(gridGeom); |
||||||
|
gridGeom.setLocalTranslation(-125, -25, -125); |
||||||
|
|
||||||
|
area.setCenter(Vector3f.ZERO); |
||||||
|
area.setExtent(new Vector3f(4, 8, 5)); |
||||||
|
makeAreaGeom(); |
||||||
|
|
||||||
|
ln = new Node("lb"); |
||||||
|
ln.setLocalRotation(new Quaternion(-0.18826798f, -0.38304946f, -0.12780227f, 0.895261f)); |
||||||
|
ln.attachChild(areaGeom); |
||||||
|
ln.setLocalScale(4,8,5); |
||||||
|
rootNode.attachChild(ln); |
||||||
|
|
||||||
|
inputManager.addMapping("click", new MouseButtonTrigger(MouseInput.BUTTON_RIGHT)); |
||||||
|
inputManager.addMapping("shift", new KeyTrigger(KeyInput.KEY_LSHIFT), new KeyTrigger(KeyInput.KEY_RSHIFT)); |
||||||
|
inputManager.addMapping("middleClick", new MouseButtonTrigger(MouseInput.BUTTON_MIDDLE)); |
||||||
|
inputManager.addMapping("up", new MouseAxisTrigger(MouseInput.AXIS_Y, false)); |
||||||
|
inputManager.addMapping("down", new MouseAxisTrigger(MouseInput.AXIS_Y, true)); |
||||||
|
inputManager.addMapping("left", new MouseAxisTrigger(MouseInput.AXIS_X, true)); |
||||||
|
inputManager.addMapping("right", new MouseAxisTrigger(MouseInput.AXIS_X, false)); |
||||||
|
|
||||||
|
|
||||||
|
final Node camTarget = new Node("CamTarget"); |
||||||
|
rootNode.attachChild(camTarget); |
||||||
|
|
||||||
|
ChaseCameraAppState chaser = new ChaseCameraAppState(); |
||||||
|
chaser.setTarget(camTarget); |
||||||
|
chaser.setMaxDistance(150); |
||||||
|
chaser.setDefaultDistance(70); |
||||||
|
chaser.setDefaultHorizontalRotation(FastMath.HALF_PI); |
||||||
|
chaser.setMinVerticalRotation(-FastMath.PI); |
||||||
|
chaser.setMaxVerticalRotation(FastMath.PI * 2); |
||||||
|
chaser.setToggleRotationTrigger(new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); |
||||||
|
stateManager.attach(chaser); |
||||||
|
flyCam.setEnabled(false); |
||||||
|
|
||||||
|
inputManager.addListener(new AnalogListener() { |
||||||
|
public void onAnalog(String name, float value, float tpf) { |
||||||
|
Spatial s = null; |
||||||
|
float mult = 1; |
||||||
|
if (moving) { |
||||||
|
s = ln; |
||||||
|
} |
||||||
|
if (panning) { |
||||||
|
s = camTarget; |
||||||
|
mult = -1; |
||||||
|
} |
||||||
|
if ((moving || panning) && s != null) { |
||||||
|
if (shift) { |
||||||
|
if (name.equals("left")) { |
||||||
|
tmp.set(cam.getDirection()); |
||||||
|
s.rotate(tmpQuat.fromAngleAxis(value, tmp)); |
||||||
|
} |
||||||
|
if (name.equals("right")) { |
||||||
|
tmp.set(cam.getDirection()); |
||||||
|
s.rotate(tmpQuat.fromAngleAxis(-value, tmp)); |
||||||
|
} |
||||||
|
} else { |
||||||
|
value *= MOVE_SPEED * mult; |
||||||
|
if (name.equals("up")) { |
||||||
|
tmp.set(cam.getUp()).multLocal(value); |
||||||
|
s.move(tmp); |
||||||
|
} |
||||||
|
if (name.equals("down")) { |
||||||
|
tmp.set(cam.getUp()).multLocal(-value); |
||||||
|
s.move(tmp); |
||||||
|
} |
||||||
|
if (name.equals("left")) { |
||||||
|
tmp.set(cam.getLeft()).multLocal(value); |
||||||
|
s.move(tmp); |
||||||
|
} |
||||||
|
if (name.equals("right")) { |
||||||
|
tmp.set(cam.getLeft()).multLocal(-value); |
||||||
|
s.move(tmp); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}, "up", "down", "left", "right"); |
||||||
|
|
||||||
|
inputManager.addListener(new ActionListener() { |
||||||
|
public void onAction(String name, boolean isPressed, float tpf) { |
||||||
|
if (name.equals("click")) { |
||||||
|
if (isPressed) { |
||||||
|
moving = true; |
||||||
|
} else { |
||||||
|
moving = false; |
||||||
|
} |
||||||
|
} |
||||||
|
if (name.equals("middleClick")) { |
||||||
|
if (isPressed) { |
||||||
|
panning = true; |
||||||
|
} else { |
||||||
|
panning = false; |
||||||
|
} |
||||||
|
} |
||||||
|
if (name.equals("shift")) { |
||||||
|
if (isPressed) { |
||||||
|
shift = true; |
||||||
|
} else { |
||||||
|
shift = false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}, "click", "middleClick", "shift"); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public void makeAreaGeom() { |
||||||
|
|
||||||
|
Vector3f[] points = new Vector3f[8]; |
||||||
|
|
||||||
|
for (int i = 0; i < points.length; i++) { |
||||||
|
points[i] = new Vector3f(); |
||||||
|
} |
||||||
|
|
||||||
|
points[0].set(-1, -1, 1); |
||||||
|
points[1].set(-1, 1, 1); |
||||||
|
points[2].set(1, 1, 1); |
||||||
|
points[3].set(1, -1, 1); |
||||||
|
|
||||||
|
points[4].set(-1, -1, -1); |
||||||
|
points[5].set(-1, 1, -1); |
||||||
|
points[6].set(1, 1, -1); |
||||||
|
points[7].set(1, -1, -1); |
||||||
|
|
||||||
|
Mesh box = WireFrustum.makeFrustum(points); |
||||||
|
areaGeom = new Geometry("light", (Mesh)box); |
||||||
|
areaGeom.setMaterial(new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md")); |
||||||
|
areaGeom.getMaterial().setColor("Color", ColorRGBA.White); |
||||||
|
} |
||||||
|
|
||||||
|
public void makeCamFrustum() { |
||||||
|
Vector3f[] points = new Vector3f[8]; |
||||||
|
for (int i = 0; i < 8; i++) { |
||||||
|
points[i] = new Vector3f(); |
||||||
|
} |
||||||
|
ShadowUtil.updateFrustumPoints2(frustumCam, points); |
||||||
|
WireFrustum frustumShape = new WireFrustum(points); |
||||||
|
frustumGeom = new Geometry("frustum", frustumShape); |
||||||
|
frustumGeom.setMaterial(new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md")); |
||||||
|
rootNode.attachChild(frustumGeom); |
||||||
|
} |
||||||
|
|
||||||
|
public void makeBoxWire(BoundingBox box) { |
||||||
|
Vector3f[] points = new Vector3f[8]; |
||||||
|
for (int i = 0; i < 8; i++) { |
||||||
|
points[i] = new Vector3f(); |
||||||
|
} |
||||||
|
points[0].set(-1, -1, 1); |
||||||
|
points[1].set(-1, 1, 1); |
||||||
|
points[2].set(1, 1, 1); |
||||||
|
points[3].set(1, -1, 1); |
||||||
|
|
||||||
|
points[4].set(-1, -1, -1); |
||||||
|
points[5].set(-1, 1, -1); |
||||||
|
points[6].set(1, 1, -1); |
||||||
|
points[7].set(1, -1, -1); |
||||||
|
|
||||||
|
WireFrustum frustumShape = new WireFrustum(points); |
||||||
|
aabbGeom = new Geometry("box", frustumShape); |
||||||
|
aabbGeom.setMaterial(new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md")); |
||||||
|
aabbGeom.getMaterial().getAdditionalRenderState().setWireframe(true); |
||||||
|
aabbGeom.setLocalTranslation(box.getCenter()); |
||||||
|
aabbGeom.setLocalScale(box.getXExtent(), box.getYExtent(), box.getZExtent()); |
||||||
|
rootNode.attachChild(aabbGeom); |
||||||
|
} |
||||||
|
|
||||||
|
public void makeSphereWire(BoundingSphere sphere) { |
||||||
|
|
||||||
|
sphereGeom = new Geometry("box", new Sphere(16, 16, 10)); |
||||||
|
sphereGeom.setMaterial(new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md")); |
||||||
|
sphereGeom.getMaterial().getAdditionalRenderState().setWireframe(true); |
||||||
|
sphereGeom.setLocalTranslation(sphere.getCenter()); |
||||||
|
rootNode.attachChild(sphereGeom); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void simpleUpdate(float tpf) { |
||||||
|
|
||||||
|
area.setCenter(ln.getLocalTranslation()); |
||||||
|
area.setRotation(ln.getLocalRotation()); |
||||||
|
|
||||||
|
TempVars vars = TempVars.get(); |
||||||
|
boolean intersectBox = area.intersectsBox(aabb, vars); |
||||||
|
boolean intersectFrustum = area.intersectsFrustum(frustumCam, vars); |
||||||
|
boolean intersectSphere = area.intersectsSphere(sphere, vars); |
||||||
|
vars.release(); |
||||||
|
|
||||||
|
boolean intersect = intersectBox || intersectFrustum || intersectSphere; |
||||||
|
|
||||||
|
areaGeom.getMaterial().setColor("Color", intersect ? ColorRGBA.Green : ColorRGBA.White); |
||||||
|
sphereGeom.getMaterial().setColor("Color", intersectSphere ? ColorRGBA.Cyan : ColorRGBA.White); |
||||||
|
frustumGeom.getMaterial().setColor("Color", intersectFrustum ? ColorRGBA.Cyan : ColorRGBA.White); |
||||||
|
aabbGeom.getMaterial().setColor("Color", intersectBox ? ColorRGBA.Cyan : ColorRGBA.White); |
||||||
|
|
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue