use of com.jme3.scene.plugins.fbx.obj.FbxObject in project jmonkeyengine by jMonkeyEngine.
the class SceneLoader method buildAnimations.
private void buildAnimations() {
if (skeleton == null)
return;
if (animList == null || animList.list.size() == 0) {
animList = new AnimationList();
for (long layerId : alayerMap.keySet()) {
FbxObject layer = alayerMap.get(layerId);
animList.add(layer.name, layer.name, 0, -1);
}
}
// Extract aminations
HashMap<String, Animation> anims = new HashMap<String, Animation>();
for (AnimInverval animInfo : animList.list) {
float realLength = 0;
float length = (animInfo.lastFrame - animInfo.firstFrame) / this.animFrameRate;
float animStart = animInfo.firstFrame / this.animFrameRate;
float animStop = animInfo.lastFrame / this.animFrameRate;
Animation anim = new Animation(animInfo.name, length);
// Search source layer for animation nodes
long sourceLayerId = 0L;
for (long layerId : alayerMap.keySet()) {
FbxObject layer = alayerMap.get(layerId);
if (layer.name.equals(animInfo.layerName)) {
sourceLayerId = layerId;
break;
}
}
// Build bone tracks
for (FbxNode limb : limbMap.values()) {
// Animation channels may have different keyframes (non-baked animation).
// So we have to restore intermediate values for all channels cause of JME requires
// a bone track as a single channel with collective transformation for each keyframe
// Sorted unique timestamps
Set<Long> stamps = new TreeSet<Long>();
FbxAnimNode animTranslation = limb.animTranslation(sourceLayerId);
FbxAnimNode animRotation = limb.animRotation(sourceLayerId);
FbxAnimNode animScale = limb.animScale(sourceLayerId);
boolean haveTranslation = haveAnyChannel(animTranslation);
boolean haveRotation = haveAnyChannel(animRotation);
boolean haveScale = haveAnyChannel(animScale);
// Collect keyframes stamps
if (haveTranslation)
animTranslation.exportTimes(stamps);
if (haveRotation)
animRotation.exportTimes(stamps);
if (haveScale)
animScale.exportTimes(stamps);
if (stamps.isEmpty())
continue;
long[] keyTimes = new long[stamps.size()];
int cnt = 0;
for (long t : stamps) keyTimes[cnt++] = t;
// Calculate keys interval by animation time interval
int firstKeyIndex = 0;
int lastKeyIndex = keyTimes.length - 1;
for (int i = 0; i < keyTimes.length; ++i) {
// Translate into seconds
float time = (float) (((double) keyTimes[i]) * secondsPerUnit);
if (time <= animStart)
firstKeyIndex = i;
if (time >= animStop && animStop >= 0) {
lastKeyIndex = i;
break;
}
}
int keysCount = lastKeyIndex - firstKeyIndex + 1;
if (keysCount <= 0)
continue;
float[] times = new float[keysCount];
Vector3f[] translations = new Vector3f[keysCount];
Quaternion[] rotations = new Quaternion[keysCount];
Vector3f[] scales = null;
// Calculate keyframes times
for (int i = 0; i < keysCount; ++i) {
int keyIndex = firstKeyIndex + i;
// Translate into seconds
float time = (float) (((double) keyTimes[keyIndex]) * secondsPerUnit);
times[i] = time - animStart;
realLength = Math.max(realLength, times[i]);
}
// Load keyframes from animation curves
if (haveTranslation) {
for (int i = 0; i < keysCount; ++i) {
int keyIndex = firstKeyIndex + i;
FbxAnimNode n = animTranslation;
// Why do it here but not in other places? FBX magic?
Vector3f tvec = n.getValue(keyTimes[keyIndex], n.value).subtractLocal(n.value);
translations[i] = tvec.divideLocal(unitSize);
}
} else {
for (int i = 0; i < keysCount; ++i) translations[i] = Vector3f.ZERO;
}
RotationOrder ro = RotationOrder.EULER_XYZ;
if (haveRotation) {
for (int i = 0; i < keysCount; ++i) {
int keyIndex = firstKeyIndex + i;
FbxAnimNode n = animRotation;
Vector3f tvec = n.getValue(keyTimes[keyIndex], n.value);
rotations[i] = ro.rotate(tvec);
}
} else {
for (int i = 0; i < keysCount; ++i) rotations[i] = Quaternion.IDENTITY;
}
if (haveScale) {
scales = new Vector3f[keysCount];
for (int i = 0; i < keysCount; ++i) {
int keyIndex = firstKeyIndex + i;
FbxAnimNode n = animScale;
Vector3f tvec = n.getValue(keyTimes[keyIndex], n.value);
scales[i] = tvec;
}
}
BoneTrack track = null;
if (haveScale)
track = new BoneTrack(limb.boneIndex, times, translations, rotations, scales);
else
track = new BoneTrack(limb.boneIndex, times, translations, rotations);
anim.addTrack(track);
}
if (realLength != length && animInfo.lastFrame == -1) {
Track[] tracks = anim.getTracks();
if (tracks == null || tracks.length == 0)
continue;
anim = new Animation(animInfo.name, realLength);
for (Track track : tracks) anim.addTrack(track);
}
anims.put(anim.getName(), anim);
}
animControl.setAnimations(anims);
}
use of com.jme3.scene.plugins.fbx.obj.FbxObject in project jmonkeyengine by jMonkeyEngine.
the class SceneLoader method loadDeformer.
private FbxObject loadDeformer(FbxElement element) {
String type = (String) element.properties.get(2);
switch(type) {
case "Skin":
FbxSkin skinData = new FbxSkin(this, element);
skinMap.put(skinData.id, skinData);
return skinData;
case "Cluster":
FbxCluster clusterData = new FbxCluster(this, element);
return clusterData;
}
return null;
}
use of com.jme3.scene.plugins.fbx.obj.FbxObject in project jmonkeyengine by jMonkeyEngine.
the class SceneLoader method loadConnections.
private void loadConnections(FbxElement element) {
for (FbxElement e : element.children) {
if (e.id.equals("C")) {
String type = (String) e.properties.get(0);
long objId, refId;
FbxObject obj, ref;
switch(type) {
case "OO":
objId = (Long) e.properties.get(1);
refId = (Long) e.properties.get(2);
obj = allObjects.get(objId);
ref = allObjects.get(refId);
if (ref != null) {
ref.link(obj);
} else if (refId == 0) {
obj.linkToZero();
}
break;
case "OP":
objId = (Long) e.properties.get(1);
refId = (Long) e.properties.get(2);
String propName = (String) e.properties.get(3);
obj = allObjects.get(objId);
ref = allObjects.get(refId);
if (ref != null)
ref.link(obj, propName);
break;
}
}
}
}
use of com.jme3.scene.plugins.fbx.obj.FbxObject in project jmonkeyengine by jMonkeyEngine.
the class FbxNode method connectObjectProperty.
@Override
public void connectObjectProperty(FbxObject object, String property) {
// (FbxAnimCurveNode)
if (object instanceof FbxAnimCurveNode) {
FbxAnimCurveNode curveNode = (FbxAnimCurveNode) object;
if (property.equals("Lcl Translation") || property.equals("Lcl Rotation") || property.equals("Lcl Scaling")) {
List<FbxAnimCurveNode> curveNodes = propertyToAnimCurveMap.get(property);
if (curveNodes == null) {
curveNodes = new ArrayList<FbxAnimCurveNode>();
curveNodes.add(curveNode);
propertyToAnimCurveMap.put(property, curveNodes);
}
curveNodes.add(curveNode);
// Make sure the curve knows about it animating
// this node as well.
curveNode.addInfluencedNode(this, property);
} else {
logger.log(Level.WARNING, "Animating the property ''{0}'' is not " + "supported. Ignoring.", property);
}
} else {
unsupportedConnectObjectProperty(object, property);
}
}
Aggregations