Using Recast.js via NPM package import

Hi. I’m trying to reproduce this example Babylon.js Playground in my Nuxt (Vue) environment. It works correctly if I include Recast library via <script src="https://preview.babylonjs.com/recast.js"></script>

But I’d like to use import for that. So I’ve installed recast npm package but cannot bind BABYLON.RecastJSPlugin with that. Please pay attention to line 24

Sandbox: CodeSandbox

I also tried to use recast-detour but there is an another issue with that

This dependency was not found:

  • fs in ./node_modules/recast-detour/recast.js

The raycast plugin constructor accepts a different version of recast other than the one populated in the global namespace. you will need to pass the imported recast package to the constructor

I tried to pass it to the plugin:

let navigationPlugin = new BABYLON.RecastJSPlugin(recast);

But it returns an error:

this.bjsRECAST.Vec3 is not a constructor

Could you explain how I can do it properly?

you should probably import react from 'react' and not * as reacst. I can’t seem to be able to edit the demo you sent, so I can’t play around with it. just make sure recast is a container.

import react from ‘react’

I guess you meant recast (not react).

To edit this sandbox you need to be logged in to make ability clone it.
I would use BabylonJS sandbox but it already uses Recast.

Updated: CodeSandbox

That’s not the right reacst import - https://www.npmjs.com/package/recast

You want this - recastjs - npm

Tried many variants but still no luck.
I have installed recastjs (+recast, the first one requires it).
But even only with one requiring string it fails.
A new sandbox: CodeSandbox

ERROR in ./node_modules/recastjs/lib/recast.js
Module not found: Error: Can’t resolve ‘fs’ in ‘/sandbox/node_modules/recastjs/lib’

I tried to fix it via Nuxt configuration. If you uncomment lines in nuxt.config.js this error will gone. But the next one will appear :neutral_face:

Cannot read property ‘match’ of undefined

Also I found that it happens because of checking process.platform in that recast library.

I have no clue how to use it. Docs says https://github.com/vincent/recast.js/tree/master/getting-started that we can use node version or browser. I am going to run my code only in browser. But I need to merge all the code into one dist file. That’s why I am trying to use node version.

There is sometimes little we can do about it, especially when it comes to external dependencies.
You might want to build recast yourself without the external dependencies, or make sure the fs package is somehow mocked. I am sorry that I cannot be of any help.

We do provide recast as a compiled library that uses the global namespace. I know it’s frowned upon, but there are certain edge cases (i think you found one), where it would make sense to use those packages as they are.

I would recommend talking to recast about it, maybe submit an issue there.

Hi @Cocojambo

I encountered the error as well after I upgraded babylon version.

this.bjsRECAST.Vec3 is not a constructor

I used to only need this line before creating the RecastJSPlugin instance.

window.Recast = require('recast-detour');

After upgrading babylon version, I had the error above. Now I need to do the following to fix the error.

window.Recast = require('recast-detour');
window.Recast();
3 Likes

Hey,

Had a hard time here too, but I finally succeed. My project is based on this template GitHub - RaananW/babylonjs-webpack-es6: Babylon.js basic scene with typescript, webpack, es6 modules, editorconfig, eslint, hot loading and more. Will even make coffee if you ask nicely..

npm install recast-detour

In src/externalFileTypes.d.ts add the line declare module “recast-detour”;

Create a file src/externals/recast.ts

import * as Recast from 'recast-detour';

export let recastModule: any;
export const recastReadyPromise = new Promise((resolve) => {
    new Recast().then((res: unknown) => {
        recastModule = res;
        resolve(res);
    });
});

Then

import * as Recast from 'recast-detour';

this.recast = await new Recast();


this.recastPlugin = new RecastJSPlugin(this.recast);

Hope that help!

2 Likes

Awesome! do you want to add an example to the template repository so others can benefit from it? i’d be happy to accept a PR for that!!

1 Like

I’ll try in the next days, thanks for the opportunity!

3 Likes

Can’t even compile my TS code that using recast-detour :grinning:

