|
|
|
@ -47,14 +47,14 @@ import java.io.IOException; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Determines what Level of Detail a spatial should be, based on how many pixels |
|
|
|
|
* on the screen the spatial is taking up. The more pixels covered, the more detailed |
|
|
|
|
* the spatial should be. |
|
|
|
|
* It calculates the area of the screen that the spatial covers by using its bounding box. |
|
|
|
|
* When initializing, it will ask the spatial for how many triangles it has for each LOD. |
|
|
|
|
* It then uses that, along with the trisPerPixel value to determine what LOD it should be at. |
|
|
|
|
* It requires the camera to do this. |
|
|
|
|
* The controlRender method is called each frame and will update the spatial's LOD |
|
|
|
|
* if the camera has moved by a specified amount. |
|
|
|
|
* on the screen the spatial is taking up. The more pixels covered, the more |
|
|
|
|
* detailed the spatial should be. It calculates the area of the screen that the |
|
|
|
|
* spatial covers by using its bounding box. When initializing, it will ask the |
|
|
|
|
* spatial for how many triangles it has for each LOD. It then uses that, along |
|
|
|
|
* with the trisPerPixel value to determine what LOD it should be at. It |
|
|
|
|
* requires the camera to do this. The controlRender method is called each frame |
|
|
|
|
* and will update the spatial's LOD if the camera has moved by a specified |
|
|
|
|
* amount. |
|
|
|
|
*/ |
|
|
|
|
public class LodControl extends AbstractControl implements Cloneable { |
|
|
|
|
|
|
|
|
@ -66,27 +66,28 @@ public class LodControl extends AbstractControl implements Cloneable { |
|
|
|
|
private int[] numTris; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Creates a new <code>LodControl</code>. |
|
|
|
|
* Creates a new |
|
|
|
|
* <code>LodControl</code>. |
|
|
|
|
*/ |
|
|
|
|
public LodControl(){ |
|
|
|
|
public LodControl() { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Returns the distance tolerance for changing LOD. |
|
|
|
|
* |
|
|
|
|
* |
|
|
|
|
* @return the distance tolerance for changing LOD. |
|
|
|
|
* |
|
|
|
|
* @see #setDistTolerance(float) |
|
|
|
|
* |
|
|
|
|
* @see #setDistTolerance(float) |
|
|
|
|
*/ |
|
|
|
|
public float getDistTolerance() { |
|
|
|
|
return distTolerance; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Specifies the distance tolerance for changing the LOD level on the geometry. |
|
|
|
|
* The LOD level will only get changed if the geometry has moved this |
|
|
|
|
* distance beyond the current LOD level. |
|
|
|
|
* |
|
|
|
|
* Specifies the distance tolerance for changing the LOD level on the |
|
|
|
|
* geometry. The LOD level will only get changed if the geometry has moved |
|
|
|
|
* this distance beyond the current LOD level. |
|
|
|
|
* |
|
|
|
|
* @param distTolerance distance tolerance for changing LOD |
|
|
|
|
*/ |
|
|
|
|
public void setDistTolerance(float distTolerance) { |
|
|
|
@ -95,21 +96,21 @@ public class LodControl extends AbstractControl implements Cloneable { |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Returns the triangles per pixel value. |
|
|
|
|
* |
|
|
|
|
* |
|
|
|
|
* @return the triangles per pixel value. |
|
|
|
|
* |
|
|
|
|
* @see #setTrisPerPixel(float) |
|
|
|
|
* |
|
|
|
|
* @see #setTrisPerPixel(float) |
|
|
|
|
*/ |
|
|
|
|
public float getTrisPerPixel() { |
|
|
|
|
return trisPerPixel; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Sets the triangles per pixel value. |
|
|
|
|
* The <code>LodControl</code> will use this value as an error metric |
|
|
|
|
* to determine which LOD level to use based on the geometry's |
|
|
|
|
* area on the screen. |
|
|
|
|
* |
|
|
|
|
* Sets the triangles per pixel value. The |
|
|
|
|
* <code>LodControl</code> will use this value as an error metric to |
|
|
|
|
* determine which LOD level to use based on the geometry's area on the |
|
|
|
|
* screen. |
|
|
|
|
* |
|
|
|
|
* @param trisPerPixel triangles per pixel |
|
|
|
|
*/ |
|
|
|
|
public void setTrisPerPixel(float trisPerPixel) { |
|
|
|
@ -117,19 +118,22 @@ public class LodControl extends AbstractControl implements Cloneable { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void setSpatial(Spatial spatial){ |
|
|
|
|
if (!(spatial instanceof Geometry)) |
|
|
|
|
public void setSpatial(Spatial spatial) { |
|
|
|
|
if (!(spatial instanceof Geometry)) { |
|
|
|
|
throw new IllegalArgumentException("LodControl can only be attached to Geometry!"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
super.setSpatial(spatial); |
|
|
|
|
Geometry geom = (Geometry) spatial; |
|
|
|
|
Mesh mesh = geom.getMesh(); |
|
|
|
|
numLevels = mesh.getNumLodLevels(); |
|
|
|
|
numTris = new int[numLevels]; |
|
|
|
|
for (int i = numLevels - 1; i >= 0; i--) |
|
|
|
|
for (int i = numLevels - 1; i >= 0; i--) { |
|
|
|
|
numTris[i] = mesh.getTriangleCount(i); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public Control cloneForSpatial(Spatial spatial) { |
|
|
|
|
try { |
|
|
|
|
LodControl clone = (LodControl) super.clone(); |
|
|
|
@ -146,7 +150,7 @@ public class LodControl extends AbstractControl implements Cloneable { |
|
|
|
|
protected void controlUpdate(float tpf) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected void controlRender(RenderManager rm, ViewPort vp){ |
|
|
|
|
protected void controlRender(RenderManager rm, ViewPort vp) { |
|
|
|
|
BoundingVolume bv = spatial.getWorldBound(); |
|
|
|
|
|
|
|
|
|
Camera cam = vp.getCamera(); |
|
|
|
@ -155,21 +159,21 @@ public class LodControl extends AbstractControl implements Cloneable { |
|
|
|
|
float newDistance = bv.distanceTo(vp.getCamera().getLocation()) / ratio; |
|
|
|
|
int level; |
|
|
|
|
|
|
|
|
|
if (Math.abs(newDistance - lastDistance) <= distTolerance) |
|
|
|
|
if (Math.abs(newDistance - lastDistance) <= distTolerance) { |
|
|
|
|
level = lastLevel; // we haven't moved relative to the model, send the old measurement back.
|
|
|
|
|
else if (lastDistance > newDistance && lastLevel == 0) |
|
|
|
|
} else if (lastDistance > newDistance && lastLevel == 0) { |
|
|
|
|
level = lastLevel; // we're already at the lowest setting and we just got closer to the model, no need to keep trying.
|
|
|
|
|
else if (lastDistance < newDistance && lastLevel == numLevels - 1) |
|
|
|
|
} else if (lastDistance < newDistance && lastLevel == numLevels - 1) { |
|
|
|
|
level = lastLevel; // we're already at the highest setting and we just got further from the model, no need to keep trying.
|
|
|
|
|
else{ |
|
|
|
|
} else { |
|
|
|
|
lastDistance = newDistance; |
|
|
|
|
|
|
|
|
|
// estimate area of polygon via bounding volume
|
|
|
|
|
float area = AreaUtils.calcScreenArea(bv, lastDistance, cam.getWidth()); |
|
|
|
|
float trisToDraw = area * trisPerPixel; |
|
|
|
|
level = numLevels - 1; |
|
|
|
|
for (int i = numLevels; --i >= 0;){ |
|
|
|
|
if (trisToDraw - numTris[i] < 0){ |
|
|
|
|
for (int i = numLevels; --i >= 0;) { |
|
|
|
|
if (trisToDraw - numTris[i] < 0) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
level = i; |
|
|
|
@ -181,7 +185,7 @@ public class LodControl extends AbstractControl implements Cloneable { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void write(JmeExporter ex) throws IOException{ |
|
|
|
|
public void write(JmeExporter ex) throws IOException { |
|
|
|
|
super.write(ex); |
|
|
|
|
OutputCapsule oc = ex.getCapsule(this); |
|
|
|
|
oc.write(trisPerPixel, "trisPerPixel", 1f); |
|
|
|
@ -191,7 +195,7 @@ public class LodControl extends AbstractControl implements Cloneable { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void read(JmeImporter im) throws IOException{ |
|
|
|
|
public void read(JmeImporter im) throws IOException { |
|
|
|
|
super.read(im); |
|
|
|
|
InputCapsule ic = im.getCapsule(this); |
|
|
|
|
trisPerPixel = ic.readFloat("trisPerPixel", 1f); |
|
|
|
@ -199,5 +203,4 @@ public class LodControl extends AbstractControl implements Cloneable { |
|
|
|
|
numLevels = ic.readInt("numLevels", 0); |
|
|
|
|
numTris = ic.readIntArray("numTris", null); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|