How I can fill a loaded STL mesh ( like Suzanne but NOT SIMPLE SHAPES LIKE CUBE etc) with random particles and animate it inside this geometry bounds with three.js ?
I see many examples but all of it for simple shapes with geometrical bounds like cube or sphere with limit by coordinates around center
was found this example: https://threejs.org/examples/?q=points#webgl_points_dynamic but it’s another solution when using vertexes of geometry of mesh like points material… I already do it , but how I can fill volume of this meshes?
I need algorithm to detect coordinates includes in the mesh volume ((
Also I think about raycasting from center of mesh, but this method also cant cover all volume of complex meshes (
Hi!
You can “raycast” your mesh with infinite ray from the desired point with the direction, for example, [1, 0, 0] against all the triangles in the mesh and count how many triangles were intersected. If the number of interstected faces is odd, then the point is inside the mesh.
I think about another method about slice of object for the first with Z and then by Y and after that by X and we have lines with only one coordinates for testing, but I think performance in this case is not so good as raycasing… will wait your concept
Okay, here it is. Works like I said: counts the number of intersected faces, and if it’s odd, then a point is inside of a mesh (geometry):
function fillWithPoints(geometry, count) {
var ray = new THREE.Ray()
var size = new THREE.Vector3();
geometry.computeBoundingBox();
let bbox = geometry.boundingBox;
let points = [];
var dir = new THREE.Vector3(1, 1, 1).normalize();
for (let i = 0; i < count; i++) {
let p = setRandomVector(bbox.min, bbox.max);
points.push(p);
}
function setRandomVector(min, max){
let v = new THREE.Vector3(
THREE.Math.randFloat(min.x, max.x),
THREE.Math.randFloat(min.y, max.y),
THREE.Math.randFloat(min.z, max.z)
);
if (!isInside(v)){return setRandomVector(min, max);}
return v;
}
function isInside(v){
ray.set(v, dir);
let counter = 0;
let pos = geometry.attributes.position;
let faces = pos.count / 3;
let vA = new THREE.Vector3(), vB = new THREE.Vector3(), vC = new THREE.Vector3();
for(let i = 0; i < faces; i++){
vA.fromBufferAttribute(pos, i * 3 + 0);
vB.fromBufferAttribute(pos, i * 3 + 1);
vC.fromBufferAttribute(pos, i * 3 + 2);
if (ray.intersectTriangle(vA, vB, vC)) counter++;
}
return counter % 2 == 1;
}
return new THREE.BufferGeometry().setFromPoints(points);
}