use of com.jme3.animation.Track in project jmonkeyengine by jMonkeyEngine.
the class EffectTrack method findEmitter.
/**
* recursive function responsible for finding the newly cloned Emitter
*
* @param spat
* @return
*/
private ParticleEmitter findEmitter(Spatial spat) {
if (spat instanceof ParticleEmitter) {
//spat is a PArticleEmitter
ParticleEmitter em = (ParticleEmitter) spat;
//getting the UserData TrackInfo so check if it should be attached to this Track
TrackInfo t = (TrackInfo) em.getUserData("TrackInfo");
if (t != null && t.getTracks().contains(this)) {
return em;
}
return null;
} else if (spat instanceof Node) {
for (Spatial child : ((Node) spat).getChildren()) {
ParticleEmitter em = findEmitter(child);
if (em != null) {
return em;
}
}
}
return null;
}
use of com.jme3.animation.Track in project jmonkeyengine by jMonkeyEngine.
the class EffectTrack method read.
/**
* Internal use only serialization
*
* @param im importer
* @throws IOException Exception
*/
public void read(JmeImporter im) throws IOException {
InputCapsule in = im.getCapsule(this);
this.particlesPerSeconds = in.readFloat("particlesPerSeconds", 0);
//reading the emitter even if the track will then reference its cloned counter part if it's loaded with the assetManager.
//This also avoid null pointer exception if the model is not loaded via the AssetManager.
emitter = (ParticleEmitter) in.readSavable("emitter", null);
emitter.setParticlesPerSec(0);
//if the emitter was saved with a KillParticleControl we remove it.
// Control c = emitter.getControl(KillParticleControl.class);
// if(c!=null){
// emitter.removeControl(c);
// }
//emitter.removeControl(KillParticleControl.class);
length = in.readFloat("length", length);
startOffset = in.readFloat("startOffset", 0);
}
use of com.jme3.animation.Track 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.animation.Track in project jmonkeyengine by jMonkeyEngine.
the class SkeletonLoader method endElement.
public void endElement(String uri, String name, String qName) {
if (qName.equals("translate") || qName.equals("position") || qName.equals("scale")) {
} else if (qName.equals("axis")) {
} else if (qName.equals("rotate") || qName.equals("rotation")) {
rotation = new Quaternion();
axis.normalizeLocal();
rotation.fromAngleNormalAxis(angle, axis);
angle = 0;
axis = null;
} else if (qName.equals("bone")) {
bone.setBindTransforms(position, rotation, scale);
bone = null;
position = null;
rotation = null;
scale = null;
} else if (qName.equals("bonehierarchy")) {
Bone[] bones = new Bone[indexToBone.size()];
// also assign the bones to the bonelist
for (Map.Entry<Integer, Bone> entry : indexToBone.entrySet()) {
Bone bone = entry.getValue();
bones[entry.getKey()] = bone;
}
indexToBone.clear();
skeleton = new Skeleton(bones);
} else if (qName.equals("animation")) {
animations.add(animation);
animation = null;
} else if (qName.equals("track")) {
if (track != null) {
// if track has keyframes
tracks.add(track);
track = null;
}
} else if (qName.equals("tracks")) {
BoneTrack[] trackList = tracks.toArray(new BoneTrack[tracks.size()]);
animation.setTracks(trackList);
tracks.clear();
} else if (qName.equals("keyframe")) {
assert time >= 0;
assert position != null;
assert rotation != null;
times.add(time);
translations.add(position);
rotations.add(rotation);
if (scale != null) {
scales.add(scale);
} else {
scales.add(new Vector3f(1, 1, 1));
}
time = -1;
position = null;
rotation = null;
scale = null;
} else if (qName.equals("keyframes")) {
if (times.size() > 0) {
float[] timesArray = new float[times.size()];
for (int i = 0; i < timesArray.length; i++) {
timesArray[i] = times.get(i);
}
Vector3f[] transArray = translations.toArray(new Vector3f[translations.size()]);
Quaternion[] rotArray = rotations.toArray(new Quaternion[rotations.size()]);
Vector3f[] scalesArray = scales.toArray(new Vector3f[scales.size()]);
track.setKeyframes(timesArray, transArray, rotArray, scalesArray);
//track.setKeyframes(timesArray, transArray, rotArray);
} else {
track = null;
}
times.clear();
translations.clear();
rotations.clear();
scales.clear();
} else if (qName.equals("skeleton")) {
nameToBone.clear();
}
assert elementStack.peek().equals(qName);
elementStack.pop();
}
Aggregations