Multiple animation channels

Blender 2.61 + JME Nightly



Hello!

i want to split character animation into 2 animations: Top & Bottom



but it seem i do something wrong and i play with it like 4 hours… i need your help - i mean from people who done multichannel animations



http://i.imgur.com/Dj5Wb.jpg

http://i.imgur.com/o8yHg.jpg





track:

http://i.imgur.com/8mZfd.jpg



configuration of all animations look like this:

http://i.imgur.com/RGuoR.jpg



walkBottom (it dont share bones with walkTop):

http://i.imgur.com/joajw.jpg



walkTop (it dont share bones with walkBottom):

http://i.imgur.com/s80CZ.jpg



so when i look at Blender, it seem work, but when i look into SceneComposer or ingame, then:





- All animations override each other

for example walkTop have bottom bones position like in walkBottom first/last frame.

and walkBottom have bottom bones position like in walkTop first/last frame.





to be sure, ingame here is a code(becouse maybe SceneComposer always override):









[java]/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.

    */

    package oxplay.assets.controls;



    import com.jme3.animation.AnimChannel;

    import com.jme3.animation.AnimControl;

    import com.jme3.animation.AnimEventListener;

    import com.jme3.animation.LoopMode;

    import com.jme3.scene.Node;

    import com.jme3.scene.Spatial;

    import java.util.ArrayList;

    import java.util.Iterator;

    import java.util.Map;

    import java.util.HashMap;

    import java.util.logging.Level;

    import java.util.logging.Logger;







    WorldElementControl is just a Extended Control(nothin to do with animations).

    /**

    *
  • @author oxplay

    /

    public abstract class AbstractAnimationControl extends WorldElementControl implements AnimEventListener {



    private final static Logger logger = Logger.getLogger(AbstractAnimationControl.class.getName());

    private Map<Integer, AnimChannel> channels = new HashMap<Integer, AnimChannel>();

    public ArrayList<AnimControl> controls;



    public AbstractAnimationControl() {

    }



    @Override

    public void onSpatialSet() {

    initAnimations(spatial);

    }



    private void initAnimations(Spatial spat) {

    controls = findAnimControlSpatial(spat);

    if (controls == null) {

    logger.log(Level.SEVERE, “initAnimations can’t get control”);

    }

    for (Iterator<AnimControl> it = controls.iterator(); it.hasNext():wink: {

    AnimControl animControl = it.next();

    animControl.addListener(this);

    }

    init();

    }



    public abstract void init();

    public abstract void moveStart();

    public abstract void moveEnd();



    @Override

    public void simpleUpdate(float tpf) {

    }



    public ArrayList<String> getAnimationList() {

    ArrayList<String> animatiionList = new ArrayList<String>();

    for (Iterator<AnimControl> it = controls.iterator(); it.hasNext():wink: {

    AnimControl animControl = it.next();

    for (Iterator<String> it2 = animControl.getAnimationNames().iterator(); it2.hasNext():wink: {

    String animName = it2.next();

    animatiionList.add(animName);

    }

    }

    return animatiionList;

    }



    public boolean issetAnimation(String animation) {

    boolean isset = false;

    for (Iterator<AnimControl> it = controls.iterator(); it.hasNext():wink: {

    AnimControl animControl = it.next();

    if (animControl.getAnimationNames().contains(animation)) {

    isset = true;

    }

    }

    return isset;

    }



    public ArrayList<AnimControl> findAnimControlSpatial(Spatial spatial) {

    ArrayList<AnimControl> findControls = new ArrayList<AnimControl>();

    if (spatial instanceof Node) {

    Node findingnode = (Node) spatial;

    for (int i = 0; i < findingnode.getQuantity(); i++) {

    Spatial child = findingnode.getChild(i);

    findControls.addAll(findAnimControlSpatial(child));

    }

    }

    AnimControl foundControl = spatial.getControl(AnimControl.class);

    if (foundControl != null) {

    findControls.add(foundControl);

    }

    return findControls;

    }



    public void setAnim(String text, LoopMode mode, int channel, float speed) {

    for (Iterator<AnimControl> it = controls.iterator(); it.hasNext():wink: {

    AnimControl animControl = it.next();

    if (animControl != null && issetAnimation(text)) {

    if (channels.get(channel) == null) {

    channels.put(channel, animControl.createChannel());

    channels.get(channel).setLoopMode(mode);

    }

    channels.get(channel).setAnim(text);

    channels.get(channel).setSpeed(speed);

    } else {

    logger.log(Level.WARNING, “Animation: “+text+” do not exist!”);

    }

    }

    }

    }

    [/java]











    [java]/

  • To change this template, choose Tools | Templates
  • and open the template in the editor.

    */

    package controls;



    import com.jme3.animation.AnimChannel;

    import com.jme3.animation.AnimControl;

    import com.jme3.animation.LoopMode;

    import com.jme3.scene.Spatial;

    import com.jme3.scene.control.Control;

    import java.util.Random;

    import oxplay.assets.controls.AbstractAnimationControl;



    /**

    *
  • @author oxplay

    */

    public class CharacterAnimationControl extends AbstractAnimationControl {

    public static Random randomGenerator = new Random();

    public boolean run = false;



    @Override

    public void init() {

    setAnim("IdleTop1", LoopMode.Loop, 0, 1f);

    }



    @Override

    public void onAnimCycleDone(AnimControl control, AnimChannel channel, String animName) {

    if(animName.equals("IdleTop1") || animName.equals("IdleTop2")){

    int value = randomGenerator.nextInt(10);

    if(value <= 9){

    channel.setAnim("IdleTop1");

    } else {

    channel.setAnim("IdleTop2");

    }

    }

    }



    @Override

    public void onAnimChange(AnimControl control, AnimChannel channel, String animName) {

    }



    @Override

    public void moveStart() {

    if(run == false){

    setAnim("WalkTop", LoopMode.Loop, 0, 1f);

    setAnim("WalkBottom", LoopMode.Loop, 1, 1f);

    } else {

    setAnim("RunTop", LoopMode.Loop, 0, 1f);

    setAnim("RunBottom", LoopMode.Loop, 1, 1f);

    }

    }



    @Override

    public void moveEnd() {

    setAnim("IdleTop1", LoopMode.Loop, 0, 1f);

    }



    public void idle() {

    setAnim("IdleTop1", LoopMode.Loop, 0, 1f);

    }



    public Control cloneForSpatial(Spatial spatial) {

    throw new UnsupportedOperationException("Not supported yet.");

    }

    }

    [/java]
