Preparation of the environment – Global variables
Let’s start by creating some global variables :
// Wave configuration var wavespeed = 1; var wavewidth = 200; var waveheight = 100; var objects_margin = 20; //Array var waveobjects = new Array();
wavespeed
– Speed of the waveswavewidth
– Width of the waveswaveheight
– Height of the wavesobjects_margin
– Spacing between particleswaveobjects
– List of particles in the scene
Preparation of the environment – Creation of the particles
Then, using a nesting of for
loops, we create the particles composing our wave.
Our group of particles will be ordered in square via a simple increment on the X and Z axes.
Each particle is a Three.js Sprite
instance.
// ---------------- PARTICLES ---------------- const loader = new THREE.TextureLoader(); var particleTexture = loader.load( '../Particles/firefly.png' ); var spriteMaterial = new THREE.SpriteMaterial( { map: particleTexture, transparent : true, opacity :1, color: 0x000000 } ); for ( var x = 0; x < 100; x ++ ) { for ( var y = 0; y < 100; y ++ ) { // Sprite creation var mesh = new THREE.Sprite( spriteMaterial ); mesh.scale.set(10,10,10); // scale mesh.position.x = x * objects_margin; // POSITION X mesh.position.y = 0; mesh.position.z = y * objects_margin; //POSITION Y scene.add( mesh ); waveobjects.push(mesh); } }
As explained, the position of each Sprite
on the X and Z axes depends on its creation order in the for
loops.
The Particles we create, instances of Sprite
, are added to the scene and referenced in the waveobjects
structure (JavaScript Array
).
Wave creation
The motion of each particle is calculated using the Math.sin
function, its position in the group and the elapsed time.
Thus, the combination of these three parameters is used to calculate the position of each particle in the scene, and thus create a wave animation.
Three.js Clock and Math.sin
So, to keep track of the elapsed time, we create a Three.js Clock
class instance .
clock = new THREE.Clock();
Then, in our main loop :
function animate() { var delta = clock.getDelta(); var elapsed = clock.elapsedTime; [...] }
Note that the elapsed
variable contains the total number of elapsed seconds since the launch of the application.
Particle animation
Still in the main loop, we loop over the list of particles in order to modify the positions one by one :
for(var i = 0 ; i < waveobjects.length ; i++) { waveobjects[i].position.y = Math.cos( (elapsed + (waveobjects[i].position.x /wavewidth) + (waveobjects[i].position.z /wavewidth) ) *wavespeed ) * waveheight; }
As explained, we determine the new position of each particle by its position on the X and Z axes, the elapsed time and the Math.sin
method.
Final code and result
// Wave configuration var wavespeed = 1; var wavewidth = 200; var waveheight = 100; var objects_margin = 20; //Array var waveobjects = new Array(); [...] clock = new THREE.Clock(); [...] // ---------------- PARTICLES ---------------- const loader = new THREE.TextureLoader(); var particleTexture = loader.load( '../Particles/firefly.png' ); var spriteMaterial = new THREE.SpriteMaterial( { map: particleTexture, transparent : true, opacity :1, color: 0x000000 } ); for ( var x = 0; x < 100; x ++ ) { for ( var y = 0; y < 100; y ++ ) { // Sprite creation var mesh = new THREE.Sprite( spriteMaterial ); mesh.scale.set(10,10,10); // scale mesh.position.x = x * objects_margin; // POSITION X mesh.position.y = 0; mesh.position.z = y * objects_margin; //POSITION Y scene.add( mesh ); waveobjects.push(mesh); } } [...] function animate() { var delta = clock.getDelta(); var elapsed = clock.elapsedTime; requestAnimationFrame( animate ); for(var i = 0 ; i < waveobjects.length ; i++) { waveobjects[i].position.y = Math.cos( (elapsed + (waveobjects[i].position.x /wavewidth) + (waveobjects[i].position.z /wavewidth) ) *wavespeed ) * waveheight; } renderer.render( scene, camera ); }
[…] 24 juin 202125 août 2021 thomassifferlen 1 commentaire Available in English […]
[…] Creating a Wave of Particles with Three.JS Tagsparticlesspritethree.jsthreejs […]