У меня есть Mesh
, созданный с помощью BufferGeometry
.У меня также есть координаты, где моя мышь пересекает Mesh
, используя Raycaster
.
. Я пытаюсь обнаружить лица в радиусе (и касаясь) радиуса от точки пересечения.После того как я обнаружу «касательные» лица, я хочу покрасить лица.Поскольку я работаю с BufferGeometry
, я манипулирую атрибутами буфера в моей геометрии.
Вот мой код:
let vertexA;
let vertexB;
let vertexC;
let intersection;
const radius = 3;
const color = new THREE.Color('red');
const positionsAttr = mesh.geometry.attributes.position;
const colorAttr = mesh.geometry.attributes.color;
// on every mouseMove event, do below:
vertexA = new THREE.Vector3();
vertexB = new THREE.Vector3();
vertexC = new THREE.Vector3();
intersection = raycaster.intersectObject(mesh).point;
// function to detect tangent edge
function isEdgeTouched(v1, v2, point, radius) {
const line = new THREE.Line3();
const closestPoint = new THREE.Vector3();
line.set(v1, v2);
line.closestPointToPoint(point, true, closestPoint);
return point.distanceTo(closestPoint) < radius;
}
// function to color a face
function colorFace(faceIndex) {
colorAttr.setXYZ(faceIndex * 3 + 0, color.r, color.g, color.b);
colorAttr.setXYZ(faceIndex * 3 + 0, color.r, color.g, color.b);
colorAttr.setXYZ(faceIndex * 3 + 0, color.r, color.g, color.b);
colorAttr.needsUpdate = true;
}
// iterate over each face, color it if tangent
for (let i=0; i < (positionsAttr.count) /3); i++) {
vertexA.fromBufferAttribute(positionsAttr, i * 3 + 0);
vertexB.fromBufferAttribute(positionsAttr, i * 3 + 1);
vertexC.fromBufferAttribute(positionsAttr, i * 3 + 2);
if (isEdgeTouched(vertexA, vertexB, point, radius)
|| isEdgeTouched(vertexA, vertexB, point, radius)
|| isEdgeTouched(vertexA, vertexB, point, radius)) {
colorFace(i);
}
Хотя этот код работает, он выглядит оченьплохая производительность, особенно когда я работаю с геометрией с множеством граней.Когда я проверил монитор производительности в Chrome DevTools, я заметил, что функции isEdgeTouched
и colorFace
отнимают слишком много времени на каждой итерации для грани.
Есть ли способ улучшить этот алгоритм,или есть лучший алгоритм, чтобы использовать для обнаружения смежных лиц?
Edit
Я получил некоторую помощь от слабого канала THREE.js и изменил алгоритм для использования Three's Sphere
.Теперь я больше не выполняю «краевое» обнаружение, а проверяю, находится ли лицо в пределах Sphere
Обновленного кода ниже:
const sphere = new THREE.Sphere(intersection, radius);
// now checking if each vertex of a face is within sphere
// if all are, then color the face at index i
for (let i=0; i < (positionsAttr.count) /3); i++) {
vertexA.fromBufferAttribute(positionsAttr, i * 3 + 0);
vertexB.fromBufferAttribute(positionsAttr, i * 3 + 1);
vertexC.fromBufferAttribute(positionsAttr, i * 3 + 2);
if (sphere.containsPoint(vertexA)
&& sphere.containsPoint(vertexA)
&& sphere.containsPoint(vertexA)) {
colorFace(i);
}
Когда я проверял это в своем приложении,Я заметил, что производительность значительно улучшилась по сравнению с предыдущей версией.Однако мне все еще интересно, смогу ли я улучшить это дальше.