Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extending Physx API Bindings - exploration of options. #15

Open
diarmidmackenzie opened this issue Mar 15, 2023 · 18 comments
Open

Extending Physx API Bindings - exploration of options. #15

diarmidmackenzie opened this issue Mar 15, 2023 · 18 comments

Comments

@diarmidmackenzie
Copy link
Member

I've been looking at extending the available PhysX API bindings.

My immediate goal was to experiment with Projection on Fixed Joints to solve a problem where walls of bricks joined together with fixed joints become wobbly above a certain size.

For future reference, this issue documents my progress on a couple of fronts.

  1. Rebuilding the existing WASM build, using the approach described here.

This is the "obvious" approach, and should have been straightforward.

I made some minor updates to enable a couple of new API calls here

Rebuilding should be pretty straightforward, but I had a few issues

  • running natively on Windows, the npm scripts hit errors
  • so I ran WSL so that I had a linux environment on my Windows PC
  • I was able to set that up with Docker following these instructions and to set up node on WSL using these instructions
  • Having cloned repos within Windows, I found I had some problems with file format (CRLF vs LF). Simplest solution was to delete the repos I had cloned in Windows, and re-clone from the WSL command line.
  • That was enough to get things going, but I hit a couple of compiler warnings, which stopped the build from working, as described here.
  • Potentially I could work around those issues by either changing the compiler flags so it's more tolerant of warnings, or fixing up the cpp code. But it seemed odd that I should have to do either of these. At this point I paused & looked at a 2nd option.
  1. Migrating to physx-js-webidl

This is used by PHY, a Physics library for Three.js that I've been looking at.

Benefits of using this WASM build include:

  • it's already updated tp use PhysX 5.1
  • it seems to aleady expose more of the API (e.g. projection tolerance settings above).

I've been making some changes on this branch to try to get this working. Unfortunately it's not staightforward.

The way the PhysX CPP API gets translated into a JS API is quite different for this alternative build.

Working through the differences has basically been a matter of:

  • running examples to see what errors are hit
  • comparing bindings defined for the perviosu version of PhysX here with the web IDL bindings here
  • making updates & testing again.

If made a bunch of fixes & hit a number of errors, but still hitting problems inside the physics simulation:

physx-js-webidl.wasm:0x11b817 Uncaught RuntimeError: null function or function signature mismatch
    at physx-js-webidl.wasm:0x11b817
    at physx-js-webidl.wasm:0x11bc19
    at physx-js-webidl.wasm:0x9ff13
    at eval (physx-js-webidl.js:969:22)
    at PxScene.simulate.PxScene.simulate (physx-js-webidl.js:30889:50)
    at i.tock (physics.js:746:16)
    at bind.js:12:17
    at i.tock (index.js:127:7)
    at v.tock (a-scene.js:724:36)
    at e.object3D.onAfterRender (a-scene.js:52:34)

Presumably something has been initialized incorrectly due to the change in API, but it's not straightforward to find out what.

I'm wrapping up this investigation for now. While I had wanted to experiment with projection of Fixed Joints, I only thought there was a small chance of it solving my problems, and think a better solution is likely to be by following the advice in the API docs and use a single actor with multiple shapes...

Note All joints are enforced by the dynamics solver, so although under ideal conditions the objects will maintain their spatial relationship, there may be some drift. A common alternative, which is cheaper to simulate and does not suffer from drift, is to construct a single actor with multiple shapes. However fixed joints are useful, for example, when a joint must be breakable or report its constraint force.

Nevertheless, it's likely that we'll want to extend the exposed parts of the PhysX API and/or move to 5.1+ at some point, so with that in mind, I've documented my investigations so far here.

@kfarr
Copy link

kfarr commented May 9, 2023

Wow thanks for this writeup and sharing this repo! https://github.com/fabmax/physx-js-webidl

  • I notice webidl bindings include vehicles :)
  • For the error at eval (physx-js-webidl.js:969:22) I notice that js file is minimized, is it possible to see the context of the error in a non-minified version?
  • Another approach could be to step through the logic in this js example: https://github.com/fabmax/physx-js-webidl/blob/main/dist/helloworld.html and see if there are any obvious steps missing?

