Parameter Passing of a Float

Hi there! :slight_smile:

I’m a bit new to Java so please forgive me for what is probably a very straightforward problem!

I’ve posted code below so you can see what I’m getting at, but quite simply I’m trying to rotate a single triangle with time-based movement.

I can’t seem to convert the elapsed time from long to float and pass this into the required object without error. I feel like an idiot!

I’ve made a Timer class which gives me the elapsed time in millis as a long and casts to a float:


m_fElapsedTime = (float)( System.currentTimeMillis() - m_iLastLoopTime );

My game loop takes this float from my Timer object and passes it into my Renderer object. The game loop:


while ( bRunning )
{
float fElapsedTime = Timer.GetElapsedTime();
m_Timer.Begin();
m_Renderer.SetElapsedTime( fElapsedTime );
m_Canvas.display();
m_Timer.End();
}

The problem is, my float never seems to pass correctly from the Timer object to the Renderer object. The code to pass the elapsed time into Renderer is simple:


public class Renderer implements GLEventListener
{
// cut...

private float m_fElapsedTime;
public void SetElapsedTime( float f ) { m_fElapsedTime = f; }

//...cut
}

Is there a problem passing this value? If I were to do a System.out.println( m_fElapsedTime ) right there, it would show me the correct value 33 milliseconds.

Yet if I now go to use m_fElapsedTime in my triangle rotation code like this:


public class Renderer implements GLEventListener
{
// cut...

public void display( GLAutoDrawable drawable )
{
// cut...
m_fRotSpeed = 0.2f * m_fElapsedTime;
m_fAngle += m_fRotSpeed;
gl.glRotatef( m_fAngle, 0.0f, 1.0f, 0.0f );
// ...cut
}

it goes wonky. Printing out these values shows strange results:


m_fRotSpeed = 6.6 Correct!
m_fAngle = 2.44404437E11 Wrong!

Can anybody shed some light on what’s going on with m_fElapsedTime?

One last thing - how do you indent code on a forum post?

Many thanks,
Mulvey

  1. What is the value of m_fAngle before you add m_fRotSpeed to it? I believe it is 2.44404437E11 minus that 6.6 (which probably the same as 2.44404437E11 because of floating point inaccuracy). So the problem is not in m_fElapsedTime but in the original value of m_fAngle.

