Search code examples
three.jstexturesauto-update

Three.js - Updating texture on plane


I'm trying to make a terrain editor. So I have a plane with multiple materials on it, which I initialize like so:

var materials = [];
var grasstexture = THREE.ImageUtils.loadTexture('Img/grass.png', {}, function() { });
var rocktexture = THREE.ImageUtils.loadTexture('Img/rock.png', {}, function() { });
materials.push(new THREE.MeshPhongMaterial({color: 0xffffff, map: grasstexture}));
materials.push(new THREE.MeshPhongMaterial({color: 0xffffff, map: rocktexture}));
// Plane

this.geometry.materials = materials;
for(var i = 0; i <  this.geometry.faces.length; i++)
{
    this.geometry.faces[i].materialIndex = 0;
}

this.geometry.dynamic = true;
this.mesh = new THREE.Mesh( this.geometry, new THREE.MeshFaceMaterial(  ) );
this.mesh.receiveShadow = true;

The result is a square plane stripped with the two textures.

Now, I can't seem to update the materialIndex for each vertex during the runtime. I have tried:

face.materialIndex = 1;

for(var i = 0; i < geo.materials.length; i++){
    geo.materials[i].needsUpdate = true;
}

for(var i = 0; i <  this.geometry.faces.length; i++)
{
    geo.faces[i].materialIndex = 0;
}

for(var i = 0; i < geo.materials.length; i++){
    geo.materials[i].needsUpdate = true;
}
this.mesh.needsUpdate = true;
this.mesh.material.needsUpdate = true;

geo.verticesNeedUpdate = true;
geo.normalsNeedUpdate = true;
geo.colorsNeedUpdate = true;

geo.computeFaceNormals();
geo.computeVertexNormals();

geo.computeCentroids();
geo.computeTangents() ;

And every other 'materialIndex' and 'needsUpdate' variable in Three.js I was able to find, but still nothing happens. How do I force an update on the material indices?


Solution

  • You can't. materialIndex is only used in the first render to partition the geometry into chunks, with each chunk having the same material. Also, you cannot re-partition the chunks.

    What you can do, however, is change a material in the materials array.

    materials[ 0 ] = new THREE.MeshBasicMaterial();
    

    You do not need to set any needsUpdate flags to true after doing so, either.

    An alternate thing you can do is give each face it's own material from the start, and then, for example, just change a material's texture.

    mesh.geometry.materials[ 0 ].map = texture;
    texture.needsUpdate = true;