Hey everyone, I’m almost done adding a feature where you can measure stuff and snap it to the closest corner, middle, or edge. I’ve got it mostly working using something called a raycaster to figure out the measurements and snap points. However, the points where it snaps aren’t quite right yet. I’ve put red spheres in a screenshot to show where it’s trying to snap, the snapping to points is working but it’s not accurate. Could anyone help me figure out what I’m missing to get the snap points (corners, midpoints ) right?
Below is the code that I am using to calculate my snapping points.
Since the groups containing geometry data has specific names I have filter out only those and done the calculation.
calculateSnapPointsForNamedGroups(scene) {
var _this = this;
const snapPoints = {};
scene.traverse(child => {
// Check if the child's name matches the pattern "0 part X"
if (child.name.match(/^0 part \d+$/)) {
snapPoints[child.name] = { corners: [], midpoints: [] };
console.log(child)
child.traverse(descendant => {
// Check for Mesh with ExtrudeGeometry or BufferGeometry
if (descendant instanceof THREE.Mesh &&
(descendant.geometry instanceof THREE.ExtrudeGeometry || descendant.geometry instanceof THREE.BufferGeometry)) {
const geometry = descendant.geometry;
const vertices = _this.extractVerticesFromGeometry(geometry);
snapPoints[child.name].corners.push(...vertices);
if (!(geometry instanceof THREE.EdgesGeometry)) { // Avoid midpoint calculation for EdgesGeometry
const midpoints = _this.calculateMidpointsFromVertices(vertices);
snapPoints[child.name].midpoints.push(...midpoints);
}
}
// Check for LineSegments with EdgesGeometry
else if (descendant instanceof THREE.LineSegments && descendant.geometry instanceof THREE.EdgesGeometry) {
const corners = _this.extractVerticesFromGeometry(descendant.geometry);
snapPoints[child.name].corners.push(...corners);
}
});
}
});
// After calculating the snap points, add spheres for visualization
Object.values(snapPoints).forEach(groupSnapPoints => {
groupSnapPoints.corners.forEach(corner => {
this.addSphereAtPoint(corner, 0xff0f00); // Red spheres for corners
});
groupSnapPoints.midpoints.forEach(midpoint => {
this.addSphereAtPoint(midpoint, 0xff0f00); // Blue spheres for midpoints
});
});
return snapPoints;
}
extractVerticesFromGeometry(geometry) {
const vertices = [];
const positionAttribute = geometry.attributes.position;
for (let i = 0; i < positionAttribute.count; i++) {
const vertex = new THREE.Vector3().fromBufferAttribute(positionAttribute, i);
vertices.push(vertex);
}
return vertices;
}
calculateMidpointsFromVertices(vertices) {
const midpoints = [];
for (let i = 0; i < vertices.length - 1; i++) {
const midpoint = new THREE.Vector3()
.addVectors(vertices[i], vertices[i + 1])
.multiplyScalar(0.5);
midpoints.push(midpoint);
}
return midpoints;
}