Jump to content

BJS / TS question about instance/class properties


Recommended Posts



I'm currently coding the tube update feature.

I want it easy : the user only needs to pass a path, a radius and a tessellation to build his tube. So I want he just passes another path and another radius to update the existing tube.

As the number of tube vertices depends directly upon the tessellation, it can't be changed once the mesh is created.


So the tessellation (as well as other properties like pathArray array or path3D, in the purpose not to reallocate memory each update call) should be stored with the tube object.


TypeScript doesn't allow to add a new property to an instance of a class.


The tube is just a particular ribbon. This ribbon is a Mesh instance.

Actually, the tube mesh is just a big math helper for some complex sub-types of ribbons (tubular).


Should I add some properties to the Mesh class although they aren't pertinent for other kinds of mesh : pathArray, path3D, tessellation ?

they could be then re-used in almost any tubular kind of mesh, I guess, and this would be very easy to do


Or do you (BJS architects) prefer another solution ?

I don't think having a Tube class really is worth it imho ...



Link to comment
Share on other sites

You can do something like this:

var tess = (<any>mesh).tessellation;(<any>mesh).pathArray = new_path_array;

This way you can add dynamic properties to TS object without compile errors! It's not very pretty, but immensely useful when you need the flexibility of JS.

Link to comment
Share on other sites

What about an object in Mesh class : MeshOptions, or MeshParameters, or MeshSpecifics.


This object could be empty for 'classics' meshes, and contains stuff like this for a Tube : 

this.meshOptions = {tesselation : 8;pathArray : [];...}

In your Tube code : 

if (this.meshOptions && this.meshOptions.tesselation) {  // Do something}

Sorry i don't know how to TypeScript...

Link to comment
Share on other sites

thank you all for your clever answers :)


well, the only right clean way seems to create another class anyway.

I just didn't want to add too much code in BJS for storing only 3 properties just for a single type of mesh. But...

Link to comment
Share on other sites


Not as easy as for the GroundMesh.

In the CreateGroundMesh code, we create a GroundMesh object which is a raw Mesh and then we applied computations to it to make the right associated vertexData.


Here, it's a little different : I get a ribbon instance (Mesh). Everything is computed in the ribbon. The ribbon constructor can't return a Tube instance (which is only a particular case), it must return a Mesh instance.


I need to find a way to add these properties after the Mesh instance (ribbon) is created.


If I can't ... maybe the right way would then be to adjust the Tube class constructor to accept a ribbon instance (instead of the mesh usual super constructor) and just add these 3 properties.

Any ideas ?

