fabmax / physx-jni

Java JNI bindings for Nvidia PhysX
MIT License
85 stars 8 forks source link

Physx 5 support #43

Open tlf30 opened 1 year ago

tlf30 commented 1 year ago

Hello, I'm going to make a huge request, apologies. Physx 5 was finally released today. https://github.com/NVIDIA-Omniverse/PhysX

Would it be possible to create bindings for it as well?

Thanks, Trevor

fabmax commented 1 year ago

Oh wow, I was waiting for PhysX 5 for years! I'm definetly going to work on this but it will probably take a while...

tlf30 commented 1 year ago

No worries if it takes a while, Physx 5 took so long that I think we are used to waiting πŸ˜†

Perhaps topic for a different discussion, but you do an amazing job on these C++ to JNI bindings, if you get some free time (which none of us have) it would be awesome to get bindings for NVIDIA aftermath built with the VULKAN directives in place (DirectX is not usable from java so no need to support it). I have run into many situations where it would be very handy to have a way to get a GPU crash report. If you got a base repo started, I would be more than happy to contribute PRs to it and do testing.

Once you have Physx5 started, I will also be active on that. I did not want to bother with Physx4 support in my engine as I was holding out for 5, so once momentum starts on 5 I will be working on getting it integrated and can help with PRs and testing.

fabmax commented 1 year ago

Alright, I took a quick glimpse into the PhysX5 code and apparently the API hasn't changed too much, so the existing stuff should be rather easy to port.

A bit disappointing is that the cool new stuff (soft-bodies and particles / cloth) requires CUDA. So that part will only be usable with an Nvidia GPU.

For the aftermath stuff, I will keep that in mind but no promises when/if I will come to that :smile:

tlf30 commented 1 year ago

I personally only run NVIDIA GPUs, but I agree, many of my target end users are running many non-NVIDIA GPUs. I was especially looking forward to the particle system, but I guess I will only enable it on NVIDIA systems....

fabmax commented 1 year ago

Ok, the basic setup is done: https://github.com/fabmax/physx-jni/tree/physx5

For now, it's only a working Hello World. More to come in the next days...

fabmax commented 1 year ago

Alright, I think the PhysX 5 bindings are usable now and I merged them into main πŸš€

They aren't yet complete though. Compared to the old PhysX 4 binsings, vehicles and Mac OS support are atill missing. The vehicle API has changed substantially with v5 and unfortunately isn't very Java friendly, so I have postponed this for now. Mac OS isn't an officially supported build target anymore, although it should be possible to compile the native libs for Mac anyway (later).

CUDA already works but for now only with rigid bodies. I still haven't looked into the new stuff.

So still lots of work to do but the standard stuff already works well

tlf30 commented 1 year ago

Great, thank you much for working on this. I'm currently traveling for work and won't have much time to test yet. I get home on the 29th and will be able to begin playing with it.

Sm0keySa1m0n commented 1 year ago

Is custom geometry support on the roadmap (PxCustomGeometry)?

fabmax commented 1 year ago

Is custom geometry support on the roadmap (PxCustomGeometry)?

Not so far. The callbacks look quite complex but at first glance it seems doable, so maybe πŸ˜„ Any particular usecases?

Sm0keySa1m0n commented 1 year ago

Is custom geometry support on the roadmap (PxCustomGeometry)?

Not so far. The callbacks look quite complex but at first glance it seems doable, so maybe πŸ˜„

Any particular usecases?

I'm building a Minecraft-like voxel game so it'll be very useful for block collision detection.

fabmax commented 1 year ago

Is custom geometry support on the roadmap (PxCustomGeometry)?

The latest snapshot contains bindings for PxCustomGeometry. In order to use it you need to subclass SimpleCustomGeometryCallbacksImpl and implement the required callback methods. Then, pass an instance of the callbacks to the PxCustomGeometry constructor.

It's completely untested though...

Sm0keySa1m0n commented 1 year ago

Is custom geometry support on the roadmap (PxCustomGeometry)?

The latest snapshot contains bindings for PxCustomGeometry. In order to use it you need to subclass SimpleCustomGeometryCallbacksImpl and implement the required callback methods. Then, pass an instance of the callbacks to the PxCustomGeometry constructor.

