有效地捕捉到三个顶点 [英] Efficiently snap to vertices in threejs
问题描述
我想制作一个捕捉功能来捕捉我的网格顶点。我尝试了几种解决方案。
I wanted to make a snapping functionality to snap to my mesh vertices. I experimented with several solutions.
一种解决方案是为场景中的所有顶点添加 THREE.Sprite
实例然后使用 rayCaster
来判断中的
数组。它工作得很好;在这里是一个演示的小提琴。 snap
点是否相交
想法是隐藏精灵在最终解决方案中,所以它们不会被渲染,但是我的场景非常大,所以它仍然意味着在我的场景中添加大量的精灵(对于每个顶点,可能有数千个精灵)来检测我的<$ c的快照点$ c> rayCaster 。
One solution is to add THREE.Sprite
instances for all vertices in my scene and then using a rayCaster
to decide whether there is a snap
point in the intersects
array. It works pretty well; here is a fiddle with a demo.
The idea is to hide the sprites in the final solution so they won't be rendered, but my scenes are pretty big so it would still mean adding lots of sprites to my scene (for every vertex one so possibly thousands of sprites) to detect snap points with my rayCaster
.
var intersects = rayCaster.intersectObject(scene, true);
var snap = null;
if (intersects.length > 0) {
var index = 0;
var intersect = intersects[index];
while (intersect && intersect.object.name === 'snap') {
snap = sprite.localToWorld(sprite.position.clone());
index++
intersect = intersects[index];
}
if (intersect) {
var face = intersect.face;
var point = intersect.point;
var object = intersect.object;
mouse3D.copy(point);
}
}
if (snap) {
renderer.domElement.style.cursor = 'pointer';
} else {
renderer.domElement.style.cursor = 'no-drop';
}
我还想到了使用 rayCaster
的结果进行数学计算的替代解决方案。 在这个小提琴中展示了该解决方案。
这里的想法是从对象的几何
(网格)测试所有顶点
相交,然后检查交叉点
和那些顶点之间的
距离
是否小于snap 阈值
。
I also thought of an alternative solution by doing the math using results from the rayCaster
. That solution is demonstrated in this fiddle.
The idea here is to test all vertices
from the geometry of the object
(mesh) that is intersected and then check whether the distance
between the intersect point
and those vertices
from the geometry is smaller then the snap threshold
.
var intersects = rayCaster.intersectObject(mesh, true);
if (intersects.length > 0) {
var distance, intersect = intersects[0];
var face = intersects[0].face;
var point = intersects[0].point;
var object = intersects[0].object;
var snap = null;
var test = object.worldToLocal(point);
var points = object.geometry.vertices;
for (var i = 0, il = points.length; i < il; i++) {
distance = points[i].distanceTo(test);
if (distance > threshold) {
continue;
}
snap = object.localToWorld(points[i]);
}
if (snap) {
sphereHelper.position.copy(snap);
sphereHelper.visible = true;
renderer.domElement.style.cursor = 'pointer';
} else {
sphereHelper.visible = false;
renderer.domElement.style.cursor = 'no-drop';
}
}
令人遗憾的是,在第二个解决方案中仅当鼠标从相交对象的表面移向顶点时才起作用。如果鼠标从对象外部移动(因此没有交叉点),则捕捉将不起作用。在这方面,第一个带有精灵的解决方案更加实用......
The sad thing is that in the second solution snap will only work when the mouse is moved from the surface of the intersected object towards a vertex. In case the mouse is moved from outside the object (so there is no intersection) the snapping won't work. In that respect the first solution with sprites is much more usable...
我的问题是,我是否过于复杂,是否有更好/更简单/更有效的方法这个?欢迎任何有关替代方法的建议。
My question, am I overcomplicating things and is there a better/simpler/more efficient way to do this? Any suggestions for alternative approaches are welcome.
推荐答案
我查看@meepzh他建议使用八叉树并使用以下解决方案来自github的 threeoctree 存储库。 THREE.Octree
类没有解决我的所有问题开箱即用所以
我添加了自定义方法 findClosestVertex
到可以这样使用的 THREE.Octree
类。
I looked into @meepzh his suggestion of using an octree and made the following solution using this threeoctree repository from github. The THREE.Octree
class did not solve all my problems out-of-the-box so
I added custom method findClosestVertex
to the THREE.Octree
class that can be used like this.
var snap = octree.findClosestVertex(position, radius);
snap
是 null
如果 radius
中没有顶点位置
并返回最近点( THREE.Vector3
)否则在世界空间中。
snap
is null
in case no vertices within the radius
of position
and returns the closest point (THREE.Vector3
) in world space otherwise.
我做了一个Pull-Request 这里是github 的新方法。
I made a Pull-Request here on github for the new method.
< a href =https://jsfiddle.net/wilt/3ahg0hmg/ =nofollow>这是一个小提琴演示
Here is a demo in a fiddle
这篇关于有效地捕捉到三个顶点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!