1 Like

the same with simple cube(extended face 3x) with 3 bones(root, top, bottom)… in blender work nice, in JME override…



what is going on… anyone?

1 Like

Give people time, you only posted 3 hours ago and it’s a Sunday afternoon :wink:



I’ve not used animations at all yet (don’t need any except procedural ones for my game) so I can’t help you…

3 Likes

You might need to add the respective bones to each AnimChannel by hand. (ie AnimChannel#addBone or AnimChannel#addFromRootBone)

So for the bottom channel you’d add the legs and boots, for the top one head, torso and everything else.



I don’t have much experience here either so I’m just poking around

2 Likes

damn right, it is issue(i thinked that JME automaticly check what bones are not used :()

thank you for help!



btw: i have theoretical question, so if i need not “splitted” animation i just need a 3 channel(with all bones)? and do i need to stop 1 and 2 channels?(will it slow game when i dont set animation to null on 1 and 2 channels?)



btw2: how to easy synchronize walkTop & walkBottom, after changing top animation while walk? i mean character walk, and while walk i need to use other top animation, and then go back to walkTop animation(but then walkTop and walkBottom are not synchronized)

1 Like
@oxplay2 said:
damn right, it is issue(i thinked that JME automaticly check what bones are not used :()
thank you for help!

If you have the animation applied to all bones, then you won't be able to use channels, that's too limited.

@oxplay2 said:
btw: i have theoretical question, so if i need not "splitted" animation i just need a 3 channel(with all bones)? and do i need to stop 1 and 2 channels?(will it slow game when i dont set animation to null on 1 and 2 channels?)

What do you mean 3 channels with all bones? That's not supported.

@oxplay2 said:
btw2: how to easy synchronize walkTop & walkBottom, after changing top animation while walk? i mean character walk, and while walk i need to use other top animation, and then go back to walkTop animation(but then walkTop and walkBottom are not synchronized)

I guess you will need to use AnimChannel.getTime() and AnimChannel.setTime(). If you set both channels to the same time and same animation, then they will be synchronized.
2 Likes
What do you mean 3 channels with all bones? That’s not supported.


sorry i mean third channel(not three). i should name it "channel nr. 3"

I guess you will need to use AnimChannel.getTime() and AnimChannel.setTime(). If you set both channels to the same time and same animation, then they will be synchronized.


hmm ok
so i hope it would be possible to start animation from time/frame(the same frame that second animation is actual playing).
1 Like
@oxplay2 said:
sorry i mean third channel(not three). i should name it "channel nr. 3"

Still don't understand what you're talking about. What are you trying to accomplish?

@oxplay2 said:
so i hope it would be possible to start animation from time/frame(the same frame that second animation is actual playing).

Yes that's what I said. Once you set the animation, set the time as well.
2 Likes
Still don’t understand what you’re talking about. What are you trying to accomplish?


its not so important, i will see later if its possible.

i mean that i have (Top / Bottom / All bones) channels. so if i set Bottom and Top, and then set All bones channel animation, so it override/stop Top and Bottom channels? or it will be just bugged/error?
1 Like
@oxplay2 said:
i mean that i have (Top / Bottom / All bones) channels. so if i set Bottom and Top, and then set All bones channel animation, so it override/stop Top and Bottom channels? or it will be just bugged/error?

It doesn't quite work like that .. You can only have one animation per bone and there's no way to disable an AnimChannel
1 Like
there’s no way to disable an AnimChannel


hmm, then how i can add animation for a whole skeleton, when i have Top and Bottom channels?

change their bones? i hoped i will be possible just to stop/remove Top and Bottom channels and replace them with one for all bones.
1 Like
@oxplay2 said:
hmm, then how i can add animation for a whole skeleton, when i have Top and Bottom channels?

change their bones? i hoped i will be possible just to stop/remove Top and Bottom channels and replace them with one for all bones.

Well you can remove them and add the 3rd .. Can't you just apply the animation to both?
2 Likes
Can’t you just apply the animation to both?


well, i can :D i just thought it will not work with single animation for all bones.
1 Like