Coder Social home page Coder Social logo

physx-jni's Introduction

physx-jni

License Maven Central Build

Java JNI bindings for Nvidia PhysX 5.4.1.

How to use

The library is published on maven central, so you can easily add this to your dependencies:

Desktop Java

dependencies {
    // java bindings
    implementation("de.fabmax:physx-jni:2.4.1")
    
    // native libraries - you can add the one matching your system or all
    runtimeOnly("de.fabmax:physx-jni:2.4.1:natives-windows")
    runtimeOnly("de.fabmax:physx-jni:2.4.1:natives-linux")
    runtimeOnly("de.fabmax:physx-jni:2.4.1:natives-macos")
    runtimeOnly("de.fabmax:physx-jni:2.4.1:natives-macos-arm64")
}

Android

The Android version of the library is packaged as a single aar archive containing both java classes and native libs:

dependencies {
    implementation("de.fabmax:physx-jni-android:2.4.1")
}

Library Coverage

This is still work in progress, but the bindings already include most major parts of the PhysX SDK:

  • Basics
    • Static and dynamic actors
    • All geometry types (box, capsule, sphere, plane, convex mesh, triangle mesh and height field)
  • All joint types (revolute, spherical, prismatic, fixed, distance and D6)
  • Articulations
  • Vehicles
  • Character controllers
  • CUDA (requires a Platform with CUDA support, see below)
    • Rigid bodies
    • Particles (Fluids + Cloth)
    • Soft bodies
  • Scene serialization

Furthermore, I added bindings to V-HACD, which is not part of PhysX but fits in the context very well.

The detailed list of mapped functions is given by the interface definition files. The Java classes containing the actual bindings are generated from these files during build.

After build (or after running the corresponding gradle task generateJniBindings) the generated Java classes are located under physx-jni/src/main/generated.

Supported platforms:

  • Windows (x86_64)
  • Linux (x86_64)
  • MacOS (x86_64, and arm64)
  • Android (arm-v8 (aarch64) only for now)

Moreover, there is also a version for javascript/webassembly: physx-js-webidl.

Examples

You can take a look at HelloPhysX.java for a hello world example on how to use the library. There also are a few tests with slightly more advanced examples (custom simulation callbacks, triangle mesh collision, custom filter shader, etc.).

To see a few real life demos you can take a look at my kool demos:

  • Vehicle: Vehicle demo with a racetrack and a few obstacles.
  • Character: 3rd person character demo on an island.
  • Ragdolls: Simple Ragdoll demo.
  • Joints: A chain running over two gears.
  • Collision: Various collision shapes.

Note: These demos run directly in the browser and obviously don't use this library, but the webassembly version mentioned above. However, the two are functionally identical, so it shouldn't matter too much. The JNI version is much faster though.

The particle simulation unfortunately requires CUDA and therefore only works on Windows / Linux systems with an Nvidia GPU. Here are a few images what this can look like:

Fluid Simulation Cloth Simulation
Fluid simulation Cloth simulation

Simplified non-graphical versions of the two scenes are available in source as tests: FluidTest and ClothTest They are more or less 1:1 translations of the corresponding PhysX example snippets.

Documentation

The generated bindings contain most of the original documentation converted to javadoc. For further reading there is also the official PhysX documentation.

Things to consider when working with native objects

Whenever you create an instance of a wrapper class within this library, this also creates an object on the native side. Native objects are not covered by the garbage collector, so, in order to avoid a memory leak, you have to clean up these objects yourself when you are done with them.

Here is an example:

// create an object of PxVec3, this also creates a native PxVec3
// object behind the scenes.
PxVec3 vector = new PxVec3(1f, 2f, 3f);

// do something with vector...

// destroy the object once you are done with it
vector.destroy();

This approach has two potential problems: First, as mentioned, if you forget to call destroy(), the memory on the native heap is not released resulting in a memory leak. Second, creating new objects on the native heap comes with a lot of overhead and is much slower than creating a new object on the Java side.

These issues aren't a big problem for long living objects, which you create on start-up and use until you exit the program. However, for short-lived objects like, in many cases, PxVec3 this can have a large impact. Therefore, there is a second method to allocate these objects: Stack allocation. To use this, you will need some sort of memory allocator like LWJGL's MemoryStack. With that one the above example could look like this:

try (MemoryStack mem = MemoryStack.stackPush()) {
    // create an object of PxVec3. The native object is allocated in memory
    // provided by MemoryStack
    PxVec3 vector = PxVec3.createAt(mem, MemoryStack::nmalloc, 1f, 2f, 3f);
    
    // do something with vector...
    // no explicit destroy needed, memory is released when we leave the scope
}