@enzofrancescaHM
Copy link

Sorry to write on this thread 1 year after last communications, but it would be nice to have Physx migrated to physx-js-webidl because it have support for vehicles and this is a big point, useful for a-frame + physx.
So, just a manifestation of interest!

@vincentfretin
Copy link
Member

vincentfretin commented Feb 22, 2025

I got it to build with the trzeci/emscripten:1.39.5-upstream docker image, without your commit

git clone [email protected]:ashconnell/physx-js.git
cd physx-js
#git clone -b emscripten_wip [email protected]:prestomation/PhysX.git
git clone -b emscripten_wip [email protected]:zach-capalbo/PhysX.git
cd PhysX
# rebase to ashconnell/PhysX? https://github.com/zach-capalbo/PhysX/compare/emscripten_wip...ashconnell%3APhysX%3Aemscripten_wip
git remote add nvidia [email protected]:NVIDIAGameWorks/PhysX.git
git fetch nvidia
git rebase nvidia/4.1
# fix the conflict in physx/source/geomutils/src/gjk/GuGJKType.h search for HEAD and keep the 2nd line
git add physx/source/geomutils/src/gjk/GuGJKType.h
git rebase --continue
git remote add diarmidmackenzie [email protected]:diarmidmackenzie/PhysX-1.git
git fetch diarmidmackenzie
#git cherry-pick 95391dccde94bc11829c615da76d9c6a63346295 # https://github.com/zach-capalbo/PhysX/compare/emscripten_wip...diarmidmackenzie:PhysX-1:joint-projection
cd ..
sed -i -e 's|trzeci/emscripten |trzeci/emscripten:1.39.5-upstream |' package.json
npm run generate
mkdir dist
npm run make
cp dist/physx.release.js ../physx/src/physx.release.js 
cp dist/physx.release.wasm ../physx/wasm/physx.release.wasm

With your commit I got an error:

[100%] Building CXX object sdk_source_bin/CMakeFiles/PhysXWebBindings.dir/src/PhysX/physx/source/physxwebbindings/src/PxWebBindings.cpp.o
/src/PhysX/physx/source/physxwebbindings/src/PxWebBindings.cpp:344:59: error: no member named 'setProjectionLinearTolerance' in 'physx::PxJoint'
      .function("setProjectionLinearTolerance", &PxJoint::setProjectionLinearTolerance)
                                                 ~~~~~~~~~^
/src/PhysX/physx/source/physxwebbindings/src/PxWebBindings.cpp:345:60: error: no member named 'setProjectionAngularTolerance' in 'physx::PxJoint'
      .function("setProjectionAngularTolerance", &PxJoint::setProjectionAngularTolerance)
                                                  ~~~~~~~~~^
2 errors generated.

Without your commit:

cd ../physx
npm run dist
npm run dev

http://localhost:8080/examples/basic/

