有效地捕捉到三个顶点 [英] Efficiently snap to vertices in threejs

查看:120
本文介绍了有效地捕捉到三个顶点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想制作一个捕捉功能来捕捉我的网格顶点。我尝试了几种解决方案。

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