Added the base of the blending system. Smooth transition between anims
This commit is contained in:
parent
dd5b90e281
commit
449429974e
@ -11,12 +11,12 @@ import java.io.IOException;
|
|||||||
/**
|
/**
|
||||||
* Created by Nehon on 20/12/2017.
|
* Created by Nehon on 20/12/2017.
|
||||||
*/
|
*/
|
||||||
public class AnimClip implements Tween, JmeCloneable, Savable {
|
public class AnimClip implements JmeCloneable, Savable {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private double length;
|
private double length;
|
||||||
|
|
||||||
private SafeArrayList<Tween> tracks = new SafeArrayList<>(Tween.class);
|
private TransformTrack[] tracks;
|
||||||
|
|
||||||
public AnimClip() {
|
public AnimClip() {
|
||||||
}
|
}
|
||||||
@ -25,26 +25,11 @@ public class AnimClip implements Tween, JmeCloneable, Savable {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTracks(Tween[] tracks) {
|
public void setTracks(TransformTrack[] tracks) {
|
||||||
for (Tween track : tracks) {
|
this.tracks = tracks;
|
||||||
addTrack(track);
|
for (TransformTrack track : tracks) {
|
||||||
}
|
if (track.getLength() > length) {
|
||||||
}
|
length = track.getLength();
|
||||||
|
|
||||||
public void addTrack(Tween track) {
|
|
||||||
tracks.add(track);
|
|
||||||
if (track.getLength() > length) {
|
|
||||||
length = track.getLength();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeTrack(Tween track) {
|
|
||||||
if (tracks.remove(track)) {
|
|
||||||
length = 0;
|
|
||||||
for (Tween t : tracks.getArray()) {
|
|
||||||
if (t.getLength() > length) {
|
|
||||||
length = t.getLength();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,24 +38,14 @@ public class AnimClip implements Tween, JmeCloneable, Savable {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public double getLength() {
|
public double getLength() {
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean interpolate(double t) {
|
|
||||||
// Sanity check the inputs
|
|
||||||
if (t < 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Tween track : tracks.getArray()) {
|
public TransformTrack[] getTracks() {
|
||||||
if (t <= track.getLength()) {
|
return tracks;
|
||||||
track.interpolate(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return t <= length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -84,9 +59,9 @@ public class AnimClip implements Tween, JmeCloneable, Savable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cloneFields(Cloner cloner, Object original) {
|
public void cloneFields(Cloner cloner, Object original) {
|
||||||
SafeArrayList<Tween> newTracks = new SafeArrayList<>(Tween.class);
|
TransformTrack[] newTracks = new TransformTrack[tracks.length];
|
||||||
for (Tween track : tracks) {
|
for (int i = 0; i < tracks.length; i++) {
|
||||||
newTracks.add(cloner.clone(track));
|
newTracks[i] = (cloner.clone(tracks[i]));
|
||||||
}
|
}
|
||||||
this.tracks = newTracks;
|
this.tracks = newTracks;
|
||||||
}
|
}
|
||||||
@ -95,7 +70,7 @@ public class AnimClip implements Tween, JmeCloneable, Savable {
|
|||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
OutputCapsule oc = ex.getCapsule(this);
|
OutputCapsule oc = ex.getCapsule(this);
|
||||||
oc.write(name, "name", null);
|
oc.write(name, "name", null);
|
||||||
oc.write(tracks.getArray(), "tracks", null);
|
oc.write(tracks, "tracks", null);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,9 +80,13 @@ public class AnimClip implements Tween, JmeCloneable, Savable {
|
|||||||
name = ic.readString("name", null);
|
name = ic.readString("name", null);
|
||||||
Savable[] arr = ic.readSavableArray("tracks", null);
|
Savable[] arr = ic.readSavableArray("tracks", null);
|
||||||
if (arr != null) {
|
if (arr != null) {
|
||||||
tracks = new SafeArrayList<>(Tween.class);
|
tracks = new TransformTrack[arr.length];
|
||||||
for (Savable savable : arr) {
|
for (int i = 0; i < arr.length; i++) {
|
||||||
addTrack((Tween) savable);
|
TransformTrack t = (TransformTrack) arr[i];
|
||||||
|
tracks[i] = t;
|
||||||
|
if (t.getLength() > length) {
|
||||||
|
length = t.getLength();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
package com.jme3.anim;
|
package com.jme3.anim;
|
||||||
|
|
||||||
|
import com.jme3.anim.tween.AnimClipTween;
|
||||||
|
import com.jme3.anim.tween.Tween;
|
||||||
|
import com.jme3.anim.tween.action.Action;
|
||||||
|
import com.jme3.anim.tween.action.SequenceAction;
|
||||||
import com.jme3.export.*;
|
import com.jme3.export.*;
|
||||||
import com.jme3.renderer.RenderManager;
|
import com.jme3.renderer.RenderManager;
|
||||||
import com.jme3.renderer.ViewPort;
|
import com.jme3.renderer.ViewPort;
|
||||||
@ -16,7 +20,8 @@ public class AnimComposer extends AbstractControl {
|
|||||||
|
|
||||||
private Map<String, AnimClip> animClipMap = new HashMap<>();
|
private Map<String, AnimClip> animClipMap = new HashMap<>();
|
||||||
|
|
||||||
private AnimClip currentAnimClip;
|
private Action currentAction;
|
||||||
|
private Map<String, Action> actions = new HashMap<>();
|
||||||
private float time;
|
private float time;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,16 +59,45 @@ public class AnimComposer extends AbstractControl {
|
|||||||
animClipMap.remove(anim.getName());
|
animClipMap.remove(anim.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrentAnimClip(String name) {
|
public void setCurrentAction(String name) {
|
||||||
currentAnimClip = animClipMap.get(name);
|
Action action = action(name);
|
||||||
time = 0;
|
if (currentAction != null) {
|
||||||
if (currentAnimClip == null) {
|
currentAction.reset();
|
||||||
throw new IllegalArgumentException("Unknown clip " + name);
|
|
||||||
}
|
}
|
||||||
|
currentAction = action;
|
||||||
|
time = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action action(String name) {
|
||||||
|
Action action = actions.get(name);
|
||||||
|
if (action == null) {
|
||||||
|
AnimClipTween tween = tweenFromClip(name);
|
||||||
|
action = new SequenceAction(tween);
|
||||||
|
actions.put(name, action);
|
||||||
|
}
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnimClipTween tweenFromClip(String clipName) {
|
||||||
|
AnimClip clip = animClipMap.get(clipName);
|
||||||
|
if (clip == null) {
|
||||||
|
throw new IllegalArgumentException("Cannot find clip named " + clipName);
|
||||||
|
}
|
||||||
|
return new AnimClipTween(clip);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SequenceAction actionSequence(String name, Tween... tweens) {
|
||||||
|
SequenceAction action = new SequenceAction(tweens);
|
||||||
|
actions.put(name, action);
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action actionBlended(String name, Tween... tweens) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
currentAnimClip = null;
|
currentAction = null;
|
||||||
time = 0;
|
time = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,11 +111,11 @@ public class AnimComposer extends AbstractControl {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void controlUpdate(float tpf) {
|
protected void controlUpdate(float tpf) {
|
||||||
if (currentAnimClip != null) {
|
if (currentAction != null) {
|
||||||
time += tpf;
|
time += tpf;
|
||||||
boolean running = currentAnimClip.interpolate(time);
|
boolean running = currentAction.interpolate(time);
|
||||||
if (!running) {
|
if (!running) {
|
||||||
time -= currentAnimClip.getLength();
|
time -= currentAction.getLength();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,6 +142,11 @@ public class AnimComposer extends AbstractControl {
|
|||||||
for (String key : animClipMap.keySet()) {
|
for (String key : animClipMap.keySet()) {
|
||||||
clips.put(key, cloner.clone(animClipMap.get(key)));
|
clips.put(key, cloner.clone(animClipMap.get(key)));
|
||||||
}
|
}
|
||||||
|
Map<String, Action> act = new HashMap<>();
|
||||||
|
for (String key : actions.keySet()) {
|
||||||
|
act.put(key, cloner.clone(actions.get(key)));
|
||||||
|
}
|
||||||
|
actions = act;
|
||||||
animClipMap = clips;
|
animClipMap = clips;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,6 +155,7 @@ public class AnimComposer extends AbstractControl {
|
|||||||
super.read(im);
|
super.read(im);
|
||||||
InputCapsule ic = im.getCapsule(this);
|
InputCapsule ic = im.getCapsule(this);
|
||||||
animClipMap = (Map<String, AnimClip>) ic.readStringSavableMap("animClipMap", new HashMap<String, AnimClip>());
|
animClipMap = (Map<String, AnimClip>) ic.readStringSavableMap("animClipMap", new HashMap<String, AnimClip>());
|
||||||
|
actions = (Map<String, Action>) ic.readStringSavableMap("actions", new HashMap<String, Action>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -123,5 +163,6 @@ public class AnimComposer extends AbstractControl {
|
|||||||
super.write(ex);
|
super.write(ex);
|
||||||
OutputCapsule oc = ex.getCapsule(this);
|
OutputCapsule oc = ex.getCapsule(this);
|
||||||
oc.writeStringSavableMap(animClipMap, "animClipMap", new HashMap<String, AnimClip>());
|
oc.writeStringSavableMap(animClipMap, "animClipMap", new HashMap<String, AnimClip>());
|
||||||
|
oc.writeStringSavableMap(actions, "actions", new HashMap<String, Action>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.jme3.anim;
|
package com.jme3.anim;
|
||||||
|
|
||||||
|
import com.jme3.anim.util.HasLocalTransform;
|
||||||
import com.jme3.anim.util.JointModelTransform;
|
import com.jme3.anim.util.JointModelTransform;
|
||||||
import com.jme3.export.*;
|
import com.jme3.export.*;
|
||||||
import com.jme3.material.MatParamOverride;
|
import com.jme3.material.MatParamOverride;
|
||||||
@ -18,7 +19,7 @@ import java.util.List;
|
|||||||
* A Joint is the basic component of an armature designed to perform skeletal animation
|
* A Joint is the basic component of an armature designed to perform skeletal animation
|
||||||
* Created by Nehon on 15/12/2017.
|
* Created by Nehon on 15/12/2017.
|
||||||
*/
|
*/
|
||||||
public class Joint implements Savable, JmeCloneable {
|
public class Joint implements Savable, JmeCloneable, HasLocalTransform {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private Joint parent;
|
private Joint parent;
|
||||||
|
@ -1,108 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are
|
|
||||||
* met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
package com.jme3.anim;
|
|
||||||
|
|
||||||
import com.jme3.export.*;
|
|
||||||
import com.jme3.math.*;
|
|
||||||
import com.jme3.util.clone.Cloner;
|
|
||||||
import com.jme3.util.clone.JmeCloneable;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains a list of transforms and times for each keyframe.
|
|
||||||
*
|
|
||||||
* @author Rémy Bouquet
|
|
||||||
*/
|
|
||||||
public final class JointTrack extends TransformTrack implements JmeCloneable, Savable {
|
|
||||||
|
|
||||||
private Joint target;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serialization-only. Do not use.
|
|
||||||
*/
|
|
||||||
public JointTrack() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a joint track for the given joint index
|
|
||||||
*
|
|
||||||
* @param target The Joint target of this track
|
|
||||||
* @param times a float array with the time of each frame
|
|
||||||
* @param translations the translation of the bone for each frame
|
|
||||||
* @param rotations the rotation of the bone for each frame
|
|
||||||
* @param scales the scale of the bone for each frame
|
|
||||||
*/
|
|
||||||
public JointTrack(Joint target, float[] times, Vector3f[] translations, Quaternion[] rotations, Vector3f[] scales) {
|
|
||||||
super(times, translations, rotations, scales);
|
|
||||||
this.target = target;
|
|
||||||
this.defaultTransform = target.getLocalTransform();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean interpolate(double t) {
|
|
||||||
boolean running = super.interpolate(t);
|
|
||||||
Transform transform = getInterpolatedTransform();
|
|
||||||
target.setLocalTransform(transform);
|
|
||||||
return running;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTarget(Joint target) {
|
|
||||||
this.target = target;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object jmeClone() {
|
|
||||||
return super.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cloneFields(Cloner cloner, Object original) {
|
|
||||||
this.target = cloner.clone(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(JmeExporter ex) throws IOException {
|
|
||||||
super.write(ex);
|
|
||||||
OutputCapsule oc = ex.getCapsule(this);
|
|
||||||
oc.write(target, "target", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void read(JmeImporter im) throws IOException {
|
|
||||||
super.read(im);
|
|
||||||
InputCapsule ic = im.getCapsule(this);
|
|
||||||
target = (Joint) ic.readSavable("target", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,111 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2009-2012 jMonkeyEngine
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are
|
|
||||||
* met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
||||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
package com.jme3.anim;
|
|
||||||
|
|
||||||
import com.jme3.export.*;
|
|
||||||
import com.jme3.math.*;
|
|
||||||
import com.jme3.scene.Spatial;
|
|
||||||
import com.jme3.util.clone.Cloner;
|
|
||||||
import com.jme3.util.clone.JmeCloneable;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains a list of transforms and times for each keyframe.
|
|
||||||
*
|
|
||||||
* @author Rémy Bouquet
|
|
||||||
*/
|
|
||||||
public final class SpatialTrack extends TransformTrack implements JmeCloneable, Savable {
|
|
||||||
|
|
||||||
private Spatial target;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serialization-only. Do not use.
|
|
||||||
*/
|
|
||||||
public SpatialTrack() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a spatial track for the given Spatial
|
|
||||||
*
|
|
||||||
* @param target The Spatial target of this track
|
|
||||||
* @param times a float array with the time of each frame
|
|
||||||
* @param translations the translation of the bone for each frame
|
|
||||||
* @param rotations the rotation of the bone for each frame
|
|
||||||
* @param scales the scale of the bone for each frame
|
|
||||||
*/
|
|
||||||
public SpatialTrack(Spatial target, float[] times, Vector3f[] translations, Quaternion[] rotations, Vector3f[] scales) {
|
|
||||||
super(times, translations, rotations, scales);
|
|
||||||
this.target = target;
|
|
||||||
defaultTransform = target.getLocalTransform();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean interpolate(double t) {
|
|
||||||
|
|
||||||
boolean running = super.interpolate(t);
|
|
||||||
Transform transform = getInterpolatedTransform();
|
|
||||||
target.setLocalTransform(transform);
|
|
||||||
return running;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTarget(Spatial target) {
|
|
||||||
this.target = target;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object jmeClone() {
|
|
||||||
return super.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cloneFields(Cloner cloner, Object original) {
|
|
||||||
|
|
||||||
this.target = cloner.clone(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(JmeExporter ex) throws IOException {
|
|
||||||
super.write(ex);
|
|
||||||
OutputCapsule oc = ex.getCapsule(this);
|
|
||||||
oc.write(target, "target", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void read(JmeImporter im) throws IOException {
|
|
||||||
super.read(im);
|
|
||||||
InputCapsule ic = im.getCapsule(this);
|
|
||||||
target = (Spatial) ic.readSavable("target", null);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -33,10 +33,13 @@ package com.jme3.anim;
|
|||||||
|
|
||||||
import com.jme3.anim.interpolator.FrameInterpolator;
|
import com.jme3.anim.interpolator.FrameInterpolator;
|
||||||
import com.jme3.anim.tween.Tween;
|
import com.jme3.anim.tween.Tween;
|
||||||
|
import com.jme3.anim.util.HasLocalTransform;
|
||||||
import com.jme3.animation.CompactQuaternionArray;
|
import com.jme3.animation.CompactQuaternionArray;
|
||||||
import com.jme3.animation.CompactVector3Array;
|
import com.jme3.animation.CompactVector3Array;
|
||||||
import com.jme3.export.*;
|
import com.jme3.export.*;
|
||||||
import com.jme3.math.*;
|
import com.jme3.math.*;
|
||||||
|
import com.jme3.util.clone.Cloner;
|
||||||
|
import com.jme3.util.clone.JmeCloneable;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
@ -45,9 +48,10 @@ import java.io.IOException;
|
|||||||
*
|
*
|
||||||
* @author Rémy Bouquet
|
* @author Rémy Bouquet
|
||||||
*/
|
*/
|
||||||
public abstract class TransformTrack implements Tween, Cloneable, Savable {
|
public class TransformTrack implements JmeCloneable, Savable {
|
||||||
|
|
||||||
private double length;
|
private double length;
|
||||||
|
private HasLocalTransform target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transforms and times for track.
|
* Transforms and times for track.
|
||||||
@ -55,8 +59,6 @@ public abstract class TransformTrack implements Tween, Cloneable, Savable {
|
|||||||
private CompactVector3Array translations;
|
private CompactVector3Array translations;
|
||||||
private CompactQuaternionArray rotations;
|
private CompactQuaternionArray rotations;
|
||||||
private CompactVector3Array scales;
|
private CompactVector3Array scales;
|
||||||
private Transform transform = new Transform();
|
|
||||||
protected Transform defaultTransform = new Transform();
|
|
||||||
private FrameInterpolator interpolator = FrameInterpolator.DEFAULT;
|
private FrameInterpolator interpolator = FrameInterpolator.DEFAULT;
|
||||||
private float[] times;
|
private float[] times;
|
||||||
|
|
||||||
@ -74,7 +76,8 @@ public abstract class TransformTrack implements Tween, Cloneable, Savable {
|
|||||||
* @param rotations the rotation of the bone for each frame
|
* @param rotations the rotation of the bone for each frame
|
||||||
* @param scales the scale of the bone for each frame
|
* @param scales the scale of the bone for each frame
|
||||||
*/
|
*/
|
||||||
public TransformTrack(float[] times, Vector3f[] translations, Quaternion[] rotations, Vector3f[] scales) {
|
public TransformTrack(HasLocalTransform target, float[] times, Vector3f[] translations, Quaternion[] rotations, Vector3f[] scales) {
|
||||||
|
this.target = target;
|
||||||
this.setKeyframes(times, translations, rotations, scales);
|
this.setKeyframes(times, translations, rotations, scales);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,16 +219,13 @@ public abstract class TransformTrack implements Tween, Cloneable, Savable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public double getLength() {
|
public double getLength() {
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void getTransformAtTime(double t, Transform transform) {
|
||||||
public boolean interpolate(double t) {
|
|
||||||
float time = (float) t;
|
float time = (float) t;
|
||||||
|
|
||||||
transform.set(defaultTransform);
|
|
||||||
int lastFrame = times.length - 1;
|
int lastFrame = times.length - 1;
|
||||||
if (time < 0 || lastFrame == 0) {
|
if (time < 0 || lastFrame == 0) {
|
||||||
if (translations != null) {
|
if (translations != null) {
|
||||||
@ -237,7 +237,7 @@ public abstract class TransformTrack implements Tween, Cloneable, Savable {
|
|||||||
if (scales != null) {
|
if (scales != null) {
|
||||||
scales.get(0, transform.getScale());
|
scales.get(0, transform.getScale());
|
||||||
}
|
}
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int startFrame = 0;
|
int startFrame = 0;
|
||||||
@ -272,19 +272,20 @@ public abstract class TransformTrack implements Tween, Cloneable, Savable {
|
|||||||
if (scales != null) {
|
if (scales != null) {
|
||||||
transform.setScale(interpolated.getScale());
|
transform.setScale(interpolated.getScale());
|
||||||
}
|
}
|
||||||
|
|
||||||
return time < length;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Transform getInterpolatedTransform() {
|
|
||||||
return transform;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFrameInterpolator(FrameInterpolator interpolator) {
|
public void setFrameInterpolator(FrameInterpolator interpolator) {
|
||||||
this.interpolator = interpolator;
|
this.interpolator = interpolator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HasLocalTransform getTarget() {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTarget(HasLocalTransform target) {
|
||||||
|
this.target = target;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(JmeExporter ex) throws IOException {
|
public void write(JmeExporter ex) throws IOException {
|
||||||
OutputCapsule oc = ex.getCapsule(this);
|
OutputCapsule oc = ex.getCapsule(this);
|
||||||
@ -292,6 +293,7 @@ public abstract class TransformTrack implements Tween, Cloneable, Savable {
|
|||||||
oc.write(rotations, "rotations", null);
|
oc.write(rotations, "rotations", null);
|
||||||
oc.write(times, "times", null);
|
oc.write(times, "times", null);
|
||||||
oc.write(scales, "scales", null);
|
oc.write(scales, "scales", null);
|
||||||
|
oc.write(target, "target", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -301,16 +303,22 @@ public abstract class TransformTrack implements Tween, Cloneable, Savable {
|
|||||||
rotations = (CompactQuaternionArray) ic.readSavable("rotations", null);
|
rotations = (CompactQuaternionArray) ic.readSavable("rotations", null);
|
||||||
times = ic.readFloatArray("times", null);
|
times = ic.readFloatArray("times", null);
|
||||||
scales = (CompactVector3Array) ic.readSavable("scales", null);
|
scales = (CompactVector3Array) ic.readSavable("scales", null);
|
||||||
|
target = (Joint) ic.readSavable("target", null);
|
||||||
setTimes(times);
|
setTimes(times);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object clone() {
|
public Object jmeClone() {
|
||||||
try {
|
try {
|
||||||
return super.clone();
|
TransformTrack clone = (TransformTrack) super.clone();
|
||||||
} catch (CloneNotSupportedException e) {
|
return clone;
|
||||||
throw new RuntimeException("Error cloning", e);
|
} catch (CloneNotSupportedException ex) {
|
||||||
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cloneFields(Cloner cloner, Object original) {
|
||||||
|
this.target = cloner.clone(target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,99 @@
|
|||||||
|
package com.jme3.anim.tween;
|
||||||
|
|
||||||
|
import com.jme3.anim.AnimClip;
|
||||||
|
import com.jme3.anim.TransformTrack;
|
||||||
|
import com.jme3.anim.tween.action.Action;
|
||||||
|
import com.jme3.anim.util.HasLocalTransform;
|
||||||
|
import com.jme3.anim.util.Weighted;
|
||||||
|
import com.jme3.export.InputCapsule;
|
||||||
|
import com.jme3.export.JmeExporter;
|
||||||
|
import com.jme3.export.JmeImporter;
|
||||||
|
import com.jme3.export.OutputCapsule;
|
||||||
|
import com.jme3.math.Transform;
|
||||||
|
import com.jme3.util.clone.Cloner;
|
||||||
|
import com.jme3.util.clone.JmeCloneable;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class AnimClipTween implements Tween, Weighted, JmeCloneable {
|
||||||
|
|
||||||
|
private AnimClip clip;
|
||||||
|
private Transform transform = new Transform();
|
||||||
|
private float weight = 1f;
|
||||||
|
private Action parentAction;
|
||||||
|
|
||||||
|
public AnimClipTween() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnimClipTween(AnimClip clip) {
|
||||||
|
this.clip = clip;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getLength() {
|
||||||
|
return clip.getLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean interpolate(double t) {
|
||||||
|
// Sanity check the inputs
|
||||||
|
if (t < 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (parentAction != null) {
|
||||||
|
weight = parentAction.getWeightForTween(this);
|
||||||
|
}
|
||||||
|
TransformTrack[] tracks = clip.getTracks();
|
||||||
|
for (TransformTrack track : tracks) {
|
||||||
|
HasLocalTransform target = track.getTarget();
|
||||||
|
transform.set(target.getLocalTransform());
|
||||||
|
track.getTransformAtTime(t, transform);
|
||||||
|
|
||||||
|
if (weight == 1f) {
|
||||||
|
target.setLocalTransform(transform);
|
||||||
|
} else {
|
||||||
|
Transform tr = target.getLocalTransform();
|
||||||
|
tr.interpolateTransforms(tr, transform, weight);
|
||||||
|
target.setLocalTransform(tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t < clip.getLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(JmeExporter ex) throws IOException {
|
||||||
|
OutputCapsule oc = ex.getCapsule(this);
|
||||||
|
oc.write(clip, "clip", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(JmeImporter im) throws IOException {
|
||||||
|
InputCapsule ic = im.getCapsule(this);
|
||||||
|
clip = (AnimClip) ic.readSavable("clip", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object jmeClone() {
|
||||||
|
try {
|
||||||
|
AnimClipTween clone = (AnimClipTween) super.clone();
|
||||||
|
return clone;
|
||||||
|
} catch (CloneNotSupportedException ex) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cloneFields(Cloner cloner, Object original) {
|
||||||
|
clip = cloner.clone(clip);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Override
|
||||||
|
// public void setWeight(float weight) {
|
||||||
|
// this.weight = weight;
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParentAction(Action action) {
|
||||||
|
this.parentAction = action;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package com.jme3.anim.tween.action;
|
||||||
|
|
||||||
|
import com.jme3.anim.tween.Tween;
|
||||||
|
import com.jme3.anim.util.Weighted;
|
||||||
|
import com.jme3.export.InputCapsule;
|
||||||
|
import com.jme3.export.JmeExporter;
|
||||||
|
import com.jme3.export.JmeImporter;
|
||||||
|
import com.jme3.export.OutputCapsule;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public abstract class Action implements Tween, Weighted {
|
||||||
|
|
||||||
|
protected Tween[] tweens;
|
||||||
|
protected float weight = 1;
|
||||||
|
protected double length;
|
||||||
|
protected Action parentAction;
|
||||||
|
|
||||||
|
protected Action(Tween... tweens) {
|
||||||
|
this.tweens = tweens;
|
||||||
|
for (Tween tween : tweens) {
|
||||||
|
if (tween instanceof Weighted) {
|
||||||
|
((Weighted) tween).setParentAction(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getLength() {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean interpolate(double t) {
|
||||||
|
if (parentAction != null) {
|
||||||
|
weight = parentAction.getWeightForTween(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return doInterpolate(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract float getWeightForTween(Tween tween);
|
||||||
|
|
||||||
|
public abstract boolean doInterpolate(double t);
|
||||||
|
|
||||||
|
public abstract void reset();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParentAction(Action parentAction) {
|
||||||
|
this.parentAction = parentAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(JmeImporter im) throws IOException {
|
||||||
|
InputCapsule ic = im.getCapsule(this);
|
||||||
|
tweens = (Tween[]) ic.readSavableArray("tweens", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(JmeExporter ex) throws IOException {
|
||||||
|
OutputCapsule oc = ex.getCapsule(this);
|
||||||
|
oc.write(tweens, "tweens", null);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
package com.jme3.anim.tween.action;
|
||||||
|
|
||||||
|
import com.jme3.anim.tween.AbstractTween;
|
||||||
|
import com.jme3.anim.tween.Tween;
|
||||||
|
|
||||||
|
public class SequenceAction extends Action {
|
||||||
|
|
||||||
|
private int currentIndex = 0;
|
||||||
|
private double accumTime;
|
||||||
|
private double transitionTime = 0;
|
||||||
|
private float mainWeight = 1.0f;
|
||||||
|
private double transitionLength = 0.4f;
|
||||||
|
private TransitionTween transition = new TransitionTween(transitionLength);
|
||||||
|
|
||||||
|
|
||||||
|
public SequenceAction(Tween... tweens) {
|
||||||
|
super(tweens);
|
||||||
|
for (Tween tween : tweens) {
|
||||||
|
length += tween.getLength();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getWeightForTween(Tween tween) {
|
||||||
|
return weight * mainWeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doInterpolate(double t) {
|
||||||
|
Tween currentTween = tweens[currentIndex];
|
||||||
|
if (transition.getLength() > currentTween.getLength()) {
|
||||||
|
transition.setLength(currentTween.getLength());
|
||||||
|
}
|
||||||
|
|
||||||
|
transition.interpolate(t - transitionTime);
|
||||||
|
|
||||||
|
boolean running = currentTween.interpolate(t - accumTime);
|
||||||
|
if (!running) {
|
||||||
|
accumTime += currentTween.getLength();
|
||||||
|
currentIndex++;
|
||||||
|
transitionTime = accumTime;
|
||||||
|
transition.setLength(transitionLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t >= length) {
|
||||||
|
reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
currentIndex = 0;
|
||||||
|
accumTime = 0;
|
||||||
|
transitionTime = 0;
|
||||||
|
mainWeight = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTransitionLength(double transitionLength) {
|
||||||
|
this.transitionLength = transitionLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TransitionTween extends AbstractTween {
|
||||||
|
|
||||||
|
|
||||||
|
public TransitionTween(double length) {
|
||||||
|
super(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doInterpolate(double t) {
|
||||||
|
mainWeight = (float) t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -61,10 +61,14 @@ public class AnimMigrationUtils {
|
|||||||
armature.setBindPose();
|
armature.setBindPose();
|
||||||
skeletonArmatureMap.put(skeleton, armature);
|
skeletonArmatureMap.put(skeleton, armature);
|
||||||
|
|
||||||
|
List<TransformTrack> tracks = new ArrayList<>();
|
||||||
|
|
||||||
for (String animName : control.getAnimationNames()) {
|
for (String animName : control.getAnimationNames()) {
|
||||||
|
tracks.clear();
|
||||||
Animation anim = control.getAnim(animName);
|
Animation anim = control.getAnim(animName);
|
||||||
AnimClip clip = new AnimClip(animName);
|
AnimClip clip = new AnimClip(animName);
|
||||||
Joint[] staticJoints = new Joint[joints.length];
|
Joint[] staticJoints = new Joint[joints.length];
|
||||||
|
|
||||||
System.arraycopy(joints, 0, staticJoints, 0, joints.length);
|
System.arraycopy(joints, 0, staticJoints, 0, joints.length);
|
||||||
for (Track track : anim.getTracks()) {
|
for (Track track : anim.getTracks()) {
|
||||||
if (track instanceof BoneTrack) {
|
if (track instanceof BoneTrack) {
|
||||||
@ -72,17 +76,20 @@ public class AnimMigrationUtils {
|
|||||||
int index = boneTrack.getTargetBoneIndex();
|
int index = boneTrack.getTargetBoneIndex();
|
||||||
Bone bone = skeleton.getBone(index);
|
Bone bone = skeleton.getBone(index);
|
||||||
Joint joint = joints[index];
|
Joint joint = joints[index];
|
||||||
JointTrack jointTrack = fromBoneTrack(boneTrack, bone, joint);
|
TransformTrack jointTrack = fromBoneTrack(boneTrack, bone, joint);
|
||||||
clip.addTrack(jointTrack);
|
tracks.add(jointTrack);
|
||||||
//this joint is animated let's remove it from the static joints
|
//this joint is animated let's remove it from the static joints
|
||||||
staticJoints[index] = null;
|
staticJoints[index] = null;
|
||||||
}
|
}
|
||||||
|
//TODO spatial tracks , Effect tracks, Audio tracks
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < staticJoints.length; i++) {
|
for (int i = 0; i < staticJoints.length; i++) {
|
||||||
padJointTracks(clip, staticJoints[i]);
|
padJointTracks(tracks, staticJoints[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clip.setTracks(tracks.toArray(new TransformTrack[tracks.size()]));
|
||||||
|
|
||||||
composer.addAnimClip(clip);
|
composer.addAnimClip(clip);
|
||||||
}
|
}
|
||||||
spatial.removeControl(control);
|
spatial.removeControl(control);
|
||||||
@ -95,7 +102,7 @@ public class AnimMigrationUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void padJointTracks(AnimClip clip, Joint staticJoint) {
|
public static void padJointTracks(List<TransformTrack> tracks, Joint staticJoint) {
|
||||||
Joint j = staticJoint;
|
Joint j = staticJoint;
|
||||||
if (j != null) {
|
if (j != null) {
|
||||||
// joint has no track , we create one with the default pose
|
// joint has no track , we create one with the default pose
|
||||||
@ -103,8 +110,8 @@ public class AnimMigrationUtils {
|
|||||||
Vector3f[] translations = new Vector3f[]{j.getLocalTranslation()};
|
Vector3f[] translations = new Vector3f[]{j.getLocalTranslation()};
|
||||||
Quaternion[] rotations = new Quaternion[]{j.getLocalRotation()};
|
Quaternion[] rotations = new Quaternion[]{j.getLocalRotation()};
|
||||||
Vector3f[] scales = new Vector3f[]{j.getLocalScale()};
|
Vector3f[] scales = new Vector3f[]{j.getLocalScale()};
|
||||||
JointTrack track = new JointTrack(j, times, translations, rotations, scales);
|
TransformTrack track = new TransformTrack(j, times, translations, rotations, scales);
|
||||||
clip.addTrack(track);
|
tracks.add(track);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +151,7 @@ public class AnimMigrationUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JointTrack fromBoneTrack(BoneTrack boneTrack, Bone bone, Joint joint) {
|
public static TransformTrack fromBoneTrack(BoneTrack boneTrack, Bone bone, Joint joint) {
|
||||||
float[] times = new float[boneTrack.getTimes().length];
|
float[] times = new float[boneTrack.getTimes().length];
|
||||||
int length = times.length;
|
int length = times.length;
|
||||||
System.arraycopy(boneTrack.getTimes(), 0, times, 0, length);
|
System.arraycopy(boneTrack.getTimes(), 0, times, 0, length);
|
||||||
@ -178,8 +185,8 @@ public class AnimMigrationUtils {
|
|||||||
scales[i] = newScale;
|
scales[i] = newScale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TransformTrack t = new TransformTrack(joint, times, translations, rotations, scales);
|
||||||
return new JointTrack(joint, times, translations, rotations, scales);
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Joint fromBone(Bone b) {
|
private static Joint fromBone(Bone b) {
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.jme3.anim.util;
|
||||||
|
|
||||||
|
import com.jme3.export.Savable;
|
||||||
|
import com.jme3.math.Transform;
|
||||||
|
|
||||||
|
public interface HasLocalTransform extends Savable {
|
||||||
|
public void setLocalTransform(Transform transform);
|
||||||
|
|
||||||
|
public Transform getLocalTransform();
|
||||||
|
}
|
11
jme3-core/src/main/java/com/jme3/anim/util/Weighted.java
Normal file
11
jme3-core/src/main/java/com/jme3/anim/util/Weighted.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package com.jme3.anim.util;
|
||||||
|
|
||||||
|
import com.jme3.anim.tween.action.Action;
|
||||||
|
import com.jme3.math.Transform;
|
||||||
|
|
||||||
|
public interface Weighted {
|
||||||
|
|
||||||
|
// public void setWeight(float weight);
|
||||||
|
|
||||||
|
public void setParentAction(Action action);
|
||||||
|
}
|
@ -176,7 +176,7 @@ public final class Transform implements Savable, Cloneable, java.io.Serializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets this matrix to the interpolation between the first matrix and the second by delta amount.
|
* Sets this transform to the interpolation between the first transform and the second by delta amount.
|
||||||
* @param t1 The beginning transform.
|
* @param t1 The beginning transform.
|
||||||
* @param t2 The ending transform.
|
* @param t2 The ending transform.
|
||||||
* @param delta An amount between 0 and 1 representing how far to interpolate from t1 to t2.
|
* @param delta An amount between 0 and 1 representing how far to interpolate from t1 to t2.
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.jme3.scene;
|
package com.jme3.scene;
|
||||||
|
|
||||||
|
import com.jme3.anim.util.HasLocalTransform;
|
||||||
import com.jme3.asset.AssetKey;
|
import com.jme3.asset.AssetKey;
|
||||||
import com.jme3.asset.CloneableSmartAsset;
|
import com.jme3.asset.CloneableSmartAsset;
|
||||||
import com.jme3.bounding.BoundingVolume;
|
import com.jme3.bounding.BoundingVolume;
|
||||||
@ -67,7 +68,7 @@ import java.util.logging.Logger;
|
|||||||
* @author Joshua Slack
|
* @author Joshua Slack
|
||||||
* @version $Revision: 4075 $, $Data$
|
* @version $Revision: 4075 $, $Data$
|
||||||
*/
|
*/
|
||||||
public abstract class Spatial implements Savable, Cloneable, Collidable, CloneableSmartAsset, JmeCloneable {
|
public abstract class Spatial implements Savable, Cloneable, Collidable, CloneableSmartAsset, JmeCloneable, HasLocalTransform {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(Spatial.class.getName());
|
private static final Logger logger = Logger.getLogger(Spatial.class.getName());
|
||||||
|
|
||||||
@ -1792,4 +1793,4 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void breadthFirstTraversal(SceneGraphVisitor visitor, Queue<Spatial> queue);
|
protected abstract void breadthFirstTraversal(SceneGraphVisitor visitor, Queue<Spatial> queue);
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@ void main(){
|
|||||||
startPos.xy = (startPos * 0.5 + 0.5).xy * resolution;
|
startPos.xy = (startPos * 0.5 + 0.5).xy * resolution;
|
||||||
float len = distance(gl_FragCoord.xy,startPos.xy);
|
float len = distance(gl_FragCoord.xy,startPos.xy);
|
||||||
outColor = inColor;
|
outColor = inColor;
|
||||||
float factor = int(len * 0.25);
|
float factor = float(int(len * 0.25));
|
||||||
if(mod(factor, 2) > 0.0){
|
if(mod(factor, 2.0) > 0.0){
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ public class TestOgreConvert extends SimpleApplication {
|
|||||||
Node ogreModelReloaded = (Node) imp.load(bais, null, null);
|
Node ogreModelReloaded = (Node) imp.load(bais, null, null);
|
||||||
|
|
||||||
AnimComposer composer = ogreModelReloaded.getControl(AnimComposer.class);
|
AnimComposer composer = ogreModelReloaded.getControl(AnimComposer.class);
|
||||||
composer.setCurrentAnimClip("Walk");
|
composer.setCurrentAction("Walk");
|
||||||
|
|
||||||
rootNode.attachChild(ogreModelReloaded);
|
rootNode.attachChild(ogreModelReloaded);
|
||||||
} catch (IOException ex){
|
} catch (IOException ex){
|
||||||
|
@ -116,9 +116,9 @@ public class TestGltfLoading extends SimpleApplication {
|
|||||||
//loadModel("Models/gltf/elephant/scene.gltf", new Vector3f(0, -1, 0), 0.01f);
|
//loadModel("Models/gltf/elephant/scene.gltf", new Vector3f(0, -1, 0), 0.01f);
|
||||||
//loadModel("Models/gltf/buffalo/scene.gltf", new Vector3f(0, -1, 0), 0.1f);
|
//loadModel("Models/gltf/buffalo/scene.gltf", new Vector3f(0, -1, 0), 0.1f);
|
||||||
//loadModel("Models/gltf/war/scene.gltf", new Vector3f(0, -1, 0), 0.1f);
|
//loadModel("Models/gltf/war/scene.gltf", new Vector3f(0, -1, 0), 0.1f);
|
||||||
loadModel("Models/gltf/ganjaarl/scene.gltf", new Vector3f(0, -1, 0), 0.01f);
|
//loadModel("Models/gltf/ganjaarl/scene.gltf", new Vector3f(0, -1, 0), 0.01f);
|
||||||
//loadModel("Models/gltf/hero/scene.gltf", new Vector3f(0, -1, 0), 0.1f);
|
//loadModel("Models/gltf/hero/scene.gltf", new Vector3f(0, -1, 0), 0.1f);
|
||||||
//loadModel("Models/gltf/mercy/scene.gltf", new Vector3f(0, -1, 0), 0.01f);
|
loadModel("Models/gltf/mercy/scene.gltf", new Vector3f(0, -1, 0), 0.01f);
|
||||||
//loadModel("Models/gltf/crab/scene.gltf", Vector3f.ZERO, 1);
|
//loadModel("Models/gltf/crab/scene.gltf", Vector3f.ZERO, 1);
|
||||||
//loadModel("Models/gltf/manta/scene.gltf", Vector3f.ZERO, 0.2f);
|
//loadModel("Models/gltf/manta/scene.gltf", Vector3f.ZERO, 0.2f);
|
||||||
//loadModel("Models/gltf/bone/scene.gltf", Vector3f.ZERO, 0.1f);
|
//loadModel("Models/gltf/bone/scene.gltf", Vector3f.ZERO, 0.1f);
|
||||||
@ -190,7 +190,7 @@ public class TestGltfLoading extends SimpleApplication {
|
|||||||
if (isPressed && composer != null) {
|
if (isPressed && composer != null) {
|
||||||
String anim = anims.poll();
|
String anim = anims.poll();
|
||||||
anims.add(anim);
|
anims.add(anim);
|
||||||
composer.setCurrentAnimClip(anim);
|
composer.setCurrentAction(anim);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, "nextAnim");
|
}, "nextAnim");
|
||||||
@ -262,7 +262,7 @@ public class TestGltfLoading extends SimpleApplication {
|
|||||||
}
|
}
|
||||||
String anim = anims.poll();
|
String anim = anims.poll();
|
||||||
anims.add(anim);
|
anims.add(anim);
|
||||||
control.setCurrentAnimClip(anim);
|
control.setCurrentAction(anim);
|
||||||
composer = control;
|
composer = control;
|
||||||
}
|
}
|
||||||
if (s instanceof Node) {
|
if (s instanceof Node) {
|
||||||
|
@ -2,6 +2,7 @@ package jme3test.model.anim;
|
|||||||
|
|
||||||
import com.jme3.anim.AnimComposer;
|
import com.jme3.anim.AnimComposer;
|
||||||
import com.jme3.anim.SkinningControl;
|
import com.jme3.anim.SkinningControl;
|
||||||
|
import com.jme3.anim.util.AnimMigrationUtils;
|
||||||
import com.jme3.app.ChaseCameraAppState;
|
import com.jme3.app.ChaseCameraAppState;
|
||||||
import com.jme3.app.SimpleApplication;
|
import com.jme3.app.SimpleApplication;
|
||||||
import com.jme3.input.KeyInput;
|
import com.jme3.input.KeyInput;
|
||||||
@ -24,8 +25,8 @@ public class TestAnimMigration extends SimpleApplication {
|
|||||||
|
|
||||||
ArmatureDebugAppState debugAppState;
|
ArmatureDebugAppState debugAppState;
|
||||||
AnimComposer composer;
|
AnimComposer composer;
|
||||||
Queue<String> anims = new LinkedList<>();
|
LinkedList<String> anims = new LinkedList<>();
|
||||||
boolean playAnim = true;
|
boolean playAnim = false;
|
||||||
|
|
||||||
public static void main(String... argv) {
|
public static void main(String... argv) {
|
||||||
TestAnimMigration app = new TestAnimMigration();
|
TestAnimMigration app = new TestAnimMigration();
|
||||||
@ -40,12 +41,12 @@ public class TestAnimMigration extends SimpleApplication {
|
|||||||
rootNode.addLight(new DirectionalLight(new Vector3f(-1, -1, -1).normalizeLocal()));
|
rootNode.addLight(new DirectionalLight(new Vector3f(-1, -1, -1).normalizeLocal()));
|
||||||
rootNode.addLight(new AmbientLight(ColorRGBA.DarkGray));
|
rootNode.addLight(new AmbientLight(ColorRGBA.DarkGray));
|
||||||
|
|
||||||
//Spatial model = assetManager.loadModel("Models/Jaime/Jaime.j3o");
|
Spatial model = assetManager.loadModel("Models/Jaime/Jaime.j3o");
|
||||||
Spatial model = assetManager.loadModel("Models/Oto/Oto.mesh.xml").scale(0.2f).move(0, 1, 0);
|
// Spatial model = assetManager.loadModel("Models/Oto/Oto.mesh.xml").scale(0.2f).move(0, 1, 0);
|
||||||
//Spatial model = assetManager.loadModel("Models/Sinbad/Sinbad.mesh.xml");
|
//Spatial model = assetManager.loadModel("Models/Sinbad/Sinbad.mesh.xml");
|
||||||
//Spatial model = assetManager.loadModel("Models/Elephant/Elephant.mesh.xml").scale(0.02f);
|
//Spatial model = assetManager.loadModel("Models/Elephant/Elephant.mesh.xml").scale(0.02f);
|
||||||
|
|
||||||
// AnimMigrationUtils.migrate(model);
|
AnimMigrationUtils.migrate(model);
|
||||||
|
|
||||||
rootNode.attachChild(model);
|
rootNode.attachChild(model);
|
||||||
|
|
||||||
@ -87,7 +88,7 @@ public class TestAnimMigration extends SimpleApplication {
|
|||||||
if (playAnim) {
|
if (playAnim) {
|
||||||
String anim = anims.poll();
|
String anim = anims.poll();
|
||||||
anims.add(anim);
|
anims.add(anim);
|
||||||
composer.setCurrentAnimClip(anim);
|
composer.setCurrentAction(anim);
|
||||||
System.err.println(anim);
|
System.err.println(anim);
|
||||||
} else {
|
} else {
|
||||||
composer.reset();
|
composer.reset();
|
||||||
@ -102,7 +103,7 @@ public class TestAnimMigration extends SimpleApplication {
|
|||||||
if (isPressed && composer != null) {
|
if (isPressed && composer != null) {
|
||||||
String anim = anims.poll();
|
String anim = anims.poll();
|
||||||
anims.add(anim);
|
anims.add(anim);
|
||||||
composer.setCurrentAnimClip(anim);
|
composer.setCurrentAction(anim);
|
||||||
System.err.println(anim);
|
System.err.println(anim);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,13 +133,26 @@ public class TestAnimMigration extends SimpleApplication {
|
|||||||
for (String name : composer.getAnimClipsNames()) {
|
for (String name : composer.getAnimClipsNames()) {
|
||||||
anims.add(name);
|
anims.add(name);
|
||||||
}
|
}
|
||||||
|
composer.actionSequence("Sequence",
|
||||||
|
composer.tweenFromClip("Walk"),
|
||||||
|
composer.tweenFromClip("Run"),
|
||||||
|
composer.tweenFromClip("Jumping"));
|
||||||
|
|
||||||
|
// composer.actionSequence("Sequence",
|
||||||
|
// composer.tweenFromClip("Walk"),
|
||||||
|
// composer.tweenFromClip("Dodge"),
|
||||||
|
// composer.tweenFromClip("push"));
|
||||||
|
|
||||||
|
|
||||||
|
anims.addFirst("Sequence");
|
||||||
|
|
||||||
if (anims.isEmpty()) {
|
if (anims.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (playAnim) {
|
if (playAnim) {
|
||||||
String anim = anims.poll();
|
String anim = anims.poll();
|
||||||
anims.add(anim);
|
anims.add(anim);
|
||||||
composer.setCurrentAnimClip(anim);
|
composer.setCurrentAction(anim);
|
||||||
System.err.println(anim);
|
System.err.println(anim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ public class TestAnimSerialization extends SimpleApplication {
|
|||||||
if (playAnim) {
|
if (playAnim) {
|
||||||
String anim = anims.poll();
|
String anim = anims.poll();
|
||||||
anims.add(anim);
|
anims.add(anim);
|
||||||
composer.setCurrentAnimClip(anim);
|
composer.setCurrentAction(anim);
|
||||||
System.err.println(anim);
|
System.err.println(anim);
|
||||||
} else {
|
} else {
|
||||||
composer.reset();
|
composer.reset();
|
||||||
@ -117,7 +117,7 @@ public class TestAnimSerialization extends SimpleApplication {
|
|||||||
if (isPressed && composer != null) {
|
if (isPressed && composer != null) {
|
||||||
String anim = anims.poll();
|
String anim = anims.poll();
|
||||||
anims.add(anim);
|
anims.add(anim);
|
||||||
composer.setCurrentAnimClip(anim);
|
composer.setCurrentAction(anim);
|
||||||
System.err.println(anim);
|
System.err.println(anim);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,7 +144,7 @@ public class TestAnimSerialization extends SimpleApplication {
|
|||||||
if (playAnim) {
|
if (playAnim) {
|
||||||
String anim = anims.poll();
|
String anim = anims.poll();
|
||||||
anims.add(anim);
|
anims.add(anim);
|
||||||
composer.setCurrentAnimClip(anim);
|
composer.setCurrentAction(anim);
|
||||||
System.err.println(anim);
|
System.err.println(anim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,10 +78,10 @@ public class TestArmature extends SimpleApplication {
|
|||||||
new Vector3f(1, 1, 1),
|
new Vector3f(1, 1, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
JointTrack track1 = new JointTrack(j1, times, null, rotations, scales);
|
TransformTrack track1 = new TransformTrack(j1, times, null, rotations, scales);
|
||||||
JointTrack track2 = new JointTrack(j2, times, null, rotations, null);
|
TransformTrack track2 = new TransformTrack(j2, times, null, rotations, null);
|
||||||
clip.addTrack(track1);
|
|
||||||
clip.addTrack(track2);
|
clip.setTracks(new TransformTrack[]{track1, track2});
|
||||||
|
|
||||||
//create the animComposer control
|
//create the animComposer control
|
||||||
final AnimComposer composer = new AnimComposer();
|
final AnimComposer composer = new AnimComposer();
|
||||||
@ -103,7 +103,7 @@ public class TestArmature extends SimpleApplication {
|
|||||||
node.addControl(composer);
|
node.addControl(composer);
|
||||||
node.addControl(ac);
|
node.addControl(ac);
|
||||||
|
|
||||||
composer.setCurrentAnimClip("anim");
|
composer.setCurrentAction("anim");
|
||||||
|
|
||||||
ArmatureDebugAppState debugAppState = new ArmatureDebugAppState();
|
ArmatureDebugAppState debugAppState = new ArmatureDebugAppState();
|
||||||
debugAppState.addArmatureFrom(ac);
|
debugAppState.addArmatureFrom(ac);
|
||||||
@ -134,7 +134,7 @@ public class TestArmature extends SimpleApplication {
|
|||||||
armature.resetToBindPose();
|
armature.resetToBindPose();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
composer.setCurrentAnimClip("anim");
|
composer.setCurrentAction("anim");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, "bind");
|
}, "bind");
|
||||||
|
@ -85,10 +85,10 @@ public class TestBaseAnimSerialization extends SimpleApplication {
|
|||||||
new Vector3f(1, 1, 1),
|
new Vector3f(1, 1, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
JointTrack track1 = new JointTrack(j1, times, null, rotations, scales);
|
TransformTrack track1 = new TransformTrack(j1, times, null, rotations, scales);
|
||||||
JointTrack track2 = new JointTrack(j2, times, null, rotations, null);
|
TransformTrack track2 = new TransformTrack(j2, times, null, rotations, null);
|
||||||
clip.addTrack(track1);
|
|
||||||
clip.addTrack(track2);
|
clip.setTracks(new TransformTrack[]{track1, track2});
|
||||||
|
|
||||||
//create the animComposer control
|
//create the animComposer control
|
||||||
composer = new AnimComposer();
|
composer = new AnimComposer();
|
||||||
@ -125,7 +125,7 @@ public class TestBaseAnimSerialization extends SimpleApplication {
|
|||||||
ac = newNode.getControl(SkinningControl.class);
|
ac = newNode.getControl(SkinningControl.class);
|
||||||
ac.setHardwareSkinningPreferred(false);
|
ac.setHardwareSkinningPreferred(false);
|
||||||
armature = ac.getArmature();
|
armature = ac.getArmature();
|
||||||
composer.setCurrentAnimClip("anim");
|
composer.setCurrentAction("anim");
|
||||||
|
|
||||||
ArmatureDebugAppState debugAppState = new ArmatureDebugAppState();
|
ArmatureDebugAppState debugAppState = new ArmatureDebugAppState();
|
||||||
debugAppState.addArmatureFrom(ac);
|
debugAppState.addArmatureFrom(ac);
|
||||||
@ -156,7 +156,7 @@ public class TestBaseAnimSerialization extends SimpleApplication {
|
|||||||
armature.resetToBindPose();
|
armature.resetToBindPose();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
composer.setCurrentAnimClip("anim");
|
composer.setCurrentAction("anim");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, "bind");
|
}, "bind");
|
||||||
|
@ -48,9 +48,9 @@ import java.util.List;
|
|||||||
public class TestHWSkinning extends SimpleApplication implements ActionListener{
|
public class TestHWSkinning extends SimpleApplication implements ActionListener{
|
||||||
|
|
||||||
|
|
||||||
private AnimComposer composer;
|
// private AnimComposer composer;
|
||||||
private String[] animNames = {"Dodge", "Walk", "pull", "push"};
|
private String[] animNames = {"Dodge", "Walk", "pull", "push"};
|
||||||
private final static int SIZE = 50;
|
private final static int SIZE = 40;
|
||||||
private boolean hwSkinningEnable = true;
|
private boolean hwSkinningEnable = true;
|
||||||
private List<SkinningControl> skControls = new ArrayList<SkinningControl>();
|
private List<SkinningControl> skControls = new ArrayList<SkinningControl>();
|
||||||
private BitmapText hwsText;
|
private BitmapText hwsText;
|
||||||
@ -80,9 +80,9 @@ public class TestHWSkinning extends SimpleApplication implements ActionListener{
|
|||||||
Spatial model = (Spatial) assetManager.loadModel("Models/Oto/Oto.mesh.xml");
|
Spatial model = (Spatial) assetManager.loadModel("Models/Oto/Oto.mesh.xml");
|
||||||
model.setLocalScale(0.1f);
|
model.setLocalScale(0.1f);
|
||||||
model.setLocalTranslation(i - SIZE / 2, 0, j - SIZE / 2);
|
model.setLocalTranslation(i - SIZE / 2, 0, j - SIZE / 2);
|
||||||
composer = model.getControl(AnimComposer.class);
|
AnimComposer composer = model.getControl(AnimComposer.class);
|
||||||
|
|
||||||
composer.setCurrentAnimClip(animNames[(i + j) % 4]);
|
composer.setCurrentAction(animNames[(i + j) % 4]);
|
||||||
SkinningControl skinningControl = model.getControl(SkinningControl.class);
|
SkinningControl skinningControl = model.getControl(SkinningControl.class);
|
||||||
skinningControl.setHardwareSkinningPreferred(hwSkinningEnable);
|
skinningControl.setHardwareSkinningPreferred(hwSkinningEnable);
|
||||||
skControls.add(skinningControl);
|
skControls.add(skinningControl);
|
||||||
|
@ -60,19 +60,19 @@ public class TestModelExportingCloning extends SimpleApplication {
|
|||||||
|
|
||||||
Spatial originalModel = assetManager.loadModel("Models/Oto/Oto.mesh.xml");
|
Spatial originalModel = assetManager.loadModel("Models/Oto/Oto.mesh.xml");
|
||||||
composer = originalModel.getControl(AnimComposer.class);
|
composer = originalModel.getControl(AnimComposer.class);
|
||||||
composer.setCurrentAnimClip("Walk");
|
composer.setCurrentAction("Walk");
|
||||||
rootNode.attachChild(originalModel);
|
rootNode.attachChild(originalModel);
|
||||||
|
|
||||||
Spatial clonedModel = originalModel.clone();
|
Spatial clonedModel = originalModel.clone();
|
||||||
clonedModel.move(10, 0, 0);
|
clonedModel.move(10, 0, 0);
|
||||||
composer = clonedModel.getControl(AnimComposer.class);
|
composer = clonedModel.getControl(AnimComposer.class);
|
||||||
composer.setCurrentAnimClip("push");
|
composer.setCurrentAction("push");
|
||||||
rootNode.attachChild(clonedModel);
|
rootNode.attachChild(clonedModel);
|
||||||
|
|
||||||
Spatial exportedModel = BinaryExporter.saveAndLoad(assetManager, originalModel);
|
Spatial exportedModel = BinaryExporter.saveAndLoad(assetManager, originalModel);
|
||||||
exportedModel.move(20, 0, 0);
|
exportedModel.move(20, 0, 0);
|
||||||
composer = exportedModel.getControl(AnimComposer.class);
|
composer = exportedModel.getControl(AnimComposer.class);
|
||||||
composer.setCurrentAnimClip("pull");
|
composer.setCurrentAction("pull");
|
||||||
rootNode.attachChild(exportedModel);
|
rootNode.attachChild(exportedModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -793,6 +793,7 @@ public class GltfLoader implements AssetLoader {
|
|||||||
|
|
||||||
List<Spatial> spatials = new ArrayList<>();
|
List<Spatial> spatials = new ArrayList<>();
|
||||||
AnimClip anim = new AnimClip(name);
|
AnimClip anim = new AnimClip(name);
|
||||||
|
List<TransformTrack> ttracks = new ArrayList<>();
|
||||||
int skinIndex = -1;
|
int skinIndex = -1;
|
||||||
|
|
||||||
List<Joint> usedJoints = new ArrayList<>();
|
List<Joint> usedJoints = new ArrayList<>();
|
||||||
@ -806,8 +807,8 @@ public class GltfLoader implements AssetLoader {
|
|||||||
if (node instanceof Spatial) {
|
if (node instanceof Spatial) {
|
||||||
Spatial s = (Spatial) node;
|
Spatial s = (Spatial) node;
|
||||||
spatials.add(s);
|
spatials.add(s);
|
||||||
SpatialTrack track = new SpatialTrack(s, trackData.times, trackData.translations, trackData.rotations, trackData.scales);
|
TransformTrack track = new TransformTrack(s, trackData.times, trackData.translations, trackData.rotations, trackData.scales);
|
||||||
anim.addTrack(track);
|
ttracks.add(track);
|
||||||
} else if (node instanceof JointWrapper) {
|
} else if (node instanceof JointWrapper) {
|
||||||
JointWrapper jw = (JointWrapper) node;
|
JointWrapper jw = (JointWrapper) node;
|
||||||
usedJoints.add(jw.joint);
|
usedJoints.add(jw.joint);
|
||||||
@ -822,8 +823,8 @@ public class GltfLoader implements AssetLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JointTrack track = new JointTrack(jw.joint, trackData.times, trackData.translations, trackData.rotations, trackData.scales);
|
TransformTrack track = new TransformTrack(jw.joint, trackData.times, trackData.translations, trackData.rotations, trackData.scales);
|
||||||
anim.addTrack(track);
|
ttracks.add(track);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -834,19 +835,21 @@ public class GltfLoader implements AssetLoader {
|
|||||||
if (skinIndex != -1) {
|
if (skinIndex != -1) {
|
||||||
SkinData skin = fetchFromCache("skins", skinIndex, SkinData.class);
|
SkinData skin = fetchFromCache("skins", skinIndex, SkinData.class);
|
||||||
for (Joint joint : skin.joints) {
|
for (Joint joint : skin.joints) {
|
||||||
if (!usedJoints.contains(joint)) {// && !equalBindAndLocalTransforms(joint)
|
if (!usedJoints.contains(joint)) {
|
||||||
//create a track
|
//create a track
|
||||||
float[] times = new float[]{0};
|
float[] times = new float[]{0};
|
||||||
|
|
||||||
Vector3f[] translations = new Vector3f[]{joint.getLocalTranslation()};
|
Vector3f[] translations = new Vector3f[]{joint.getLocalTranslation()};
|
||||||
Quaternion[] rotations = new Quaternion[]{joint.getLocalRotation()};
|
Quaternion[] rotations = new Quaternion[]{joint.getLocalRotation()};
|
||||||
Vector3f[] scales = new Vector3f[]{joint.getLocalScale()};
|
Vector3f[] scales = new Vector3f[]{joint.getLocalScale()};
|
||||||
JointTrack track = new JointTrack(joint, times, translations, rotations, scales);
|
TransformTrack track = new TransformTrack(joint, times, translations, rotations, scales);
|
||||||
anim.addTrack(track);
|
ttracks.add(track);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
anim.setTracks(ttracks.toArray(new TransformTrack[ttracks.size()]));
|
||||||
|
|
||||||
anim = customContentManager.readExtensionAndExtras("animations", animation, anim);
|
anim = customContentManager.readExtensionAndExtras("animations", animation, anim);
|
||||||
|
|
||||||
if (skinIndex != -1) {
|
if (skinIndex != -1) {
|
||||||
|
@ -54,16 +54,16 @@ public class SkeletonLoader extends DefaultHandler implements AssetLoader {
|
|||||||
private Stack<String> elementStack = new Stack<String>();
|
private Stack<String> elementStack = new Stack<String>();
|
||||||
private HashMap<Integer, Joint> indexToJoint = new HashMap<>();
|
private HashMap<Integer, Joint> indexToJoint = new HashMap<>();
|
||||||
private HashMap<String, Joint> nameToJoint = new HashMap<>();
|
private HashMap<String, Joint> nameToJoint = new HashMap<>();
|
||||||
private JointTrack track;
|
private TransformTrack track;
|
||||||
private ArrayList<JointTrack> tracks = new ArrayList<>();
|
private ArrayList<TransformTrack> tracks = new ArrayList<>();
|
||||||
private AnimClip animClip;
|
private AnimClip animClip;
|
||||||
private ArrayList<AnimClip> animClips;
|
private ArrayList<AnimClip> animClips;
|
||||||
private Joint joint;
|
private Joint joint;
|
||||||
private Armature armature;
|
private Armature armature;
|
||||||
private ArrayList<Float> times = new ArrayList<Float>();
|
private ArrayList<Float> times = new ArrayList<>();
|
||||||
private ArrayList<Vector3f> translations = new ArrayList<Vector3f>();
|
private ArrayList<Vector3f> translations = new ArrayList<>();
|
||||||
private ArrayList<Quaternion> rotations = new ArrayList<Quaternion>();
|
private ArrayList<Quaternion> rotations = new ArrayList<>();
|
||||||
private ArrayList<Vector3f> scales = new ArrayList<Vector3f>();
|
private ArrayList<Vector3f> scales = new ArrayList<>();
|
||||||
private float time = -1;
|
private float time = -1;
|
||||||
private Vector3f position;
|
private Vector3f position;
|
||||||
private Quaternion rotation;
|
private Quaternion rotation;
|
||||||
@ -92,7 +92,7 @@ public class SkeletonLoader extends DefaultHandler implements AssetLoader {
|
|||||||
assert elementStack.peek().equals("tracks");
|
assert elementStack.peek().equals("tracks");
|
||||||
String jointName = SAXUtil.parseString(attribs.getValue("bone"));
|
String jointName = SAXUtil.parseString(attribs.getValue("bone"));
|
||||||
joint = nameToJoint.get(jointName);
|
joint = nameToJoint.get(jointName);
|
||||||
track = new JointTrack();
|
track = new TransformTrack();
|
||||||
track.setTarget(joint);
|
track.setTarget(joint);
|
||||||
} else if (qName.equals("boneparent")) {
|
} else if (qName.equals("boneparent")) {
|
||||||
assert elementStack.peek().equals("bonehierarchy");
|
assert elementStack.peek().equals("bonehierarchy");
|
||||||
@ -163,10 +163,6 @@ public class SkeletonLoader extends DefaultHandler implements AssetLoader {
|
|||||||
armature = new Armature(joints);
|
armature = new Armature(joints);
|
||||||
armature.setBindPose();
|
armature.setBindPose();
|
||||||
} else if (qName.equals("animation")) {
|
} else if (qName.equals("animation")) {
|
||||||
//nameToJoint contains the joints with no track
|
|
||||||
for (Joint j : unusedJoints) {
|
|
||||||
AnimMigrationUtils.padJointTracks(animClip, j);
|
|
||||||
}
|
|
||||||
animClips.add(animClip);
|
animClips.add(animClip);
|
||||||
animClip = null;
|
animClip = null;
|
||||||
} else if (qName.equals("track")) {
|
} else if (qName.equals("track")) {
|
||||||
@ -176,7 +172,11 @@ public class SkeletonLoader extends DefaultHandler implements AssetLoader {
|
|||||||
track = null;
|
track = null;
|
||||||
}
|
}
|
||||||
} else if (qName.equals("tracks")) {
|
} else if (qName.equals("tracks")) {
|
||||||
JointTrack[] trackList = tracks.toArray(new JointTrack[tracks.size()]);
|
//nameToJoint contains the joints with no track
|
||||||
|
for (Joint j : unusedJoints) {
|
||||||
|
AnimMigrationUtils.padJointTracks(tracks, j);
|
||||||
|
}
|
||||||
|
TransformTrack[] trackList = tracks.toArray(new TransformTrack[tracks.size()]);
|
||||||
animClip.setTracks(trackList);
|
animClip.setTracks(trackList);
|
||||||
tracks.clear();
|
tracks.clear();
|
||||||
} else if (qName.equals("keyframe")) {
|
} else if (qName.equals("keyframe")) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user