Don't render updated colors when geometry.ToNonIndex()

Im trying to apply a color map on a geometry. I have a simpe box (see image). It is triangulated so I expect 12 faces, 36 verticies and 108 positions and 108 colors values. The original color is green. I want it to be purple and orange.

I have a color array with 12 values (for the faces). I want to color the mesh by faces and realised that I needed to use geometry.toNonIndex() in order to end up with 108 positions and 108 color values. It works to update the colors (even though the indecies are wrong) in my scene when I don’t use toNonIndex(), but as soon as I add ToNonIndex() the colors do not change. The values are updated in the console but no changes happens in the scene. Any clues why it is not possible to see the updated colors when .toNonIndex() is implemented? (im using THREE 0.129.0)


export function updateColors(mesh) {
  let lut;
  let params;

  const valueArray = [50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0];

  params = {
    colorMap: "rainbow",
  };

  lut = new Lut("rainbow", 512);
  lut.setColorMap(params.colorMap);

  lut.setMax(50);
  lut.setMin(0);

  const geometry = mesh.geometry.toNonIndexed(); //This does not work in the scene
  //const geometry = mesh.geometry; // This works in the scene
  const colors = geometry.attributes.color;

  for (let i = 0; i < valueArray.length; i++) {
    const colorValue = valueArray[i];

    const color = lut.getColor(colorValue);

    if (color === undefined) {
      console.log("Unable to determine color for value:", colorValue);
    } else {
      colors.setXYZ(i, color.r, color.g, color.b);
    }
  }

  console.log(geometry);
  geometry.attributes.color.needsUpdate = true;
  geometry.attributes.position.needsUpdate = true;
  geometry.attributes.normal.needsUpdate = true;
}

Hi!
Could you provide a picture with the desired result?

I want one side of the cube (two faces) to be purple, and the rest of the faces to be yellow/oragne. See the principle here:

Then you don’t need a non-indexed buffer geometry.
Think of a box as of 6 indexed plane geometries. Each plane has 4 vertices (triangles defined in index).
So you need to assign color to 4 vertices to paint one side of the box.

The box is only an example to start simple. The geometries we use are always meshes (not box geomety). We convert Rhino meshes into three meshes. Sometimes I need to color two triangles in the same plane in different colors (see imange here). I always need to color the mesh by faces and in this case my color array lenght is 12 (as the faces in the mesh box).

When we dont use toNonIndex() the faces (vertex list) dont match our color array. If we dont use .toNonIndex() we only have 72 items in the color array (nr of rgb(3) x nr of verticies per face(3) x number of verticies(8)) but when we use .toNonIndex() we get 108 values since the verticies are repeated for each face. This would work for setting the colors by faces, but the porblem is that it is not rendered/updated in the scene at all.

If count by vertices of an indexed geometry, then yes, there is that mismatch. Count by index.

Thanks for all the help, it really helps! I have tried for a few days now. The problem is that if we don’t use toNonIndexed(), we have 24 unique positions in attributes.position and 12*3=36 indices in the geometry.index list. If we write a loop where we set all the color values to a BufferAttribute like this

//we make a color array that matches with the position array
const colors = new THREE.BufferAttribute(new Float32Array(geometry.attributes.position.count3),3); 
  const indecis = geometry.index.array;

  for (let i = 0; i < colorList.length; i++) {

    let colorValue = colorList[i];

    let i1 = indecis[i3+0]; //this is the position of the 1st vertex of the ith face 
    let i2 = indecis[i3+1]; /this is the position of the 2nd vertex of the ith face 
    let i3 = indecis[i3+2]; /this is the position of the 3rd vertex of the ith face 

    // we set the three color values for the three positions in the color array where the matching points are
    colors.setXYZ(i1, color.r, color.g, color.b); 
    colors.setXYZ(i2, color.r, color.g, color.b); 
    colors.setXYZ(i3, color.r, color.g, color.b);

geometry.setAttribute("color", colors);
}

then we set 3*12=36 values in the color array, but since the length of the color array has to match with the number of vertecis (24), some of the vertices gets repeated and overwritten. When I use the toNonIndexed() method, all the vertecies gets repeated so that we in this case would get 36 distinct positions and the arrays matches. Am I missing something?

I’ve also seen that it is possible to set the Mesh.material.vertexColor property to THREE.faceColor/false but not sure how this works of if it is still supported in v 0.129.0.

Thanks!

@prisoner849

Are meshes of Rhino, loaded into the scene, of indexed geometry?

We convert rhino geometry to three geometry. It is a bufferGeometry in the scene. We use toThreejsJSON() for converting from Rhino tho Three. The method is defined here:

The resulting three mesh is indexed.

Any chance to provide a minimal example with such mesh?

YEs. Here is a JSON file containing the three cube mentioned above. And here is the value array we import to the color map function. We are using lut for convering the values to colors.

cubeMeshObject.json (9.7 KB)
colorValues.json (247 Bytes)

[49.727775, 49.916674, 49.717626, 49.520243, 49.646205, 49.52973, 49.780455, 49.9006, 99.799123, 99.780525, 0, 0]