It's completely untested though...

Awesome, I'll give it a go.

fabmax commented 1 year ago

One more thing I forgot to mention: The original C++ usePersistentContactManifold() callback method has an output float parameter breakingThreshold, which does not work in Java (because primitive types are always passed by value). As a workaround there is a member variable setPersistentContactManifold_outBreakingThreshold, which you can set when usePersistentContactManifold() is called. The value of the member is then assigned to the C++ parameter.

Here's the C++ code for that: https://github.com/fabmax/PhysX/blob/00e0f60f615b1cc6e7e9ef7bce521ec430c4439a/physx/source/webidlbindings/src/common/WebIdlBindings.h#L284

tlf30 commented 1 year ago

I took a quick glance and might have missed it, but I did not see anything for blast or flow yet. Are those on your list to build bindings for?

fabmax commented 1 year ago

Generally yes but not with particularly high priority. At least for blast, the PhysX 5 integration also seems still to be in progress (see this discussion)

Flow I haven't really checked out yet...

zalo commented 7 months ago

@fabmax Would it be possible to add the functions for creating Tetrahedral Meshes? I wrote a GPU Simulator for PhysX-style TetMesh + Simulation Mesh pairs, but the primary thing missing is the ability to bake TetMeshes from Surface Meshes.

The functions from PxTetMakerExt.h (and optionally PxTetrahedronMeshExt.h?) would be ideal!

It would be cool to put a pretty-serious foot forward towards ubiquitous soft-body simulation in the browser πŸ˜„

fabmax commented 7 months ago

At first glance, I think it should be possible, but I haven't really looked into the whole soft-body stuff yet. As far as I know the PhysX soft bodies require CUDA, do you have an alternative solution for the browser?

zalo commented 7 months ago

As far as I know the PhysX soft bodies require CUDA, do you have an alternative solution for the browser?

Yes! I’m writing one: https://zalo.github.io/TetSim/

fabmax commented 7 months ago

Ah nice! I will see what I can do for the tet meshes

fabmax commented 7 months ago

@zalo I added bindings for PxTetMakerExt and PxTetrahedronMeshExt: https://github.com/fabmax/physx-jni/commit/3611603f50b666e97e041a7b92322bea0fc6f4aa

They are also already included in the js version. I haven't tested them yet, so feedback is welcome :smile:

zalo commented 7 months ago

Awesome; thank you so much for setting this up! I’ll look into writing a test app asap!

zalo commented 6 months ago

Looks like at least remeshTriangleMesh works!

image

My implementation is a bit verbose though πŸ˜…

        // Load PhysX
        const px       = await PhysX();
        let version    = px.PHYSICS_VERSION;
        let allocator  = new px.PxDefaultAllocator();
        let errorCb    = new px.PxDefaultErrorCallback();
        let foundation = px.CreateFoundation(version, allocator, errorCb);
        console.log('PhysX loaded! Version: ' + ((version >> 24) & 0xff) + '.' + ((version >> 16) & 0xff) + '.' + ((version >> 8) & 0xff));

        // Transform the test mesh to PhysX arrays
        let inputVertices  = new px.PxArray_PxVec3(sphereMesh.vertProperties.length/3);
        let inputIndices   = new px.PxArray_PxU32 (sphereMesh.triVerts.length);
        for(let i = 0; i < sphereMesh.vertProperties.length; i+=3){
            inputVertices.set(i/3, new px.PxVec3(sphereMesh.vertProperties[i], sphereMesh.vertProperties[i+1], sphereMesh.vertProperties[i+2]));
        }
        for(let i = 0; i < sphereMesh.triVerts.length; i++){
            inputIndices.set(i, sphereMesh.triVerts[i]);
        }

        // Remesh the test mesh!
        let outputVertices = new px.PxArray_PxVec3();
        let outputIndices  = new px.PxArray_PxU32 ();
        let vertexMap      = new px.PxArray_PxU32 ();
        let remesherGridResolution = 20;
        px.PxTetMaker.prototype.remeshTriangleMesh(inputVertices, inputIndices, remesherGridResolution, outputVertices, outputIndices, vertexMap);

        // Transform From PhysX back to three.js's Mesh Representation
        let triIndices = new Uint32Array(outputIndices.size());
        for(let i = 0; i < triIndices.length; i++){
            triIndices[i] = outputIndices.get(i);
        }
        let vertPositions = new Float32Array(outputVertices.size() * 3);
        for(let i = 0; i < outputVertices.size(); i++){
            let vec3 = outputVertices.get(i);
            vertPositions[i*3+0] = vec3.get_x();
            vertPositions[i*3+1] = vec3.get_y();
            vertPositions[i*3+2] = vec3.get_z();
        }
        let remeshedBufferGeo = new THREE.BufferGeometry();
        remeshedBufferGeo.setAttribute('position', new THREE.BufferAttribute(vertPositions, 3));
        remeshedBufferGeo.setIndex(new THREE.BufferAttribute(triIndices, 1));
        remeshedBufferGeo.computeVertexNormals();
        let remeshedThreeMesh = new THREE.Mesh(remeshedBufferGeo, new THREE.MeshPhysicalMaterial({ color: 0x00ff00, wireframe: true }));
        remeshedThreeMesh.position.set(2.0, 0.0, 0.0);
        this.world.scene.add(remeshedThreeMesh);

        // Clean up the PhysX Arrays
        inputVertices .__destroy__();
        inputIndices  .__destroy__();
        outputVertices.__destroy__();
        outputIndices .__destroy__();
        vertexMap     .__destroy__();

