[SOLVED] Jme3 Beginner: Understanding the Animation Timer

so I have class A that extends the SimpleApplication

Class B is a controller that has the function update (tpf) that looks like this

[java]@Override

public void update(float tpf)

{

if (enabled && cube != null)

{

counter += tpf;

// must change all this to read directly

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

{

if(isMoving)

{

moveCube(tpf, type, id, speed, x, y, z);

}

else if(scale == 0)

{

isMoving = true;

}

}

}

}[/java]

As this works fine, I am trying to read a trace that looks like

[java]

time = 0.00

create cube 0,0,0

time = 5.05

moveCube(…)

time = 6.54

rotateCube(…)[/java]

so what works so far is the move at every time per frame. But how do I embed rotateCube() to it? I need to make that update generic based on the time.

So for clarification, I can get the time read from the tracefile and pass it to the counter but, how would I tell the update which function to read?

[java]@Override

public void update(float tpf)

{

if (enabled && cube != null)

{

counter += tpf;



float rounded_counter = (float)Math.round(counter * 10000) / 10000; // 4 decimal pts

System.out.println("Frame Timer: " + rounded_counter);



myController j = new myController(time_read, type, id, speed, x, y, z);



if(rounded_counter == time_read)

{

// do specific event

}

}

}[/java]





the issue here is that the rounded_counter is never equal to the time read by the file. They are just never the same… If time read from trace was 1.0221 the tpf at that time would be around 1.0220 and the rounded counter would not be the same and won’t access the if statement.

first of all you should never compare 2 floats like that due to floating point arithmetic inaccuracies. You should do something like:

[java]

final float EPSILON = 0.001f;

if (FastMath.Abs(float1- float2) <= EPSILON) {

}[/java]

or I think this should also work, although i think i had issues with it previously, can’t actually remember :P: java.compareTo(float2);[/java]

I guess i’ll just switch it to double and be safe. But the question remains so even when I get the counter if statement to work the event needed whether move , rotate, or whatever it is , I can’t differentiate them in the update(tpf) so if my trace is this:



[java]time = 0.00

create cube 0,0,0

time = 5.05

moveCube(…)

time = 6.54

rotateCube(…)[/java]



I want to write



[java]@Override

public void update(float tpf)

{

if (enabled && cube != null)

{

counter += tpf;

double rounded_counter = (double)Math.round(counter * 10000) / 10000; // 4 decimal pts

System.out.println("Frame Timer: " + rounded_counter);

myController j = new myController(time_read, type, id, speed, x, y, z);

if(rounded_counter == time_read)

{

<strong> A GENERIC FUNCTION THAT CALLS THE METHOD DEPENDING ON THE time of occurance (i.e move if at time 5.05, rotate at 6.54 etc)</strong>

}

}

}[/java]

You’d best stick with floats, as almost everything in jme deals with floats, and you’ll still need to do the comparison like I posted before.

For this generic function you want, it all depends what information you have at your disposal. How do you distinguish when to rotate or to move? If you have access to a string command from your file then you would do something like:



[java]public void genericFunction(String action) {

if(action.equals(“rotate”)) {

rotate(…);

}

else if(action.equals(“move”)) {

move(…);

}

}



public void update(float tpf) {





if (FastMath.Abs(float1- float2) <= EPSILON) {

genericFunction(action);

}

}[/java]



not too sure what your doing creating a new controller every frame tho

1 Like

I see, that actually should do it.

however, the problem now is that if the action is initated at time 5.05 to move the spatial as it’s moving the counter reaches 6.54 and time to rotate the cube but it wouldn’t do it (although both methods have @ovrride) at that time but waits till the spatial (cube) finishes its move (which maen the time is no longer accurate)

PS: oh no I forgot that from a previous debug , no I am not creating a controller every frame (just took it off).

more clarification

if I debug I can read that the trace output is something like

[java]frame timer = 5.0 // the tpf counter

file trace timer = 5.05 // the next time on which an event will occur (i.e. move())

frame timer = 5.0

file trace timer = 6.54

frame timer = 1.1

file trace timer = 5.05

file trace timer = 6.54

frame timer = 1.2

file trace timer = 5.05

file trace timer = 6.54

[/java]

I don’t understand why it is looping through the trace timer that is directly read from the file? the trace timer should be the LATEST time read from the file…



note that I get that trace file time from a class that calls the controller in order to move the spatial according to update(tpf)

Another way of asking this question





Class A that reads and calls controls from Class B that has the update(tpf) and implements MyControl



As I am parsing the file line by line, how should I call a function moveSpatial (for example) from Class B?



by doing something like:



[java] Jme3Controller controller = new Jme3Controller(event , time_read, type, id, speed, x, y, z);

animator.spatial.addControl(controller);[/java]



every time I read a move (let’s say) from the trace file will end up looping through the whole file at the update(tpf) which is definitely not efficient (although it does the job right)



any input on how should I call the controls in my case?