Apply subMaterial to top side of extruded polygon only

I would like to put a texture only on top of an extruded polygon, and use a different one for the sides. My code looks pretty much like this:

As you can see, I tried to do special cases for triangles and quadrilaterals, but I couldn’t figure it out for pentagons. I would like to support at least octagons (regular or irregular), more if possible. Is there a simple formula that works for all shapes? I couldn’t find any code related to vertices in the polygonBuilder.ts:

Is there an easier solution than going into the VertexData and comparing the height of the vertices? Are they even guaranteed to be contiguous? When I tried to access the vertex positions like this: const positions = polygon.getVerticesData(VertexBuffer.PositionKind).positions;, I got undefined. Is that the right approach here?

By the way, I can’t use face colors, I need a proper material.

Thanks in advance for your help! I’m sure it’s just a case of not knowing what to look for.

You can do it like this with faceUV (or color with faceColors)

The slightly complicated part is the edge uvs are applied internally so the max range for faceUV[1] needs to be a fraction of the saved image. (I need to add explanation in docs)


Thanks for the solution! I knew about the faceUV option and something like that was actually my back-up plan. UV maps can do a lot! ATM simple textures/StandardMaterial are enough so this solution is also viable, but something more fancy may be required in the future. With MultiMaterials I could use PBR etc. Any way that can be made to work?

For that I need to replicate whatever the extrusion algorithm does in my formula. It looks like at least the number of triangles doesn’t change when simply changing the shape and keeping the number of points the same.

Having looked further the uv calculations for the edges is incorrect. I will rewrite over the coming days.

1 Like

The UVs for the edges/sides are a bit weird, yes. Somehow I don’t understand how they work. The top/bottom ones are easy. No matter what I do, it only seems to fill at most one edge.

I tried the straightforward solution like this, where all the edges should have the third image:

But that obviously works only for one of the five sides. How exactly is the UV map applied to each side?

I only need two images, by the way. The bottom doesn’t matter.

The simple answer is - wrongly. It doesn’t look wrong if you apply a single homogeneous image over the whole mesh but it is wrong.

Do you know what the cause is? Is earcut the culprit? I don’t know anything about that library except that the name sounds a bit painful :wink: Could it be that the submesh issue is related to that?

Thanks in advance for helping me track this down. I really appreciate the effort.

Yes I know what is wrong and it is definitely not earcut which is a triangulation method for complex polygons. The calculation used a wrong formula just for the sides.

1 Like

ExtrudePolygon is now updated so that you can either apply faceUV[1] to each side or by setting a new wrap parameter to true you can wrap faceUV[1] across all sides

I will be doing a PR to update docs later this week.

If you want to see the code used it is in Babylon.js/polygonBuilder.ts at master · BabylonJS/Babylon.js · GitHub

line 13 to 115

which uses Babylon.js/polygonMesh.ts at master · BabylonJS/Babylon.js · GitHub

lines 253 to 275 for top and bottom and overwrites lines 315 to 376 for the sides

1 Like

Thank you! I like the two modes, let’s see which one looks best.

By the way: This is what I love about Babylon! Devs here go out of their way to add new features just because someone had a vague need for them :wink:

I just tried it and noticed the code was not yet in my npm @preview version (which reports on the console as Babylon.js v4.2.0-alpha.11 - WebGL2). Will I have to wait for alpha 12 to show up or is it just the deploy taking its time?