While the PxVec3.createAt() call looks a bit more complicated, this approach is much faster and comes without the risk of leaking memory, so it should be preferred whenever possible.

Java Callbacks

At a few places it is possible to register callbacks, e.g., PxErrorCallback or PxSimulationEventCallback. In order to implement a callback, the corresponding Java callback class has to be extended. The implementing class can then be passed into the corresponding PhysX API.

Here's an example how this might look:

// implement callback
public class CustomErrorCallback extends PxErrorCallbackImpl {
    @Override
    public void reportError(PxErrorCodeEnum code, String message, String file, int line) {
        System.out.println(code + ": " + message);
    }
}

// register / use callback
CustomErrorCallback errorCb = new CustomErrorCallback();
PxFoundation foundation = PxTopLevelFunctions.CreateFoundation(PX_PHYSICS_VERSION, new PxDefaultAllocator(), errorCb);

User Data

Several PhysX classes (e.g. PxActor, PxMaterial, ...) have a userData field, which can be used to store an arbitrary object reference. Since the native userData field is a void pointer, a wrapper class JavaNativeRef is needed to store a java object reference in it:

PxRigidDynamic myActor = ...

// set user data, can be any java object, here we use a String:
myActor.setUserData(new JavaNativeRef<>("Arbitrary data"));

// get user data, here we expect it to be a String:
JavaNativeRef<String> userData = JavaNativeRef.fromNativeObject(myActor.getUserData());
System.out.println(userData.get());

CUDA Support

PhysX supports accelerating physics simulation with CUDA (this, of course, requires an Nvidia GPU). However, using CUDA requires different runtime libraries, which are not available via maven central. Instead, you can grab them from the releases section (those suffixed with -cuda). Apart from that, enabling CUDA acceleration for a scene is straight forward:

// Setup your scene as usual
PxSceneDesc sceneDesc = new PxSceneDesc(physics.getTolerancesScale());
sceneDesc.setCpuDispatcher(PxTopLevelFunctions.DefaultCpuDispatcherCreate(8));
sceneDesc.setFilterShader(PxTopLevelFunctions.DefaultFilterShader());

// Create the PxCudaContextManager
PxCudaContextManagerDesc desc = new PxCudaContextManagerDesc();
desc.setInteropMode(PxCudaInteropModeEnum.NO_INTEROP);
PxCudaContextManager cudaMgr = PxCudaTopLevelFunctions.CreateCudaContextManager(foundation, desc);

// Check if CUDA context is valid / CUDA support is available
if (cudaMgr != null && cudaMgr.contextIsValid()) {
    // enable CUDA!
    sceneDesc.setCudaContextManager(cudaMgr);
    sceneDesc.getFlags().set(PxSceneFlagEnum.eENABLE_GPU_DYNAMICS);
    sceneDesc.setBroadPhaseType(PxBroadPhaseTypeEnum.eGPU);
    
    // optionally fine tune amount of allocated CUDA memory
    // PxgDynamicsMemoryConfig memCfg = new PxgDynamicsMemoryConfig();
    // memCfg.setStuff...
    // sceneDesc.setGpuDynamicsConfig(memCfg);
} else {
    System.err.println("No CUDA support!");
}

// Create scene as usual
PxScene scene = physics.createScene(sceneDesc);

CUDA comes with some additional overhead (a lot of data has to be copied around between CPU and GPU). For smaller scenes this overhead seems to outweigh the benefits and physics computation might actually be slower than with CPU only. I wrote a simple CudaTest, which runs a few simulations with an increasing number of bodies. According to this the break even point is around 5k bodies. At 20k boxes the CUDA version runs about 3 times faster than the CPU Version (with an RTX 2080 / Ryzen 2700X). The results may be different when using other body shapes (the test uses boxes), joints, etc.

Building

You can build the bindings yourself. However, this requires cmake, python3 and the C++ compiler appropriate to your platform (Visual Studio 2022 (Community) on Windows / clang on Linux):

# Clone this repo
git clone https://github.com/fabmax/physx-jni.git

# Enter that directory
cd physx-jni

# Download submodule containing the PhysX source code
git submodule update --init

# Optional, but might help in case build fails
./gradlew generateNativeProject

# Build native PhysX (requires Visual Studio 2022 (Community) on Windows / clang on Linux)
./gradlew buildNativeProject

# Generate Java/JNI code and build library
./gradlew build

physx-jni's People

Contributors

fabmax avatar sm0keysa1m0n avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