  2. The value of m_fAngle is not used. You pass m_fAngle1 as a parameter to glRotatef(), not m_fAngle.

Apologies, it’s the same angle variable in the code.

The value of m_fAngle is initialised to 0.0f at the Renderer creation.

Edited my post!

Post more of your code. Especially all methods where m_fAngle is modified.

Also, why not just do this:


public void update()
{
     triangleRot += 0.1f;
     if (triangleRot >= 2*Math.PI)
          triangleRot = 0;
}

It seems overly complicated to use the timer.

The triangle rotates just fine when I increment it with a local value, but the problem was that I couldn’t seem to pass in an external value without rotation error. I’ve been working on my timer, and I want to be able to use it!

Thanks to Jackal’s excellent suggestion, I’ve watched the value of m_fAngle before and after it is modified and I now suspect my problem is a threading issue.

What I was hoping for:


Applet init.
Applet start.
OpenGL init.
INIT GL IS: com.sun.opengl.impl.GLImpl
OpenGL reshape.
=== Main Game Count 0 ===
Game loop elapsed time value = 0.0
=== Renderer Count 0 ===
Renderer elapsed time value = 0.0
Angle before = 0.0
Angle after = 0.0
=== Main Game Count 1 ===
Game loop elapsed time value = 33.0
=== Renderer Count 1 ===
Renderer elapsed time value = 33.0
Angle before = 0.0
Angle after = 6.6
..etc...

All nice and in sequential order.

But here’s what I get!


Applet init.
=== Main Game Count 0 ===
Game loop elapsed time value = 0.0
Applet start.
OpenGL init.
INIT GL IS: com.sun.opengl.impl.GLImpl
OpenGL reshape.
OpenGL reshape.
=== Renderer Count 0 ===
Renderer elapsed time value = 0.0
Angle before = 0.0
Angle after = 0.0
=== Renderer Count 1 ===
Renderer elapsed time value = 0.0
Angle before = 0.0
Angle after = 0.0
=== Main Game Count 1 ===
Game loop elapsed time value = 1.22207535E12
=== Renderer Count 2 ===
Renderer elapsed time value = 1.22207535E12
Angle before = 0.0
Angle after = 2.4441507E11
=== Main Game Count 2 ===
Game loop elapsed time value = 5.0
=== Renderer Count 3 ===
Renderer elapsed time value = 5.0
Angle before = 2.4441507E11
Angle after = 2.4441507E11
=== Main Game Count 3 ===
Game loop elapsed time value = 34.0
=== Renderer Count 4 ===
Renderer elapsed time value = 34.0
Angle before = 2.4441507E11
Angle after = 2.4441507E11
=== Main Game Count 4 ===
Game loop elapsed time value = 32.0

I think I need to read more JOGL and applet info, particularly with regards to implementing your own render loop properly…

You’re leaking rotation.

public void update()
{
     triangleRot += 0.1f;
     if (triangleRot >= 2*Math.PI)
          triangleRot -= 2*Math.PI;
}

ouch, never make a sum with float ![quote]
triangleRot += 0.1f;
[/quote]
try that to see why (only 10 iteration) :

float n=0.0f;
for (int x=0;x<10;x++)
{
 n+=0.1f;
 System.out.println("n="+n);
}

or rather (10000 iterations):

float n=0.0f;
for (int x=0;x<10000;x++)
{
 n+=0.1f;
 
}
System.out.println("n="+n);	

n=999.9029

nb: addition and substraction are not really good with float they are more intended for multiplication and division.

Just recently I made a similar mistake…


int max = 500;
int[] values = new int[max];

void dummy(float select)
{
   if(select >= max)
      select = max - 0.001f;

   int index = (int)select; // potentially index==max
   float fract = select - index;

   int value = values[index]; // potential AIOOBE
}

But well, floats are not really specially intended for multiplication, think about DOT and matrix transformations… lots of ADD and MUL.

@mulvey: Something funky is happening with your timer - I’m guessing it’s that in the first time through the loop your base time (m_iLastLoopTime) is set at zero, right? System.currentTimeMillis() gives me 1.22209855E12 at the moment, which tells me that’s where that bizarre timing value came from (see the log you posted). Make sure to initialize m_iLastLoopTime to System.currentTimeMillis() when you start out, then you should get more reasonable deltas and hopefully the rest of your code will work right.

That was the problem all along - well spotted, I can’t believe I missed that!

:slight_smile:

[quote]Just recently I made a similar mistake…
[/quote]
I remender some years ago, at work they found that financial value had some error on an application they made after some monthes in production!, one of my work knowledge have used float for doing sum on money value… they was stupefact when they see how float can be wrong after severals operations. float stay accurate for a little number of ops.

the best way to minimize that is to combine mathematical ops in a big one to reduce numbr of operations, and also to use int when dealing with integer.

short exemple for the above function :

public void update()
{
     triangleRot += 0.1f;
     if (triangleRot >= 2*Math.PI)
          triangleRot = 0;
}

can be coded like below to reduce errors:


int step;
public void update()
{
     step++;
     triangleRot = step*0.1f;
     if (triangleRot >= 2*Math.PI)
    {
          step=0;
          triangleRot = 0f;
    }
}

[quote]But well, floats are not really specially intended for multiplication, think about DOT and matrix transformations… lots of ADD and MUL.
[/quote]
yup :frowning: float introduce a lot of bug (especially in collision detection…), this is why matrix should be combined when possible rather than performed sequentially.

True. I was just whipping up an example. Also, I usually force my programs to disallow negative rotations so that everything is 0 <= angle <= 2*Pi. I find it easier to follow that way.