Skip to content

Instantly share code, notes, and snippets.

@mindon
Created August 2, 2024 04:13
Show Gist options
  • Save mindon/62e963e41daba9903467faaac831bbd9 to your computer and use it in GitHub Desktop.
Save mindon/62e963e41daba9903467faaac831bbd9 to your computer and use it in GitHub Desktop.
Fill a geometry with points in THREE.js
// generate points inside a geometry, with THREE.js
// Mindon<[email protected]> https://mindon.dev, 2024.08.01
// Example code:
// const inside = Inside(THREE);
// const material = new THREE.PointsMaterial({color: 0xffffff, size: 0.25});
// scene.add(inside.points(num, geometry, material));
// // scene.add(new THREE.Points(inside.geometry(num, geometry), material));
export function Inside(THREE) {
const ray = new THREE.Ray();
const dir = new THREE.Vector3(1, 1, 1).normalize();
const dummys = [0, 0, 0].map(() => new THREE.Vector3());
const dummyTarget = new THREE.Vector3();
const boundings = {};
function isInside(v, geometry) {
ray.set(v, dir);
let k = 0;
const pos = geometry.attributes.position;
let d = dummys.slice(0);
for (let i = 0, imax = pos.count / 3; i < imax; i++) {
const d = dummys.map((p, j) => p.fromBufferAttribute(pos, i * 3 + j));
if (ray.intersectTriangle(d[0], d[1], d[2], false, dummyTarget)) {
k++;
}
}
return k % 2 == 1;
}
function fill(count, geometry) {
const tp = new Date().getTime();
geometry.computeBoundingBox();
const bbox = geometry.boundingBox;
const x = [bbox.min.x, bbox.max.x];
const y = [bbox.min.y, bbox.max.y];
const z = [bbox.min.z, bbox.max.z];
const { uuid } = geometry;
console.assert(x[1] > x[0] || y[1] > y[0] || z[1] > z[0]);
let points = [];
let n = 0;
let skipped = 0;
const breakAt = count * 20; // avoid dead-loop
const randFloat = THREE.MathUtils.randFloat;
while (n < count) {
let v = new THREE.Vector3(
randFloat(x[0], x[1]),
randFloat(y[0], y[1]),
randFloat(z[0], z[1]),
);
if (isInside(v, geometry)) {
points.push(v);
n++;
} else if (skipped++ > breakAt) {
break;
}
}
console.log(`geometry ${uuid}`);
console.log(`${count} points generated in ${new Date() - tp}ms`);
return new THREE.BufferGeometry().setFromPoints(points);
}
return {
geometry: fill, // geometry(count, geometry)
points: (count, geometry, material) =>
new THREE.Points(fill(count, geometry), material),
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment