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:

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:

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.

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.

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…