Uncaught (in promise) RuntimeError: abort(LinkError: WebAssembly.instantiate(): Import #48 "env" "memory": memory import has no maximum limit, expected at most 4294967295) at Error

@vincentfretin
Copy link
Member

Comparing the current and new physx.release.js, it seems that the current physx.release.js we have was build with a later version than emscripten:1.39.5, it's using the newer INITIAL_MEMORY instead of the deprecated TOTAL_MEMORY
So that was a version between 1.39.5 and 1.39.18 https://hub.docker.com/r/trzeci/emscripten/tags

Image

@vincentfretin
Copy link
Member

vincentfretin commented Feb 23, 2025

I'm still testing some versions. I tested also with the official docker image -e EMSCRIPTEN=/emsdk/upstream/emscripten emscripten/emsdk:3.1.x in package.json
and those patches

diff --git a/generate.sh b/generate.sh
index 0e39d36..268cf84 100755
--- a/generate.sh
+++ b/generate.sh
@@ -1,4 +1,7 @@
 #!/bin/bash
 
 cd ./PhysX/physx
-./generate_projects.sh emscripten
\ No newline at end of file
+apt-get update
+apt-get -y install python3
+ln -s /usr/bin/python3 /usr/bin/python
+./generate_projects.sh emscripten
diff --git a/make.sh b/make.sh
index 993710a..dbd2f4e 100755
--- a/make.sh
+++ b/make.sh
@@ -1,7 +1,8 @@
 #!/bin/bash
+set -e
 
 cd PhysX/physx/compiler/emscripten-release/
 make
-mkdir -p /src/lib
+mkdir -p /src/dist
 cp /src/PhysX/physx/bin/emscripten/release/physx.release.js /src/dist/physx.release.js
 cp /src/PhysX/physx/bin/emscripten/release/physx.release.wasm /src/dist/physx.release.wasm

The latest version of emscripten / clang is more strict with the cpp code, instead of fixing the cpp code, I ended up adding a bunch of flags
-Wno-dtor-name -Wno-suggest-override -Wno-suggest-destructor-override -Wno-tautological-value-range-compare -Wno-deprecated-copy-dtor -Wno-deprecated-copy -Wno-unsafe-buffer-usage -Wno-unsafe-buffer-usage-in-libc-call -Wno-reserved-identifier -Wno-missing-include-dirs -Wno-invalid-offsetof -Wno-bitwise-instead-of-logical -Wno-switch-default -Wno-unused-but-set-variable -Wno-unaligned-access
to physx/source/compiler/cmake/emscripten/CMakeLists.txt
The PhysX code compiles but the final emscripten step for the bindings fails.

I'm trying old emscripten versions with the deprecated trzeci/emscripten image and first trying to reproduce the build we currently have. To reproduce the memory maximum, I had to set -s MAXIMUM_MEMORY=2GB (edit: that was needed only for 1.39.11, not needed for 1.39.12-1.39.18) in physx/source/compiler/cmake/emscripten/PhysXWebBindings.cmake
full line:
SET(EMSCRIPTEN_BASE_OPTIONS "--bind -s MODULARIZE=1 -s EXPORT_NAME=PHYSX -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=2GB")
but still getting Uncaught (in promise) RuntimeError: null function or function signature mismatch error when the wasm is loaded so I'm thinking there is an issue in the binding code, and I'm not sure from what commit the current build we have came from.

@vincentfretin
Copy link
Member

Zachary definitely used at least trzeci/emscripten:1.39.17-upstream because we have that change
emscripten-core/emscripten@6f98f6a
in the current build that was introduced in 1.39.17. The latest from deprecated image is 1.39.18-upstream and has the same output for the js file.
But even that version we have the PX_UNUSED(hitsSpaceLeft) error.
I think he just added the flags to silence the errors or just simply removed -Wall from the list that treats warnings as errors.
But unfortunately I still get "RuntimeError: null function or function signature mismatch" even with original branch https://github.com/zach-capalbo/PhysX/commits/emscripten_wip/ without rebasing from nvidia 4.1 branch.

@vincentfretin
Copy link
Member

vincentfretin commented Feb 23, 2025

Oh! With https://github.com/zach-capalbo/PhysX/commits/emscripten_wip/ without the last commit TriMesh bindings, it works!
And src/physx.release.js is exactly the same, so I confirm the current build was done with trzeci/emscripten:1.39.18-upstream
without -Werror in physx/source/compiler/cmake/emscripten/CMakeLists.txt and without the last commit from Zach's emscripten_wip branch.

@vincentfretin
Copy link
Member

vincentfretin commented Feb 23, 2025

Rebasing from nvidia 4.1 branch also produces "Uncaught (in promise) RuntimeError: null function or function signature mismatch" so I gave up on that rebase.

I forked the two repos in c-frame
https://github.com/c-frame/physx-js
https://github.com/c-frame/PhysXSDK
and made those changes to have a reproducible build
https://github.com/c-frame/PhysXSDK/commits?author=vincentfretin&since=2025-01-23&until=2025-02-28
https://github.com/c-frame/physx-js/commits?author=vincentfretin&since=2025-01-23&until=2025-02-28
You can try again your changes @diarmidmackenzie if you want.

@vincentfretin
Copy link
Member

vincentfretin commented Feb 24, 2025

If you're testing locally a build, be sure to put back in src/physics.js
wasmUrl: {default: "/wasm/physx.release.wasm"},
instead of
wasmUrl: {default: "https://cdn.jsdelivr.net/gh/c-frame/physx/wasm/physx.release.wasm"},
and run npm run dist

I was testing with the wasm file from the cdn this whole time. No wonder that I got the "Uncaught (in promise) RuntimeError: null function or function signature mismatch" error. TT

@vincentfretin
Copy link
Member

Okay so the latest commit from Zach about TriMesh bindings is actually working. I force pushed the branch to revert my revert. I merged the nvidia 4.1 branch so we get the 4.1.2 changes https://nvidiagameworks.github.io/PhysX/4.1/release_notes.html and I exposed joint limit and projection tolerances in c-frame/PhysXSDK@0f6fa8b
I will try now to use the limit for the revolute and prismatic joints, that's what I'm interested in.

@vincentfretin
Copy link
Member

FYI setProjectionLinearTolerance/setProjectionAngularTolerance are not on the base class PxJoint, but on each joint that supports it. That's why your commit didn't compile.

Image

@enzofrancescaHM
Copy link

Impressive, @vincentfretin. As I stated in my previous message my interest is on exposing vehicle bindings for using in A-Frame. If I can help in some way, here I am.

@vincentfretin
Copy link
Member

@enzofrancescaHM feel free to experiment exposing the bindings for that now that we have a working process to build the wasm file. Note that the vehicle api changed completely in PhysX 5.x so it may not be worth it to spend time on that with the current 4.1.2 version we use. See https://nvidia-omniverse.github.io/PhysX/physx/5.5.1/docs/MigrationTo51.html#vehicles
My current scope is to make the revolute and prismatic constraints work for a customer project.
For vehicles I think we should try to use the physx-js-webidl bindings like @diarmidmackenzie explored.

For ammo, I did https://github.com/c-frame/aframe-racing-game to test vehicles controls if you didn't see it.

@vincentfretin
Copy link
Member

Yeah I got the angular limit for Revolute constraint working (for the door).

@vincentfretin
Copy link
Member

I need a second pair of eyes about the api here #25

@enzofrancescaHM
Copy link

@enzofrancescaHM feel free to experiment exposing the bindings for that now that we have a working process to build the wasm file. Note that the vehicle api changed completely in PhysX 5.x so it may not be worth it to spend time on that with the current 4.1.2 version we use. See https://nvidia-omniverse.github.io/PhysX/physx/5.5.1/docs/MigrationTo51.html#vehicles My current scope is to make the revolute and prismatic constraints work for a customer project. For vehicles I think we should try to use the physx-js-webidl bindings like @diarmidmackenzie explored.

For ammo, I did https://github.com/c-frame/aframe-racing-game to test vehicles controls if you didn't see it.

yeah, I played with ammo extensively in the past, you can watch a little experiment here: https://www.youtube.com/watch?v=W6zhs0Gzy1U

@enzofrancescaHM
Copy link

I need a second pair of eyes about the api here #25

perfect, I've I'll give it a look today and test the joints

@vincentfretin
Copy link
Member

If you're testing locally a build, be sure to put back in src/physics.js wasmUrl: {default: "/wasm/physx.release.wasm"}, instead of wasmUrl: {default: "https://cdn.jsdelivr.net/gh/c-frame/physx/wasm/physx.release.wasm"}, and run npm run dist

I was testing with the wasm file from the cdn this whole time. No wonder that I got the "Uncaught (in promise) RuntimeError: null function or function signature mismatch" error. TT

If fixed this in #26 you just need to run npm run dev now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants