glTF: fix animation defautl pose when no track is specified

empirephoenix-patch-1
Nehon 7 years ago
parent c971a4758f
commit 806663990d
  1. 63
      jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfLoader.java
  2. 12
      jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/TrackData.java

@ -713,7 +713,7 @@ public class GltfLoader implements AssetLoader {
assertNotNull(samplers, "No samplers for animation " + name); assertNotNull(samplers, "No samplers for animation " + name);
//temp data storage of track data //temp data storage of track data
TrackData[] animatedNodes = new TrackData[nodes.size()]; TrackData[] tracks = new TrackData[nodes.size()];
for (JsonElement channel : channels) { for (JsonElement channel : channels) {
@ -732,10 +732,10 @@ public class GltfLoader implements AssetLoader {
logger.log(Level.WARNING, "Morph animation is not supported by JME yet, skipping animation"); logger.log(Level.WARNING, "Morph animation is not supported by JME yet, skipping animation");
continue; continue;
} }
TrackData trackData = animatedNodes[targetNode]; TrackData trackData = tracks[targetNode];
if (trackData == null) { if (trackData == null) {
trackData = new TrackData(); trackData = new TrackData();
animatedNodes[targetNode] = trackData; tracks[targetNode] = trackData;
} }
Integer samplerIndex = getAsInteger(channel.getAsJsonObject(), "sampler"); Integer samplerIndex = getAsInteger(channel.getAsJsonObject(), "sampler");
@ -776,11 +776,9 @@ public class GltfLoader implements AssetLoader {
} else { } else {
//TODO support weights //TODO support weights
logger.log(Level.WARNING, "Morph animation is not supported"); logger.log(Level.WARNING, "Morph animation is not supported");
animatedNodes[targetNode] = null;
continue; continue;
} }
animatedNodes[targetNode] = customContentManager.readExtensionAndExtras("channel", channel, trackData); tracks[targetNode] = customContentManager.readExtensionAndExtras("channel", channel, trackData);
} }
if (name == null) { if (name == null) {
@ -792,9 +790,9 @@ public class GltfLoader implements AssetLoader {
anim.setName(name); anim.setName(name);
int skinIndex = -1; int skinIndex = -1;
for (int i = 0; i < animatedNodes.length; i++) { for (int i = 0; i < tracks.length; i++) {
TrackData trackData = animatedNodes[i]; TrackData trackData = tracks[i];
if (trackData == null) { if (trackData == null || trackData.timeArrays.isEmpty()) {
continue; continue;
} }
trackData.update(); trackData.update();
@ -938,7 +936,7 @@ public class GltfLoader implements AssetLoader {
} }
if (isKeepSkeletonPose(info)) { if (isKeepSkeletonPose(info)) {
//Set local transforms. The skeleton may come in a given pose, that is not the rest pose, so let's apply it. //Set local transforms.The skeleton may come in a given pose, that is not the rest pose, so let 's apply it.
for (int i = 0; i < joints.size(); i++) { for (int i = 0; i < joints.size(); i++) {
applyPose(joints.get(i).getAsInt()); applyPose(joints.get(i).getAsInt());
} }
@ -960,7 +958,6 @@ public class GltfLoader implements AssetLoader {
bw.bone.setLocalTranslation(bw.localTransform.getTranslation()); bw.bone.setLocalTranslation(bw.localTransform.getTranslation());
bw.bone.setLocalRotation(bw.localTransform.getRotation()); bw.bone.setLocalRotation(bw.localTransform.getRotation());
bw.bone.setLocalScale(bw.localTransform.getScale()); bw.bone.setLocalScale(bw.localTransform.getScale());
bw.bone.setUserControl(false);
} }
private void computeBindTransforms(BoneWrapper boneWrapper, Skeleton skeleton) { private void computeBindTransforms(BoneWrapper boneWrapper, Skeleton skeleton) {
@ -986,7 +983,6 @@ public class GltfLoader implements AssetLoader {
BoneWrapper child = fetchFromCache("nodes", childIndex, BoneWrapper.class); BoneWrapper child = fetchFromCache("nodes", childIndex, BoneWrapper.class);
computeBindTransforms(child, skeleton); computeBindTransforms(child, skeleton);
} }
} }
private BoneWrapper findBoneWrapper(Bone bone) { private BoneWrapper findBoneWrapper(Bone bone) {
@ -1012,9 +1008,8 @@ public class GltfLoader implements AssetLoader {
} }
Bone bone = new Bone(name); Bone bone = new Bone(name);
Transform boneTransforms = null; Transform boneTransforms = null;
if (isKeepSkeletonPose(info)) { boneTransforms = readTransforms(nodeData);
boneTransforms = readTransforms(nodeData);
}
addToCache("nodes", nodeIndex, new BoneWrapper(bone, boneIndex, skinIndex, modelBindMatrix, boneTransforms), nodes.size()); addToCache("nodes", nodeIndex, new BoneWrapper(bone, boneIndex, skinIndex, modelBindMatrix, boneTransforms), nodes.size());
return bone; return bone;
@ -1147,6 +1142,7 @@ public class GltfLoader implements AssetLoader {
Transform localTransform; Transform localTransform;
Matrix4f modelBindMatrix; Matrix4f modelBindMatrix;
boolean isRoot = false; boolean isRoot = false;
boolean localUpdated = false;
Spatial attachedSpatial; Spatial attachedSpatial;
List<Integer> children = new ArrayList<>(); List<Integer> children = new ArrayList<>();
@ -1165,6 +1161,13 @@ public class GltfLoader implements AssetLoader {
Transform bindTransforms = new Transform(bone.getBindPosition(), bone.getBindRotation(), bone.getBindScale()); Transform bindTransforms = new Transform(bone.getBindPosition(), bone.getBindRotation(), bone.getBindScale());
SkinData skinData = fetchFromCache("skins", skinIndex, SkinData.class); SkinData skinData = fetchFromCache("skins", skinIndex, SkinData.class);
if (!localUpdated) {
//LocalTransform of the bone are default position to use for animations when there is no track.
//We need to transform them so that JME can us them in blendAnimTransform.
reverseBlendAnimTransforms(localTransform, bindTransforms);
localUpdated = true;
}
for (int i = 0; i < data.getNbKeyFrames(); i++) { for (int i = 0; i < data.getNbKeyFrames(); i++) {
Vector3f translation = getTranslation(data, bindTransforms, i); Vector3f translation = getTranslation(data, bindTransforms, i);
@ -1177,15 +1180,7 @@ public class GltfLoader implements AssetLoader {
t.combineWithParent(skinData.armatureTransforms); t.combineWithParent(skinData.armatureTransforms);
} }
//This is wrong reverseBlendAnimTransforms(t, bindTransforms);
//You'd normally combine those transforms with transform.combineWithParent()
//Here we actually do in reverse what JME does to combine anim transforms with bind transfoms (add trans/mult rot/ mult scale)
//The code to fix is in Bone.blendAnimTransforms
//TODO fix blendAnimTransforms
t.getTranslation().subtractLocal(bindTransforms.getTranslation());
t.getScale().divideLocal(bindTransforms.getScale());
tmpQuat.set(bindTransforms.getRotation()).inverseLocal().multLocal(t.getRotation());
t.setRotation(tmpQuat);
if(data.translations != null) { if(data.translations != null) {
data.translations[i] = t.getTranslation(); data.translations[i] = t.getTranslation();
@ -1198,12 +1193,24 @@ public class GltfLoader implements AssetLoader {
} }
} }
data.ensureTranslationRotations(); data.ensureTranslationRotations(localTransform);
}
private void reverseBlendAnimTransforms(Transform t, Transform bindTransforms) {
//This is wrong
//You'd normally combine those transforms with transform.combineWithParent()
//Here we actually do in reverse what JME does to combine anim transforms with bind transfoms (add trans/mult rot/ mult scale)
//The code to fix is in Bone.blendAnimTransforms
//TODO fix blendAnimTransforms
t.getTranslation().subtractLocal(bindTransforms.getTranslation());
t.getScale().divideLocal(bindTransforms.getScale());
tmpQuat.set(bindTransforms.getRotation()).inverseLocal().multLocal(t.getRotation());
t.setRotation(tmpQuat);
} }
private Vector3f getTranslation(TrackData data, Transform bindTransforms, int i) { private Vector3f getTranslation(TrackData data, Transform bindTransforms, int i) {
Vector3f translation; Vector3f translation;
if(data.translations == null){ if (data.translations == null) {
translation = bindTransforms.getTranslation(); translation = bindTransforms.getTranslation();
} else { } else {
translation = data.translations[i]; translation = data.translations[i];
@ -1213,7 +1220,7 @@ public class GltfLoader implements AssetLoader {
private Quaternion getRotation(TrackData data, Transform bindTransforms, int i) { private Quaternion getRotation(TrackData data, Transform bindTransforms, int i) {
Quaternion rotation; Quaternion rotation;
if(data.rotations == null){ if (data.rotations == null) {
rotation = bindTransforms.getRotation(); rotation = bindTransforms.getRotation();
} else { } else {
rotation = data.rotations[i]; rotation = data.rotations[i];
@ -1223,7 +1230,7 @@ public class GltfLoader implements AssetLoader {
private Vector3f getScale(TrackData data, Transform bindTransforms, int i) { private Vector3f getScale(TrackData data, Transform bindTransforms, int i) {
Vector3f scale; Vector3f scale;
if(data.scales == null){ if (data.scales == null) {
scale = bindTransforms.getScale(); scale = bindTransforms.getScale();
} else { } else {
scale = data.scales[i]; scale = data.scales[i];

@ -260,17 +260,23 @@ public class TrackData {
//JME assumes there are translation and rotation track every time, so we create them with identity transforms if they don't exist //JME assumes there are translation and rotation track every time, so we create them with identity transforms if they don't exist
//TODO change this behavior in BoneTrack. //TODO change this behavior in BoneTrack.
public void ensureTranslationRotations() { public void ensureTranslationRotations(Transform localTransforms) {
if (translations == null) { if (translations == null) {
translations = new Vector3f[times.length]; translations = new Vector3f[times.length];
for (int i = 0; i < translations.length; i++) { for (int i = 0; i < translations.length; i++) {
translations[i] = new Vector3f(); translations[i] = localTransforms.getTranslation();
} }
} }
if (rotations == null) { if (rotations == null) {
rotations = new Quaternion[times.length]; rotations = new Quaternion[times.length];
for (int i = 0; i < rotations.length; i++) { for (int i = 0; i < rotations.length; i++) {
rotations[i] = new Quaternion(); rotations[i] = localTransforms.getRotation();
}
}
if (scales == null) {
scales = new Vector3f[times.length];
for (int i = 0; i < scales.length; i++) {
scales[i] = localTransforms.getScale();
} }
} }
} }

Loading…
Cancel
Save