Correct/performant way to build my own mesh/geometry?

Hi, I’m making something where I dynamically create a lot of large meshes. I am currently doing it like this as described in the docs:

        var mesh = new Mesh(name, scene)
        var vdat = new VertexData()

        vdat.positions = // big array of numbers
        vdat.normals =   // big array of numbers
        vdat.indices =   // big array of numbers
        vdat.colors =    // big array of numbers
        vdat.uvs =       // big array of numbers
        vdat.applyToMesh(mesh)

However there seem to be some drawbacks. E.g.:

  1. Babylon appears to look through the entire position array in order to check its bounds, which in my case I already know. I could easily create a BoundingInfo object, but I can’t find a way to get Babylon to use it.
  2. I’m not sure but it looks like some of the data arrays are being internally recreated (maybe to convert to typed arrays)?

There could be other issues. I understand that the default API is meant to be simple and easy to use, but in my case I’m creating lots and lots of large meshes. Is there any way that I can create custom meshes while avoiding internal overhead?

Your arrays should be Float32Array and not plain javascript array to avoid a conversion when applyToMesh is calling setVerticesData internally.

You can call mesh.getBoundingInfo().reConstruct(...) to set the min/max bounds of the bounding infos to overwrite the values computed by the applyToMesh call but I can’t see a way for you to stop Babylon doing the automatic reconstruction…

2 Likes

@Evgeni_Popov Thanks for the reply!

However, from looking at the source it looks like incoming data arrays get converted (i.e. duplicated) to typed arrays even if they were typed already.

Is this correct? It seems like a pretty big waste.

Also - even the indices array gets converted to Float32? Even though it’s all integers?

The conversion is done here:

In fact it’s only done if you flag the data as updatable.

But later on, when we pass the data to WebGL, the API expects a ArrayBuffer / ArrayBufferView. If not, we convert it:

So, to be sure there’s no conversion even if the data are updatable, you should use a Float32Array.

Where are you seeing this?

Indices are generally of type IndicesArray, which is defined as type IndicesArray = number[] | Int32Array | Uint32Array | Uint16Array;.

In the low level layer it’s also IndicesArray or Uint16Array / Uint32Array:

Where are you seeing indices being converted to float?

Hi, thanks for the answers - the internals are quite hard to follow but I sort of see what’s going on.

That said, is there any more performant way to create meshes? Basically I have code that builds lots of dynamic meshes, something like this:

// part A
var vdat =   // lots of very heavy math to build a VertexData object
var ranges = // more heavy math to partition the data into subMesh ranges

// part B
var mesh = new Mesh(name, scene)
vdat.applyToMesh(mesh)
mesh.subMeshes = ranges.map(r => new SubMesh( /* .. */ ))

And basically what I’m finding is that Part B takes a significant amount of time compared to part A, even though all the work should already be done. So apparently Babylon is doing some heavy (unnecessary?) work by default, and I’m wondering if there’s any way to skip such work.

E.g. can I perhaps create a Geometry object manually and then somehow create a Mesh around it? Or something like that. I’m not sure what Babylon is doing, but I’m finding that even new Mesh(name, scene) takes a measurable amount of time, so I’m wondering if I’m invoking lots of stuff that could be skipped.

Thanks for any info!

I don’t think there’s other ways to create meshes… Part B is what all the mesh builders (sphere, plane, etc) are doing.

Regarding the constructor of mesh taking some time, it may be because it calls refreshBoundingInfo that computes the min/max bounding box/sphere. What you could do is temporarily overrides this method so that it does nothing:

const saved = BABYLON.Mesh.prototype.refreshBoundingInfo;
BABYLON.Mesh.prototype.refreshBoundingInfo = function() { }
...your work...
BABYLON.Mesh.prototype.refreshBoundingInfo = saved

[…] My bad, it is calling refreshBoundingInfo only if passing a source mesh to the constructor (4th parameter)!

I don’t really see why the mesh constructor would be so slow, you could maybe try to use the performance tab of the browser and see what’s going on? Even for the applyToMesh call, maybe there’s something to optimize here.