|
@@ -31,12 +31,10 @@
|
|
|
*/
|
|
|
package com.jme3.anim;
|
|
|
|
|
|
-import com.jme3.export.InputCapsule;
|
|
|
-import com.jme3.export.JmeExporter;
|
|
|
-import com.jme3.export.JmeImporter;
|
|
|
-import com.jme3.export.OutputCapsule;
|
|
|
-import com.jme3.export.Savable;
|
|
|
-import com.jme3.material.*;
|
|
|
+import com.jme3.export.*;
|
|
|
+import com.jme3.material.MatParam;
|
|
|
+import com.jme3.material.MatParamOverride;
|
|
|
+import com.jme3.material.Material;
|
|
|
import com.jme3.renderer.*;
|
|
|
import com.jme3.scene.*;
|
|
|
import com.jme3.scene.control.AbstractControl;
|
|
@@ -47,6 +45,7 @@ import com.jme3.util.SafeArrayList;
|
|
|
import com.jme3.util.clone.Cloner;
|
|
|
import java.io.IOException;
|
|
|
import java.nio.FloatBuffer;
|
|
|
+import java.util.ArrayList;
|
|
|
import java.util.logging.Level;
|
|
|
import java.util.logging.Logger;
|
|
|
|
|
@@ -55,6 +54,9 @@ import java.util.logging.Logger;
|
|
|
* All stock shaders only support morphing these 3 buffers, but note that MorphTargets can have any type of buffers.
|
|
|
* If you want to use other types of buffers you will need a custom MorphControl and a custom shader.
|
|
|
*
|
|
|
+ * Note that if morphed children are attached to or detached from the sub graph after the MorphControl is added to
|
|
|
+ * spatial, you must detach and attach the control again for the changes to get reflected.
|
|
|
+ *
|
|
|
* @author Rémy Bouquet
|
|
|
*/
|
|
|
public class MorphControl extends AbstractControl implements Savable {
|
|
@@ -65,6 +67,7 @@ public class MorphControl extends AbstractControl implements Savable {
|
|
|
private final static float MIN_WEIGHT = 0.005f;
|
|
|
|
|
|
private static final String TAG_APPROXIMATE = "approximateTangents";
|
|
|
+ private static final String TAG_TARGETS = "targets";
|
|
|
|
|
|
private SafeArrayList<Geometry> targets = new SafeArrayList<>(Geometry.class);
|
|
|
private TargetLocator targetLocator = new TargetLocator();
|
|
@@ -79,22 +82,31 @@ public class MorphControl extends AbstractControl implements Savable {
|
|
|
private static final VertexBuffer.Type bufferTypes[] = VertexBuffer.Type.values();
|
|
|
|
|
|
@Override
|
|
|
- protected void controlUpdate(float tpf) {
|
|
|
- if (!enabled) {
|
|
|
- return;
|
|
|
+ public void setSpatial(Spatial spatial) {
|
|
|
+ super.setSpatial(spatial);
|
|
|
+
|
|
|
+ // Remove matparam override from the old targets
|
|
|
+ for (Geometry target : targets.getArray()) {
|
|
|
+ target.removeMatParamOverride(nullNumberOfBones);
|
|
|
}
|
|
|
+
|
|
|
// gathering geometries in the sub graph.
|
|
|
- // This must be done in the update phase as the gathering might add a matparam override
|
|
|
+ // This must not be done in the render phase as the gathering might add a matparam override
|
|
|
+ // which then will throw an IllegalStateException if done in the render phase.
|
|
|
targets.clear();
|
|
|
- this.spatial.depthFirstTraversal(targetLocator);
|
|
|
+ if (spatial != null) {
|
|
|
+ spatial.depthFirstTraversal(targetLocator);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void controlUpdate(float tpf) {
|
|
|
+
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
protected void controlRender(RenderManager rm, ViewPort vp) {
|
|
|
- if (!enabled) {
|
|
|
- return;
|
|
|
- }
|
|
|
- for (Geometry geom : targets) {
|
|
|
+ for (Geometry geom : targets.getArray()) {
|
|
|
Mesh mesh = geom.getMesh();
|
|
|
if (!geom.isDirtyMorph()) {
|
|
|
continue;
|
|
@@ -428,6 +440,7 @@ public class MorphControl extends AbstractControl implements Savable {
|
|
|
super.read(importer);
|
|
|
InputCapsule capsule = importer.getCapsule(this);
|
|
|
approximateTangents = capsule.readBoolean(TAG_APPROXIMATE, true);
|
|
|
+ targets.addAll(capsule.readSavableArrayList(TAG_TARGETS, null));
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -442,6 +455,7 @@ public class MorphControl extends AbstractControl implements Savable {
|
|
|
super.write(exporter);
|
|
|
OutputCapsule capsule = exporter.getCapsule(this);
|
|
|
capsule.write(approximateTangents, TAG_APPROXIMATE, true);
|
|
|
+ capsule.writeSavableArrayList(new ArrayList(targets), TAG_TARGETS, null);
|
|
|
}
|
|
|
|
|
|
private class TargetLocator extends SceneGraphVisitorAdapter {
|