ERROR in ../../../node_modules/recast-detour/recast.js 9:4815-4828
Module not found: Error: Can't resolve 'fs' in '/home/user/node/node_modules/recast-detour'
resolve 'fs' in '/home/user/node/node_modules/recast-detour'
  Parsed request is a module
    using description file: /home/user/node/node_modules/recast-detour/package.json (relative path: .)
    Field 'browser' doesn't contain a valid alias configuration
    resolve as module
      /home/user/node/node_modules/recast-detour/node_modules doesn't exist or is not a directory
      /home/user/node/node_modules/node_modules doesn't exist or is not a directory
      looking for modules in /home/user/node/node_modules
        single file module
          using description file: /home/user/node/package.json (relative path: ./node_modules/fs)
            no extension
              Field 'browser' doesn't contain a valid alias configuration
              /home/user/node/node_modules/fs doesn't exist
            .ts
              Field 'browser' doesn't contain a valid alias configuration
              /home/user/node/node_modules/fs.ts doesn't exist
            .tsx
              Field 'browser' doesn't contain a valid alias configuration
              /home/user/node/node_modules/fs.tsx doesn't exist
            .js
              Field 'browser' doesn't contain a valid alias configuration
              /home/user/node/node_modules/fs.js doesn't exist
        /home/user/node/node_modules/fs doesn't exist
      /home/user/node/node_modules doesn't exist or is not a directory
      /home/user/node/node_modules doesn't exist or is not a directory
      /home/node_modules doesn't exist or is not a directory
      /node_modules doesn't exist or is not a directory

cc @RaananW

Ok, the first issue was fixed with changing:

webpack5 config
	resolve: {
		fallback: {
			fs: false, //!!! Not "empty"! as it was in webpack4
			browser: false,
		},
	},

It’s strange but now I have “File: …/node_modules/recast-detour/raycast.d.ts is not a module” on line:

import * as Recast from "recast-detour";

Tried to solve with:

webidl2ts -i  https://raw.githubusercontent.com/BabylonJS/Extensions/master/recastjs/recast.idl  -o recast.d.ts

it gives me an error message:

