[SOLVED] How to change color of grid vertices during mesh deformation?

Hoping to get ideas / advice for implementing color change during mesh deformation - I’ve been building on this project which deforms a 2D grid mesh based on cursor input to mimic digging through snow. That project’s logic changes the y-position of grid vertices (decreases, then resets after some milliseconds).

Is it possible to change the color of the specific grid vertices? If so, how would you approach this problem?

I attempted to implement a shader based on various other projects posted on forum, but unfortunately couldn’t get anything to work for this scenario and gave up frustrated. Maybe this controller could be used for terrain-building sims (eg. digging a water channel, etc).

mesh deform 3

Hi @Vdizzle,

You can use the setColors/setColors32 methods available in the Mesh API:

https://playcanvas.com/editor/code/828222?tabs=54841571

Similarly to how you find the coordinates for each position when you are updating the elevation, you can create an indexed array for colors and update that with color values.

2 Likes

Hmm I’m not able to get any color to even initialize, so I’m assuming I’m making a mistake in using the setColors32 method? (using same project)

In MeshGeneration.prototype.initialize

//////MESH COLOR ATTEMPT
    const colors =  new Float32Array(4 * resolution * resolution);
    this.colors = colors;

    let index = 0;
    for (let x = 0; x < resolution; x++) {
        for (let z = 0; z < resolution; z++) {
            positions[3 * index + 0] = scale * (x - resolution * 0.5);
            positions[3 * index + 1] = 0;  // no elevation, flat grid
            positions[3 * index + 2] = scale * (z - resolution * 0.5);
            
            uvs[2 * index + 0] = x / resolution;
            uvs[2 * index + 1] = 1 - z / resolution;
            
            colors[4 * index + 0] = 255;
            colors[4 * index + 1] = 0;
            colors[4 * index + 2] = 0;
            colors[4 * index + 3] = 1;
            
            index++;
        }
    }

and then MeshGeneration.prototype.updateMesh

MeshGeneration.prototype.updateMesh = function(mesh, initAll) {
    
    mesh.setPositions(this.positions);
    mesh.setNormals(pc.calculateNormals(this.positions, this.indexArray));
    
    mesh.setColors32(this.colors);
    // console.log(this.colors);

    // update mesh Uvs and Indices only one time, as they do not change each frame
    if (initAll) {
        mesh.setUvs(0, this.uvs);
        mesh.setIndices(this.indexArray);
    }

    // Let mesh update Vertex and Index buffer as needed
    mesh.update(pc.PRIMITIVE_TRIANGLES);    
};

Actually you did it, your code is correct, you just need to instruct your material to render vertex colors. I did that in your project in editor and then set that material to the model created, instead of spawning a new material:

image

    // create material 
    const material = this.app.assets.find('New Material').resource;
    
    // Create the mesh instance
    const meshInstance = new pc.MeshInstance(mesh, material);

2 Likes

Brilliant @Leonidas !!! That was exactly the fix!!! (always blows my mind how easy PC implements cool functionality - once you learn through the Leonidas Bootcamp :wink:)

If it helps anyone else, original project has been updated to update mesh color relative to cursor input.

mesh deform 4

3 Likes

Well done and thanks for sharing! I see the birth of a terrain editor there :innocent:

1 Like