【发布时间】:2016-06-30 16:38:17
【问题描述】:
我想制作一个捕捉功能来捕捉我的网格顶点。我尝试了几种解决方案。
一种解决方案是为场景中的所有顶点添加THREE.Sprite 实例,然后使用rayCaster 来确定@987654326@ 数组中是否存在snap 点。它工作得很好;这里is a fiddle with a demo.
这个想法是在最终解决方案中隐藏精灵,这样它们就不会被渲染,但是我的场景非常大,所以它仍然意味着向我的场景添加大量精灵(对于每个顶点,可能有数千个精灵)来检测使用我的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 的结果进行数学运算。该解决方案在in this fiddle 进行了演示。
这里的想法是从相交的object(网格)的几何中测试所有vertices,然后检查相交point和几何中的vertices之间的distance是否小于捕捉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';
}
}
可悲的是,在第二种解决方案中,只有当鼠标从相交对象的表面移向顶点时,捕捉才会起作用。如果鼠标从对象外部移动(因此没有交叉点),捕捉将不起作用。在这方面,第一个带有精灵的解决方案更有用......
我的问题是,我是否使事情过于复杂,是否有更好/更简单/更有效的方法来做到这一点?欢迎对替代方法提出任何建议。
【问题讨论】:
-
我假设您想点击点击?如果是这样,我可以帮助你,但我想在回答之前先确定一下。另外,当你捕捉到什么角度时,你想看什么?如果是立方体,那很明显,但如果你有一个顶点平面,你想从哪个角度看它就不太明显了
-
是的,这就是最终的想法。但补充说这不是问题,我更加努力地寻找正确的顶点以有效地捕捉到。该模型将有 1000 多个顶点,我需要以某种方式计算哪个顶点在鼠标的阈值距离内。
-
Raycaster.intersects[0] 应该总是返回它相交的最近的对象
-
@Rush2112 我明白这一点,我不确定您想在评论中指出什么。也许我的问题不够清楚,我会稍微编辑一下我的帖子......
-
您能否为每个对象的顶点构建一个八叉树或 kd 树(假设使用 sprites 方法)并通过它进行光线投射以找到您的顶点?或者,使用第二种方法,创建一个比您可以相交的网格稍大的盒子或球体,这样光线投射就不必一定要击中网格?我对 three.js 不太熟悉,但希望这会有所帮助。
标签: javascript three.js