Error message
WebIDLParseError: Syntax error at line 23, since `interface rcConfig`:
    attribute float[] bmin; 
                   ^ Attribute lacks a name
    at Tokeniser.error (/home/denis/.local/lib/node_modules/webidl2ts/node_modules/webidl2/dist/webidl2.js:1:19433)
    at parse (/home/denis/.local/lib/node_modules/webidl2ts/node_modules/webidl2/dist/webidl2.js:1:13800)
    at Function.parse (/home/denis/.local/lib/node_modules/webidl2ts/node_modules/webidl2/dist/webidl2.js:1:23168)
    at Function.parse (/home/denis/.local/lib/node_modules/webidl2ts/node_modules/webidl2/dist/webidl2.js:1:26441)
    at i (/home/denis/.local/lib/node_modules/webidl2ts/node_modules/webidl2/dist/webidl2.js:1:32064)
    at o (/home/denis/.local/lib/node_modules/webidl2ts/node_modules/webidl2/dist/webidl2.js:1:32259)
    at /home/denis/.local/lib/node_modules/webidl2ts/node_modules/webidl2/dist/webidl2.js:1:32622
    at B (/home/denis/.local/lib/node_modules/webidl2ts/node_modules/webidl2/dist/webidl2.js:1:32754)
    at Module.F (/home/denis/.local/lib/node_modules/webidl2ts/node_modules/webidl2/dist/webidl2.js:1:32915)
    at Object.<anonymous> (/home/denis/.local/lib/node_modules/webidl2ts/dist/parse-idl.js:47:43) {
  bareMessage: 'Attribute lacks a name',
  context: 'Syntax error at line 23, since `interface rcConfig`:\n' +
    '    attribute float[] bmin; \n' +
    '                   ^',
  line: 23,
  sourceName: undefined,
  input: '[] bmin; \n' +
    '\n' +
    "    /// The maximum bounds of the field's AABB. [(x, y, z)] [Units: wu]\n" +
    '    attribute',
  tokens: [
    { type: '[', value: '[', trivia: '', line: 23, index: 34 },
    { type: ']', value: ']', trivia: '', line: 23, index: 35 },
    {

...
Node.js v17.0.1

@Cedric, don’t you know what’s wrong with my webidl2ts attempt?

In my browser I have: Uncaught (in promise) TypeError: Recast is not a constructor because I don’t know how to include Recast in my final js-bundle :grinning:
In TS I use

the following code
import * as Recast from "recast-detour"; 
//<-- I removed recast.d.ts for now to flush the error "is not a module"
import { RecastJSPlugin } from '@babylonjs/core';

( async () => {
	const recast = await new Recast();
	const navigationPlugin = new RecastJSPlugin( recast );
	navigationPlugin.setWorkerURL( "workers/navMeshWorker.js" );
} ) ();

well might be I’m having this problem because of removing recast.d.ts so it not imports into a final js bundle :grinning:

If I manually download recast.js and include it as a script in my HTML file, I get this error:

Uncaught (in promise) TypeError: this.bjsRECAST.Vec3 is not a constructor

We will need to see how the package is built and what can be done to improve this.

Can you share a reproduction of your issue? since I can see others are using it correctly.

Well, I didn’t build it by my own. Tried to build it but emspripten can’t locate my libsdl2-dev installation when it’s installed successfully and SDL2_LIBRARY, SDL2_INCLUDE_DIR points to correct places.

My first case of trying to get recast to work.
$ npm i recast-detour

TS:

import * as Recast from "recast-detour"; // File '...../node_modules/recast-detour/recast.d.ts' is not a module.

Trying to fix this:

webidl2ts -i  https://raw.githubusercontent.com/BabylonJS/Extensions/master/recastjs/recast.idl  -o recast.d.ts
error message
WebIDLParseError: Syntax error at line 23, since `interface rcConfig`:
    attribute float[] bmin; 
                   ^ Attribute lacks a name
    at Tokeniser.error (/home/denis/.local/lib/node_modules/webidl2ts/node_modules/webidl2/dist/webidl2.js:1:19433)
    at parse (/home/denis/.local/lib/node_modules/webidl2ts/node_modules/webidl2/dist/webidl2.js:1:13800)
    at Function.parse (/home/denis/.local/lib/node_modules/webidl2ts/node_modules/webidl2/dist/webidl2.js:1:23168)
    at Function.parse (/home/denis/.local/lib/node_modules/webidl2ts/node_modules/webidl2/dist/webidl2.js:1:26441)
    at i (/home/denis/.local/lib/node_modules/webidl2ts/node_modules/webidl2/dist/webidl2.js:1:32064)
    at o (/home/denis/.local/lib/node_modules/webidl2ts/node_modules/webidl2/dist/webidl2.js:1:32259)
    at /home/denis/.local/lib/node_modules/webidl2ts/node_modules/webidl2/dist/webidl2.js:1:32622
    at B (/home/denis/.local/lib/node_modules/webidl2ts/node_modules/webidl2/dist/webidl2.js:1:32754)
    at Module.F (/home/denis/.local/lib/node_modules/webidl2ts/node_modules/webidl2/dist/webidl2.js:1:32915)
    at Object.<anonymous> (/home/denis/.local/lib/node_modules/webidl2ts/dist/parse-idl.js:47:43) {
  bareMessage: 'Attribute lacks a name',
  context: 'Syntax error at line 23, since `interface rcConfig`:\n' +
    '    attribute float[] bmin; \n' +
    '                   ^',
  line: 23,
  sourceName: undefined,
  input: '[] bmin; \n' +
    '\n' +
    "    /// The maximum bounds of the field's AABB. [(x, y, z)] [Units: wu]\n" +
    '    attribute',
  tokens: [
    { type: '[', value: '[', trivia: '', line: 23, index: 34 },
    { type: ']', value: ']', trivia: '', line: 23, index: 35 },
    {

...
Node.js v17.0.1

So it’s not an option.


My second case of trying to get recast to work.
TS
import { RecastJSPlugin } from "@babylonjs/core/Navigation/Plugins/recastJSPlugin";
declare const Recast: any;
...
	( async () => {
		// const recast = await new Recast();
		const recast = new Recast();
		const navigationPlugin = new RecastJSPlugin( recast );
		navigationPlugin.setWorkerURL( "libs/navMeshWorker.js" );
	} ) ();

Copying recast.js to my local project’s folder:

$ cp .../node_modules/recast-detour/recast.js .../my_project/build/libs/recast.js
$ wget "https://raw.githubusercontent.com/BabylonJS/Babylon.js/master/packages/tools/playground/public/workers/navMeshWorker.js" -O .../my_project/build/libs/navMeshWorker.js
HTML
<script src="libs/recast.js"></script>
<script src="webpacked_bundle.js"></script>
Error in browser console
index.js:96949 Uncaught (in promise) TypeError: this.bjsRECAST.Vec3 is not a constructor
    at new RecastJSPlugin

I didn’t say you built it on your own :slight_smile:
I just said we will need to see how it is built so we can understand what the issue is. @Cedric can help here for sure. We have a task to move those packages to the babylon org and on the way also make the es6 friendly. But that shouldn’t cause the issue you are experiencing.

1 Like

Wow that would be really great deal!

will still be happy to see a reproduction to understand what’s going on in your case