I'll look into the tetrahedralization next... putting WIP code into https://github.com/zalo/TetSim/compare/feat-physx-baking

EDIT: It all works! Thank you!

image Left: CAD Mesh, Middle: Remeshed + Simplified, Right: Tetrahedral Mesh

Took a fair amount of trial and error (and spelunking through the PhysX codebase for examples of constructing 'Simple'TriangleMeshes), but it appears to be working great!

zalo commented 6 months ago

Alrighty, here's a quick Benchmark showing what the PhysX TetMesh looks like on another model, with tunable parameters: https://zalo.github.io/TetForm/

I think this was the missing piece for making a larger collection of FEM Physics Simulations; thank you again for adding this to your library!

By the way, I notice PhysX might benefit from something I've been working on the side: a faster exact convex decomposition for physics meshes...

fabmax commented 6 months ago

That's pretty awesome!

Convex mesh decomposition is also something I still have on my todo list. I had this one on my radar: https://github.com/kmammou/v-hacd But I haven't dived into that topic yet.

zalo commented 6 months ago

VHACD has the nicest build config (since it’s just a header file now πŸ˜„), but CoACD makes twice as accurate decompositions in about the same amount of time, and has a comparable license.

But, since I have Physics-based modeling/crafting on the brain, neither are quite fast enough for real-time use….

I compare them to my method here for a very concave test shape: https://github.com/elalish/manifold/pull/663#issue-2045336428

I started porting all the code/algorithms to an independent project last night, so that may bear some fruit soon…

fabmax commented 6 months ago

That looks promising! Although I guess for most game use-cases accuracy is not that important.

fabmax commented 6 months ago

Alright, I finally played around with VHACD a bit and while the accuracy is ok for me, the speed is not (at least for online mesh conversion; low-resolution stanford bunny takes ~7.5 secs when running single-threaded in native, haven't tried WASM yet, but it won't be faster...). So, if your (@zalo) voronoi approach is really that much faster I would like to give it a try once it's there :smile:

What surprised me the most, is the performance of PhysX when simulating convex meshes: 500 actors, 16 meshes each and only ~3 ms per sim step

https://github.com/fabmax/physx-jni/assets/3752161/538ee8b9-846e-4115-acb6-b9ac643ca41e

tlf30 commented 6 months ago

In the past when using VHACD, I have prebaked the physics mesh into my main mesh, and the loader will load both. This works fine as long as you know the mesh in advance. If using shape keys this can be problematic. I was experimenting with what it would take to use shape keys with physics meshes (in bullet), but did not get a chance to dive into it in detail.

I too am interested in a solution that is faster and can do real time mesh conversions (even at the cost of a lower accuracy).