2
votes

For future viewers, I was able to solve it by using mesh.material.map.image.src = texture;

Original question:

As part of my ThreeJS project, I need to change the texture on a mesh. Unfortunately, I can't get Three to update to the new texture.

I've tried all the things mentioned in the following SO questions, but nothing has worked so far:

The texture that I am trying to change is scene.children[0].children[1].material.map.sourceFile and the structure looks like this:

  • SCENE scene
    • 3DOBJECT banner
      • MESH flag
        • MESHBASICMATERIAL flag_M
          • TEXTURE flag_MT

flag_MT texture is the one I want to update and these are the following methods I've tried:

  • flag_M.needsUpdate = true;
  • flag_MT.needsUpdate = true;
  • flag_MT = THREE.ImageUtils.loadTexture(texture); with texture being a base64 data string
  • practically remaking the entire object and replacing that into the scene

Thanks.

Edit: The important parts of code:

init()

flag_MT = THREE.ImageUtils.loadTexture(app.setFlagTexture());
flag_MT.magFilter = THREE.NearestFilter;
flag_MT.minFilter = THREE.NearestFilter;

flag_M = new THREE.MeshBasicMaterial({map: flag_MT});
flag_M.needsUpdate = true;

flag_T = { //easyVectory64 just provides a clean function for making vector maps
    u: easyVector64(2, 62, 20, 1), //up face
    d: easyVector64(22, 62, 20, 1), //down face
    f: easyVector64(1, 23, 20, 40), //front face
    b: easyVector64(22, 23, 20, 40), //back face
    l: easyVector64(0, 23, 1, 40), //left face
    r: easyVector64(41, 23, 1, 40)}; //right face

flag_G.faceVertexUvs[0] = []; //Map texture to mesh
flag_G.faceVertexUvs[0][0] = [flag_T["r"][0], flag_T["r"][1], flag_T["r"][3]];
flag_G.faceVertexUvs[0][1] = [flag_T["r"][1], flag_T["r"][2], flag_T["r"][3]];
flag_G.faceVertexUvs[0][2] = [flag_T["l"][0], flag_T["l"][1], flag_T["l"][3]];
flag_G.faceVertexUvs[0][3] = [flag_T["l"][1], flag_T["l"][2], flag_T["l"][3]];
flag_G.faceVertexUvs[0][4] = [flag_T["u"][0], flag_T["u"][1], flag_T["u"][3]];
flag_G.faceVertexUvs[0][5] = [flag_T["u"][1], flag_T["u"][2], flag_T["u"][3]];
flag_G.faceVertexUvs[0][6] = [flag_T["d"][0], flag_T["d"][1], flag_T["d"][3]];
flag_G.faceVertexUvs[0][7] = [flag_T["d"][1], flag_T["d"][2], flag_T["d"][3]];
flag_G.faceVertexUvs[0][8] = [flag_T["f"][0], flag_T["f"][1], flag_T["f"][3]];
flag_G.faceVertexUvs[0][9] = [flag_T["f"][1], flag_T["f"][2], flag_T["f"][3]];
flag_G.faceVertexUvs[0][10] = [flag_T["b"][0], flag_T["b"][1], flag_T["b"][3]];
flag_G.faceVertexUvs[0][11] = [flag_T["b"][1], flag_T["b"][2], flag_T["b"][3]];

flag_G.applyMatrix(new THREE.Matrix4().makeTranslation(0, -20, 0));

flag = new THREE.Mesh(flag_G, flag_M);

app.setFlagTexture()

//Bunch of code that pre-mixes several textures into a single texture
var texture = "data:image/png;base64,..."; //texture being a base64 png data string
flag_MT = THREE.ImageUtils.loadTexture(texture);
if(flag_M !== undefined){ //because flag_M is undefined on the first call
    flag_M.needsUpdate = true;
}
return texture;
1

1 Answers

4
votes

I had a similar issue in my project and your first try should have worked flag_M.needsUpdate = true;

You can recreate a texture with ImageUtils, flag_MT = THREE.ImageUtils.loadTexture(texture); and then do flag_M.needsUpdate = true; and this should work.

But this solution is really not the best if you change your texture too often and you should think about updating by yourself the image source in the Texture Object and then put to true the needsUpdate flag.

For example in my code I did this :

mesh.material.materials[0].map.image = { data: array, width: 20, height: 20 };
mesh.material.materials[0].map.needsUpdate = true;

mesh was a cube with a FaceMaterial. array is an Uint8Array buffer containing all the data in RGB format and did the work. If you can, for performance purpose, avoid deleting and creating things just to change it. It's more expensive for your GPU and your bus to do that, than just update the texture buffer.

And please, post the code you have to see what is wrong in it, since your firt try should have done what you want.