physx-jni's Issues

PxMeshOverlapUtil

I am using the PxController to create a character controller. When the player is moved (PxController::move method is called), the following error occurs.
/usr/lib/jvm/java-15-openjdk/bin/java: symbol lookup error: /tmp/de.fabmax.physx-jni/0.4.15/libPhysXJniBindings_64.so: undefined symbol: _ZN5physx17PxMeshOverlapUtilC1Ev

I started researching and I found that the class PxMeshOverlapUtil is also missing. Is this a missing feature? Is there a workarrownd?

Thanks

EDIT: I realicen that doesnt happen con windows. Maybe there is a linking error con linux when building the linux native libs.

Any easy way to visualize a setup?

New to the library, having fun exploring. Is there an easy-ish way to see what is going on, like a no-fancy-materials scene renderer?

Incompatibility with Java 9 Modules

In my build.gradle file, i both included the base library and natives with

  implementation "de.fabmax:physx-jni:2.0.5"
  runtimeOnly "de.fabmax:physx-jni:2.0.5:natives-linux"

and when running just the initialization:

    int physicsVersion = PxTopLevelFunctions.getPHYSICS_VERSION();
    int physicsVersionMajor = physicsVersion >> 24;
    int physicsVersionMinor = (physicsVersion >> 16) & 0xff;
    int physicsVersionMicro = (physicsVersion >> 8) & 0xff;
    PxDefaultAllocator physicsAllocator = new PxDefaultAllocator();
    PxDefaultErrorCallback physicsErrorCallback = new PxDefaultErrorCallback();
    PxFoundation physicsFoundation = PxTopLevelFunctions.CreateFoundation(physicsVersion, physicsAllocator, physicsErrorCallback);
    PxTolerancesScale physicsTolerances = new PxTolerancesScale();
    PxPhysics physics = PxTopLevelFunctions.CreatePhysics(physicsVersion, physicsFoundation, physicsTolerances);
    System.out.printf("PhysX loaded, version: %d.%d.%d%n", physicsVersionMajor, physicsVersionMinor, physicsVersionMicro);
    int amountOfThreadsForPhysics = Math.max(1, (int) (Runtime.getRuntime().availableProcessors() / 2f));
    PxDefaultCpuDispatcher physicsCpuDispatcher = PxTopLevelFunctions.DefaultCpuDispatcherCreate(amountOfThreadsForPhysics);
    System.out.printf("PhysX CPU Dispatcher created, threads: %d%n", amountOfThreadsForPhysics);

I get the error Caused by: java.lang.IllegalStateException: Failed loading native PhysX libraries for platform LINUX and the cause of that is Caused by: java.lang.ClassNotFoundException: de.fabmax.physxjni.NativeMetaLinux. I think this is because of the native library not having a module-info.class. I am also not able to manually import the NativeMetaLinux class due to that.

my module-info.class looks like that

  ...

  requires de.fabmax.physxjni;

full error log:

Exception in thread "main" java.lang.ExceptionInInitializerError
	at <CENSORED>.main(<CENSORED>.java:52)
Caused by: java.lang.IllegalStateException: Failed loading native PhysX libraries for platform LINUX
	at de.fabmax.physxjni/de.fabmax.physxjni.Loader.load(Loader.java:31)
	at de.fabmax.physxjni/physx.NativeObject.<clinit>(NativeObject.java:7)
	... 1 more
Caused by: java.lang.ClassNotFoundException: de.fabmax.physxjni.NativeMetaLinux
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
	at de.fabmax.physxjni/de.fabmax.physxjni.Platform.getMeta(Platform.java:17)
	at de.fabmax.physxjni/de.fabmax.physxjni.Loader.load(Loader.java:22)
	... 2 more

Segmentation fault on Linux

The original issue is haubna/PhysicsMod#709, but since it is a problem at JNI, so I guess I should report the problem here.

The trace from gdb is below:

pwndbg> conti
Continuing.
[New Thread 0x7ffe4e8fc6c0 (LWP 7728)]
[Thread 0x7ffe4e8fc6c0 (LWP 7728) exited]
[10:56:44] [Render thread/WARN]: Received passengers for unknown entity
[10:56:47] [Render thread/WARN]: Received passengers for unknown entity
[10:56:53] [Render thread/WARN]: Received passengers for unknown entity

