One limitation in Babylon.js is that once you create a mesh, its geometry isn’t easily editable in real time—you lose the original primitive parameters.
I wrote a short article explaining how to solve this problem, including a method for real-time updates and a clean parametric wrapper pattern.
Hey mate, NodeGeometry is really neat for creating procedural meshes, but it’s not great for real-time editing like in CAD. The reason is that every geometry update triggers a full CPU recomputation of all vertices and attributes through the entire node graph… , Imagine that happening in every frame!
So even small tweaks take a lot of time. If you want fast, interactive editing, it’s much better to use an updatable mesh and change the vertices directly.
I felt like this would be another option when performance is so much critical especially in real time modelling applications.
Please tell me if I am wrong, I could learn something new from you .
In fairness, I don’t think it’s a limitation, but a feature . The updatable mesh option is clearlydocumented.
For certain parametric meshes, because the amount of faces can vary, I find it useful to create a larger pool/array of vertices (positions) with a variable number of indices depending on parameters, which provides more flexibility and performance.
Yeah you right, it is just ment to be like that as most cases it is better to save meshes as only vertices for performance.
What i ment by limitations is that if you want to keep the geometry information of a mesh, you need to work around that for own use case, just as mine when I needed to make a parametric real time modelling.
It’s not always clear how/when to get the best performance, especially when source data is in a JavaScript Array(). It is better to use a TypedArray, I think. I use the same technique as @Rayan_Farhat, and have extended it to resizable-like TypedArray. Real resizable typed array doesn’t seem supported by WebGL2 (it produces a WebGL error), but I’ve gotten around that by maintaining overlay and max size seperately.
TypeError: Failed to execute ‘bufferData’ on ‘WebGL2RenderingContext’: The provided ArrayBufferView value must not be resizable.
An overlay TypedArray using the same underlying buffer is created like this:
floatArray = new Float32Array(buffer.buffer,0,floatCount);
In the case of thinInstanceMatrix, only instanceCount number of matrices are uploaded, but I don’t think points is treated the same way.
Other useful methods are update and updateDirectly.
Actually, what are use cases that require updating parametric geometry every frame?
In CAD-like scenarios, technicians enter precise values and only then the geometry is updated
In consumer-oriented scenarios it seems much better to work with some neat gizmos while transforming.
In my particular (stalled) use case of furniture design, it’s much more user-friendly to replace a transformed object with a simple and clear gizmo while moving around, and only materialize it when it’s dropped. The gizmo approach also solves usability/immersivity issues of overlapping, inconsistent, invalid states.
For me, it’s more of a UX polish thing - responding immediately to incremental changes of say a gizmo/slider rather than only updating after the slider thumb is released. For example, a complex mesh like a house roof with intersecting pyramid, hip and gable geometry, dormer windows, ridge caps, tiles, gutters and downpipes etc.
The UX aspects are highly dependant on particular use cases.
For instance, in my case, when users move furniture around the room they’re apparently more interested in dimensions, height relations, and gaps around, but totally not how the ridges would look like.
In other cases of luxury furniture people would be interested in overall look and feel and not about precise dimensions.
Anyway,
in a complex structures, even in case of furniture (box + internals) it ends up in a parameter dependencies, which are solved by graph structures anyway.
So it ends up in reinventing node graph, just without nodes.
I havent tried the nodes yet though.
Personally, I believe an optimal approach would be to create custom nodes for whole objects or just their parts. That’s what i’m going to try.
One example would be something close to the Hammer Editor or even a basic ‘level editor’ that gives the tools to modify the mesh, faces, edges, vertices, directly because they need/want to in order to shape the model. Modeling software would definitely use these types of updates in this way and more.
Ah, that makes sense — so if I understand correctly, by using custom NodeGeometry blocks that cache and modify the same VertexData instance in place, we could technically achieve partial updates instead of a full rebuild each time.
But yeah, in practice most built-in nodes — especially anything coming from MeshBuilder or a MergeBlock — will still end up regenerating new vertex data each time. So while it’s technically possible to design a graph that updates in place, it feels a bit against how NodeGeometry is meant to be used.
For real-time modeling or frame-by-frame updates, directly working with an updatable mesh still makes a lot more sense — it’s simpler, predictable, and designed exactly for that kind of use case.
Still, it’s cool to know there’s a bit of flexibility there — might be fun to experiment with it too.
Usually with direct ogl or dx we would keep the data as streaming so we only would do partial updates and those are sent in.. it’s a little extra work but it reduces the amount of gpu upload that happens.. could do similar here, just more limited because of the TypedArray limitations (non dynamically resizeable).
The nodes are intended to generate geometry, and the only usage of it is
nodegeo.onBuildObservable.addOnce(() => {
var mesh = nodegeo.createMesh("nodegeomesh");
})
nodegeo.build();
There’s no any nodegeo.update()
So, the nodes are totally not for realtime.
My hope was that the nodegraph can handle dependencies, like in Blender.
But that’s not the case. It should be resolved manually with myBlock.evaluateContext = false;
That leaves us with necessity to build our own graphs or something to handle dependant parameters.