How to make an animated IcosahedronGeometry "blob" with perlin noise?

Hey all!

I’ve been playing with Three.js for the last few days, but by now I got stuck because all the differences in builds and examples on the internet. :slight_smile:

Them main item I get stuck on is IcosahedronGeometry. The shift from geometry.vertices to geometry.attributes Is where I get stuck. I understand it went from a vector array to a single array for each coordinate. But I don’t know how to get → calculate → and set the new values.

This is an example that gets closest to the effect I have in mind. In updateVertices() you can see a perlin noise beeing applied to the vectors.

And this is my current approach. But the blob just disappears in the abyss of nothingness.

function setNewPoints( a ) {
    const positionAttribute = blob.geometry.getAttribute( 'position' );
    let newPositionAttribute = [];
    const vertex = new THREE.Vector3();

    for ( let vertexIndex = 0; vertexIndex < positionAttribute.count; vertexIndex++ ) {

        vertex.fromBufferAttribute( positionAttribute, vertexIndex );

        var perlin = noise.simplex3(
            vertex.x * 0.006 + a * 0.0002,
            vertex.y * 0.006 + a * 0.0003,
            vertex.z * 0.006 );

        var ratio = perlin * 0.4 * ( mouse.y + 0.1 ) + 0.8;
        vertex.multiplyScalar( ratio );

        newPositionAttribute.push(vertex.x, vertex.y, vertex.z);

    }
    blob.geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( newPositionAttribute, 3 ) );
    blob.geometry.attributes.position.needsUpdate = true; // required after the first render
    blob.geometry.computeBoundingSphere();
}

The code above is, I think, the main focus point of the effect.
The MaxTween morphs the mouse with an ease, so that the height of the Perlin is not abrupt.

So, the question would be, how could I get my code in the current build to work and look like the example.

Hi!
You perfrom noise computation on already changed vertex coordinates, whereas you need to do it on original coordinates.
Add a new buffer attribute, where you store the original coordinates, then, in animation loop, read data from it, apply the noise, save the result into the attribute with actual positions.

Example: https://jsfiddle.net/prisoner849/p1o8hrvn/

3 Likes

Holy shjizzle, that would have taken me ages to figure out :slight_smile: Thanks for the example, I wouldn’t have thought to set it as an attribute to the object itself :slight_smile: Thanks Paul!

Now I have you here, do happen to know how to smooth the surface? It now is hard and looks low poly.

Increase the detail parameter for IcosahedronGeometry.
For example: let blobGeometry = new THREE.IcosahedronGeometry( 50, 10 );. 10 is the level of detail. The greater that value, the smoother surface you get, as the geometry has more vertices.

Gorgeous, that looks way better :slight_smile: Thanks.
New result: Edit fiddle - JSFiddle - Code Playground

With lights I see the blob is turning itself inside-out. I guess that has something to do with the Perlin Noise. It even feels like one point of the object is not affected

Also you need to re-compute vertex normals after you changed vertex coordinates for correct shading.

    blob.geometry.attributes.position.needsUpdate = true;
    blob.geometry.computeVertexNormals();

And I would merge vertices of the geometry to have smooth shading: https://jsfiddle.net/prisoner849/cL97oerq/

Thanks for that Paul. Now, what I have to do is t figure out how the perlin in the script works to get it more like the first sketch.

But that’s playing with this part I think

        var perlin = noise.simplex3(
            vertex.x * 0.006 + a * 0.0002,
            vertex.y * 0.006 + a * 0.0003,
            vertex.z * 0.006 );

        var ratio = perlin * 0.4 * ( mouse.y + 0.1 ) + 0.8;
        vertex.multiplyScalar( ratio );