Problems with PhysicsRayTestResult (and the normal vector)

Ok, i bet that this is a bug, or i lost tens of I.Q. points during my sleep and i can’t understand simple things.

First, I have problems with the physic PhysicsRayTestResult.

First of all (for you, not for me) i have this javadoc page.
http://hub.jmonkeyengine.org/javadoc/com/jme3/bullet/collision/PhysicsRayTestResult.html

Where you have the description :

Contains the results of a PhysicsSpace rayTest bulletAppState.getPhysicsSpace().rayTest(new Vector3f(0,1000,0),new Vector3f(0,-1000,0)); javap -s java.util.List

Well, i think that this is just a “normal” bug. But, when i looked into an other javadoc page here:
http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/jbullet/com/jme3/bullet/collision/PhysicsRayTestResult.java
You have this:

Contains the results of a PhysicsSpace rayTest. * <b>Read data only in callback method, object is reused</b>
It seems to make much more sense but ... where can i put this "callback" method ? There is nothing like that in this class, and nothing in the PhysicsSpace.rayTest either. I tried to extend the ArrayList and print the result when the object is added to the collection (well, it could be understand as a callback method) but nothing change.

Oh wait, i didn’t explain my problem yet, so :

the normal seems to be f*** up. I get results like (0.0, 360.0, 0.0), (-99.0, 0.0, 0.0) (30.0, 0.0, 0.0)
or even (30.0, -0.0, 0.0) oh yeah

As you can see, none of them are normalized (which is already a problem, but not a that big one). But, the real problem is that i got these results when i was shooting at walls, so rays collides with walls to give me this. These walls are straight, vertical walls, and corners between them are 90°, it’s really a standard room. But i get collisions that are only along the y axis.

So, either i am stupid or this is a bug. And if it’s a bug, how can i fix this ? I want to give a proper initial speed direction to my sparks when a bullet hit the wall, and i also need it to turn the bullet hole in the right direction.

I guessed that is has something to do with the original ray direction, but it seems that the orientation of the camera (and of the gun) doesn’t make a difference.

Thanks for help :slight_smile:

@bubuche said: where can i put this “callback” method ? There is nothing like that in this class, and nothing in the PhysicsSpace.rayTest either

I always assumed that meant in the PhysicsListener callbacks. A very good rule of thumb is to never, ever, do physics on any other thread than the one that physics listener callbacks are on.

I do it in the main thread (the scene thread, but as it’s server side there isn’t really a “render thread”), but i thought that it was synchronized with the physics thread.

Plus, the PhysicsRayTestResult is NOT the PhysicsCollisionEvent. The first one is obtained from the physicsSpace.rayTest method, and i think that i should be able to call it myself, i don’t think it’s a “intern use only” method. And the fraction part works well (it’s for exemple used in a lot of charactercontrol-like classes, to check if the player is on the ground and at which distance of it).

EDIT : i “solved” the bug. Actually, the bug is still here, and i still don’t know why and how to fix it at the root. However, this code transform this “crazy” vector into the intended one :

[java]
Vector3f normal = new Vector3f();
normal.set(physicsRayTestResult.getHitNormalLocal());
float y, z;

// this is the key part
y = -normal.z;
z = normal.y;

//place the correct values in the vector
normal.y = y;
normal.z = z;

//normalize it, as it is way too big
normal.normalizeLocal();
[/java]

This is only if nobody find a fix and if later somebody else have the same bug. I didn’t try it on non-“standard” surfaces, like curves etc. I’ll go to eat now, i’ll do more test later.

EDIT 2 : more test later, i can say that there is 2 case :

In the first case, the vector is correct ! It has a normal direction and a good size. In the second case, the z contains “- the good y” and y contains " the good z"

With this, i modified the code above and now i have this that works - it seems - always.

[java]
Vector3f normal = new Vector3f();
Vector3f hitNormal = result.getHitNormalLocal();
if ( hitNormal.length() > 2 ) //way bigger than one
{
normal.set(
hitNormal.x,
-hitNormal.z,
hitNormal.y);
}
else
{
normal.set(hitNormal);
}
normal.normalizeLocal();
[/java]

the " > 2" contains the number 2 and not the number 1 to avoid precision problems (the length of the correct vector is 1 but it’s always a bit more or less than one). This shouldn’t mess the detection of the buggy case as then the length of the vector is huge (the smallest i got was 11, the biggest 10000).
I always normalize it to be sure the length is good after that. Maybe (maybe !) i could just normalize it when a buggy case occurs.