A Three js example making waves for the first time
So I wanted to start making some posts on three.js examples, and one of the first ideas that came to mind was to make a waves example. In this post I will be writing about helper method that I made that can be used to create an instance of buffered geometry that is set of points that move in a wave like pattern.
1 - This is a three.js example
This is a post on a three.js example where I made some waves. In this example I am just using the Points material, as in this example I only have points set out for the buffered geometry that I am using. As such it would be a good idea to get up to speed with the Points material, and buffered geometry if you have not done so before hand. This is also a more advanced post on three.js, if you are new to three.js you might want to look at my getting started post on three.js first.
1.1 - version numbers matter
When working out this example I was using revision 98 of three.js
2 - The wave Example
The wave example I made involves a helper method that can be used to create, or update geometry, buffered geometry, or just about anything by making the helper a higher-order function. This method accepts another method as one of the arguments that is passed the x,y,and z values for each point that will compose the vertices of the wave. I then use this method in conjunction with others to help make an update the geometry of the wave.
2.1 - The waveGrid helper
Here is the wave grid helper method that accepts a method that I can use to define what to do for each point in the grid of points. I use this to create an instance of buffer geometry and again later to update it in a loop.
opt.forPoint.call(opt.context, x * opt.xStep, y * opt.yStep, z * opt.zStep, i);
// step z, and point index
z += 1;
i += 3;
}
x += 1;
};
};
2.2 -Make Points helper
Here I have a method that makes use of my waveGrid method by making the initial state of the buffered geometry, as well as updating it as well.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// make a points mesh
var makePoints = function () {
var geometry = new THREE.BufferGeometry();
var points = [],
opt = {};
opt.forPoint = function (x, y, z, i) {
points.push(x, y, z);
};
waveGrid(opt);
var vertices = newFloat32Array(points);
// itemSize = 3 because there are 3 values (components) per vertex
geometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3));
returnnew THREE.Points(
// geometry as first argument
geometry,
// then Material
new THREE.PointsMaterial({
size: .05
}));
};
2.3 - Update Points
I again use my waveGrid method to update points.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// update points
var updatePoints = function (points, per) {
var position = points.geometry.getAttribute('position');
// update points
waveGrid({
waveOffset: per,
xStep: 0.125,
zStep: 0.125,
forPoint: function (x, y, z, i) {
position.array[i] = x - 2;
position.array[i + 1] = y - 2;
position.array[i + 2] = z - 2;
}
});
position.needsUpdate = true;
}
2.4 - Get it going
So now it is time to get this all working with the usual scene, camera, and renderer. I just use my makePoints helper to make the instance of a Points mesh that makes use of my geometry, and the Points material.