Hi! I've been thinking, afaik there aren't many 3D physics libs available for Java gamedevs, I know of two flavors of Bullet: An outdated Bullet Java port, and libGDX's Bullet bindings. The later being more complete (it has heightmap collider for a change).
It would be awesome to have another option based on a different library.
Source is available for registered "NVIDIA developers" (ie, gotta register in their thingy, free account, can download Gameworks SDK stuff). And I believe there are some requirements to fulfill if you use PhysX in your game (add NVIDIA logo, "powered by PhysX" somewhere in the opening, stuff like that), but that should be it.
It used to be that PhysX was free to use on Windows only but recently they made free to use the whole stack https://developer.nvidia.com/physx-source-github Although I haven't checked if 32 bit and 64 bit libs are available for all platforms that LWJGL supports (probably they are).
They swear for their performance relative to Bullet, particularly on 3+ versions. Sadly I can't find the performance review I read right now.
EDIT: Here http://physxinfo.com/news/tag/bullet/ You can follow the links to one of the PhysX dev's blogs, although I warn you: They're half and half of ranting/drama and technical data.
While signing up for the developer program, the EULA clearly statess that if you wish to use nVidia's SDKs you must either: use personally; or apply for a commercial license through their gameworks licensing team. The former is impossible for this and the latter MAY be possible but I doubt this.
EDIT: agreement here https://developer.nvidia.com/content/apply-access-nvidia-physx-source-code
Um where exactly?
It only says " use of the NVIDIA GameWorks Licensed Software with platforms other than the Authorized Platforms requires entering into a separate commercial license agreement with NVIDIA. "
That means you're free to use it on Windows, Linux and Android as long you accept that EULA you linked. It mentions the "Authorized Platforms" a little bit above.
Although now that you mention it, OSX isn't included, hm.
I would say this part
You are required to notify NVIDIA prior to use of the NVIDIA GameWorks Licensed Software in the development of any commercial Game, Expansion Pack or Demo. Please send notification by email to: [email protected] and provide the following information in the email:
- Company Name
- Publisher and Developer Name
- Game Title or Application Name
- Platform (i.e. PC, Linux)
- Scheduled Ship Date
- WebLink to product/video
where as LWJGL would not be distributing the games, everyone who makes games with LWJGL would be.
But hey, I'm 16, and am not by any means a legal expert.
where as LWJGL would not be distributing the games, everyone who makes games with LWJGL would be.
No. Only if you use PhysX, not if you use LWJGL. You have the option to use PhysX or not. And I already mentioned those kind of conditions. You have to put a few nVidia logos here and there, and let them know you're going to release a game with it. It literally says just send a mail. Not "applying" for anything, it doesn't says they have to greenlight your game, it doesn't says you have to pay for it. It only says you have to accept those conditions. Thats it.
Still I understand why some of this might be annoying to do for some people. Plenty wouldn't want to put nVidia's logo in their game. Then again, if anybody is going to sell their game, certainly it isn't the biggest paperwork he/she is going to do (taxes, company papers, bank accounts, steam eulas, etc). And as I said, simply go and use Bullet or something if it annoys you.
Gah, this obviously won't go anywhere, better just close it.
If an LWJGL user decides to use PhysX or any other library that comes with legal/marketing obligations, it's their decision and not LWJGL's. As long as it doesn't affect other users or the library itself, I don't see a problem with supporting such libraries.
With that said, PhysX has the same problem with Bullet afaik: it's a C++ API. Technically that's not a major problem, but I personally won't have time to work on C++ bindings support until well after the 3.0.0 release. See #22.
I understand. Glad that you're open to the idea though.
PhysX is now open-source, Should this become an active idea again?
It being a C++ API is still an issue. I've detailed a few other options in #428 Personally I take a jab at Newton bindings every now and then when I have time for example.
I very much enjoy PhysX due to its physx visual debugger. I've never used Newton before, Bullet3D was nice back in the day, but I really think PhysX is the way forward. I see how C++ API might be an issue. @Spasi said it wasn't a huge problem but he just didn't have time until 3.0 released. Which would be now :) ?
I have heard of people doing JNI bindings to PhysX, is that not a possibility?
It is, nobody is saying that it isn't possible at all.
LWJGL is built around a bindings generator engine, which with a (fat) bit of manual input in a DSL Spasi made in Kotlin, and some magic sprinkled on top, it can generate Java bindings, with native interop code and all, from C libraries. It can generate the Java side and the native glue that casts JVM types back and forth when calling said native libraries, with all the LWJGL ecosystem supporting it (ie, type safe struct handling, memory management utilities, debug mode that checks for nulls and array sizes on each call, etc).
Mind you, this is all still using JNI. It's just that JNI alone isn't enough to make bindings work as you would expect. You might have a nk_font_color(nk_color* color) function in C, but LWJGL makes sure you have a "NkColor" class that has neat set_red(float) and set_blue(float) methods that place those 4 bytes each in the right offset from the memory allocation, it makes sure that NkColor gets unwrapped nicely into a long/int64 and passed to nk_font_color as a pointer like it expects, all the while making it so it's easier for HotSpot to allocate that NkColor object in the stack if you play your cards right.
What I am saying is that C++ library bindings aren't possible within the LWJGL framework for now, it has no concept of classes, methods and all that jazz that makes C++ the Zee Plus Plus. That's why all the bindings right now are pure C libraries like stb, or C++ libraries that expose a C API like bgfx.
Talking to @Spasi in slack, there is a C wrapper for physx that is built for use by rust. It could be used for lwjgl to get a working c wrapper for it.
https://github.com/EmbarkStudios/physx-rs/tree/master/physx-sys
With the C wrapper for PhysX, somebody could generate a Java binding automatically using Project Panama:
https://openjdk.java.net/projects/panama/
https://jdk.java.net/panama/
I believe that LWJGL has its own way to generate the bindings.
LWJGL is already planned to migrate to Panama regardless: https://github.com/LWJGL/lwjgl3/issues/509#issuecomment-541128047
@tlf30 any news from @Spasi? PhysX would be a major improvement for the Java game dev community! Using the libgdx wrapper for Bullet is a pain in the ass. It lacks the physics profiling functionality.
@haubna I have not heard anything from @Spasi, and unfortunately I have been too busy to look into building this wrapper myself.
I am fully allocated for the foreseeable future, so perhaps someone else can work on getting a basic wrapper and PR setup?
Sorry for reviving such an old story, but I started my own PhysX JNI binding project and thought it might be helpful: https://github.com/fabmax/physx-jni
It's still in a rather early state but the basic stuff (and vehicles) is working. Also the binding code is completely generated from a single interface definition file (WebIDL, the stuff emscripten uses to generate C++ bindings for javascript) so it should be easy to further extend the bindings.
@fabmax This is pretty cool, have you considered doing those bindings in LWJGL style? One of the core ideas of LWJGL is not to pass Java objects to the native side (which you seem to be doing there, correct me if I'm wrong), and rather pass plain long addresses. This allows the VM not to lock onto the object in the JNI side (which introduces sync points for the GC unless I'm mistaken), and gives more chances for escape-analysis to do their thing.
Usually in LWJGL you have something like
// This fetches pre-allocated off-heap "stack-like" memory for the current thread.
try(var mem = MemoryStack.push()) {
// This creates a new SomeStruct object which is a wrapper over a plain pointer to somewhere in the stack.
var struct = SomeStruct.malloc(mem);
// Internally this resolves where in memory should someValue be placed, given the shape of the struct
struct.someValue(2.5);
// And apparently we hand this object to the native JNI side, but this isn't the case.
NativeLib.nativeCall(struct);
}
// Rather inside NativeLib::nativeCall we have a bit of Java code that looks like this:
public void nativeCall(SomeStruct v) {
// Instead of passing SomeStruct, it passes the primitive long address of said struct.
actualNativeCall(v.address());
}
This works wonders because the VM has enough context to notice SomeStruct never "escapes" the scope, thus often allocations are never made in the heap, and in turn we reduce GC pressure, while at the same time maintaining a nice "object-like" API.
If we had passed that SomeStruct instance directly to the C JNI side, the object is considered to "escape" and it will always be heap allocated.
This is particularly what differentiates LWJGL from most (if not all that I've seen) native binding projects for Java, its carefully designed API to provide not only near original look of the native calls (which makes easier to use the native library's docs as reference), but also great Java side performance.
It also allows the user to do neat stuff on Java side like have their own off heap allocator entirely on Java side and use it for native interop with LWJGL (like I do, I implemented a simple free-list one), or even use some other allocator like LWJGL encourages (jemalloc, tmalloc, etc), since the memory handling is a strictly separate matter from the classes that give a shape to that memory (ie, all the struct wrapper objects).
The LWJGL binding generator is designed around these "principles" if you will. So it will emit the proper overloads in that fashion, which I'm sure you've seen if you've used LWJGL. That said, the binding generator is C only for now, so unless someone has a C API for PhysX, I don't think it will work as-is for C++.
@dustContributor Thanks for the hint! You are right currenlty I am passing Java objects to the native side, but I don't really need to.
Currently my call pattern looks like this:
public class SomeClass {
private long address;
private native void _someFunction(long address);
public void someFunction() {
_someFunction(address);
}
}
As you already noticed the native function is a member function resulting in the object being passed over to the native side. The thing is that I don't use the Java object in native code, all information I need is the address, which is passed separately. So I can easily change the pattern to this:
public class SomeClass {
private long address;
private static native void _someFunction(long address);
public void someFunction() {
_someFunction(address);
}
}
The only difference is the native function now being static.
I did a little stress test with 5000 simulated rigid bodys and with the old version the Java heap grew by ~52 MB/s. The new version lowers that to ~10 MB/s, which is still a little more than what I would like it to be, but nevertheless a huge improvement!
Now for the stack allocation of native objects: (I believe that's a independent thing, but I might be wrong). Let's assume we want to pass a PxVec3 into a method. Currently, this looks something like this:
PxVec3 force = new PxVec3(1, 2, 3);
rigidBody.addForce(force);
force.destroy();
The problem in my naiive implementation is that the call to new PxVec3() allocates the native object on the native heap. First problem is that we have to explicitly destroy the object after use to avoid a memory leak. Second problem is that native heap allocation is rather slow so this wastes a lot of time. My current not-so-great solution to this is to keep temp objects as private members and reuse them whenever I need them.
In C++, a temp object like this would usually be created on the stack and the LWJGL MemoryStack can do this as well, however my code generator is much less sophisticated and integrating that requires a little more than adding a static keyword, so this optimization will have to wait a little longer (but I added this to my wishlist).
Edit: Also important to note: the rigidBody.addForce(force) call internally calls a private static function, which, like above, only receives rigidBody.address and force.address and not the objects themselves.
@fabmax Excellent! Glad that you liked the idea.
My current not-so-great solution to this is to keep temp objects as private members and reuse them whenever I need them.
I believe we don't have much choice from Java-land. The only way we could better interop would be with memory pinning a-la .NET (ie, allocate a PxVec3 struct with an explicit layout, pin it, then hand it to the native side, un-pin it at the end, the VM takes care of the rest). We don't have that thus we keep the objects around.
this optimization will have to wait a little longer (but I added this to my wishlist).
How hard would it be to allow the user to pass its own address to it, and in turn the implementation does something like placement new on the C++ side? (ie, constructing the C++ object in an existing chunk of memory). It's slightly more involved than your wrapPointer static method since it'd require to call the ctor/dtor on the existing address.
I mean, for the case of classes that is. Classes usually need their constructors to be called, and destructors too. Via placament new you essentially prevent the ctor/dtor from allocating/deallocating the memory, since they don't own it, but only they call their ctor/dtor routines on existing memory.
Of course, for "plain old structs" there wouldn't be a need of placement-new or a destructor since they're already just a chunk of memory with an explicit layout. I'm guessing PxVec3 is a plain struct, regardless I'll use it for my example.
Imagine an API like this, borrowing some LWJGL idioms:
try(var mem = MemoryStack.push()) {
long addr = mem.nmalloc(PxVec3.ALIGNOF, PxVec3.SIZEOF);
// This would call the PxVec3 ctor on the address.
PxVec3 vec3 = new PxVec3(addr);
// A bit wordy but bear with me.
vec3.setX(0.0f);
vec3.setY(-9.81f);
vec3.setZ(0.0f);
body.addForce(vec3);
// This would call the dtor on the address.
vec3.destroy();
// At the end MemoryStack decrements the pointer and the memory is "freed"
}
With this I'm leveraging both your library and LWJGLs memory management facilities, without the two of them depending on each other.
Two key points here:
Granted, a bit wordy since I can't use the PxVec3 constructor. I'm not a C++ guy so I'm not sure if PxVec3.java constructor overloads could be generated that call each of the possible PxVec3.cpp constructors via placement new (ie, doing new PxVec3(address, 0.0f, -9.81f, 0.0f)).
This is pretty much what LWJGL does except in this case, it already pre-generates the mem.nmalloc/new two-liner for you in a static factory method, it'd look something like:
// Inside PxVec3.java
public static PxVec3 mallocStack(MemoryStack stack) {
long addr = mem.nmalloc(PxVec3.ALIGNOF, PxVec3.SIZEOF);
return new PxVec3(addr);
}
// And you use it like
try(var mem = MemoryStack.push()) {
var vec3 = PxVec3.mallocStack(mem);
}
But this would require your library to depend on LWJGL obviously. A workaround without capturing lambdas would generating static factory methods like:
// Functional interface
public interface Allocate<T> {
public long on(T allocator, int alignment, int size);
}
// Remove 'stack' from the name since it could be anything now.
public static <T> PxVec3 malloc(T allocator, Allocator<T> allocate) {
long addr = allocate.on(allocator, PxVec3.ALIGNOF, PxVec3.SIZEOF);
return new PxVec3(addr);
}
// And you use it like
try(var mem = MemoryStack.push()) {
var vec3 = PxVec3.malloc(mem, MemoryStack::nmalloc);
}
But eh, it's just one liner vs the two liner of the first example, not a big deal and honestly I don't mind calling mem.nmalloc(PxVec3.ALIGNOF, PxVec3.SIZEOF) that much.
EDIT: It seems in placement new you don't call the destructor. As I said, I'm not a C++ guy so I'm not privy on the details, but I do know that via placement new you can construct a new object on an existing chunk of memory.
Even this could just exist for select "high frequency" plain objects/structs like PxVec3, PxQuat and so on. I don't see much value in doing these for say, rigid bodies, scenes or whatever long lived objects you'd use.
@dustContributor I like that idea!
With placement new it should still be possible to call the constructors accepting parameters, so it's just a matter of generating an additional set of jni functions which take the target address as an additional parameter.
With this said, I would like to avoid the dependency to LWJGL, so I would opt for something like your second option (I love LWJGL, but fewer dependencies are better dependencies :smiley:). Hopefully I find some time on the weekend to play around with this concept.
@fabmax Sweet, I'll be looking forward to it.
Let me clarify something (for you and/or for whoever else is reading) since when you say "I would opt for something like your second option" it's confusing to me since that's the one that depends on LWJGL.
The first code example uses LWJGL but the idea is that you could allocate that chunk of memory however you please. Your API wouldn't depend on it to work, since it'd just receive the long address. I was just using MemoryStack in the example just to demonstrate how well would it synergize with LWJGL facilities. The address could be provided via some other allocator (ie Unsafe, loading libc and calling malloc directly, etc).
For instance, the same example rewritten with some other allocator:
static { System.load("libcoolallocator"); }
public native static long alignedMalloc(int alignment, int size);
public native static void free(long address);
// Using these like.
long addr = alignedMalloc(PxVec3.ALIGNOF, PxVec3.SIZEOF);
PxVec3 vec3 = new PxVec3(addr);
// Use the vec3 however you like then free it, and no dtor sice PxVec3 doesn't needs it.
free(addr);
The second example does the exact same thing with a nicer API but depending explicitly on LWJGLs MemoryStack class (aka, what you said you wanted to avoid). This is quite literally what LWJGL does already with any struct in its bindings.
The third example does the same as the previous one while taking advantage of a functional interface to not to depend on LWJGL, again allowing the user to provide their own allocation mechanism. The important part on that example is that it's a non-capturing lambda, since a capturing lambda would it make it nicer to use buuut it would be capturing and it'd allocate an object every time. Maybe it gets EAd, maybe not. Better just make it non-capturing like I did and be safe.
Those would be my three "proposals" so to speak.
In any case, thank you for your time and for being open to these suggestions.
@dustContributor ah, weill I kinda miscountet there :smiley:, anyway the third one was the one I meant...
The first one obviously is the easiest to implement, but passing a naked long in there feels a little unsafe somehow. Using a dedicated interface reduces the chance using it wrong and generally looks a bit nicer.
Works like a charm! I just pushed a version 0.3.2 with support for stack-allocating PxVec3, PxQuat, PxTransform and a few others.
The current version supports two allocation methods: The simple one which just takes a long as target address and the more sophisticated one with interface / non-capturing lambda. I'm still not entirely sure which is the better one...
In order to get the values for SIZEOF and ALIGNOF I had to things a little bit differently than LWJGL, which apparently computes these values itself based on the layout of the corresponding struct. However, that requires a much deeper understanding of the native struct / class than my generator currently has. So for SIZEOF I simply wrote another native getter which is called on class load and returns sizeof(SomeClass). For ALIGNOF it's a bit difficult to choose an optimal value. For now, I hard-coded that to 8. This should work for pretty much everything at the cost of wasting a few bytes for very small objects, which should be fine.
Great! I'm happy to hear you didn't have any issues implementing it.
I was thinking if maybe there was a way to remove the isStackAllocated flag but thinking about it, NativeObject is a plain object with a single long field, that already will take 20 bytes (12 bytes header, 8 bytes field), and the VM will pad it to 24 bytes since by default every Java allocation is 8 byte aligned anyway. So you have 4 spare bytes there, one taken by the boolean flag, so it doesn't matters.
Just a minor thing, I don't think isStackAllocated is a good name for that flag in the context of your library. From the POV of the library, you only care if the memory was "externally" allocated. It may be a stack allocator, it may be a plain ByteBuffer, etc. So a more appropriate name may be isExternallyAllocated or isExternallyOwned or something like that. ie, the flag indicates if your library owns the memory or not, which is really what you care about.
Talking about naming schemes, I'm not entirely sure 'malloc' is appropriate for the public static PxVec3 malloc(long address) static factory method since it actually doesn't allocates anything. It's more like a method to initialize and create the object on the specified address. Something like public static PxVec3 createOn(long address) perhaps? Although I imagine it's to keep it similar to the other method that receives the Allocator.
Just stuff that popped out for me when reading the code.
The simple one which just takes a long as target address and the more sophisticated one with interface / non-capturing lambda. I'm still not entirely sure which is the better one...
Unless I'm mistaken, LWJGL provides access to both. I mean, I'd say it's on the user if they want to use the less "hand holdy" version or not. I wouldn't worry too much about it.
Thank you for your work in this. Hopefully I'll have some time to try it out. It's like the 4th time I rewrite my physics, first with libGDX Bullet, then with Bullet C API bindings, then with my crappy incomplete Newton bindings, then with libGDX Bullet again, and now hopefully with PhysX.
For the isStackAllocated flag I wasn't sure if it's really neccessary. I guess the extra safety it provides by preventing destroying such objects isn't super critical. But then, as you mentioned yourself, it also doesn't do any harm, so why not. A different name probably makes sens. I like isExternallyAllocated.
For the malloc functions I wasn't sure about the name either. I would rather stick to the same name for both functions, to make clear that they are two alternatives for the same thing. I'm not sure if malloc is the right name though. Maybe something like create[On/At] or alloc (without the 'm') would be a better choice. On the other hand malloc is such a familiar term that it should be clear what these functions do, even if the malloc(long address) version isn't actually allocating any memory.
Most helpful comment
Sorry for reviving such an old story, but I started my own PhysX JNI binding project and thought it might be helpful: https://github.com/fabmax/physx-jni
It's still in a rather early state but the basic stuff (and vehicles) is working. Also the binding code is completely generated from a single interface definition file (WebIDL, the stuff emscripten uses to generate C++ bindings for javascript) so it should be easy to further extend the bindings.