Thread 2 "Render thread" received signal SIGSEGV, Segmentation fault.
0x00007ffef9ee9cbc in physx::NpRigidDynamic::wakeUp() () from /tmp/de.fabmax.physx-jni/2.1.0-pre1/libPhysXJniBindings_64.so
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
──────────────────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]───────────────────────────────────────────────────────────────
*RAX  0x0
*RBX  0x7ffed99b3370 —▸ 0x7ffff79ef738 —▸ 0x7ffff6a1eda0 ◂— endbr64 
*RCX  0x7ffed99e8b70 ◂— 0xffffffff00000024 /* '$' */
*RDX  0x7ffff3f38080 —▸ 0x7ffefa1e2c70 (vtable for physx::NpRigidDynamic+16) —▸ 0x7ffef9ee74f0 (physx::NpRigidDynamic::release()) ◂— push r15
*RDI  0x7ffff3f38080 —▸ 0x7ffefa1e2c70 (vtable for physx::NpRigidDynamic+16) —▸ 0x7ffef9ee74f0 (physx::NpRigidDynamic::release()) ◂— push r15
*RSI  0x7ffff7bd8c80 —▸ 0x66d027fb8 ◂— 0x12e9f8a219
*R8   0x2
*R9   0x0
*R10  0x7fffe10c2df9 ◂— vzeroupper  /* 0xc2df9ba4977f8c5 */
*R11  0x7fffe10c2dc0 ◂— mov dword ptr [rsp - 0x14000], eax /* 0x55fffec000248489 */
 R12  0x0
*R13  0x7ffff7bd8ca8 —▸ 0x7ffff3f38080 —▸ 0x7ffefa1e2c70 (vtable for physx::NpRigidDynamic+16) —▸ 0x7ffef9ee74f0 (physx::NpRigidDynamic::release()) ◂— push r15
*R14  0x7ffff7bd8c80 —▸ 0x66d027fb8 ◂— 0x12e9f8a219
 R15  0x7ffff001ade0 —▸ 0x7ffff79386d8 —▸ 0x7ffff6c5c570 ◂— endbr64 
*RBP  0x7ffff7bd8c90 —▸ 0x7ffff7bd8d00 —▸ 0x6629349a0 ◂— 0x31 /* '1' */
*RSP  0x7ffff7bd8c40 —▸ 0x7ffefa1e2c70 (vtable for physx::NpRigidDynamic+16) —▸ 0x7ffef9ee74f0 (physx::NpRigidDynamic::release()) ◂— push r15
*RIP  0x7ffef9ee9cbc (physx::NpRigidDynamic::wakeUp()+28) ◂— movss xmm0, dword ptr [rax + 0x1cb0]
───────────────────────────────────────────────────────────────────────[ DISASM / x86-64 / set emulate on ]────────────────────────────────────────────────────────────────────────
 ► 0x7ffef9ee9cbc <physx::NpRigidDynamic::wakeUp()+28>                      movss  xmm0, dword ptr [rax + 0x1cb0]
   0x7ffef9ee9cc4 <physx::NpRigidDynamic::wakeUp()+36>                      add    rdi, 0x50
   0x7ffef9ee9cc8 <physx::NpRigidDynamic::wakeUp()+40>                      mov    esi, 1
   0x7ffef9ee9ccd <physx::NpRigidDynamic::wakeUp()+45>                      pop    rax
   0x7ffef9ee9cce <physx::NpRigidDynamic::wakeUp()+46>                      jmp    physx::Sc::BodyCore::setWakeCounter(float, bool)@plt                <physx::Sc::BodyCore::setWakeCounter(float, bool)@plt>
    ↓
   0x7ffef9c7cb50 <physx::Sc::BodyCore::setWakeCounter(float, bool)@plt>    jmp    qword ptr [rip + 0x574252]    <physx::Sc::BodyCore::setWakeCounter(float, bool)>
    ↓
   0x7ffef9f94f70 <physx::Sc::BodyCore::setWakeCounter(float, bool)>        push   rbp
   0x7ffef9f94f71 <physx::Sc::BodyCore::setWakeCounter(float, bool)+1>      push   rbx
   0x7ffef9f94f72 <physx::Sc::BodyCore::setWakeCounter(float, bool)+2>      push   rax
   0x7ffef9f94f73 <physx::Sc::BodyCore::setWakeCounter(float, bool)+3>      movss  dword ptr [rdi + 0x9c], xmm0
   0x7ffef9f94f7b <physx::Sc::BodyCore::setWakeCounter(float, bool)+11>     mov    rbx, qword ptr [rdi]
