Home > Software design >  Three.js Buffer Geometry Animation
Three.js Buffer Geometry Animation

Time:10-11

I have Three.js scene that basically spreads out a bunch of triangles over a given area.


        geometry = new THREE.BufferGeometry();
        geometry.dynamic = true;

        positions = new Float32Array(triangles * 3 * 3);
        const normals = new Float32Array(triangles * 3 * 3);
        const colors = new Float32Array(triangles * 3 * 3);

        const color = new THREE.Color();

        const n = 200,
          n2 = n / 2; // triangle's spread distance

        const d = 1000,
          d2 = d / 2; // individual triangle size

        const pA = new THREE.Vector3();
        const pB = new THREE.Vector3();
        const pC = new THREE.Vector3();

        const cb = new THREE.Vector3();
        const ab = new THREE.Vector3();

        for (let i = 0; i < positions.length; i  = 9) {
          // position

          const x = Math.random() * n - n2;
          const y = Math.random() * n - n2;
          const z = Math.random() * n - n2;

          const ax = x   Math.random() * d - d2;
          const ay = y   Math.random() * d - d2;
          const az = z   Math.random() * d - d2;

          const bx = x   Math.random() * d - d2;
          const by = y   Math.random() * d - d2;
          const bz = z   Math.random() * d - d2;

          const cx = x   Math.random() * d - d2;
          const cy = y   Math.random() * d - d2;
          const cz = z   Math.random() * d - d2;

          positions[i] = ax;
          positions[i   1] = ay;
          positions[i   2] = az;

          positions[i   3] = bx;
          positions[i   4] = by;
          positions[i   5] = bz;

          positions[i   6] = cx;
          positions[i   7] = cy;
          positions[i   8] = cz;

          if (i === 0) console.log(positions);

          // flat face normals

          pA.set(ax, ay, az);
          pB.set(bx, by, bz);
          pC.set(cx, cy, cz);

          cb.subVectors(pC, pB);
          ab.subVectors(pA, pB);
          cb.cross(ab);

          cb.normalize();

          const nx = cb.x;
          const ny = cb.y;
          const nz = cb.z;

          normals[i] = nx;
          normals[i   1] = ny;
          normals[i   2] = nz;

          normals[i   3] = nx;
          normals[i   4] = ny;
          normals[i   5] = nz;

          normals[i   6] = nx;
          normals[i   7] = ny;
          normals[i   8] = nz;

          // colors

          const vx = x / n   0.5;
          const vy = y / n   0.5;
          const vz = z / n   0.5;

          color.setRGB(vx, vy, vz);

          colors[i] = color.r;
          colors[i   1] = color.g;
          colors[i   2] = color.b;

          colors[i   3] = color.r;
          colors[i   4] = color.g;
          colors[i   5] = color.b;

          colors[i   6] = color.r;
          colors[i   7] = color.g;
          colors[i   8] = color.b;
        }

        geometry.setAttribute(
          "position",
          new THREE.BufferAttribute(positions, 3)
        );
        geometry.setAttribute("normal", new THREE.BufferAttribute(normals, 3));
        geometry.setAttribute("color", new THREE.BufferAttribute(colors, 3));

        geometry.computeBoundingSphere();

        let material = new THREE.MeshPhongMaterial({
          color: 0xaaaaaa,
          specular: 0xffffff,
          shininess: 250,
          side: THREE.DoubleSide,
          vertexColors: true,
        });

        mesh = new THREE.Mesh(geometry, material);
        scene.add(mesh);

What I would like to do is have the triangles start close together, and expand in every direction randomly.

How can I create an animation loop that updates the triangles position?

I have been using this example code from three.js's website: https://github.com/mrdoob/three.js/blob/master/examples/webgl_interactive_buffergeometry.html

edit: I was able to make the triangles expand with this.mesh.scale.z = 0.005 but the triangles themselves grow as well. Is there a way to hold the triangle size the same but change the area the cover?

CodePudding user response:

You could use morph targets.

Made a codepen available here:
https://codepen.io/cdeep/pen/WNENOmK

The code is inspired from the three.js example:
https://threejs.org/examples/?q=morph#webgl_morphtargets.

While assigning the initial position for each vertex, also assign the final position of where the vertex must end up after expanding.

In essence,

const positions = new Float32Array( triangles * 3 * 3 );
const morphedPositions = new Float32Array(triangles * 3 * 3);
...
...
geometry.morphAttributes.position = [];
geometry.morphAttributes.position[ 0 ] = new THREE.BufferAttribute( morphedPositions, 3);
mesh.morphTargetInfluences[ 0 ] = morphValue;

Animate the morphValue to influence how far the position attribute is closer to morphedPositions.

  • Related