[SOLVED] Animation using JME3

Hello,

I am trying to use jme3 as an animation tool for my simulation. As I have the simulation that spits something like:

time 0s

create object1 posx pos y posz

time 2s

move object1 posx2 posy2 posz2

time 30s

rotate object1 theta

etc…

I managed to read it with jme3 and parse it accordingly. The only issue is how to synchronize it with the time. As I run it now without the time notion, I will get an object that is already rotated and moved to the last position (obviously).

So, my question is what is the best approach to embed the time notion so I can see the object created at time 0s and moving at time 2s and takes the object a delay of 28s to start rotating… etc (following the trace file). How can I see this frame by frame?

I hope I made sense.

Thanks in advance! :slight_smile:

I think i understood what your asking. You would either do the time management in the update(float tpf) of a control, or the simpleUpdate(tpf) of the SimpleApplication.



[java]

counter = 0;



simpleUpdate(float tpf) {



counter += tpf;

if(counter > 28) {

rotatefuction();

}

else if(counter > 2) {

move();

}



}[/java]



Something along these lines. The other way is to start at the lowest counter and add a bool to make sure its not called more than once.

Thanks wezrule,



however that wouldn’t show you the actual movement of the vehicle frame by frame would it? it would simply move it at time 2 to that position that rotate it at 28 but not the frame by frame animation.



am I right?

well simpleUpdate() is called every frame, if thats what you mean, not sure i understand fully, do you want it to interpolate it to a location that takes X number of seconds while an animation is playing?

Correct and when I do add your code what I have right now is the object created at time 0 at location 0,0,0 then at time 2 moves (say to 2,2,2,) all of a sudden. Then is idle till time 28 where it rotates (say 180 degrees) also all of a sudden.



I need to animate the move(); in other words I need to have some sort of a speed, a tpf, and other time related variables in the move() to be able to actually see the object moving from the initial location (0,0,0) to (2,2,2)



makes more sense? sorry didn’t explain myself right before.

It was probably me not reading it properly the first time :P, i understand now tho. Well what you can do for the movement at least, is if you know the start and end locations, you can interpolate between them over a period of time:

[java]



Vector3f start;

Vector3f end;

float scale = 0;

float counter = 0;

boolean isMoving = false;

public void simpleUpdate(float tpf) {

counter += tpf;

if(counter >= 2) {

if(isMoving)

move(tpf);

else if(scale == 0)

isMoving = true;

}

}

private void move(float tpf) {

scale += tpf/10; //this will make it take 10 seconds to reach the end, from the the start (i think)

Vector3f newLocation = FastMath.interpolateLinear(scale, start, end);

spatial.setLocalTranslation(newLocation);

if(scale >= 1) //then you reached the end

isMoving = false;

}

[/java]



I haven’t tested it, but i think something like this should work, might not be the most efficient but hopefully gives you the idea

That is exactly what I was looking for. Great!!!



Thanks a lot!!!

just a quick follow up wezrule, can I pass anything to the simpleUpdate() from another class?

I am reading from a trace file and as I want to automate that (counter > time)

class A // the parser that reads the lines and gets the ones that has the time in it

{

catch: time 0



skip: bla bla bla



catch: time 2



skip: bla bla bla

catch: time 30

}

how can I pass those times to the simpleUpdate() ??? Of course I don’t want to create an instance of the parser and use it in the class containing the simpleUpdater() because I am actually calling that one from the parser class. In other words

class A parses and at the end calls the animator class (that contains the simpleUpdater() ) which will draw the animation.

Thanks again for your quick and accurate replies

Maybe it’s best if you implement a control, which has it’s own update(float tpf). check https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:custom_controls

I would suggest creating a class which implements Control, and then attach it to the spatial you want to animate, using spatial.addControl(new MyControl()); or similar and then the update() method will be called just like simpleUpdate() is.

Ok so here’s what I did (and correct me if my approach is wrong) - looks like I’m back to the same problem:



I have Class A (reads the file and parse it)

Class B (main file contains the spatial - i’m actually using a cube, the rootNode and the SimpleUpdate() )

Class C that implements a controller and I put all the motion functions in it (it has the update(tpf) )



so update(tpf) gets called fine (from class C) whenever I call something like (from class B):

ClassC MyController = new ClassC();

cube.addControl(MyController);






fine, so we start with Class A - reads the file , gets a motion function, calls class B, that in return calls the controller of class C , however in Class C I cannot do the actual move, rotate, etc because cube is not initialized there, it is initialized in class B… bck to the same issue…???

Update: if I put the motion functions in Class B and only keep the controller (update (tpf) ) in Class C and just pass the tpf to class B that implements it



the move(tpf) would not work… and I can’t figure out why… really weird although it is getting all the parameters, the spatial would just not move



cube.setLocalTranslation(newLocation); // I do get a newLocation (its not null) however the cube is immobile



sorry about the many questions , hope this will be the last :slight_smile:

In your controller, you have access to the spatial in which the controller is attached. So in MyController, there is a variable called “spatial” which is your cube.

I’m sorry but I didn’t get it. Are you saying you defined spatial twice? in the main file and the controller? what do you mean by having access?



sorry for the confusion

Its just a variable, a reference to the spatial object that is automatically set in the Control class. Read up a bit on java and objects if thats unclear.

I think I didn’t explain myself well. Here’s a snippet of my code:



[java]

void createCube(int cube_id, float x, float y, float z)

{

cube = new Node(“cuboid”);

rootNode.attachChild(cube); /

cube.attachChild(drawCube(cube_id, x, y, z)); // draw Cube is called and let’s not worry about that



Jme3Controller MyController = new Jme3Controller(); // attach it to controller

cube.addControl(MyController);

}[/java]



I am already creating that in the main file and then when the controller is added/called:



[java]@Override

public void update(float tpf)

{

if (enabled)

{

counter += tpf;

if(counter >= 5 && counter <= 5.5)

{

moveDrive(tpf); // NOW THIS IS INITIALIZED IN THE MAIN FILE THAT IS INHERITED BY THE CONTROLLER

}

}

}

[/java]



So although the cube is defined in the main file, I am still getting a null ptr exception when I reach the moveDrive at this specific line of the function

cube.setLocalTranslation(newLocation); // cube is null



I am sorry if this might be simple , and I do believe my background in java and objects isn’t bad, I am just very new to jme3

There is no variable called “cube” in all of jME3, if that variable is null then you did not set it yourself. The control has a variable called “spatial” which references the spatial the control has been added to, so its the cube in your case.

cube is the spatial I am using, that’s not the issue though. I set it at the beginning



Spatial cube;



then initialize it when the cube is created thru createDrive()



so for some reason when I call moveDrive() after createDrive() it is still not initialized!

Alright I got it to work but not sure that was the right way (more like a dirty hack to the problem)



At the moveDrive function I have now:



MAIN_CLASS_NAME.cube.setLocalTranslation(newLocation);



instead of



cube.setLocalTranslation(newLocation);




You suggested that I should have the spatial cube accessed by using the Controller so I am guessing I am doing something wrong although it works like this.

So as said, entirely your own code… Its not possible what you describe, you do something wrong.

you can use static references if you want, up to you. Inside the controller, there is a variable called “spatial” which references your cube anyways.

In the update it really should be:

[java]public void update(float tpf) {

if(enabled && spatial != null) {

//your code

}

}[/java]

And where you reference your cube, just can use “spatial” instead as in: spatial.setLocalTranslation() not cube.getLocalTranslation()