─────────────────────────────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────────────────────────────
00:0000│ rsp 0x7ffff7bd8c40 —▸ 0x7ffefa1e2c70 (vtable for physx::NpRigidDynamic+16) —▸ 0x7ffef9ee74f0 (physx::NpRigidDynamic::release()) ◂— push r15
01:0008│     0x7ffff7bd8c48 —▸ 0x7fffe10c2e71 ◂— vzeroupper  /* 0x37487c74177f8c5 */
02:0010│     0x7ffff7bd8c50 —▸ 0x7ffff7bd8cc0 —▸ 0x7ffed99b32c0 ◂— 0x9ed01ffb1001db8
03:0018│     0x7ffff7bd8c58 —▸ 0x7fffdfd54479 ◂— mov rsp, qword ptr [rbp - 0x10] /* 0xf045c748f0658b48 */
04:0020│     0x7ffff7bd8c60 ◂— 0x1c
05:0028│     0x7ffff7bd8c68 ◂— 0x8
06:0030│     0x7ffff7bd8c70 —▸ 0x6629349a0 ◂— 0x31 /* '1' */
07:0038│     0x7ffff7bd8c78 ◂— 0x7ffff7bd8c78
───────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────────────────────────────────
 ► f 0   0x7ffef9ee9cbc physx::NpRigidDynamic::wakeUp()+28
   f 1   0x7fffe10c2e71
   f 2   0x7ffff7bd8cc0
   f 3   0x7fffdfd54479
   f 4             0x1c
   f 5              0x8
   f 6      0x6629349a0
   f 7   0x7ffff7bd8c78
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> disas
Dump of assembler code for function _ZN5physx14NpRigidDynamic6wakeUpEv:
   0x00007ffef9ee9ca0 <+0>:     push   rax
   0x00007ffef9ee9ca1 <+1>:     mov    rax,QWORD PTR [rdi+0x18]
   0x00007ffef9ee9ca5 <+5>:     test   rax,rax
   0x00007ffef9ee9ca8 <+8>:     je     0x7ffef9ee9cbc <physx::NpRigidDynamic::wakeUp()+28>
   0x00007ffef9ee9caa <+10>:    cmp    BYTE PTR [rax+0x4d2],0x0
   0x00007ffef9ee9cb1 <+17>:    je     0x7ffef9ee9cbc <physx::NpRigidDynamic::wakeUp()+28>
   0x00007ffef9ee9cb3 <+19>:    cmp    DWORD PTR [rax+0x1bec],0x2
   0x00007ffef9ee9cba <+26>:    jne    0x7ffef9ee9cd3 <physx::NpRigidDynamic::wakeUp()+51>
=> 0x00007ffef9ee9cbc <+28>:    movss  xmm0,DWORD PTR [rax+0x1cb0]
   0x00007ffef9ee9cc4 <+36>:    add    rdi,0x50
   0x00007ffef9ee9cc8 <+40>:    mov    esi,0x1
   0x00007ffef9ee9ccd <+45>:    pop    rax
   0x00007ffef9ee9cce <+46>:    jmp    0x7ffef9c7cb50 <physx::Sc::BodyCore::setWakeCounter(float, bool)@plt>
   0x00007ffef9ee9cd3 <+51>:    call   0x7ffef9c7d250 <PxGetFoundation@plt>
   0x00007ffef9ee9cd8 <+56>:    mov    rcx,QWORD PTR [rax]
   0x00007ffef9ee9cdb <+59>:    mov    r9,QWORD PTR [rcx+0x58]
   0x00007ffef9ee9cdf <+63>:    lea    rdx,[rip+0x22155a]        # 0x7ffefa10b240
   0x00007ffef9ee9ce6 <+70>:    lea    r8,[rip+0x221c98]        # 0x7ffefa10b985
   0x00007ffef9ee9ced <+77>:    mov    rdi,rax
   0x00007ffef9ee9cf0 <+80>:    mov    esi,0x8
   0x00007ffef9ee9cf5 <+85>:    mov    ecx,0x19a
   0x00007ffef9ee9cfa <+90>:    xor    eax,eax
   0x00007ffef9ee9cfc <+92>:    pop    r11
   0x00007ffef9ee9cfe <+94>:    jmp    r9
End of assembler dump.
pwndbg> 

And according to the trace of gdb, it is a null pointer dereference problem and caused Minecraft to freeze

I'm not familiar in debugging C++ code so I'm sorry that I can't provide any more information.

Constraint Break is not passing in an array in Java (PhysX 4.0)

