Converted spatial over to use Cloner to do its various
deep and semi-shallow cloning. I'd be very surprised if nothing is broken as there is only so much testing I can easily do. Also various fixes for places I forgot to call super.cloneFields().
This commit is contained in:
parent
0a876b04d2
commit
ab6fb03171
@ -118,22 +118,17 @@ public class EffectTrack implements ClonableTrack {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public Object jmeClone() {
|
||||
KillParticleControl c = new KillParticleControl();
|
||||
//this control should be removed as it shouldn't have been persisted in the first place
|
||||
//In the quest to find the less hackish solution to achieve this,
|
||||
//making it remove itself from the spatial in the first update loop when loaded was the less bad.
|
||||
//In the quest to find the less hackish solution to achieve this,
|
||||
//making it remove itself from the spatial in the first update loop when loaded was the less bad.
|
||||
c.remove = true;
|
||||
c.spatial = spatial;
|
||||
return c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
this.spatial = cloner.clone(spatial);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void controlRender(RenderManager rm, ViewPort vp) {
|
||||
}
|
||||
@ -143,8 +138,8 @@ public class EffectTrack implements ClonableTrack {
|
||||
|
||||
KillParticleControl c = new KillParticleControl();
|
||||
//this control should be removed as it shouldn't have been persisted in the first place
|
||||
//In the quest to find the less hackish solution to achieve this,
|
||||
//making it remove itself from the spatial in the first update loop when loaded was the less bad.
|
||||
//In the quest to find the less hackish solution to achieve this,
|
||||
//making it remove itself from the spatial in the first update loop when loaded was the less bad.
|
||||
c.remove = true;
|
||||
c.setSpatial(spatial);
|
||||
return c;
|
||||
@ -261,7 +256,7 @@ public class EffectTrack implements ClonableTrack {
|
||||
public float[] getKeyFrameTimes() {
|
||||
return new float[] { startOffset };
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clone this track
|
||||
*
|
||||
@ -302,21 +297,21 @@ public class EffectTrack implements ClonableTrack {
|
||||
return effectTrack;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public Object jmeClone() {
|
||||
try {
|
||||
return super.clone();
|
||||
} catch( CloneNotSupportedException e ) {
|
||||
throw new RuntimeException("Error cloning", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
this.emitter = cloner.clone(emitter);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* recursive function responsible for finding the newly cloned Emitter
|
||||
*
|
||||
|
@ -730,6 +730,8 @@ public class AudioNode extends Node implements AudioSource {
|
||||
*/
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
super.cloneFields(cloner, original);
|
||||
|
||||
this.direction = cloner.clone(direction);
|
||||
this.velocity = cloner.clone(velocity);
|
||||
|
||||
|
@ -174,6 +174,13 @@ public class ParticleEmitter extends Geometry {
|
||||
|
||||
@Override
|
||||
public ParticleEmitter clone(boolean cloneMaterial) {
|
||||
return (ParticleEmitter)super.clone(cloneMaterial);
|
||||
}
|
||||
|
||||
/**
|
||||
* The old clone() method that did not use the new Cloner utility.
|
||||
*/
|
||||
public ParticleEmitter oldClone(boolean cloneMaterial) {
|
||||
ParticleEmitter clone = (ParticleEmitter) super.clone(cloneMaterial);
|
||||
clone.shape = shape.deepClone();
|
||||
|
||||
@ -216,6 +223,8 @@ public class ParticleEmitter extends Geometry {
|
||||
*/
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
super.cloneFields(cloner, original);
|
||||
|
||||
this.shape = cloner.clone(shape);
|
||||
this.control = cloner.clone(control);
|
||||
this.faceNormal = cloner.clone(faceNormal);
|
||||
|
@ -125,6 +125,8 @@ public class RadialParticleInfluencer extends DefaultParticleInfluencer {
|
||||
*/
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
super.cloneFields(cloner, original);
|
||||
|
||||
// Change in behavior: the old origin was not cloned -pspeed
|
||||
this.origin = cloner.clone(origin);
|
||||
}
|
||||
|
@ -90,6 +90,8 @@ public class BitmapText extends Node {
|
||||
*/
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
super.cloneFields(cloner, original);
|
||||
|
||||
for( int i = 0; i < textPages.length; i++ ) {
|
||||
textPages[i] = cloner.clone(textPages[i]);
|
||||
}
|
||||
|
@ -76,6 +76,8 @@ public class AssetLinkNode extends Node {
|
||||
*/
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
super.cloneFields(cloner, original);
|
||||
|
||||
// This is a change in behavior because the old version did not clone
|
||||
// this list... changes to one clone would be reflected in all.
|
||||
// I think that's probably undesirable. -pspeed
|
||||
|
@ -727,6 +727,8 @@ public class BatchNode extends GeometryGroupNode {
|
||||
*/
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
super.cloneFields(cloner, original);
|
||||
|
||||
this.batches = cloner.clone(batches);
|
||||
this.tmpFloat = cloner.clone(tmpFloat);
|
||||
this.tmpFloatN = cloner.clone(tmpFloatN);
|
||||
|
@ -100,6 +100,8 @@ public class CameraNode extends Node {
|
||||
*/
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
super.cloneFields(cloner, original);
|
||||
|
||||
// A change in behavior... I think previously CameraNode was probably
|
||||
// not really cloneable... or at least its camControl would be pointing
|
||||
// to the wrong control. -pspeed
|
||||
|
@ -44,6 +44,7 @@ import com.jme3.math.Matrix4f;
|
||||
import com.jme3.renderer.Camera;
|
||||
import com.jme3.scene.VertexBuffer.Type;
|
||||
import com.jme3.util.clone.Cloner;
|
||||
import com.jme3.util.clone.IdentityCloneFunction;
|
||||
import com.jme3.util.TempVars;
|
||||
import java.io.IOException;
|
||||
import java.util.Queue;
|
||||
@ -492,6 +493,13 @@ public class Geometry extends Spatial {
|
||||
*/
|
||||
@Override
|
||||
public Geometry clone(boolean cloneMaterial) {
|
||||
return (Geometry)super.clone(cloneMaterial);
|
||||
}
|
||||
|
||||
/**
|
||||
* The old clone() method that did not use the new Cloner utility.
|
||||
*/
|
||||
public Geometry oldClone(boolean cloneMaterial) {
|
||||
Geometry geomClone = (Geometry) super.clone(cloneMaterial);
|
||||
|
||||
// This geometry is managed,
|
||||
@ -535,6 +543,10 @@ public class Geometry extends Spatial {
|
||||
*/
|
||||
@Override
|
||||
public Spatial deepClone() {
|
||||
return super.deepClone();
|
||||
}
|
||||
|
||||
public Spatial oldDeepClone() {
|
||||
Geometry geomClone = clone(true);
|
||||
geomClone.mesh = mesh.deepClone();
|
||||
return geomClone;
|
||||
@ -545,9 +557,42 @@ public class Geometry extends Spatial {
|
||||
*/
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
this.mesh = cloner.clone(mesh);
|
||||
super.cloneFields(cloner, original);
|
||||
|
||||
// If this is a grouped node and if our group node is
|
||||
// also cloned then we'll grab it's reference.
|
||||
if( groupNode != null ) {
|
||||
if( cloner.isCloned(groupNode) ) {
|
||||
// Then resolve the reference
|
||||
this.groupNode = cloner.clone(groupNode);
|
||||
} else {
|
||||
// We are on our own now
|
||||
this.groupNode = null;
|
||||
this.startIndex = -1;
|
||||
}
|
||||
|
||||
// The above is based on the fact that if we were
|
||||
// cloning the hierarchy that contained the parent
|
||||
// group then it would have been shallow cloned before
|
||||
// this child. Can't really be otherwise.
|
||||
}
|
||||
|
||||
this.cachedWorldMat = cloner.clone(cachedWorldMat);
|
||||
|
||||
// See if we are doing a shallow clone or a deep mesh clone
|
||||
boolean shallowClone = (cloner.getCloneFunction(Mesh.class) instanceof IdentityCloneFunction);
|
||||
|
||||
// See if we clone the mesh using the special animation
|
||||
// semi-deep cloning
|
||||
if( shallowClone && mesh != null && mesh.getBuffer(Type.BindPosePosition) != null ) {
|
||||
// Then we need to clone the mesh a little deeper
|
||||
this.mesh = mesh.cloneForAnim();
|
||||
} else {
|
||||
// Do whatever the cloner wants to do about it
|
||||
this.mesh = cloner.clone(mesh);
|
||||
}
|
||||
|
||||
this.material = cloner.clone(material);
|
||||
this.groupNode = cloner.clone(groupNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -100,6 +100,8 @@ public class LightNode extends Node {
|
||||
*/
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
super.cloneFields(cloner, original);
|
||||
|
||||
// A change in behavior... I think previously LightNode was probably
|
||||
// not really cloneable... or at least its lightControl would be pointing
|
||||
// to the wrong control. -pspeed
|
||||
|
@ -307,7 +307,9 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
|
||||
@Override
|
||||
public Mesh jmeClone() {
|
||||
try {
|
||||
return (Mesh)super.clone();
|
||||
Mesh clone = (Mesh)super.clone();
|
||||
clone.vertexArrayID = -1;
|
||||
return clone;
|
||||
} catch (CloneNotSupportedException ex) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
@ -697,7 +697,17 @@ public class Node extends Spatial {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spatial deepClone(){
|
||||
public Spatial deepClone() {
|
||||
Node nodeClone = (Node)super.deepClone();
|
||||
|
||||
// Reset the fields of the clone that should be in a 'new' state.
|
||||
nodeClone.updateList = null;
|
||||
nodeClone.updateListValid = false; // safe because parent is nulled out in super.clone()
|
||||
|
||||
return nodeClone;
|
||||
}
|
||||
|
||||
public Spatial oldDeepClone(){
|
||||
Node nodeClone = (Node) super.clone();
|
||||
nodeClone.children = new SafeArrayList<Spatial>(Spatial.class);
|
||||
for (Spatial child : children){
|
||||
@ -713,6 +723,8 @@ public class Node extends Spatial {
|
||||
*/
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
super.cloneFields(cloner, original);
|
||||
|
||||
this.children = cloner.clone(children);
|
||||
|
||||
// Only the outer cloning thing knows whether this should be nulled
|
||||
|
@ -48,6 +48,7 @@ import com.jme3.renderer.queue.RenderQueue.Bucket;
|
||||
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
|
||||
import com.jme3.scene.control.Control;
|
||||
import com.jme3.util.clone.Cloner;
|
||||
import com.jme3.util.clone.IdentityCloneFunction;
|
||||
import com.jme3.util.clone.JmeCloneable;
|
||||
import com.jme3.util.SafeArrayList;
|
||||
import com.jme3.util.TempVars;
|
||||
@ -1263,12 +1264,42 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
||||
* Note that meshes of geometries are not cloned explicitly, they
|
||||
* are shared if static, or specially cloned if animated.
|
||||
*
|
||||
* All controls will be cloned using the Control.cloneForSpatial method
|
||||
* on the clone.
|
||||
*
|
||||
* @see Mesh#cloneForAnim()
|
||||
*/
|
||||
public Spatial clone(boolean cloneMaterial) {
|
||||
public Spatial clone( boolean cloneMaterial ) {
|
||||
|
||||
// Setup the cloner for the type of cloning we want to do.
|
||||
Cloner cloner = new Cloner();
|
||||
|
||||
// First, we definitely do not want to clone our own parent
|
||||
cloner.setClonedValue(parent, null);
|
||||
|
||||
// If we aren't cloning materials then we will make sure those
|
||||
// aren't cloned also
|
||||
if( !cloneMaterial ) {
|
||||
cloner.setCloneFunction(Material.class, new IdentityCloneFunction<Material>());
|
||||
}
|
||||
|
||||
// By default the meshes are not cloned. The geometry
|
||||
// may choose to selectively force them to be cloned but
|
||||
// normally they will be shared
|
||||
cloner.setCloneFunction(Mesh.class, new IdentityCloneFunction<Mesh>());
|
||||
|
||||
// Clone it!
|
||||
Spatial clone = cloner.clone(this);
|
||||
|
||||
// Because we've nulled the parent out we need to make sure
|
||||
// the transforms and stuff get refreshed.
|
||||
clone.setTransformRefresh();
|
||||
clone.setLightListRefresh();
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* The old clone() method that did not use the new Cloner utility.
|
||||
*/
|
||||
public Spatial oldClone(boolean cloneMaterial) {
|
||||
try {
|
||||
Spatial clone = (Spatial) super.clone();
|
||||
if (worldBound != null) {
|
||||
@ -1344,7 +1375,22 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
||||
*
|
||||
* @see Spatial#clone()
|
||||
*/
|
||||
public abstract Spatial deepClone();
|
||||
public Spatial deepClone() {
|
||||
// Setup the cloner for the type of cloning we want to do.
|
||||
Cloner cloner = new Cloner();
|
||||
|
||||
// First, we definitely do not want to clone our own parent
|
||||
cloner.setClonedValue(parent, null);
|
||||
|
||||
Spatial clone = cloner.clone(this);
|
||||
|
||||
// Because we've nulled the parent out we need to make sure
|
||||
// the transforms and stuff get refreshed.
|
||||
clone.setTransformRefresh();
|
||||
clone.setLightListRefresh();
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called internally by com.jme3.util.clone.Cloner. Do not call directly.
|
||||
@ -1381,13 +1427,15 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
||||
// to avoid all of the nasty cloneForSpatial() fixup style code that
|
||||
// used to inject stuff into the clone's user data. By using cloner
|
||||
// to clone the user data we get this automatically.
|
||||
userData = (HashMap<String, Savable>)userData.clone();
|
||||
for( Map.Entry<String, Savable> e : userData.entrySet() ) {
|
||||
Savable value = e.getValue();
|
||||
if( value instanceof Cloneable ) {
|
||||
// Note: all JmeCloneable objects are also Cloneable so this
|
||||
// catches both cases.
|
||||
e.setValue(cloner.clone(value));
|
||||
if( userData != null ) {
|
||||
userData = (HashMap<String, Savable>)userData.clone();
|
||||
for( Map.Entry<String, Savable> e : userData.entrySet() ) {
|
||||
Savable value = e.getValue();
|
||||
if( value instanceof Cloneable ) {
|
||||
// Note: all JmeCloneable objects are also Cloneable so this
|
||||
// catches both cases.
|
||||
e.setValue(cloner.clone(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -349,6 +349,8 @@ public class InstancedGeometry extends Geometry {
|
||||
*/
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
super.cloneFields(cloner, original);
|
||||
|
||||
this.globalInstanceData = cloner.clone(globalInstanceData);
|
||||
this.transformInstanceData = cloner.clone(transformInstanceData);
|
||||
this.geometries = cloner.clone(geometries);
|
||||
|
@ -350,6 +350,8 @@ public class InstancedNode extends GeometryGroupNode {
|
||||
*/
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
super.cloneFields(cloner, original);
|
||||
|
||||
this.control = cloner.clone(control);
|
||||
this.lookUp = cloner.clone(lookUp);
|
||||
|
||||
|
@ -84,6 +84,7 @@ public class NormalRecalcControl extends AbstractControl {
|
||||
*/
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
super.cloneFields(cloner, original);
|
||||
this.terrain = cloner.clone(terrain);
|
||||
}
|
||||
|
||||
|
@ -74,12 +74,12 @@ import java.util.logging.Logger;
|
||||
* This control serializes, but it does not save the Camera reference.
|
||||
* This camera reference has to be manually added in when you load the
|
||||
* terrain to the scene!
|
||||
*
|
||||
*
|
||||
* When the control or the terrain are removed from the scene, you should call
|
||||
* TerrainLodControl.detachAndCleanUpControl() to remove any threads it created
|
||||
* to handle the LOD processing. If you supply your own executor service, then
|
||||
* you have to handle its thread termination yourself.
|
||||
*
|
||||
*
|
||||
* @author Brent Owens
|
||||
*/
|
||||
public class TerrainLodControl extends AbstractControl {
|
||||
@ -92,15 +92,15 @@ public class TerrainLodControl extends AbstractControl {
|
||||
|
||||
private HashMap<String,UpdatedTerrainPatch> updatedPatches;
|
||||
private final Object updatePatchesLock = new Object();
|
||||
|
||||
|
||||
protected List<Vector3f> lastCameraLocations; // used for LOD calc
|
||||
private AtomicBoolean lodCalcRunning = new AtomicBoolean(false);
|
||||
private int lodOffCount = 0;
|
||||
|
||||
|
||||
protected ExecutorService executor;
|
||||
protected Future<HashMap<String, UpdatedTerrainPatch>> indexer;
|
||||
private boolean forceUpdate = true;
|
||||
|
||||
|
||||
public TerrainLodControl() {
|
||||
}
|
||||
|
||||
@ -111,7 +111,7 @@ public class TerrainLodControl extends AbstractControl {
|
||||
this.cameras = cams;
|
||||
lodCalculator = new DistanceLodCalculator(65, 2.7f); // a default calculator
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Only uses the first camera right now.
|
||||
* @param terrain to act upon (must be a Spatial)
|
||||
@ -134,7 +134,7 @@ public class TerrainLodControl extends AbstractControl {
|
||||
public void setExecutor(ExecutorService executor) {
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
|
||||
protected ExecutorService createExecutorService() {
|
||||
return Executors.newSingleThreadExecutor(new ThreadFactory() {
|
||||
public Thread newThread(Runnable r) {
|
||||
@ -145,14 +145,14 @@ public class TerrainLodControl extends AbstractControl {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void controlUpdate(float tpf) {
|
||||
//list of cameras for when terrain supports multiple cameras (ie split screen)
|
||||
|
||||
if (lodCalculator == null)
|
||||
return;
|
||||
|
||||
|
||||
if (!enabled) {
|
||||
if (!hasResetLod) {
|
||||
// this will get run once
|
||||
@ -160,7 +160,7 @@ public class TerrainLodControl extends AbstractControl {
|
||||
lodCalculator.turnOffLod();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (cameras != null) {
|
||||
cameraLocations.clear();
|
||||
for (Camera c : cameras) // populate them
|
||||
@ -170,7 +170,7 @@ public class TerrainLodControl extends AbstractControl {
|
||||
updateLOD(cameraLocations, lodCalculator);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Call this when you remove the terrain or this control from the scene.
|
||||
* It will clear up any threads it had.
|
||||
@ -186,7 +186,7 @@ public class TerrainLodControl extends AbstractControl {
|
||||
if(getSpatial() == null){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// update any existing ones that need updating
|
||||
updateQuadLODs();
|
||||
|
||||
@ -196,9 +196,9 @@ public class TerrainLodControl extends AbstractControl {
|
||||
return;
|
||||
else
|
||||
lodOffCount++;
|
||||
} else
|
||||
} else
|
||||
lodOffCount = 0;
|
||||
|
||||
|
||||
if (lastCameraLocations != null) {
|
||||
if (!forceUpdate && lastCameraLocationsTheSame(locations) && !lodCalculator.isLodOff())
|
||||
return; // don't update if in same spot
|
||||
@ -218,9 +218,9 @@ public class TerrainLodControl extends AbstractControl {
|
||||
|
||||
if (executor == null)
|
||||
executor = createExecutorService();
|
||||
|
||||
|
||||
prepareTerrain();
|
||||
|
||||
|
||||
UpdateLOD updateLodThread = getLodThread(locations, lodCalculator);
|
||||
indexer = executor.submit(updateLodThread);
|
||||
}
|
||||
@ -232,12 +232,12 @@ public class TerrainLodControl extends AbstractControl {
|
||||
public void forceUpdate() {
|
||||
this.forceUpdate = true;
|
||||
}
|
||||
|
||||
|
||||
protected void prepareTerrain() {
|
||||
TerrainQuad terrain = (TerrainQuad)getSpatial();
|
||||
terrain.cacheTerrainTransforms();// cache the terrain's world transforms so they can be accessed on the separate thread safely
|
||||
}
|
||||
|
||||
|
||||
protected UpdateLOD getLodThread(List<Vector3f> locations, LodCalculator lodCalculator) {
|
||||
return new UpdateLOD(locations, lodCalculator);
|
||||
}
|
||||
@ -249,7 +249,7 @@ public class TerrainLodControl extends AbstractControl {
|
||||
if (indexer != null) {
|
||||
if (indexer.isDone()) {
|
||||
try {
|
||||
|
||||
|
||||
HashMap<String, UpdatedTerrainPatch> updated = indexer.get();
|
||||
if (updated != null) {
|
||||
// do the actual geometry update here
|
||||
@ -257,7 +257,7 @@ public class TerrainLodControl extends AbstractControl {
|
||||
utp.updateAll();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch (InterruptedException ex) {
|
||||
Logger.getLogger(TerrainLodControl.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} catch (ExecutionException ex) {
|
||||
@ -268,7 +268,7 @@ public class TerrainLodControl extends AbstractControl {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean lastCameraLocationsTheSame(List<Vector3f> locations) {
|
||||
boolean theSame = true;
|
||||
for (Vector3f l : locations) {
|
||||
@ -281,7 +281,7 @@ public class TerrainLodControl extends AbstractControl {
|
||||
}
|
||||
return theSame;
|
||||
}
|
||||
|
||||
|
||||
protected synchronized boolean isLodCalcRunning() {
|
||||
return lodCalcRunning.get();
|
||||
}
|
||||
@ -297,11 +297,11 @@ public class TerrainLodControl extends AbstractControl {
|
||||
return cloned;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Object jmeClone() {
|
||||
if (spatial instanceof Terrain) {
|
||||
TerrainLodControl cloned = new TerrainLodControl((Terrain) spatial, cameras);
|
||||
@ -310,21 +310,23 @@ public class TerrainLodControl extends AbstractControl {
|
||||
return cloned;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
super.cloneFields(cloner, original);
|
||||
|
||||
this.lodCalculator = cloner.clone(lodCalculator);
|
||||
|
||||
try {
|
||||
|
||||
try {
|
||||
// Not deep clone of the cameras themselves
|
||||
this.cameras = cloner.javaClone(cameras);
|
||||
} catch( CloneNotSupportedException e ) {
|
||||
throw new RuntimeException("Error cloning", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Control cloneForSpatial(Spatial spatial) {
|
||||
if (spatial instanceof Terrain) {
|
||||
@ -346,7 +348,7 @@ public class TerrainLodControl extends AbstractControl {
|
||||
cams.add(camera);
|
||||
setCameras(cams);
|
||||
}
|
||||
|
||||
|
||||
public void setCameras(List<Camera> cameras) {
|
||||
this.cameras = cameras;
|
||||
cameraLocations.clear();
|
||||
@ -374,7 +376,7 @@ public class TerrainLodControl extends AbstractControl {
|
||||
public void setLodCalculator(LodCalculator lodCalculator) {
|
||||
this.lodCalculator = lodCalculator;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
@ -386,8 +388,8 @@ public class TerrainLodControl extends AbstractControl {
|
||||
lodCalculator.turnOnLod();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the LOD of all child terrain patches.
|
||||
*/
|
||||
@ -408,7 +410,7 @@ public class TerrainLodControl extends AbstractControl {
|
||||
setLodCalcRunning(true);
|
||||
|
||||
TerrainQuad terrainQuad = (TerrainQuad)getSpatial();
|
||||
|
||||
|
||||
// go through each patch and calculate its LOD based on camera distance
|
||||
HashMap<String,UpdatedTerrainPatch> updated = new HashMap<String,UpdatedTerrainPatch>();
|
||||
boolean lodChanged = terrainQuad.calculateLod(camLocations, updated, lodCalculator); // 'updated' gets populated here
|
||||
@ -418,8 +420,8 @@ public class TerrainLodControl extends AbstractControl {
|
||||
setLodCalcRunning(false);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// then calculate its neighbour LOD values for seaming in the shader
|
||||
terrainQuad.findNeighboursLod(updated);
|
||||
|
||||
@ -430,7 +432,7 @@ public class TerrainLodControl extends AbstractControl {
|
||||
//setUpdateQuadLODs(updated); // set back to main ogl thread
|
||||
|
||||
setLodCalcRunning(false);
|
||||
|
||||
|
||||
return updated;
|
||||
}
|
||||
}
|
||||
|
@ -961,6 +961,7 @@ public class TerrainPatch extends Geometry {
|
||||
*/
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
super.cloneFields(cloner, original);
|
||||
|
||||
this.stepScale = cloner.clone(stepScale);
|
||||
this.offset = cloner.clone(offset);
|
||||
|
@ -1813,6 +1813,8 @@ public class TerrainQuad extends Node implements Terrain {
|
||||
*/
|
||||
@Override
|
||||
public void cloneFields( Cloner cloner, Object original ) {
|
||||
super.cloneFields(cloner, original);
|
||||
|
||||
this.stepScale = cloner.clone(stepScale);
|
||||
this.offset = cloner.clone(offset);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user