Animators

Hey!



I have a model and want to move it along, in a certain path.



Whats the best way to do this - irrlicht had an animators thing, like a fly straight animator, or an animator which followed an array of vector positions.



Whats the  best way to do this in the glorious jME! :smiley:

Check out the SpatialTransformer. This will get you started. Also browse through the docs, as there are other controllers that might help you out like the CurveController.

Ok i settled for a nice curve transformer, and got my model moving in a straight line :



private void setEnemyMovement(Buster enemy){
      
      Vector3f[] cameraPoints = new Vector3f[]{
               new Vector3f(100, 50, 20),
               new Vector3f(100, 50, 90),
               new Vector3f(100, 50, 200),
               new Vector3f(100, 50, 300),
               new Vector3f(100, 50, 400),
           };
           // Create a path for the camera.
           BezierCurve bc = new BezierCurve("camera path", cameraPoints);
           // Create a camera node to move along that path.
        
           // Create a curve controller to move the CameraNode along the path
           CurveController cc = new CurveController(bc, enemy);
           // Cycle the animation.
           cc.setRepeatType(Controller.RT_CYCLE);
           // Slow down the curve controller a bit
           cc.setSpeed(.25f);
           enemy.addController(cc);
   }



Now. My terrain which is a heightmap has various curves etc, and thus i want my enemy to be moving along the terrain, not in freespace.

In irrlicht, i would do this by applying collision animators and gravity. Im not sure how to do this here, i know that in my main game loop i do


if(cam.getLocation().y <= (tb.getHeight(cam.getLocation())+15)) {
            cam.getLocation().y = tb.getHeight(cam.getLocation()) + 20;
            cam.update();
        }



To stop the camera from flying through the terrain which works nicely, but is this the best way to solve this problem.

An image of what I am talking about is here:

http://www.novo.game-host.org/example.JPG

Note how the legs are through the bottom of the terrain, the model needs to move along the surface instead!

Thanks in advance!

Andy

hmmm, seems this crafty little bit of code does nearly what I want!



tb.getSurfaceNormal(enemy.getLocalTranslation(), normal);

        if(normal != null) {

            enemy.rotateUpTo(normal);

       }



My enemy model is an md2 model which i Know has an animation named "run".



How do i set this to actually be the animation being seen?



I tried looking through the wiki but i get this! : http://www.jmonkeyengine.com/wiki/doku.php?id=animation



Thanks very much , Andy

The user guide in incomplete.

but  the wiki search for animation returns quite a few hits

Ive looked through those, and none of them tell you how to set the animation on an md2 model, or any model as far as I can see, and the speed of the animation too.

Have you looked at TestMd2JmeWrite.java?



I think it shows what you are looking for.

In short, the model will have a controller which handles the animation.



You get this using something like (from the above example)


kc=(KeyframeController) freakmd2.getChild(0).getController(0);



Then you can use its methods to control your animation, such as


kc.setSpeed(10);
kc.setNewAnimationTimes(39,44);

It just ends up reporting array index out of bounds :



try{
        //System.out.println("IT IS :"+enemy.getChild(0).getController(0).toString());
            KeyframeController  kc=(KeyframeController) enemy.getChild(0).getController(0);
            
             if(kc != null){
             kc.setSpeed(30);
             kc.setNewAnimationTimes(70,210);
             }
        }
        catch(Exception e){e.printStackTrace();}


On the line getChild, this doesnt seem to work :S. Enemy is my enemy class which extends node.

I'm not sure if using 0 for both parameters will be right in your case.

If the getChild part is returning null, that is odd as any node that you can see should have a child.

If it is the getController part that that seems like it isn't importing any animation for that child.

Is the animated md2 model the only child of the enemy node?

yes im pretty sure it is.



Not sure what else there is that could be classed as a child.



package Enemys;

import Tools.ModelLoader;

import com.jme.bounding.BoundingBox;
import com.jme.scene.Node;
import com.jme.scene.Spatial;