onConstraintBreak should pass an array (described here https://gameworksdocs.nvidia.com/PhysX/4.0/documentation/PhysXGuide/Manual/Joints.html).

class MySimulationEventCallback
{
    void onConstraintBreak(PxConstraintInfo* constraints, PxU32 count)
    {
        for(PxU32 i=0; i<count; i++)
        {
            PxJoint* joint = reinterpret_cast<PxJoint*>(constraints[i].externalReference);
            ...
        }
    }
}

But it passes only one value that can't be iterated. Maybe a similar solution to PxContactPair (PxContactPair pair = TypeHelpers.getContactPairAt(pairs, i);) would be feasible.

public void onConstraintBreak(PxConstraintInfo constraints, int count) {
}

Support for variable (or larger) sized PxOverlapBuffers

Currently the only (useful) object that can be passed into PxScene.overlap's PxOverlapCallback is a PxOverlapBuffer10, but as the name implies it can only store a buffer of 10 overlapping objects. From looking at the source this looks to be a limitation of "webidl" and template classes, however my use case requires storing more than 10 objects.

One possible solution is to create separate classes for handling more than 10 objects, but I don't know any reasonable number for this. However even better would be something that can support all of the objects passed back from PhysX (I don't understand the internals well so I don't know how hard this would be to implement). Similar solutions could be put in place for Raycast- and SweepBuffers.

For context, my use case is getting a collection of all objects which are near a specific point, which I do by performing an overlap of a sphere at that position. I don't need the distance to be exact, just any objects which are at least x units away from the point. If there is a better way to do this without an overlap scene query then I'd be happy to see it as well.

README wrong Cuda function

The readme uses
PxTopLevelFunctions.CreateCudaContextManager(foundation, desc);
instead of
PxCudaTopLevelFunctions.CreateCudaContextManager(foundation, desc);

It already works on mac

I use a MacBook air and I just wanted to say that this modpack already works on mac
just use forge/fabric and put it in the mods folder and it works

Module Support

It'd be good to have support for Java 9+ modularity (via module-info.java) so people don't need to resort to things like the extra-java-module-info gradle plugin.

PvdTransport Bindings (PhysX 4)

Hi, is it possibile to bring DefaultPvdSocketTransportCreate (and PvdTransport) bindings to PhysX 4 branch? (as already done for PhysX 5)

Wierd differential behaviour with any non-4WD configuration.

When setting up a car, eDIFF_TYPE_LS_4WD works fine but any other, such as eDIFF_TYPE_LS_REARWD, seems to spin the rear wheels but the front ones are "braking" and wont rotate, even though I'm not applying any braking or handbrake input. This makes the car unable to move. I don't know if this is something I'm doing wrong, or a bug. Any clues? Thanks.

Crash without log

I am not sure why but this code (extended sample code) crashes when using the convex shapes. Creating no log whatsoever and it doesn't even crash all the time. I might be using the API wrong though.

https://pastebin.com/21gDbdpE

Blast and Flow SDKs?

Is this JNI just for the PhysX SDK and if so, will Blast and Flow SDK be added in the future? This may be a trivial request, but I think it would be useful to have since they are apart of the PhysX family.

gradlew not executable

Please make gradlew executable. Currently your description how to generate does not work.
The user either has do call $ bash gradlew build or first do a chmod 755 gradlew and then use your description.

How to add to maven

image

    <dependency>
        <groupId>de.fabmax</groupId>
        <artifactId>physx-jni</artifactId>
        <version>2.3.1</version>
    </dependency>

And I am not find any pom like physx-jni-natives-macos

ARM64 support

Hi! This is not something I use, but I thought it may be fitting for the library to provide an ARM64 build. It is getting pretty popular in various fronts like the Apple M1 (destined to replace the x86 Macs), Raspberry Pi has been ARM64 capable for years, I think there are a bunch of tablets and stuff running Windows 10 for ARM, the overbearing presence of Android, etc.

As I said, I have no use of it, but I thought it may be relevant to provide an ARM64 build down the line.

PxActor userdata missing

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.

pvd debug and PxHeightField

hello, I have two question about physx-jni.
The one is I want use pvd debug, but compare to office example, i can't create PvdDefaultSocketTransport object. so how to solve the problem. if can use pvd debug , i can create object in code and see the change in pvd debug.
Other is how to create PxHeightField. I'm not found create code.

Support for non diffuse Fluids

I think the only functionality missing for it is creating the particle buffer for it

PxCudaTopLevelFunctions.CreateAndPopulateParticleBuffer

PxRenderBuffer array fields aren't mapped properly

Hi! I was researching how to implement a debug visualization using the official docs:

https://nvidia-omniverse.github.io/PhysX/physx/5.4.0/docs/DebugVisualization.html

const PxRenderBuffer& rb = scene->getRenderBuffer();

for(PxU32 i=0; i < rb.getNbPoints(); i++)
{
    const PxDebugPoint& point = rb.getPoints()[i];
    // render the point
}

for(PxU32 i=0; i < rb.getNbLines(); i++)
{
    const PxDebugLine& line = rb.getLines()[i];
    // render the line
}

It seems the array fields for points, lines, etc in PxRenderBuffer are mapped to a single element with no way to index into them.

[Const] PxDebugPoint getPoints();

I think PxDebugLine.arrayGet for example can be used to work around this:

PxRenderBuffer renderBuffer = physxScene.getRenderBuffer();
int pointsLength = renderBuffer.getNbPoints();
int pointsBaseAddress = renderBuffer.getPoints().getAddress();
for (int p = 0; p < pointsLength; ++p) {
	PxDebugPoint point = PxDebugPoint.arrayGet(pointsBaseAddress, p);
}

But I believe it should be exposed like the getAnyHit(index) accessor from PxSweepResult

[Const, Ref] PxSweepHit getAnyHit(unsigned long index);

Where you do

int hitsLength = sweepResult.getNbAnyHits();
for (int h = 0; h < hitsLength; ++h) {
	PxSweepHit hit = sweepResult.getAnyHit(h);
}

Could you please support PxDefaultFileInputData and PxSerialization ?

c++ code:

char fileName[50];
cout << "please input file path:" << endl;
cin >> fileName;
PxDefaultFileInputData inputData = physx::PxDefaultFileInputData(fileName);
bool isValid = inputData.isValid();
if (isValid)
{
printf("exist file");
}
else
{
printf("error! not exist file");
exit(0);
return;
}

registry = PxSerialization::createSerializationRegistry(*gPhysics);
cooking = PxCreateCooking(PX_PHYSICS_VERSION, gFoundation, PxCookingParams(gPhysics->getTolerancesScale()));
PxCollection
convexCollection = PxSerialization::createCollectionFromXml(inputData, *cooking, *registry, NULL);
gScene->addCollection(*convexCollection);
convexCollection->release();
registry->release();

No "garbage-free" way to interact with the library

Hi! I noticed something while using these bindings.

Having LWJGL as a reference, it provides usually a couple of overloads for every function. In particular it provides both wrapped and unwrapped versions of a native binding. It looks like this:

// I believe LWJGL prefixes all of these "direct" calls with n
public static native long ndoSomethingOnNative(long address);

public static ByteBuffer doSomethingOnNative(ByteBuffer data) {
  var result = ndoSomethingOnNative(addressOf(data)); // unwrap ByteBuffer argument
  return wrap(result); // wrap result in ByteBuffer
}

This way, if you do not want to go through object manipulation, because you're handling the long addresses directly, you have the chance to do so.

Now lets look at PxActor user data functions:

    public NativeObject getUserData() {
        checkNotNull();
        return NativeObject.wrapPointer(_getUserData(address));
    }
    private static native long _getUserData(long address);
    public void setUserData(NativeObject value) {
        checkNotNull();
        _setUserData(address, value.getAddress());
    }
    private static native void _setUserData(long address, long value);

While I can get the object's address field just fine with getAddress(), I am unable to directly call either _getUserData or _setUserData due their visibility.

Moreover, I am forced to create an object on every single call of these methods. getUserData may very well be a high frequency method to call.

Now, this limitation is propagated in the design of the whole library, you can find many cases such as this. Where you could, if it were visible, have a single PxSomething instance created, and just wrap/unwrap direct pointers mutating that lone instance's address field, instead of having to recreate those PxSomething objects on every single access.

In this particular case I'd use the native _setUserData function for something more pragmatic. I do not want to actually set an object reference there, I just want to set an int32 index. So I'd use it like:

PxActor o = // etc.
int entityId = // some entity id
PxActor._setUserData(o.getAddress(), entityId);
// and to use it, no objects created in either case
int entityId = (int)PxActor._getUserData(o.getAddress());

I do not believe this could apply on every single instance where a native call is issued, but I can imagine plenty of cases where object creation could be avoided if you could just access the native functions "directly" using long back and forth, and just manually mutating the address field of a single PxSomething object to manipulate the memory from Java.

Also I do know that physx-jni is very careful on how it uses objects and they never cross to the native side, so in theory escape analysis should be able to work its magic. However, it popped out to me since in particular the userData ID seemed a "simple" use case I couldn't emulate with just primitive usage with the API as it is.

My experience with PhysX is really barebones (and my project is nowhere near a serious one, just hobby things) so I cant comment on better ways of doing exactly what I wanted to do, but I hope it illustrates the kind of use case I'm thinking of.

Cyrillic letters issue

Caused by cyrillic letters in the username

Caused by: java.lang.UnsatisfiedLinkError: C:\Users\?????? ?????\AppData\Local\Temp\de.fabmax.physx-jni\0.4.13\PhysX_64.dll: Can't find dependent libraries
--
  | at java.base/jdk.internal.loader.NativeLibraries.load(Native Method)
  | at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(NativeLibraries.java:383)
  | at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:227)
  | at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:169)
  | at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2383)
  | at java.base/java.lang.Runtime.load0(Runtime.java:746)
  | at java.base/java.lang.System.load(System.java:1857)
  | at de.fabmax.physxjni.Loader.loadLibsFromResources(Loader.java:71)
  | at de.fabmax.physxjni.Loader.load(Loader.java:33)
  | ... 14 more

