How to create an 'empty' mesh in a class constructor

I’m using Javascript (actually Typescript) classes to create my objects, that can have several Babylon child objects.

To have my IDE (VSCode) not give errors/warnings all the time, when I create a class property that is a Babylon type, I need to already create it in the constructor, although I have a special init method as well, that is called to create the actual object the right way.

For example (simplified), I have a class like:

export class Person extends BABYLON.Mesh {

  public head: BABYLON.Mesh;
  public body: BABYLON.Mesh;

  public size: number = 10;

  constructor(name: string, scene: BABYLON.Scene) {
    super(name, scene);

    this.head = new BABYLON.MeshBuilder.CreateSphere('', scene);
    this.body = new BABYLON.MeshBuilder.CreateBox('', scene);
  }

  public init(size: number = 10) {
    this.size = size;

    this.head.dispose();
    this.head = BABYLON.MeshBuilder.CreateSphere('head', { diameter: this.size / 2 }, this.scene);
    this.addChild(this.head);

    this.body.dispose();
    this.body= BABYLON.MeshBuilder.CreateBox('body', { width: this.size,  height: this.size, depth: this.size }, this.scene);
    this.addChild(this.head);

  }
}

I find it a bit strange to have to create all these ‘empty’ meshes in the constructor, while I override them again in the init-method, just to keep my IDE happy. I also really have to make sure all these empty objects are disposed in the right way, because otherwise the inspector gets filled with ‘no name’-meshes in the root, after creating a lot of objects.

Am I doing something wrong? Is there a way to create an empty mesh, something like BABYLON.Mesh.Empty(), (a bit like BABYLON.Vector3.Zero() ) that is enough to have no warnings in the IDE, and have no ‘no name’ meshes in the inspector?

I hope I explained it well, since english is not my first language.

public body? : BABYLON.Mesh

I would use a TransformNode.

export class Person extends BABYLON.TransformNode {
  head: BABYLON.Mesh;
  body: BABYLON.Mesh;

  constructor(name: string, scene: BABYLON.Scene) {
    super(name, scene);
    this.scene = scene;
    this.head = BABYLON.MeshBuilder.CreateSphere('head', { diameter: this.size / 2 }, this.scene);
    this.body= BABYLON.MeshBuilder.CreateBox('body', { width: this.size,  height: this.size, depth: this.size }, this.scene);
  }

 
}

const player = new Player("player1", scene);

You will need to parent the meshes to the node.

https://doc.babylonjs.com/typedoc/classes/BABYLON.TransformNode

1 Like

public body? : BABYLON.Mesh;

does hide the error/warning in the IDE, but I use this body property in a camera.isInFrustum function, something like this:
const infrustum = camera.isInFrustum(person.body);

and then it says:

Argument of type 'Mesh | undefined' is not assignable to parameter of type 'ICullable'.
  Type 'undefined' is not assignable to type 'ICullable'.

When I do create the body in the constructor, I don’t get this error.

However, when I do :
const infrustum = camera.isInFrustum(person.body as BABYLON.Mesh);
it works without error, but it’s a bit ugly, I think.

As @Aus_Karlos wrote the best idea is to put those meshes under a parent TransformNode.

I’ve fixed a few errors in your code and added some stuff:


class Person extends BABYLON.TransformNode {

    public head: BABYLON.Nullable<BABYLON.Mesh>; // so we don't need to set it in the constructor
    public body: BABYLON.Nullable<BABYLON.Mesh>;

    public size: number = 10;

    private _initialized = false; // initialized flag, see below

    constructor(name: string, private scene: BABYLON.Scene) {
        super(name, scene);
    }

    public init(size: number = 10) {
        if (!this._initialized) { // prevent multiple initializations
            this._initialized = true;

            this.size = size;

            // you don't need the 'new' keyword here and the `MeshBuilder` will be deprecated.
            this.head = BABYLON.CreateSphere('head', { diameter: this.size / 2 }, this.scene);
            this.head.position.y = this.size * 0.8
            this.head.parent = this; // put the head mesh under this TransformNode

            // same changes here
            this.body = BABYLON.CreateBox('body', { width: this.size, height: this.size, depth: this.size }, this.scene);
            this.body.parent = this;
        }
    }
}

A clean solution is:

const isBodyInFrustum = person.body ? camera.isInFrustum(person.body) : false;

This will fail at runtime if person.body is not set.

Working TS example:

Both in frustum:

Head already out of frustum:

:vulcan_salute:

Thanks a lot, I’m trying out Typescript and using classes for the first time, and this helps to understand it a bit more! I never heard of BABYLON.Nullable before, and also didn’t use the < > in Typescript before, just because I thought it looked complicated :slight_smile:

However, I still get this error in the IDE with your solution:
Property 'head' has no initializer and is not definitely assigned in the constructor.

Maybe the warnings in VSCode are a bit too strict, but I’d like to keep these settings default.

Also, addChild is not a method of BABYLON.TransformNode. I understand that setting parent to the child instead seems to do the same, but addChild is a bit more clear, in my opinion.

Because you didn’t make it <Nullable> or you didn’t import the Nullable type.

It’s just a matter of taste :smiley: