Assign a texture to selected face of a mesh

Hello,
I am currently trying to figure out how to exactly assign a texture to a single face of a mesh/custom mesh the user has clicked on with his mouse.

I’ve found this post https://forum.babylonjs.com/t/how-to-assign-a-texture-to-a-singe-face-of-a-box/12590 where someone’s approach was to dispose the original box and recreate the box from a set of 6 seperate planes.
The problem with this though, is that it’s only possible for boxes, not for other meshes or custom meshes, which in my case I want to achieve, additionally I’m not sure If I like the idea of splitting the mesh into seperate planes…

I’ve created a PG where a texture is applied to the entire mesh the user selected:
https://playground.babylonjs.com/#EN0FZU#1
Hoping for someone to work from thereon.

Any help is appreciated, thanks!

It’s not really possible, as a material applies to a mesh as a whole.

What you can try to do is to assign specific uv coordinates to the face(s) so that they point to a sub area of the texture. But that means you will have to create a single “merge texture” with all the textures you need in your process (which could be impossible if you have a lot of these textures / they have large dimensions).

Or, if you only need to texture some faces of the mesh with a single texture (to temporary make these faces stand out, for eg), then it’s probably easier to create a new mesh with these faces only and assign a standard material to it.

Hm, can it not be done using multi-materials? My approach would’ve been the following:
When clicking on a face, following data for the face will be output:

  • vertex index start of face
  • vertices count of mesh
  • index start
  • index count

which are the values that BABYLON.SubMesh takes as it’s arguments.
So basically creating a submesh of a face when clicking on it, and then applying multi-material.

But since I don’t have much of an idea on how to actually get these values and then apply a multi-material, I’ve created this topic.

A multi-material will only work if you have a single face (triangle) to process.

In that case, you can do it like this:

1 Like

Thanks, that’ll work.
Though, would it not be possible to process quads? I’ve found this PG where you can select quads faces, would it be possible to merge the two PGS?
https://playground.babylonjs.com/#EC25TG#3

This PG creates a new mesh for the selected faces, it does not use a multimaterial on the picked mesh.

You can easily modify the PG to set a material with the “picked” texture on the newly created mesh:

Sorry if it’s obvious, but how exactly do I actually “apply” the the texture on the original mesh? Since all that this does is create a seperate quad plane mesh on top of the mesh.

Appreciate your help by the way

You can do it like this:

1 Like

Thanks!

Been trying to adjust the PG so that faces don’t deselect upon selecting a new face and also have the ability to deselect faces in general, but I’ve gotten nowhere. Any reason why it does that?

Because it’s not coded to do that :slight_smile:

You will have a little work to do to make it happen.

To give a bit of context for my PG, a new submesh is created for each triangle that must be rendered with the textured material, and if there are already too many submeshes compared to the number of selected faces, I simply set the indexCount to 0 instead of 3 so that this submesh is not rendered.

In your case, it’s probably easier to keep a list of selected faces and rebuild the submeshes each time the list changes: simply remove all the submeshes (mesh.subMeshes.length = 1 to keep the main submesh which actually renders the whole mesh!) and create a new submesh with something like new BABYLON.SubMesh(1, ramp.subMeshes[0].verticesStart, ramp.subMeshes[0].verticesCount, faceId * 3, 3, ramp); where you would loop on the selected faces to get faceId.

1 Like

Thanks for the instructions,
this seems to work: https://playground.babylonjs.com/#EC25TG#8
:+1:

Regarding your other question to get the material of the picked submesh, you can do it by creating a submesh for each of the non selected face:

I think what you tried (creating a single submesh for all the non-selected faces) is possible but a bit more involved because you will have to reorganize the index buffer so that the indices for this submesh are all contiguous in this buffer.

1 Like

Thank you! This works. I wanted to create a single submesh for the non-selected faces due to performance reasons, because my scene can sometimes have a lot of objects in it (1000+) and I wasn’t sure if creating a lot of submeshes would hurt performance… Is there a definitive answer to that?

Yes, creating a single submesh will hurt performance badly if you have a lot of faces, because each submesh will generate a draw call…

1 Like