module BABYLON {    export class TubularMesh extends Mesh {        public _ribbon: Mesh;        public _pathArray: new Array<Array<Vector3>>();        public _path3D: Path3D;        public _tessellation: number;        constructor(ribbon: Mesh, pathArray: Vector3[][], path3D: Path3D, tessellation: number) {            this._ribbon = ribbon;            this._pathArray = pathArray;            this._path3D = path3D;            this._tessellation = tessellation;        }...

and then in the CreateTube() code :

// something to compute the right pathArray for tubesvar ribbonTube = Mesh.CreateRibbon(name, pathArray, etc, etc);var tube = new Tube(ribbon, pathArray, path3D, tessellation);return tube;
Link to comment
Share on other sites

maybe, I just don't extend the Mesh class... and just create some kind of container.

It works but I don't know if it is really clean besides the rest of BJS code : a TubeMesh class which wouldn't extend the Mesh class.

Link to comment
Share on other sites

You are missing the super call...

Why won't you try integrating it into the RibbonMesh class? and then a tube is actually a differently calculated ribbon mesh?

module BABYLON {    export class RibbonMesh extends Mesh {        public _pathArray: new Array<Array<Vector3>>();        public _path3D: Path3D;        public _tessellation: number;        constructor(name:string, scene:Scene) {            super(name, scene);            //calculate everything        }        initTube(pathArray: Vector3[][], path3D: Path3D, tessellation: number) {            //do your magic        }...
Edited by RaananW
Link to comment
Share on other sites

Because there's no ribbonMesh class !


A ribbon is just an instance of a mesh.

It didn't need its own class because, despite there are many generic calculations, it is a very simple mesh, far more simple than a box or a sphere in terms of internal logic.

Actually, it is really an ultra-basic mesh (just triangles between two paths) but with all the tools to be handled by the user.


As we can do quite everything with a ribbon, I decided to provide some pre-computed ribbon types so the final user will have less geometric work to do by himself.

The tube is just a ribbon application. As well as the extrusion.

I just provide methods to the user in where he just gives simple parameters : an axis, a radius, etc and then the underlying ribbon is computed to build a tube or an extruded shape.


Well, the ribbon is the elementary brick to build complex shapes with math functions.

So there aren't so far any classes for these higher level constructions.

There aren't either relative CreateTube or CreateExtrusion methods in the vertexData class because the CreateRibbon method is enough to do the job.

Link to comment
Share on other sites

Well, create one :-)

If it makes sense, create one. If there is a need to add parameters that are not a part of the mesh, create one. If you can pack the entire Ribbon logic in one class, create one. I don't see the problem.

The GroundMesh class has 37 lines of code. 2 extra variables and 2 extra functions. And it made sense to create it. So I don't see the difference between the two.


TypeScript is wonderful to structure your code. I always think that If you need to use a hack to add some parameter to your class, you are doing something "wrong". Maybe unstructured, maybe a bit dirty, maybe it can be solved in a better way. The result will be the same, because eventually it is javascript... But readability, organization, they benefit from such a structure.

Link to comment
Share on other sites

I understand what you mean and I agree.


But actually ribbons don't need more than what a mesh provides.

I could have done Mesh > Ribbon, yes, but there is no need.


Tessellation, path3D, etc aren't ribbon properties. They have no sense for it (as for the global Mesh either), no value, they aren't pertinent.


They are just a way to build a tube.



The tube isn't a subclass of a ribbon but just an application of ribbon : a certain ribbon twisted in a certain way. This is why the ribbon is designed to : to mathematically build shapes.


The tube itself, as a ribbon object, doesn't need really to store these extra parameters to exist.


I wanted to store them just to simplify the end user update method call (and to reuse allocated arrays in the render loop).

As a end user, you give an axis path, a tesselletion and a radius to create your tube.

To update it, you can pass a new path and/or a new radius... but the tesselletion value was lost after the tube creation.

I could ask the end user to re-pass it with the same value, but I would prefer he just gives pertinent update values only to his point of view : those which will actually change the final shape of the tube.


not sure I'm very clear

it's more a design problem than a syntaxic one

Link to comment
Share on other sites

I honestly think this is not the best solution, but it is only an opinion  ;)


I think inheritance in OOP is there for a reason - pack all logic involving this kind of object in the class where it belongs. Technically you could simply add the init function i suggested to the Mesh class. but it doesn'T belong there. It belongs as an initialization of a Ribbon object (If I understood you correctly). The parameters are not important, and not a part of the class. The function is.


Again - this is just an opinion, this can be quite a long discussion :-)


If you are looking for a simply way to add an parameter in typescript, I would personally use jahow's way, or

mesh['parameter'] = value

this way you avoid the type-safety the easiest way. no casting at all.

Link to comment
Share on other sites

Oopps, we answered in the same time !


I agree with you about the OOP design. Definetly.

But I think my explanation wasn't clear : I had more a design problem than a typescript problem and just couldn't solve it with TS.


As the extra needed parameters weren't a part of the Mesh class, they weren't either a part of the ribbon. This was clean and I respected this design.

The tube is not a class.

Don't know how to explain ... imagine you've got a function sizing a mesh box with twice width than height and three times longer than high, and B for RGB values only greater than 0.5

and imagine you don't give sizes or colors as parameter to your function but other values (age, temperature ?) from which the size to scale the box will then be computed

(not sure my example is very good either)


Well, it's not a subclass of the box class (which didn't exist), neither a subclass of the mesh class.

It's just a particular box instance computed from strange custom parameters with a dedicated function.


This is the same for the ribbon/tube relationship :D


So I still use the mesh class which is the only logic one to be used.

And just when needed, I cast the handled object to the TubularMesh class, extended from Mesh and just embbeding memorable values, to access/store these strange values.

Only for concerned instances of the ribbon mesh and only if needed (when values should be stored).

It avoids the unnecessary inheritance : Mesh > Ribbon (which would have had nothing more) > Tube (just a functional computed case of a ribbon instance)

this would have been in my weird example : Mesh > Box (idem) > StrangeBox (computed)


Not sure again I'm more clear this time.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...