From d96f7df19116b7d0aabedea6ef88c915a558870b Mon Sep 17 00:00:00 2001 From: Yeicor <4929005+Yeicor@users.noreply.github.com> Date: Thu, 29 Feb 2024 20:56:45 +0100 Subject: [PATCH] fixes for distances --- src/misc/distances.ts | 68 ++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/src/misc/distances.ts b/src/misc/distances.ts index ae6beb6..eb376d5 100644 --- a/src/misc/distances.ts +++ b/src/misc/distances.ts @@ -1,51 +1,67 @@ -import {Vector3} from 'three'; +import {BufferAttribute, InterleavedBufferAttribute, Vector3} from 'three'; import type {MObject3D} from "../tools/Selection.vue"; +function getCenterAndVertexList(obj: InstanceType): { + center: Vector3, + vertices: Array +} { + obj.updateMatrixWorld(); + let pos: InterleavedBufferAttribute = obj.geometry.getAttribute('position'); + let ind: BufferAttribute = obj.geometry.index; + let center = new Vector3(); + let vertices = []; + for (let i = 0; i < ind.count; i++) { + let index = ind.array[i]; + let vertex = new Vector3(pos.getX(index), pos.getY(index), pos.getZ(index)); + // vertex = obj.localToWorld(vertex); // TODO: Bad locations due to with model viewer? + center.add(vertex); + vertices.push(vertex); + } + center = center.divideScalar(ind.count); + console.log("center", center) + return {center, vertices}; +} + /** * Given two THREE.Object3D objects, returns their closest and farthest vertices, and the geometric centers. * All of them are approximated and should not be used for precise calculations. */ -export function distances( - a: InstanceType, b: InstanceType): { +export function distances(a: InstanceType, b: InstanceType): { min: Array, center: Array, max: Array } { // Simplify this problem (approximate) by using the distance between each of their vertices. + // Find the center of each object. + let {center: aCenter, vertices: aVertices} = getCenterAndVertexList(a); + let {center: bCenter, vertices: bVertices} = getCenterAndVertexList(b); + + // Find the closest and farthest vertices. // TODO: Compute actual min and max distances between the two objects. - a.updateMatrixWorld(); - b.updateMatrixWorld(); // FIXME: Working for points and lines, but not triangles... - const aVertices = a.geometry.getAttribute('position').array; - const aCenter = new Vector3(); - const bVertices = b.geometry.getAttribute('position').array; - const bCenter = new Vector3(); + // FIXME: Really slow... (use a BVH or something) let minDistance = Infinity; let minDistanceVertices = [new Vector3(), new Vector3()]; let maxDistance = -Infinity; let maxDistanceVertices = [new Vector3(), new Vector3()]; - for (let i = 0; i < aVertices.length; i += 3) { - const v = new Vector3(aVertices[i], aVertices[i + 1], aVertices[i + 2]); - //a.localToWorld(v); - aCenter.add(v); - for (let j = 0; j < bVertices.length; j += 3) { - const w = new Vector3(bVertices[j], bVertices[j + 1], bVertices[j + 2]); - //b.localToWorld(w); - bCenter.add(w); - const d = v.distanceTo(w); - if (d < minDistance) { - minDistance = d; - minDistanceVertices = [v, w]; + for (let i = 0; i < aVertices.length; i++) { + for (let j = 0; j < bVertices.length; j++) { + let distance = aVertices[i].distanceTo(bVertices[j]); + if (distance < minDistance) { + minDistance = distance; + minDistanceVertices[0] = aVertices[i]; + minDistanceVertices[1] = bVertices[j]; } - if (d > maxDistance) { - maxDistance = d; - maxDistanceVertices = [v, w]; + if (distance > maxDistance) { + maxDistance = distance; + maxDistanceVertices[0] = aVertices[i]; + maxDistanceVertices[1] = bVertices[j]; } } } - aCenter.divideScalar(aVertices.length / 3); - bCenter.divideScalar(bVertices.length / 3); + + // Return the results. return { min: minDistanceVertices, center: [aCenter, bCenter],