diff --git a/jme3-core/src/main/java/com/jme3/scene/Geometry.java b/jme3-core/src/main/java/com/jme3/scene/Geometry.java index 005d0e8c7..adc1d51a5 100644 --- a/jme3-core/src/main/java/com/jme3/scene/Geometry.java +++ b/jme3-core/src/main/java/com/jme3/scene/Geometry.java @@ -601,6 +601,22 @@ public class Geometry extends Spatial { this.dirtyMorph = true; } + /** + * Set the state of the morph with the given name. + * + * If the name of the morph is not found, no state will be set. + * + * @param morphTarget The name of the morph to set the state of + * @param state The state to set the morph to + */ + public void setMorphState(String morphTarget, float state) { + int index = mesh.getMorphIndex(morphTarget); + if (index >= 0) { + morphState[index] = state; + this.dirtyMorph = true; + } + } + /** * returns true if the morph state has changed on the last frame. * @return true if changed, otherwise false @@ -629,6 +645,20 @@ public class Geometry extends Spatial { } return morphState; } + + /** + * Get the state of a morph + * @param morphTarget the name of the morph to get the state of + * @return the state of the morph, or -1 if the morph is not found + */ + public float getMorphState(String morphTarget) { + int index = mesh.getMorphIndex(morphTarget); + if (index < 0) { + return -1; + } else { + return morphState[index]; + } + } /** * Return the number of morph targets that can be handled on the GPU simultaneously for this geometry. diff --git a/jme3-core/src/main/java/com/jme3/scene/Mesh.java b/jme3-core/src/main/java/com/jme3/scene/Mesh.java index caffca063..1e3195e00 100644 --- a/jme3-core/src/main/java/com/jme3/scene/Mesh.java +++ b/jme3-core/src/main/java/com/jme3/scene/Mesh.java @@ -1529,10 +1529,46 @@ public class Mesh implements Savable, Cloneable, JmeCloneable { public MorphTarget[] getMorphTargets() { return morphTargets.getArray(); } + + /** + * Get the name of all morphs in order. + * Morphs without names will be null + * @return an array + */ + public String[] getMorphTargetNames() { + + MorphTarget[] nbMorphTargets = getMorphTargets(); + if (nbMorphTargets.length == 0) { + return new String[0]; + } + String[] targets = new String[nbMorphTargets.length]; + + for (int index = 0; index < nbMorphTargets.length; index++) { + targets[index] = nbMorphTargets[index].getName(); + } + return targets; + } public boolean hasMorphTargets() { return morphTargets != null && !morphTargets.isEmpty(); } + + /** + * Get the index of the morph that has the given name. + * @param morphName The name of the morph to search for + * @return The index of the morph, or -1 if not found. + */ + public int getMorphIndex(String morphName) { + int index = -1; + MorphTarget[] nbMorphTargets = getMorphTargets(); + for (int i = 0; i < nbMorphTargets.length; i++) { + if (nbMorphTargets[i].getName().equals(morphName)) { + index = i; + break; + } + } + return index; + } @Override public void write(JmeExporter ex) throws IOException { diff --git a/jme3-core/src/main/java/com/jme3/scene/mesh/MorphTarget.java b/jme3-core/src/main/java/com/jme3/scene/mesh/MorphTarget.java index 083d04fb7..fc80e2113 100644 --- a/jme3-core/src/main/java/com/jme3/scene/mesh/MorphTarget.java +++ b/jme3-core/src/main/java/com/jme3/scene/mesh/MorphTarget.java @@ -11,6 +11,23 @@ import java.util.Map; public class MorphTarget implements Savable { private EnumMap buffers = new EnumMap<>(VertexBuffer.Type.class); + private String name = null; + + public MorphTarget() { + + } + + public MorphTarget(String name) { + this.name = name; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } public void setBuffer(VertexBuffer.Type type, FloatBuffer buffer) { buffers.put(type, buffer); @@ -35,6 +52,7 @@ public class MorphTarget implements Savable { Buffer roData = entry.getValue().asReadOnlyBuffer(); oc.write((FloatBuffer) roData, entry.getKey().name(),null); } + oc.write(name, "morphName", null); } @Override @@ -46,6 +64,6 @@ public class MorphTarget implements Savable { setBuffer(type, b); } } - + name = ic.readString("morphName", null); } } diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java index 7b9c8d93d..cc9b54d45 100644 --- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java +++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java @@ -397,10 +397,23 @@ public class GltfLoader implements AssetLoader { mesh.generateBindPose(); } + //Read morph target names + LinkedList targetNames = new LinkedList<>(); + if (meshData.has("extras") && meshData.getAsJsonObject("extras").has("targetNames")) { + JsonArray targetNamesJson = meshData.getAsJsonObject("extras").getAsJsonArray("targetNames"); + for (JsonElement target : targetNamesJson) { + targetNames.add(target.getAsString()); + } + } + + //Read morph targets JsonArray targets = meshObject.getAsJsonArray("targets"); if(targets != null){ for (JsonElement target : targets) { MorphTarget morphTarget = new MorphTarget(); + if (targetNames.size() > 0) { + morphTarget.setName(targetNames.pop()); + } for (Map.Entry entry : target.getAsJsonObject().entrySet()) { String bufferType = entry.getKey(); VertexBuffer.Type type = getVertexBufferType(bufferType); @@ -412,7 +425,8 @@ public class GltfLoader implements AssetLoader { mesh.addMorphTarget(morphTarget); } } - + + //Read mesh extras mesh = customContentManager.readExtensionAndExtras("primitive", meshObject, mesh); Geometry geom = new Geometry(null, mesh);