dimforge / rapier.js

Official JavaScript bindings for the Rapier physics engine.
https://rapier.rs
Apache License 2.0
412 stars 57 forks source link

"Getting Started" docs won't get you started #20

Closed viridia closed 3 years ago

viridia commented 3 years ago

So, the docs leave a lot out - in particular, simply importing the rapier3d from npm isn't going to work without configuring your bundler (webpack, rollup, etc.) to handle wasm files. I've spent a couple hours trying to get it to work with snowpack - it kept complaining that the .wasm file was not a JavaScript file; switched over to webpack and got a similar error. Then I tried installing wasm-loader, but that doesn't work either - I get _rapier_wasm3d_bg_wasm__WEBPACK_IMPORTED_MODULE_0__.rawintegrationparameters_new is not a function. I'm guessing that I need to find a different loader, but I have no idea which loader I should use.

viridia commented 3 years ago

A somewhat related issue is that ForkTsCheckerWebpackPlugin is giving me a ton of errors like this:

ERROR in ../../node_modules/@dimforge/rapier3d/pipeline/world.ts:514:20
TS7051: Parameter has a name but no type. Did you mean 'arg0: ColliderHandle'?
    512 |         point: Vector,
    513 |         groups: InteractionGroups,
  > 514 |         callback: (ColliderHandle) => boolean,
        |                    ^^^^^^^^^^^^^^
    515 |     ) {
    516 |         this.queryPipeline.intersectionsWithPoint(this.colliders, point, groups, callback);
    517 |     }

Looking inside node_modules/@dimforge/rapier3d I notice a few things: First, the .js and .ts file are mixed together in the same directory; normally for these kinds of projects the compiled output (.js and .d.ts files) get located in a dist subdirectory or some such, which the package.json points to. I'm guessing that the checker is seeing both .ts and .js files, and picking the .ts ones preferentially.

And then the .ts files (I presume these were generated by emscripten or some tool) don't seem to be valid TypeScript.

The obvious solution would be to tell TypeScript to ignore the .ts files and look at only the .js ones, but despite hammering at the tsconfig include/exclude config options for about 30 minutes I can't seem to get it to ignore those files. Babel doesn't complain (it wouldn't anyway), but the type checker doesn't like it.

However, if the .ts and .js files were segregated in separate dirs, it wouldn't matter - apps that import would always use the .js and ignore the .ts. This is generally what you want anyway, since there's no guarantee that the application will be running with the same tsconfig dialect options that were used in the library - if, for example, the app enables strict null checks, but the library files are written without those checks, it's never going to compile.

LeXXik commented 3 years ago

Webpack 5 has issues with loading Wasm files. Until then you can use Webpack 4, like in the testbed example: https://github.com/dimforge/rapier.js/tree/master/testbed3d

Another option is to use @dimforge/rapier-compat, which has the Wasm injected as a string to avoid the Wasm loading issue, but also increases its size because of it (probably preferred option today).

Another option is to instantiate the Wasm manually and pass the compiled module to the init method of the glue JS file (this will require to change the build target and modify the glue flle, though).

viridia commented 3 years ago

The latter option is the most attractive to me, as it would allow me to go back to using snowpack (as suggested here) - would you perhaps have a code snippet that I could use as a starting point? I'm fairly new to wasm :)

viridia commented 3 years ago

I went ahead and tried installing rapier3d-compat. Now what I see in the JS console is:

Uncaught (in promise) TypeError: Cannot read property 'rawintegrationparameters_new' of undefined
    at new Z (rapier.js:1)
    at new A (rapier.js:1)
    at new A (rapier.js:1)
    at eval (PhysicsWorld.ts:34)

I couldn't find any docs for the rapier3d-compat package, I presume it's initialized the same way as rapier3d? I'm calling:

    import('@dimforge/rapier3d-compat').then(RAPIER => {
      const gravity = new RAPIER.Vector3(0.0, -9.81, 0.0);
      this.#world = new RAPIER.World(gravity);
    });
sebcrozet commented 3 years ago

@viridia I added some information to the "Getting started" docs regarding rapier3d-compat. You will find an example on CopdePen (it's similar in 3D). The trick is to await the RAPIER.init() future.

import RAPIER from 'https://cdn.skypack.dev/@dimforge/rapier3d-compat';

RAPIER.init().then(() => {
    // Run the simulation.
});
viridia commented 3 years ago

OK thanks, I got it working.