fabmax / physx-jni

Java JNI bindings for Nvidia PhysX
MIT License
88 stars 9 forks source link

PxActor userdata missing #10

Closed wonka007 closed 3 years ago

wonka007 commented 3 years ago

Hi, This documentation said that PxActor, PxShape, and PxMaterial should have void* userData (NativeObject in Java) for connecting my objects with them. But userData can be only used with PxShape. Can it be added to PxActor? Otherwise, I don't know how to call my custom onContact functions from my Actor without the need to use a big collection with unique names of Actors stored in PxActor as is shown in the example.

wonka007 commented 3 years ago

After further investigation, I found that I can get contacting PxShapes from PxContactPair and those can store the userData. Those data could point to a structure that would hold information about the wrapper for PxActor but, unfortunately, I did not find a way to store any of my objects there even when I extended them from physx.NativeObject. It seems that the only solution is the map with names/IDs.

fabmax commented 3 years ago

The problem is that the userData field only stores a native pointer (a raw memory address basically). Java objects on the other hand don't have a fixed memory address (they can be moved around by the garbage collector). Therefore, there is no easy solution to put a Java object into such a field, and exposing the userData to the Java side does not make much sense. That's why, at some point I stopped adding these fields to the Java interfaces (although the current state with having this field in a few classes and not having it in others is not optimal).

The best solution I have so far is the one you already mentioned: Using a Map. NativeObject overrides equals() and hashCode() (these rely on the address of the native object) and it's safe to put the native object itself as key into the map:

class MyUserData {
    // user data stuff...
}

Map<NativeObject, UserData> userDatas = new HashMap<>();

// create native object and corresponding user data
PxActor someActor = // create an actor
MyUserData someActorUserData = // create user data
userDatas.put(someActor, someActorUserData);

// use the native object to get user data
// this also works if the native object is returned by a native callback (e.g. contact callback)
MyUserData someActorUserData = userDatas.get(someActor);
wonka007 commented 3 years ago

Thanks for your clarification. I thought that is the reason why it is not possible.