Object3D.getTransformedCenter().x returns NaN

Started by eye1, December 07, 2006, 05:45:31 PM

Previous topic - Next topic

eye1

Hy!

I'm transacting, adding, removing.. objects in the World and sometimes I get value NaN from getTransformedCenter().x method... Why does this happen? Does anyone know what am I doing wrong?

Kind Regards, Ivan

eye1







I can't really do much of a debug since I don't have a source, but i think that probably transformed center is calculated with those 3 matrixes. One has a Nan in it and I'm not shure how it got there! Any Ideas?

Regards

eye1

Hello again

Since i have NaN in translationMatrix. I think I probably put it inside with Method Object3D.translate.. since I never manipulate non of the Matrixes directlly. Can anyone help me and tell me what kind of calculations returns NaN value. I think X/0 does.. anything else? I checked my code, X/0 could not happen.

Mizuki Takase

This problem is way beyond me! I hope that other people in this forum can help out...

Anyway! I found this at some random website...

Quote
"NaN" stands for "not a number". "Nan" is produced if a floating point operation has some input parameters that cause the operation to produce some undefined result. For example, 0.0 divided by 0.0 is arithmetically undefined. Taking the square root of a negative number is also undefined.

0.0 / 0.0   ->  NaN
Math.sqrt(-2.0)  ->  NaN

Operations involving NaN
Double.NaN + Double.NaN  ->  NaN
Float.NaN + 2.0  ->  NaN
Float.NaN * 3.0  ->  NaN
(0.0 / 0.0) * Float.POSITIVE_INFINITY  ->  NaN
Math.abs(0.0 / 0.0) -> NaN
(int) (Double.NaN) -> 0

All boolean operations involving "NaN" results in a false value.

Double.NaN > 1.0  ->  false
Double.NaN < 1.0  ->  false
Double.NaN == 1.0  ->  false
Float.NaN < -3.0  ->  false
Float.NaN > Float.POSITIVE_INFINITY  ->  false
Float.NaN < Float.POSITIVE_INFINITY  ->  false
(0.0 / 0.0) == (0.0 / 0.0)  ->  false

eye1

Thanks Mizuki.

For now i check every translation for NaN value and replace it with 0. Hope it will work!

The problem also is that this happen time to time, like once twice per day. So it is even harder for me to debug it. The thing i'm working is some live warehouse visualisation which reads data from database and interpolates object movements in real time as accurate as it can.

eye1

Hy.

I've got this far that now I know that first somehow I call Object3D.translate(Infinity,,).

X/0 is Infinity... anything else?

EgonOlsen

NaN can make it's way into a matrix if you are interpolating between two very different matrices for example. Or if you are doing a translation/rotation/whatever with a NaN-value or from inside another thread while some other is working on the matrix, i.e. one rotates, the other one translates and the result is most likely garbage.
However, if this problem can be reproduced by a simple test case, i would like to get my hands on it. It could also be an accuracy problem with something you are doing.

eye1

Hello

I'm only translating & rotating objects (no animation is used), Actually objects are rotated only at begining, than the only manipulation done to them is tranlsate... they are also cloned, removed & added to world

I have two threads only. One is rendering thread, while another one pools the database for data. And only the rendering thread is accesing jpct classes.


This is where I calculate on every iteration for how much does the objects need to move. I don't see where i could produce NaN or Infinity value.
start... (x or y or z) coordinate, where object was at begining
start... (x or y or z) coordinate, where object is now
start... (x or y or z) coordinate, where object destination is
fastTrans... translate the object at finish at once.



  public static float getDefaultMovementSpeed(float start, float curr,
                                              float end, boolean fastTrans)
  {
     float iOverallDistance = Math.abs(end - start);
     float iDistanceFromStart = Math.abs(curr - start);
     float iDistanceToEnd = Math.abs(end - curr);
     float nagative = 1f;
     if (start > end) {
        negative = -1f;
     }
     if (iDistanceToEnd <= 3.5 || fastTrans) {
        return nagative * iDistanceToEnd;
     }
     if (iOverallDistance <= 300) {
        if (iDistanceFromStart <= (iOverallDistance / 2f)) {
           return nagative * (0.5f + iDistanceFromStart / 50f);
        }
        else {
           return nagative * (0.5f + iDistanceToEnd / 50f);
        }
     }
     else {
        if (iDistanceFromStart <= 150) {
           return nagative * (0.5f + iDistanceFromStart / 50f);
        }
        else if (iDistanceToEnd <= 150) {
           return nagative * (0.5f + iDistanceToEnd / 50f);
        }
        else {
           return nagative * (0.5f + 3f);
        }
     }
  }




PS. One thing more.. what happens to a float number if it reaches max value.. ???

EgonOlsen

It finally becomes infinity, albeit you can add some values to a float that's already at Float.MAX_FLOAT without shifting it into infinity.

About your problem: The translation matrix is a simple thing. Values are getting added and subtracted from it according to the translations. If it contains a NaN, the problem is most likely somewhere in the calculation of your translations. From the posted code, i can only guess that one of the distances has to be strange. Maybe you can add some checks using Float.isNaN(<float>) and Float.isInfinite(<float>) to see if this may be the case.

eye1


public static float getDefaultMovementSpeed(float start, float curr,
                                              float end, boolean fastTrans)
  {
     float speed =  getDefaultMovementSpeed(start, curr, end, fastTrans, 'c');
     if (Float.isInfinite(speed) || Float.isNaN(speed))
     {
        System.out.print("I produced NaN");
     }
     return speed;
  }


  public static float getDefaultMovementSpeed(float start, float curr,
                                              float end, boolean fastTrans, char aa)
  {
     if (Float.isInfinite(start) || Float.isNaN(start) ||
         Float.isInfinite(curr) || Float.isNaN(curr) ||
         Float.isInfinite(end) || Float.isNaN(end))
     {
        System.out.print("I got NaN from somewhere else");
     }
     float iOverallDistance = Math.abs(end - start);
     float iDistanceFromStart = Math.abs(curr - start);
     float iDistanceToEnd = Math.abs(end - curr);
     float negative = 1f;
     if (start > end) {
        negative = -1f;
     }
     if (iDistanceToEnd <= 3.5 || fastTrans) {
        return negative * iDistanceToEnd;
     }
     if (iOverallDistance <= 300) {
        if (iDistanceFromStart <= (iOverallDistance / 2f)) {
           return negative * (0.5f + iDistanceFromStart / 50f);
        }
        else {
           return negative * (0.5f + iDistanceToEnd / 50f);
        }
     }
     else {
        if (iDistanceFromStart <= 150) {
           return negative * (0.5f + iDistanceFromStart / 50f);
        }
        else if (iDistanceToEnd <= 150) {
           return negative * (0.5f + iDistanceToEnd / 50f);
        }
        else {
           return negative * (0.5f + 3f);
        }
     }
  }


I setted breakpoints at system.out... lines.. I think I may see than if this part of code produces NaN somehow. Now I just have to run it & wait when this creepy thing happens again. :)
Thanks for your help & time Egon

eye1

I solved this. Sometimes current position of object was outside of start & end interval and the object due to formula went in wrong way until it finally reached Infinity and than i got NaN from getTransformedCenter()..