PxTolerancesScale is missing property modification method

In the PhysX documentation, PxTolerancesScale has two properties, length and speed, but there is no method to modify these two properties in Java.
PhysX document:
You should set tolerances based on the typical size of objects in your simulation. For example, if you are working with objects of size approximately one meter, but in units of centimeters, you should set the scale as follows:

PxFoundation* foundation = ...;
PxTolerancesScale scale;
scale.length = 100;        // typical length of an object
scale.speed = 981;         // typical speed of an object, gravity*1s is a reasonable choice
PxPhysics* p = PxCreatePhysics(PX_PHYSICS_VERSION, *foundation, scale, ...);

source code:

/**
class PxTolerancesScale
{
public: 

	PxReal	length;

	PxReal	speed;

	PX_INLINE explicit PxTolerancesScale(float defaultLength=1.0f, float defaultSpeed=10.0f);

	PX_INLINE bool isValid() const;

};

PX_INLINE PxTolerancesScale::PxTolerancesScale(float defaultLength, float defaultSpeed) :
	length	(defaultLength),
	speed	(defaultSpeed)
	{
	}
....

Java:

public class PxTolerancesScale extends NativeObject {
  public PxTolerancesScale() {
          address = _PxTolerancesScale();
      }
      private static native long _PxTolerancesScale();
....

The lack of attribute modification methods prevents me from modifying this scale

Articulations NaN

I am trying to work with articulations and there position values somtimes return NaN (running the code returns random results). I've purposely excluded releasing the memory to avoid having a mistake on those. Currently it creates only the main articulation body and even this one only returns NaN. This is the file for quick tests:

https://pastebin.com/9DJDUMpr

Task :physx-jni:generateJniBindings FAILED

Building the bindings throws an error:

What went wrong:
Execution failed for task ':physx-jni:generateJniBindings'.
java.io.FileNotFoundException: physx-jni/src/main/generated/physx/NativeObject.java (file or directory not found)`

I'm not familiar with gradle, but is there an error in physx-jni/build.gradle.kts?
The task "generateJniBindings" depends on it self?

PxGjkQuery and PxGjkQueryExt bindings

Would it be possible to get bindings for geometry/PxGjkQuery.h and extensions/PxGjkQueryExt.h? They're very useful for calculating contact points in custom geometry.

Thanks :)

Linux incompatibility

A user reported a crash on Linux. I am not that familiar with it but it seems like his distribution of Linux is missing something that others have.

Operating System: Linux (amd64) version 6.5.0-35-generic

Caused by: java.lang.IllegalStateException: Failed loading native PhysX libraries for platform LINUX
	at de.fabmax.physxjni.Loader.load(Loader.java:37)
	at physx.NativeObject.<clinit>(NativeObject.java:7)
	... 9 more
Caused by: java.lang.UnsatisfiedLinkError: /tmp/de.fabmax.physx-jni/2.3.2/libPhysXJniBindings_64.so: /lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.32' not found (required by /tmp/de.fabmax.physx-jni/2.3.2/libPhysXJniBindings_64.so)
	at java.base/jdk.internal.loader.NativeLibraries.load(Native Method)
	at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(Unknown Source)
	at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(Unknown Source)
	at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(Unknown Source)
	at java.base/java.lang.ClassLoader.loadLibrary(Unknown Source)
	at java.base/java.lang.Runtime.load0(Unknown Source)
	at java.base/java.lang.System.load(Unknown Source)
	at de.fabmax.physxjni.NativeLib.load(NativeLib.java:49)
	at de.fabmax.physxjni.Loader.load(Loader.java:35)

Edit: The user fixed it by following the instructions here.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.