Need help with including Dynamic Terrain extension. TypeError DynamicTerrain is not a constructor

Hi guys!

I’ve started using BabylonJS recently, and I’d like to make a game with server side generated procedural terrain.
So I’ve found the DynamicTerrain extension, which is exactly what I’m looking for.
The problem is, that I can’t seem to figure out how to use it.

I’m using Typescript and Webpack.
I’ve downloaded the babylon.dynamicTerrain.d.ts, babylon.dynamicTerrain.js, babylon.dynamicTerrain.mins.js and copied them to my src folder.

index.ts:
import { Scene, Engine, Vector3, UniversalCamera, DynamicTerrain } from ‘babylonjs’;


const terrain = new DynamicTerrain(“terrain”, mapParams, scene);

When I try to instantiate DynamicTerrain I get the following exception (in runtime):
Uncaught TypeError: babylonjs_1.DynamicTerrain is not a constructor.

Any help is much appreciated.

try
const terrain = new BABYLON.DynamicTerrain(foo, barr)
this should solve the issue

It’s probably not imported as a BJS module

1 Like

Thanks for the quick answer, but unfortunately it didn’t solve the issue.

Uncaught TypeError: BABYLON.DynamicTerrain is not a constructor

Update:
I’m using VS Code by the way.
Tried with 4.0.0-alpha.29 (I’ve previously used 3.3.0) but with no success.
If I import BABYLON from babylonjs, DynamicTerrain class can not be found.
If I import the classes individually (import { Engine, Scene, … } from ‘babylonjs’; ) then VS Code doesn’t show error on the line: new BABYLON.DynamicTerrain, but I can only give it a scene instance from BABYLON.Scene and not the individually imported Scene instance. (Argument of type ‘import(“babylonjs/scene”).Scene’ is not assignable to parameter of type ‘BABYLON.Scene’.)

My guess is that somehow DynamicTerrain is conflicting with BabylonJS.

I’m using npm to install babylonjs, but just simply copying DynamicTerrain to my src folder.

I don’t really know how the module importation process works. Something is probably missing in the DynamicTerrain extension so it can run as an imported module.
If someone knows, please …

Is that the same thing that is happening with my stl serializer maybe?

Nope as the DynamicTerrain is not a module of the main core engine.

@Attila_Lorincz: You cannot import the DynamicTerrain like regular babylon.js code as it is not a module.

You have to use regular JS code importation like:

var DynamicTerrain = require("dynamicTerrain.js")

Now another issue emerges.
“babylon.dynamicTerrain.js:1389 Uncaught TypeError: Cannot read property ‘Zero’ of undefined
at eval (babylon.dynamicTerrain.js:1389)
at eval (babylon.dynamicTerrain.js:1408)
at eval (babylon.dynamicTerrain.js:1410)
at Object…/src/extensions/babylon.dynamicTerrain.js (main.f598f66dac1254eb409b.js:426)
at webpack_require (main.f598f66dac1254eb409b.js:20)
at eval (index.ts:6)
at Object…/src/index.ts (main.f598f66dac1254eb409b.js:438)
at webpack_require (main.f598f66dac1254eb409b.js:20)
at main.f598f66dac1254eb409b.js:84
at main.f598f66dac1254eb409b.js:87”

mentioned code:
DynamicTerrain._vertex = {
position: BABYLON.Vector3.Zero(), <- here
uvs: BABYLON.Vector2.Zero(),

I’m sure I’m doing something entirely wrong.
If you could provide me an example.ts file with tsconfig and webpack config I would appreciate it very much.

well you can check the Inspector for instance which is a react project using bjs:

I guess the word “BABYLON.” used in the DynamicTerrain code is the problem regarding all the module system.

The DynamicTerrain extension was created at the time when we used BJS only in the browser, directly downloaded with a html tag.
Probably something should be fixed or rewritten in the code so it could become compliant to the module system. As I don’t know the module system yet, I don’t know for now what should be done :frowning:

Two solutions here:

  1. Rewrite the code of terrain and others to make use of modules. This would mean to webpack it and so on.
  2. Do not use anything from modules by configuring your webpack code to rely on BABYLON as a var by relying on ProvidePlugin | webpack

I guess 2. is a good quick workaround. 1. would require more work and tooling to be changed.

Thank you, I like the idea of the 2.
But I can’t manage to make it work.
Bear with me, I’m kinda new to js\ts.

I’ve got this in my webpack.config.js:

new webpack.ProvidePlugin({
BABYLON: “babylonjs”
})

And in my index.d.ts:

var BABYLON: any;

But at this line:

let scene: BABYLON.Scene;

I get the following error: Cannot find namespace ‘BABYLON’.

This seems so entirely trivial to everybody that no one provides a good example anywhere as to how to do it properly.

Could you explain it for me a little more in detail, please?

You can add the babylon typings as part of your code by adding this in your ts config:

types: [“babylonjs”] as described here: NPM - Babylon.js Documentation

So you would not need the var BABYLON: any; anymore.

If I include babylon-js materials in ts.config types, I get the following error:
Cannot find type definition file for ‘bablonyjs-materials’.

But anyway, managed to make the base engine + babylonjs materials work the following way:

webpack.config.js:

    new webpack.ProvidePlugin({
        BABYLON: 'babylonjs',
      }),

index.ts:

import ‘babylonjs-materials’;

Now how do I add DynamicTerrain to this?
I have added the type definition by copying the d.ts file to the src folder, and adding it to typeroots.

 "typeRoots": ["node_modules/@types", "./extensions"],

How do I include it with webpack provide plugin?
What name should I use?
Anything I try just gives me the same “e.DynamicTerrain is not a constructor”

I have also tried adding the script as an HTML element to index.html head, but that throws the “can not get .Zero of undefined” error which is mentioned above.

This really shouldn’t be this hard

It is hard because you are mixing none module code and module code so it involves a bit of config. There are several ways to solve the issue in the config. Let me detail one:

  1. Use ProvidePlugin to expose BABYLON as a global:
plugins: [
    new webpack.ProvidePlugin({
        'BABYLON': 'babylonjs'
    })
]
  1. Force the terrain script to consider BABYLON from the module babylonjs:
module: {
    rules: [{
        test: /\.tsx?$/,
        loader: 'ts-loader'
    }, {
        test: /\dynamicTerrain.js\.js$/,
        use: [ 'imports-loader?BABYLON=>require("babylonjs")' ]
    }]
},

Please not it require the imports-loader package: npm install imports-loader --save-dev
3. In your ts file where you need to use Babylon and the Material, reference their typings:

/// <reference types="babylonjs"/>
/// <reference path="./externals/babylon.dynamicTerrain.d.ts"/>
  1. Import the dynamic terrain for side effects:
import "./externals/babylon.dynamicTerrain.js";
  1. You can now use both of then in the ts file with typings.

Find attached an ultra quick sample, forumBug.zip (21.0 KB) To run it, unzip,
npm install then npm run start the ideal would be to make the extension a proper npm package to prevent some of those issues.

This is still not ideal as we are relying here on namespace typings vs module but it should be ok.

The code comes from the default example in the terrain documentation.

2 Likes

Thank you very much. I could make it work. Special thanks for the little example project.

I’ve added Angular to the project, so it took me some time to configure it’s internal hidden webpack, but it works now.
So many hours of frustration…

Big thanks again. :grinning:

hi,
are there plans to create the needed npm package in the near future?
best wishes,
barbara

I don’t think @jerome has such plans

Indeed… I have to retire from the project for a while.
But any volunteer to do it is welcome :slight_smile:

1 Like