|
|
|
@ -19,7 +19,6 @@ import com.jme3.util.mikktspace.MikktspaceTangentGenerator; |
|
|
|
|
import javax.xml.bind.DatatypeConverter; |
|
|
|
|
import java.io.*; |
|
|
|
|
import java.nio.Buffer; |
|
|
|
|
import java.sql.Time; |
|
|
|
|
import java.util.*; |
|
|
|
|
import java.util.logging.Level; |
|
|
|
|
import java.util.logging.Logger; |
|
|
|
@ -714,7 +713,7 @@ public class GltfLoader implements AssetLoader { |
|
|
|
|
assertNotNull(samplers, "No samplers for animation " + name); |
|
|
|
|
|
|
|
|
|
//temp data storage of track data
|
|
|
|
|
AnimData[] animatedNodes = new AnimData[nodes.size()]; |
|
|
|
|
TrackData[] animatedNodes = new TrackData[nodes.size()]; |
|
|
|
|
|
|
|
|
|
for (JsonElement channel : channels) { |
|
|
|
|
|
|
|
|
@ -733,10 +732,10 @@ public class GltfLoader implements AssetLoader { |
|
|
|
|
logger.log(Level.WARNING, "Morph animation is not supported by JME yet, skipping animation"); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
AnimData animData = animatedNodes[targetNode]; |
|
|
|
|
if (animData == null) { |
|
|
|
|
animData = new AnimData(); |
|
|
|
|
animatedNodes[targetNode] = animData; |
|
|
|
|
TrackData trackData = animatedNodes[targetNode]; |
|
|
|
|
if (trackData == null) { |
|
|
|
|
trackData = new TrackData(); |
|
|
|
|
animatedNodes[targetNode] = trackData; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Integer samplerIndex = getAsInteger(channel.getAsJsonObject(), "sampler"); |
|
|
|
@ -754,7 +753,7 @@ public class GltfLoader implements AssetLoader { |
|
|
|
|
logger.log(Level.WARNING, "JME only supports linear interpolation for animations"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
animData = customContentManager.readExtensionAndExtras("animation.sampler", sampler, animData); |
|
|
|
|
trackData = customContentManager.readExtensionAndExtras("animation.sampler", sampler, trackData); |
|
|
|
|
|
|
|
|
|
float[] times = fetchFromCache("accessors", timeIndex, float[].class); |
|
|
|
|
if (times == null) { |
|
|
|
@ -763,17 +762,17 @@ public class GltfLoader implements AssetLoader { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (targetPath.equals("translation")) { |
|
|
|
|
animData.timeArrays.add(new AnimData.TimeData(times, AnimData.Type.Translation)); |
|
|
|
|
trackData.timeArrays.add(new TrackData.TimeData(times, TrackData.Type.Translation)); |
|
|
|
|
Vector3f[] translations = readAccessorData(dataIndex, vector3fArrayPopulator); |
|
|
|
|
animData.translations = translations; |
|
|
|
|
trackData.translations = translations; |
|
|
|
|
} else if (targetPath.equals("scale")) { |
|
|
|
|
animData.timeArrays.add(new AnimData.TimeData(times, AnimData.Type.Scale)); |
|
|
|
|
trackData.timeArrays.add(new TrackData.TimeData(times, TrackData.Type.Scale)); |
|
|
|
|
Vector3f[] scales = readAccessorData(dataIndex, vector3fArrayPopulator); |
|
|
|
|
animData.scales = scales; |
|
|
|
|
trackData.scales = scales; |
|
|
|
|
} else if (targetPath.equals("rotation")) { |
|
|
|
|
animData.timeArrays.add(new AnimData.TimeData(times, AnimData.Type.Rotation)); |
|
|
|
|
trackData.timeArrays.add(new TrackData.TimeData(times, TrackData.Type.Rotation)); |
|
|
|
|
Quaternion[] rotations = readAccessorData(dataIndex, quaternionArrayPopulator); |
|
|
|
|
animData.rotations = rotations; |
|
|
|
|
trackData.rotations = rotations; |
|
|
|
|
} else { |
|
|
|
|
//TODO support weights
|
|
|
|
|
logger.log(Level.WARNING, "Morph animation is not supported"); |
|
|
|
@ -781,7 +780,7 @@ public class GltfLoader implements AssetLoader { |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
animatedNodes[targetNode] = customContentManager.readExtensionAndExtras("channel", channel, animData); |
|
|
|
|
animatedNodes[targetNode] = customContentManager.readExtensionAndExtras("channel", channel, trackData); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (name == null) { |
|
|
|
@ -794,26 +793,26 @@ public class GltfLoader implements AssetLoader { |
|
|
|
|
int skinIndex = -1; |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < animatedNodes.length; i++) { |
|
|
|
|
AnimData animData = animatedNodes[i]; |
|
|
|
|
if (animData == null) { |
|
|
|
|
TrackData trackData = animatedNodes[i]; |
|
|
|
|
if (trackData == null) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
animData.update(); |
|
|
|
|
if (animData.length > anim.getLength()) { |
|
|
|
|
anim.setLength(animData.length); |
|
|
|
|
trackData.update(); |
|
|
|
|
if (trackData.length > anim.getLength()) { |
|
|
|
|
anim.setLength(trackData.length); |
|
|
|
|
} |
|
|
|
|
Object node = fetchFromCache("nodes", i, Object.class); |
|
|
|
|
if (node instanceof Spatial) { |
|
|
|
|
Spatial s = (Spatial) node; |
|
|
|
|
spatials.add(s); |
|
|
|
|
SpatialTrack track = new SpatialTrack(animData.times, animData.translations, animData.rotations, animData.scales); |
|
|
|
|
SpatialTrack track = new SpatialTrack(trackData.times, trackData.translations, trackData.rotations, trackData.scales); |
|
|
|
|
track.setTrackSpatial(s); |
|
|
|
|
anim.addTrack(track); |
|
|
|
|
} else if (node instanceof BoneWrapper) { |
|
|
|
|
BoneWrapper b = (BoneWrapper) node; |
|
|
|
|
//apply the inverseBindMatrix to animation data.
|
|
|
|
|
b.update(animData); |
|
|
|
|
BoneTrack track = new BoneTrack(b.boneIndex, animData.times, animData.translations, animData.rotations, animData.scales); |
|
|
|
|
b.update(trackData); |
|
|
|
|
BoneTrack track = new BoneTrack(b.boneIndex, trackData.times, trackData.translations, trackData.rotations, trackData.scales); |
|
|
|
|
anim.addTrack(track); |
|
|
|
|
if (skinIndex == -1) { |
|
|
|
|
skinIndex = b.skinIndex; |
|
|
|
@ -961,6 +960,7 @@ public class GltfLoader implements AssetLoader { |
|
|
|
|
bw.bone.setLocalTranslation(bw.localTransform.getTranslation()); |
|
|
|
|
bw.bone.setLocalRotation(bw.localTransform.getRotation()); |
|
|
|
|
bw.bone.setLocalScale(bw.localTransform.getScale()); |
|
|
|
|
bw.bone.setUserControl(false); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void computeBindTransforms(BoneWrapper boneWrapper, Skeleton skeleton) { |
|
|
|
@ -1159,12 +1159,17 @@ public class GltfLoader implements AssetLoader { |
|
|
|
|
/** |
|
|
|
|
* Applies the inverse Bind transforms to anim data. and the armature transforms if relevant. |
|
|
|
|
*/ |
|
|
|
|
public void update(AnimData data) { |
|
|
|
|
public void update(TrackData data) { |
|
|
|
|
Transform bindTransforms = new Transform(bone.getBindPosition(), bone.getBindRotation(), bone.getBindScale()); |
|
|
|
|
SkinData skinData = fetchFromCache("skins", skinIndex, SkinData.class); |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < data.translations.length; i++) { |
|
|
|
|
Transform t = new Transform(data.translations[i], data.rotations[i], data.scales[i]); |
|
|
|
|
for (int i = 0; i < data.getNbKeyFrames(); i++) { |
|
|
|
|
|
|
|
|
|
Vector3f translation = getTranslation(data, bindTransforms, i); |
|
|
|
|
Quaternion rotation = getRotation(data, bindTransforms, i); |
|
|
|
|
Vector3f scale = getScale(data, bindTransforms, i); |
|
|
|
|
|
|
|
|
|
Transform t = new Transform(translation, rotation, scale); |
|
|
|
|
if (isRoot) { |
|
|
|
|
//Apply the armature transforms to the root bone anim track.
|
|
|
|
|
t.combineWithParent(skinData.armatureTransforms); |
|
|
|
@ -1180,11 +1185,49 @@ public class GltfLoader implements AssetLoader { |
|
|
|
|
tmpQuat.set(bindTransforms.getRotation()).inverseLocal().multLocal(t.getRotation()); |
|
|
|
|
t.setRotation(tmpQuat); |
|
|
|
|
|
|
|
|
|
if(data.translations != null) { |
|
|
|
|
data.translations[i] = t.getTranslation(); |
|
|
|
|
} |
|
|
|
|
if(data.rotations != null) { |
|
|
|
|
data.rotations[i] = t.getRotation(); |
|
|
|
|
} |
|
|
|
|
if(data.scales != null) { |
|
|
|
|
data.scales[i] = t.getScale(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
data.ensureTranslationRotations(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private Vector3f getTranslation(TrackData data, Transform bindTransforms, int i) { |
|
|
|
|
Vector3f translation; |
|
|
|
|
if(data.translations == null){ |
|
|
|
|
translation = bindTransforms.getTranslation(); |
|
|
|
|
} else { |
|
|
|
|
translation = data.translations[i]; |
|
|
|
|
} |
|
|
|
|
return translation; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private Quaternion getRotation(TrackData data, Transform bindTransforms, int i) { |
|
|
|
|
Quaternion rotation; |
|
|
|
|
if(data.rotations == null){ |
|
|
|
|
rotation = bindTransforms.getRotation(); |
|
|
|
|
} else { |
|
|
|
|
rotation = data.rotations[i]; |
|
|
|
|
} |
|
|
|
|
return rotation; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private Vector3f getScale(TrackData data, Transform bindTransforms, int i) { |
|
|
|
|
Vector3f scale; |
|
|
|
|
if(data.scales == null){ |
|
|
|
|
scale = bindTransforms.getScale(); |
|
|
|
|
} else { |
|
|
|
|
scale = data.scales[i]; |
|
|
|
|
} |
|
|
|
|
return scale; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private class SkinData { |
|
|
|
|