public class Buster extends Node {

   private Spatial model;
   float hp;
   float speed;
   boolean freezable;
   int id;
   
   public Buster(int id,float hp, float speed,boolean freezable,Spatial model){
      
      setModel(model);
      this.id=id;
      this.hp=hp;
      this.speed=speed;
      this.freezable=freezable;
      
   

   }
   
   public float getHp() {
      return hp;
   }

   public void setHp(float hp) {
      this.hp = hp;
   }

   public float getSpeed() {
      return speed;
   }

   public void setSpeed(float speed) {
      this.speed = speed;
   }

   public boolean isFreezable() {
      return freezable;
   }

   public void setFreezable(boolean freezable) {
      this.freezable = freezable;
   }

   public int getId() {
      return id;
   }

   public void setId(int id) {
      this.id = id;
   }


   
    public void setModel(Spatial model) {
           this.detachChild(this.model);
           this.model = model;
           this.attachChild(this.model);
       }

   
   
}



That is my enemy class

Can't really tell from that, but perhaps you are getting a node back from the importer which you are then adding as a child of the enemy. That would give you this:



Enemy (node)

-> Imported node

—> Geometry (controller should be here)





So you'd end up with


KeyframeController  kc=(KeyframeController) enemy.getChild(0).getChild(0).getController(0);



Which is a bit ugly. I'd break it down and see where you get the error.
Also try just replacing the file in the jmetest code with your file and see if that works.

that doesnt work as it says getChild(int) is not defined for type spatial … not sure what thast about…im not sure what to try now?

Try this code - pass it a node spatial and it will list any controllers attached to it or any of it's children.

Have only tested it briefly but might help. If not, perhaps you could upload the model somewhere.



   public void listControllers(Node n) {
      System.out.println("Node: " + n);
      for(Controller c : n.getControllers()) {
         System.out.println("->Controller: " + c);
      }
      for(Spatial s : n.getChildren()) {
         System.out.println("-->Child: " + s);
         if(s instanceof Node) {
            Node childNode = (Node)s;
            listControllers(childNode);
         } else {
            listControllers(s);
         }
      }
   }
   
   public void listControllers(Spatial n) {
      System.out.println("Spatial: " + n);
      for(Controller c : n.getControllers()) {
         System.out.println("->Controller: " + c);
      }
   }

ok the output is this :



Node: null (Enemys.Buster)

–>Child: MD2 mesh654017060 (com.jme.scene.Node)

Node: MD2 mesh654017060 (com.jme.scene.Node)

–>Child: MD2 mesh654017060 (com.jme.scene.TriMesh)

Spatial: MD2 mesh654017060 (com.jme.scene.TriMesh)

->Controller: com.jmex.model.animation.KeyframeController@8916a2



What does this mean, node null, node md2, and then node controlller which is what i want?

Yes so it's like I thought before, you have a node which is a child of another node.

The code line I posted was nonsense though as getChild returns a spatial.



Try casting it and see if it works then, should be something like this (haven't tried it):



Spatial s = buster.getChild(0);
Node n = (Node)s;
KeyframeController  kc=(KeyframeController)n.getChild(0).getController(0);

Alright! That seems to have worked.



What is the best way of working out the frame sequences for a model? I downloaded this and i know it has various ones, but i used to be able to tell irrlicht engine "run" and it would work it loop through the entire animation and show you each frame number so I can work out the correct start and stop loop?



Thanks again for your great support.

It would be pretty easy to write a simplegame app to do that, but personally I just use something like milkshape - you can play the animation or easily move to specific frames. Or be fortunate enough for the artist to have supplied that info with the model  :smiley:

took a peak at milkshake, didnt understand how to get it to play the animation, or it didnt want to play it, im not sure which.



Yeah the animator wouldve been a good guy had they included the darn numbers!



Do you know of any decent collection of free animated models?