I am trying to figure out how to move particles from one shape to another. Using a shader is probably the most efficient way but I have a very base level knowledge of how to make them. This website is a good example of what I’m looking to do with the particles.
https://dala.craftedbygc.com/
Right now I’m mapping a couple objects and placing a particle at each vertex and doing the same with a sphere geometry. I’m looking to start with the egg particles and explode them out into the sphere and then pull them back into the shape of the unicorn.
const particleMaterial = new THREE.PointsMaterial({
color: 0xffffff, // Particle color
size: 1, // Particle size
opacity: 0.8,
depthWrite: false,
blending: THREE.AdditiveBlending,
});
async function loadUnicornPoints() {
return new Promise((resolve, reject) => {
loader.load("Unicorn.glb", function (object) {
const vertices = [];
object.scene.traverse(function (child) {
if (child.isMesh) {
vertices.push(...child.geometry.attributes.position.array);
}
});
const p_geom = new THREE.BufferGeometry();
p_geom.setAttribute(
"position",
new THREE.Float32BufferAttribute(vertices, 3)
);
const unicornPoints = new THREE.Points(p_geom, particleMaterial);
unicornPoints.rotateX(Math.PI / 2);
unicornPoints.scale.set(120, 120, 120);
resolve(unicornPoints); // Resolve the promise with unicornPoints
});
});
}
async function loadEggPoints() {
return new Promise((resolve, reject) => {
loader.load("Egg.glb", function (object) {
const vertices = [];
object.scene.traverse(function (child) {
if (child.isMesh) {
vertices.push(...child.geometry.attributes.position.array);
}
});
const p_geom = new THREE.BufferGeometry();
p_geom.setAttribute(
"position",
new THREE.Float32BufferAttribute(vertices, 3)
);
const unicornPoints = new THREE.Points(p_geom, particleMaterial);
unicornPoints.rotateX(Math.PI / 2);
unicornPoints.scale.set(20, 20, 20);
resolve(unicornPoints);
});
});
}
const eggPoints = await loadEggPoints();
scene.add(eggPoints);
const unicornPoints = await loadUnicornPoints();
scene.add(unicornPoints);
const particlesCount = eggPoints.geometry.attributes.position.count;
const positions = new Float32Array(particlesCount * 3);
const sphereRadius = 100;
for (let i = 0; i < particlesCount; i++) {
const phi = Math.acos(-1 + (2 * i) / particlesCount);
const theta = Math.sqrt(particlesCount * Math.PI) * phi;
// Calculate the coordinates with the scaled radius
const x = sphereRadius * Math.cos(theta) * Math.sin(phi);
const y = sphereRadius * Math.sin(theta) * Math.sin(phi);
const z = sphereRadius * Math.cos(phi);
positions[i * 3] = x;
positions[i * 3 + 1] = y;
positions[i * 3 + 2] = z;
}
const particleGeometry = new THREE.BufferGeometry();
particleGeometry.setAttribute(
"position",
new THREE.BufferAttribute(positions, 3)
);
const particleSystem = new THREE.Points(particleGeometry, particleMaterial);
scene.add(particleSystem);
I learn best by taking code that is close enough to what I need and figuring out how to make it work for my project. If anyone could get me started or point me to an example that is fairly similar, that would be much appreciated.
Also, I think a custom shader is the way to go but I would still be interested in how to do this using something like gsap