MeshBuilder.ExtrudePolygon in React

Hi community,

I’m trying to build an updatable Polygon by using MeshBuilder.ExtrudePolygon method. Before, I writing as an non-declarative way by using Ref (React), then everytime I updated the parameters, it will take the current ref and dispose the old one, and creating new one base on new parameters.

Therefor, I have changed it to declarative way (because as the mesh grow, the ref grow), my idea is when I updated the shape props, the current polygon will update. But the Polygon don’t work as I expected (only update position and rotation), so I want to ask is there anyway to update the shape without dispose or using the ref.

Below is my current code:

If you need more information, I will be ready.
Thank you!

Sounds like a question for our friend @brianzinn :slight_smile:

2 Likes

Hi @hxxngvx - Welcome to the Babylon community.

That is a great question and describes the expected behaviour and I would like to go into the details of why that unexpected behaviour is expected by react-babylonjs. Sorry this is a bit long winded, but writing extra information here to help anybody else coming across this.

The way that the declarative version works is that it will call the MeshBuilder creation/factory method. When the <extrudePolygon /> is first encountered by React it will call that creation method, much like how a <div /> would be called by the DOM renderer with createElement.

The constructor will be called and then only the properties of the Mesh are updateable.

As an imperative example:

const box = MeshBuilder.CreateBox('box1', {depth: 2, ...}, scene);
// box is now a mesh. changing these properties will translate/scale/rotate mesh.  these are the same properties you have found are reflected in the mesh when they change
box.position = ...
box.rotation = ...
box.scaling = ...
// this is not allowed - "depth" was just used to procedurally generate the mesh
box.depth = ..

What you can do with a box is get a ref and update the position vertices data and I have done that before and did consider having this library update the vertices accordingly (and didn’t), but that will be much more complex for ExtrudePolygon and other shapes and also I wanted the react-babylonjs library to remain simple (KISS) and there is luckily an easy way to fix that, but it does dispose and create a new mesh when those constructor or factory method parameter(s) change and that is by using the “key” prop. The “key” prop lets the React reconciler know when an object is the same instance or not. You have probably seen the warnings when you are missing that property in a list.

In the case of a box, it would be as easy as:

  <box key={`depth-${post.thicknessValue}`} depth={post.thicknessValue} ... />

Now when the post.thicknessValue changes the old mesh will be disposed and a new one will replace it with the same position/rotation, but new depth/shape/etc.

In the case of ExtrudePolygon you would need to have a postSettings.polygon as a string representation and you could use something like joining the array to a string what I have found is that if you can then it would perform best to version your settings, so you would increment the “version” when constructor props change. It would be the same imperatively and that is the nature of creation/builder/factory methods. Have a look at this code line where that technique is used with <ExtrudeShape .../>:
babylonjs-directed-graph/App.tsx at master · brianzinn/babylonjs-directed-graph (github.com)

live demo here - when you add buildings the lines will be redrawn and their shape changes:
BabylonJS Directed Graph (brianzinn.github.io)

I update position vertices directly as a last resort and would try to use scaling (x/y/z are able to change “box” depth/height/width) if that was able to meet your needs. Let me know if that helps or if you have more questions.

1 Like

Thank you for mention @brianzinn :slight_smile:

Thank you @brianzinn for the suggestion! I will have a look on later today. If something approach, I will discuss more. Otherwise, I will mark for a solution. :slight_smile: