This serves as a starting point rather than the final solution.
Points can be configured from any type of geometry, whether it's typical geometry or buffer geometry.
https://i.sstatic.net/m0ePz.png
Consider having a THREE.TextGeometry()
. In this case, setting points from it would look like this:
textGeo = new THREE.TextGeometry("ABC", {
font: font,
size: 2,
height: 0.25,
curveSegments: 1,
bevelEnabled: false
});
textGeo.computeBoundingBox();
textGeo.computeVertexNormals();
textGeo.center();
fillWithPoints(textGeo, 1000); // populate our text geometry with 1000 random points
textGeo.vertices.forEach(function(vertex){
vertex.startPoint = vertex.clone(); // store initial position of a vertex
vertex.direction = vertex.clone().normalize(); // set direction
})
textPoints = new THREE.Points(textGeo, new THREE.PointsMaterial({color: 0x00ff00, size: 0.1})); // only requiring geometry and THREE.PointsMaterial()
scene.add(textPoints);
To determine if a random point is within our geometry, we project all faces of the text geometry into 2D (x,y) and check if the point (with its x,y coordinates) falls inside one of the projected triangles (faces):
function isPointInside(point, geometry) {
var retVal = false;
for (var i = 0; i < geometry.faces.length; i++) { //loop through faces
face = geometry.faces[i];
a = geometry.vertices[face.a];
b = geometry.vertices[face.b];
c = geometry.vertices[face.c];
if (ptInTriangle(point, a, b, c)) {
var retVal = true;
break; // exit the loop if the point is in a projected triangle
}
}
return retVal;
}
where
function ptInTriangle(p, p0, p1, p2) {
// credits: http://jsfiddle.net/PerroAZUL/zdaY8/1/
var A = 1/2 * (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y);
var sign = A < 0 ? -1 : 1;
var s = (p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * p.x + (p0.x - p2.x) * p.y) * sign;
var t = (p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * p.x + (p1.x - p0.x) * p.y) * sign;
return s > 0 && t > 0 && (s + t) < 2 * A * sign;
}
In the animation loop, we utilize the properties of a vertex (startPoint and direction):
textGeo.vertices.forEach(function(vertex){
vertex.copy(vertex.startPoint).addScaledVector(vertex.direction, 5 + Math.sin(Date.now() * 0.001) * 5);
});
textGeo.verticesNeedUpdate = true; // crucial step after each rendering
jsfiddle example