|
@@ -47,6 +47,8 @@ import com.jme3.renderer.queue.RenderQueue;
|
|
|
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.JmeCloneable;
|
|
|
import com.jme3.util.SafeArrayList;
|
|
|
import com.jme3.util.TempVars;
|
|
|
import java.io.IOException;
|
|
@@ -63,17 +65,17 @@ import java.util.logging.Logger;
|
|
|
* @author Joshua Slack
|
|
|
* @version $Revision: 4075 $, $Data$
|
|
|
*/
|
|
|
-public abstract class Spatial implements Savable, Cloneable, Collidable, CloneableSmartAsset {
|
|
|
+public abstract class Spatial implements Savable, Cloneable, Collidable, CloneableSmartAsset, JmeCloneable {
|
|
|
|
|
|
private static final Logger logger = Logger.getLogger(Spatial.class.getName());
|
|
|
|
|
|
/**
|
|
|
- * Specifies how frustum culling should be handled by
|
|
|
+ * Specifies how frustum culling should be handled by
|
|
|
* this spatial.
|
|
|
*/
|
|
|
public enum CullHint {
|
|
|
|
|
|
- /**
|
|
|
+ /**
|
|
|
* Do whatever our parent does. If no parent, default to {@link #Dynamic}.
|
|
|
*/
|
|
|
Inherit,
|
|
@@ -83,13 +85,13 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
* Camera planes whether or not this Spatial should be culled.
|
|
|
*/
|
|
|
Dynamic,
|
|
|
- /**
|
|
|
+ /**
|
|
|
* Always cull this from the view, throwing away this object
|
|
|
* and any children from rendering commands.
|
|
|
*/
|
|
|
Always,
|
|
|
/**
|
|
|
- * Never cull this from view, always draw it.
|
|
|
+ * Never cull this from view, always draw it.
|
|
|
* Note that we will still get culled if our parent is culled.
|
|
|
*/
|
|
|
Never;
|
|
@@ -100,15 +102,15 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
*/
|
|
|
public enum BatchHint {
|
|
|
|
|
|
- /**
|
|
|
+ /**
|
|
|
* Do whatever our parent does. If no parent, default to {@link #Always}.
|
|
|
*/
|
|
|
Inherit,
|
|
|
- /**
|
|
|
+ /**
|
|
|
* This spatial will always be batched when attached to a BatchNode.
|
|
|
*/
|
|
|
Always,
|
|
|
- /**
|
|
|
+ /**
|
|
|
* This spatial will never be batched when attached to a BatchNode.
|
|
|
*/
|
|
|
Never;
|
|
@@ -118,12 +120,12 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
*/
|
|
|
protected static final int RF_TRANSFORM = 0x01, // need light resort + combine transforms
|
|
|
RF_BOUND = 0x02,
|
|
|
- RF_LIGHTLIST = 0x04, // changes in light lists
|
|
|
+ RF_LIGHTLIST = 0x04, // changes in light lists
|
|
|
RF_CHILD_LIGHTLIST = 0x08; // some child need geometry update
|
|
|
-
|
|
|
+
|
|
|
protected CullHint cullHint = CullHint.Inherit;
|
|
|
protected BatchHint batchHint = BatchHint.Inherit;
|
|
|
- /**
|
|
|
+ /**
|
|
|
* Spatial's bounding volume relative to the world.
|
|
|
*/
|
|
|
protected BoundingVolume worldBound;
|
|
@@ -132,7 +134,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
*/
|
|
|
protected LightList localLights;
|
|
|
protected transient LightList worldLights;
|
|
|
- /**
|
|
|
+ /**
|
|
|
* This spatial's name.
|
|
|
*/
|
|
|
protected String name;
|
|
@@ -147,11 +149,11 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
protected HashMap<String, Savable> userData = null;
|
|
|
/**
|
|
|
* Used for smart asset caching
|
|
|
- *
|
|
|
- * @see AssetKey#useSmartCache()
|
|
|
+ *
|
|
|
+ * @see AssetKey#useSmartCache()
|
|
|
*/
|
|
|
protected AssetKey key;
|
|
|
- /**
|
|
|
+ /**
|
|
|
* Spatial's parent, or null if it has none.
|
|
|
*/
|
|
|
protected transient Node parent;
|
|
@@ -174,7 +176,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
/**
|
|
|
* Serialization only. Do not use.
|
|
|
* Not really. This class is never instantiated directly but the
|
|
|
- * subclasses like to use the no-arg constructor for their own
|
|
|
+ * subclasses like to use the no-arg constructor for their own
|
|
|
* no-arg constructor... which is technically weaker than
|
|
|
* forward supplying defaults.
|
|
|
*/
|
|
@@ -192,7 +194,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
*/
|
|
|
protected Spatial(String name) {
|
|
|
this.name = name;
|
|
|
-
|
|
|
+
|
|
|
localTransform = new Transform();
|
|
|
worldTransform = new Transform();
|
|
|
|
|
@@ -219,13 +221,13 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
boolean requiresUpdates() {
|
|
|
return requiresUpdates | !controls.isEmpty();
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
- * Subclasses can call this with true to denote that they require
|
|
|
+ * Subclasses can call this with true to denote that they require
|
|
|
* updateLogicalState() to be called even if they contain no controls.
|
|
|
* Setting this to false reverts to the default behavior of only
|
|
|
* updating if the spatial has controls. This is not meant to
|
|
|
- * indicate dynamic state in any way and must be called while
|
|
|
+ * indicate dynamic state in any way and must be called while
|
|
|
* unattached or an IllegalStateException is thrown. It is designed
|
|
|
* to be called during object construction and then never changed, ie:
|
|
|
* it's meant to be subclass specific state and not runtime state.
|
|
@@ -251,12 +253,12 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
// override it for more optimal behavior. Node and Geometry will override
|
|
|
// it to false if the class is Node.class or Geometry.class.
|
|
|
// This means that all subclasses will default to the old behavior
|
|
|
- // unless they opt in.
|
|
|
+ // unless they opt in.
|
|
|
if( parent != null ) {
|
|
|
- throw new IllegalStateException("setRequiresUpdates() cannot be called once attached.");
|
|
|
+ throw new IllegalStateException("setRequiresUpdates() cannot be called once attached.");
|
|
|
}
|
|
|
this.requiresUpdates = f;
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
* Indicate that the transform of this spatial has changed and that
|
|
@@ -269,13 +271,13 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
|
|
|
protected void setLightListRefresh() {
|
|
|
refreshFlags |= RF_LIGHTLIST;
|
|
|
-
|
|
|
+
|
|
|
// Make sure next updateGeometricState() visits this branch
|
|
|
// to update lights.
|
|
|
Spatial p = parent;
|
|
|
while (p != null) {
|
|
|
//if (p.refreshFlags != 0) {
|
|
|
- // any refresh flag is sufficient,
|
|
|
+ // any refresh flag is sufficient,
|
|
|
// as each propagates to the root Node
|
|
|
|
|
|
// 2015/2/8:
|
|
@@ -283,16 +285,16 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
// or getWorldTransform() activates a "partial refresh"
|
|
|
// which does not update the lights but does clear
|
|
|
// the refresh flags on the ancestors!
|
|
|
-
|
|
|
- // return;
|
|
|
+
|
|
|
+ // return;
|
|
|
//}
|
|
|
-
|
|
|
+
|
|
|
if ((p.refreshFlags & RF_CHILD_LIGHTLIST) != 0) {
|
|
|
// The parent already has this flag,
|
|
|
// so must all ancestors.
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
p.refreshFlags |= RF_CHILD_LIGHTLIST;
|
|
|
p = p.parent;
|
|
|
}
|
|
@@ -315,10 +317,10 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
p = p.parent;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
* (Internal use only) Forces a refresh of the given types of data.
|
|
|
- *
|
|
|
+ *
|
|
|
* @param transforms Refresh world transform based on parents'
|
|
|
* @param bounds Refresh bounding volume data based on child nodes
|
|
|
* @param lights Refresh light list based on parents'
|
|
@@ -401,9 +403,9 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
/**
|
|
|
* Returns the local {@link LightList}, which are the lights
|
|
|
* that were directly attached to this <code>Spatial</code> through the
|
|
|
- * {@link #addLight(com.jme3.light.Light) } and
|
|
|
+ * {@link #addLight(com.jme3.light.Light) } and
|
|
|
* {@link #removeLight(com.jme3.light.Light) } methods.
|
|
|
- *
|
|
|
+ *
|
|
|
* @return The local light list
|
|
|
*/
|
|
|
public LightList getLocalLightList() {
|
|
@@ -414,7 +416,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
* Returns the world {@link LightList}, containing the lights
|
|
|
* combined from all this <code>Spatial's</code> parents up to and including
|
|
|
* this <code>Spatial</code>'s lights.
|
|
|
- *
|
|
|
+ *
|
|
|
* @return The combined world light list
|
|
|
*/
|
|
|
public LightList getWorldLightList() {
|
|
@@ -502,14 +504,14 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
* <code>lookAt</code> is a convenience method for auto-setting the local
|
|
|
* rotation based on a position in world space and an up vector. It computes the rotation
|
|
|
* to transform the z-axis to point onto 'position' and the y-axis to 'up'.
|
|
|
- * Unlike {@link Quaternion#lookAt(com.jme3.math.Vector3f, com.jme3.math.Vector3f) }
|
|
|
+ * Unlike {@link Quaternion#lookAt(com.jme3.math.Vector3f, com.jme3.math.Vector3f) }
|
|
|
* this method takes a world position to look at and not a relative direction.
|
|
|
*
|
|
|
* Note : 28/01/2013 this method has been fixed as it was not taking into account the parent rotation.
|
|
|
* This was resulting in improper rotation when the spatial had rotated parent nodes.
|
|
|
- * This method is intended to work in world space, so no matter what parent graph the
|
|
|
+ * This method is intended to work in world space, so no matter what parent graph the
|
|
|
* spatial has, it will look at the given position in world space.
|
|
|
- *
|
|
|
+ *
|
|
|
* @param position
|
|
|
* where to look at in terms of world coordinates
|
|
|
* @param upVector
|
|
@@ -522,10 +524,10 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
TempVars vars = TempVars.get();
|
|
|
|
|
|
Vector3f compVecA = vars.vect4;
|
|
|
-
|
|
|
+
|
|
|
compVecA.set(position).subtractLocal(worldTranslation);
|
|
|
- getLocalRotation().lookAt(compVecA, upVector);
|
|
|
-
|
|
|
+ getLocalRotation().lookAt(compVecA, upVector);
|
|
|
+
|
|
|
if ( getParent() != null ) {
|
|
|
Quaternion rot=vars.quat1;
|
|
|
rot = rot.set(parent.getWorldRotation()).inverseLocal().multLocal(getLocalRotation());
|
|
@@ -579,7 +581,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Computes the world transform of this Spatial in the most
|
|
|
+ * Computes the world transform of this Spatial in the most
|
|
|
* efficient manner possible.
|
|
|
*/
|
|
|
void checkDoTransformUpdate() {
|
|
@@ -670,7 +672,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
* @param vp The ViewPort to which the Spatial is being rendered to.
|
|
|
*
|
|
|
* @see Spatial#addControl(com.jme3.scene.control.Control)
|
|
|
- * @see Spatial#getControl(java.lang.Class)
|
|
|
+ * @see Spatial#getControl(java.lang.Class)
|
|
|
*/
|
|
|
public void runControlRender(RenderManager rm, ViewPort vp) {
|
|
|
if (controls.isEmpty()) {
|
|
@@ -686,26 +688,26 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
* Add a control to the list of controls.
|
|
|
* @param control The control to add.
|
|
|
*
|
|
|
- * @see Spatial#removeControl(java.lang.Class)
|
|
|
+ * @see Spatial#removeControl(java.lang.Class)
|
|
|
*/
|
|
|
public void addControl(Control control) {
|
|
|
boolean before = requiresUpdates();
|
|
|
controls.add(control);
|
|
|
control.setSpatial(this);
|
|
|
boolean after = requiresUpdates();
|
|
|
-
|
|
|
+
|
|
|
// If the requirement to be updated has changed
|
|
|
// then we need to let the parent node know so it
|
|
|
// can rebuild its update list.
|
|
|
if( parent != null && before != after ) {
|
|
|
- parent.invalidateUpdateList();
|
|
|
+ parent.invalidateUpdateList();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Removes the first control that is an instance of the given class.
|
|
|
*
|
|
|
- * @see Spatial#addControl(com.jme3.scene.control.Control)
|
|
|
+ * @see Spatial#addControl(com.jme3.scene.control.Control)
|
|
|
*/
|
|
|
public void removeControl(Class<? extends Control> controlType) {
|
|
|
boolean before = requiresUpdates();
|
|
@@ -717,23 +719,23 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
}
|
|
|
}
|
|
|
boolean after = requiresUpdates();
|
|
|
-
|
|
|
+
|
|
|
// If the requirement to be updated has changed
|
|
|
// then we need to let the parent node know so it
|
|
|
// can rebuild its update list.
|
|
|
if( parent != null && before != after ) {
|
|
|
- parent.invalidateUpdateList();
|
|
|
+ parent.invalidateUpdateList();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Removes the given control from this spatial's controls.
|
|
|
- *
|
|
|
+ *
|
|
|
* @param control The control to remove
|
|
|
* @return True if the control was successfully removed. False if the
|
|
|
* control is not assigned to this spatial.
|
|
|
*
|
|
|
- * @see Spatial#addControl(com.jme3.scene.control.Control)
|
|
|
+ * @see Spatial#addControl(com.jme3.scene.control.Control)
|
|
|
*/
|
|
|
public boolean removeControl(Control control) {
|
|
|
boolean before = requiresUpdates();
|
|
@@ -743,14 +745,14 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
}
|
|
|
|
|
|
boolean after = requiresUpdates();
|
|
|
-
|
|
|
+
|
|
|
// If the requirement to be updated has changed
|
|
|
// then we need to let the parent node know so it
|
|
|
// can rebuild its update list.
|
|
|
if( parent != null && before != after ) {
|
|
|
- parent.invalidateUpdateList();
|
|
|
+ parent.invalidateUpdateList();
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
return result;
|
|
|
}
|
|
|
|
|
@@ -761,7 +763,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
* @param controlType The superclass of the control to look for.
|
|
|
* @return The first instance in the list of the controlType class, or null.
|
|
|
*
|
|
|
- * @see Spatial#addControl(com.jme3.scene.control.Control)
|
|
|
+ * @see Spatial#addControl(com.jme3.scene.control.Control)
|
|
|
*/
|
|
|
public <T extends Control> T getControl(Class<T> controlType) {
|
|
|
for (Control c : controls.getArray()) {
|
|
@@ -790,7 +792,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
/**
|
|
|
* @return The number of controls attached to this Spatial.
|
|
|
* @see Spatial#addControl(com.jme3.scene.control.Control)
|
|
|
- * @see Spatial#removeControl(java.lang.Class)
|
|
|
+ * @see Spatial#removeControl(java.lang.Class)
|
|
|
*/
|
|
|
public int getNumControls() {
|
|
|
return controls.size();
|
|
@@ -815,7 +817,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
* Calling this when the Spatial is attached to a node
|
|
|
* will cause undefined results. User code should only call this
|
|
|
* method on Spatials having no parent.
|
|
|
- *
|
|
|
+ *
|
|
|
* @see Spatial#getWorldLightList()
|
|
|
* @see Spatial#getWorldTransform()
|
|
|
* @see Spatial#getWorldBound()
|
|
@@ -835,7 +837,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
if ((refreshFlags & RF_BOUND) != 0) {
|
|
|
updateWorldBound();
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
assert refreshFlags == 0;
|
|
|
}
|
|
|
|
|
@@ -1067,9 +1069,9 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
|
|
|
/**
|
|
|
* <code>removeLight</code> removes the given light from the Spatial.
|
|
|
- *
|
|
|
+ *
|
|
|
* @param light The light to remove.
|
|
|
- * @see Spatial#addLight(com.jme3.light.Light)
|
|
|
+ * @see Spatial#addLight(com.jme3.light.Light)
|
|
|
*/
|
|
|
public void removeLight(Light light) {
|
|
|
localLights.remove(light);
|
|
@@ -1264,7 +1266,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
* All controls will be cloned using the Control.cloneForSpatial method
|
|
|
* on the clone.
|
|
|
*
|
|
|
- * @see Mesh#cloneForAnim()
|
|
|
+ * @see Mesh#cloneForAnim()
|
|
|
*/
|
|
|
public Spatial clone(boolean cloneMaterial) {
|
|
|
try {
|
|
@@ -1328,7 +1330,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
* All controls will be cloned using the Control.cloneForSpatial method
|
|
|
* on the clone.
|
|
|
*
|
|
|
- * @see Mesh#cloneForAnim()
|
|
|
+ * @see Mesh#cloneForAnim()
|
|
|
*/
|
|
|
@Override
|
|
|
public Spatial clone() {
|
|
@@ -1344,13 +1346,59 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
*/
|
|
|
public abstract Spatial deepClone();
|
|
|
|
|
|
+ /**
|
|
|
+ * Called internally by com.jme3.util.clone.Cloner. Do not call directly.
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Spatial jmeClone() {
|
|
|
+ try {
|
|
|
+ Spatial clone = (Spatial)super.clone();
|
|
|
+ return clone;
|
|
|
+ } catch (CloneNotSupportedException ex) {
|
|
|
+ throw new AssertionError();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Called internally by com.jme3.util.clone.Cloner. Do not call directly.
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void cloneFields( Cloner cloner, Object original ) {
|
|
|
+
|
|
|
+ // Clone all of the fields that need fix-ups and/or potential
|
|
|
+ // sharing.
|
|
|
+ this.parent = cloner.clone(parent);
|
|
|
+ this.worldBound = cloner.clone(worldBound);
|
|
|
+ this.worldLights = cloner.clone(worldLights);
|
|
|
+ this.localLights = cloner.clone(localLights);
|
|
|
+ this.worldTransform = cloner.clone(worldTransform);
|
|
|
+ this.localTransform = cloner.clone(localTransform);
|
|
|
+ this.controls = cloner.clone(controls);
|
|
|
+
|
|
|
+ // Cloner doesn't handle maps on its own just yet.
|
|
|
+ // Note: this is more advanced cloning than the old clone() method
|
|
|
+ // did because it just shallow cloned the map. In this case, we want
|
|
|
+ // 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));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public void setUserData(String key, Object data) {
|
|
|
if (userData == null) {
|
|
|
userData = new HashMap<String, Savable>();
|
|
|
}
|
|
|
|
|
|
if(data == null){
|
|
|
- userData.remove(key);
|
|
|
+ userData.remove(key);
|
|
|
}else if (data instanceof Savable) {
|
|
|
userData.put(key, (Savable) data);
|
|
|
} else {
|
|
@@ -1445,7 +1493,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
//changed for backward compatibility with j3o files generated before the AnimControl/SkeletonControl split
|
|
|
//the AnimControl creates the SkeletonControl for old files and add it to the spatial.
|
|
|
//The SkeletonControl must be the last in the stack so we add the list of all other control before it.
|
|
|
- //When backward compatibility won't be needed anymore this can be replaced by :
|
|
|
+ //When backward compatibility won't be needed anymore this can be replaced by :
|
|
|
//controls = ic.readSavableArrayList("controlsList", null));
|
|
|
controls.addAll(0, ic.readSavableArrayList("controlsList", null));
|
|
|
|
|
@@ -1508,9 +1556,9 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
/**
|
|
|
* <code>setQueueBucket</code> determines at what phase of the
|
|
|
* rendering process this Spatial will rendered. See the
|
|
|
- * {@link Bucket} enum for an explanation of the various
|
|
|
+ * {@link Bucket} enum for an explanation of the various
|
|
|
* render queue buckets.
|
|
|
- *
|
|
|
+ *
|
|
|
* @param queueBucket
|
|
|
* The bucket to use for this Spatial.
|
|
|
*/
|
|
@@ -1595,7 +1643,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|
|
*
|
|
|
* @return store if not null, otherwise, a new matrix containing the result.
|
|
|
*
|
|
|
- * @see Spatial#getWorldTransform()
|
|
|
+ * @see Spatial#getWorldTransform()
|
|
|
*/
|
|
|
public Matrix4f getLocalToWorldMatrix(Matrix4f store) {
|
|
|
if (store == null) {
|