McNidday

Selecting individual faces on imported mesh from blender or custom made by babylonjs and possibly change its texture

Recommended Posts

Hey guys, here's another random babylonjs newbie hoping to get some help :-)

So i have been playing around with babylonjs for a while and i get better at it everyday but i just hit this stumbling block that i can't seem to figure out

I have created a sample box for a demonstration of this frustration, get it 🤨

 // Create sample box
    const sampleBox = BABYLON.MeshBuilder.CreateBox('sampleBox', {
        size: 10,
        updatable: true
    }, scene, true);
    sampleBox.isPickable = true;
    sampleBox.position = new Vector3(0, 0, 0);
    let verticesCount = sampleBox.getTotalVertices();

 Then i used multimaterial to assign image textures to four of the faces of the sample box

// Create four standard materials
    let material0 = new StandardMaterial('material0', scene);
    material0.diffuseTexture = new Texture('/some0_image.jpg', scene);
    material0.diffuseTexture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
    material0.diffuseTexture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
    material0.specularColor = new Color3.Black();

    let material1 = new StandardMaterial('material2', scene);
    material1.diffuseTexture = new Texture('/some1_image.jpg', scene);
    material1.diffuseTexture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
    material1.diffuseTexture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
    material1.specularColor = new Color3.Black();

    let material2 = new StandardMaterial('material2', scene);
    material2.diffuseTexture = new Texture('/some2_image.jpg', scene);
    material2.diffuseTexture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
    material2.diffuseTexture.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
    material2.specularColor = new Color3.Black();

    let material3 = new StandardMaterial('material3', scene);
    material3.diffuseTexture = new Texture('/some3_image.jpg', scene);
    material3.diffuseTexture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
    material3.diffuseTexture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
    material3.specularColor = new Color3.Black();

 // Define the multimaterial
    let maltimat = new MultiMaterial('multi', scene);
    maltimat.subMaterials.push(material0);
    maltimat.subMaterials.push(material1);
    maltimat.subMaterials.push(material2);
    maltimat.subMaterials.push(material3);

 // Assign mesh material to the mesh
    sampleBox.material = maltimat;

 // Define the subMeshes for the sample box
    new BABYLON.SubMesh(2, 0, verticesCount, 0, 6, sampleBox);
    new BABYLON.SubMesh(1, 0, verticesCount, 6, 6, sampleBox);
    new BABYLON.SubMesh(3, 0, verticesCount, 12, 6, sampleBox);
    new BABYLON.SubMesh(0, 0, verticesCount, 16, 6, sampleBox);

So this is where the problem that has been bumming me for days comes in. I would like to change the texture of one of the faces when it is clicked, so one of the solutions i came up with to this problem was to change the submeshes material index to one of the four materials like below and it works partially. So in solution one, when a pick event happens i would access pickedMesh.subMeshes[some_index] and it would change the submeshes texture material to another one, the problem i encountered with this was

  • Getting the correct index from the pickInfo to select the submesh from the submeshes array and change it, tried using faceId, bad idea and submeshId keeps returning the value 0 when i select any of all the faces
  • The other problem with this approach was, i wanted to assign material to a face that has not been covered by the BABYLON.Submesh by getting the startIndex and indexCount automatically with the pickInfo and pushing the new data to the sampleBoxe's submesh array, In this case if the submeshId is not available, Yes i declared 4 subMeshes for a reason. 
 scene.onPointerPick = (event, pickInfo) => {
        if (pickInfo.hit) {
            let indices = pickInfo.pickedMesh.getIndices();
            let faceId = pickInfo.faceId;
            let index0 = indices[pickInfo.faceId * 3];
            let index1 = indices[pickInfo.faceId * 3 + 1];
            let index2 = indices[pickInfo.faceId * 3 + 2];
            let submeshId = pickInfo.submeshId;
            let positions = pickInfo.pickedMesh.getVerticesData(VertexBuffer.PositionKind);

       
            sampleBox.submeshes[faceId].materialIndex = 0;

            // or using submeshId, which just returns 0 for some reson uuuuurrrrgh
            if (!submeshId) {
            // How do i get the indexStart and the indexCount from the pick info
               new BABYLON.subMesh(0,0,verticesCount, indexStart, indexCount, sampleBox)
            } else {
               sampleBox.submeshes[submeshId].materialIndex = 0;
            }

           // or hard coding it but whats the essence it would just change a face material that's 
           // not even facing the screen and that's not my intent

           sampleBox.submeshes[2].materialIndex = 0;

        }
    }

The other way to go about this was to use vertexData but i couldn't get this to work with images only manipulating the colors of the facets on pick event and used updateVertexData to update the colorKind and it worked like a charm. If there is a way to use vertexData to change a face material, i would appreciate and even buy you a soda and give you a hug if you were near me 🤗

     let positions = [-5, 2, -3, -7, -2, -3, -3, -2, -3, 5, 2, 3, 7, -2, 3, 3, -2, 3];
     let indices = [0, 1, 2, 3, 4, 5];
     let colors = [1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1];
     let vertexData = new BABYLON.VertexData();
     vertexData.positions = positions;
     vertexData.indices = indices;
     vertexData.colors = colors;
     vertexData.applyToMesh(sampleBox);

 

Quote

I am not in a position to send a live file or a playground link, so am sorry for that but hope you can recreate the scene with the code snippets above or visualise

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.