Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 29 additions & 15 deletions jme3-core/src/main/java/com/jme3/anim/MorphControl.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -47,6 +45,7 @@
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;

Expand All @@ -55,6 +54,9 @@
* 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 {
Expand All @@ -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();
Expand All @@ -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;
Expand Down Expand Up @@ -428,6 +440,7 @@ public void read(JmeImporter importer) throws IOException {
super.read(importer);
InputCapsule capsule = importer.getCapsule(this);
approximateTangents = capsule.readBoolean(TAG_APPROXIMATE, true);
targets.addAll(capsule.readSavableArrayList(TAG_TARGETS, null));
}

/**
Expand All @@ -442,6 +455,7 @@ public void write(JmeExporter exporter) throws IOException {
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 {
Expand Down