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?
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
.