[英]Efficiently snap to vertices in threejs
我想要一個捕捉功能來捕捉到我的網格頂點。 我嘗試了幾種解決方案。
一種解決方案是為場景中的所有頂點添加THREE.Sprite
實例,然后使用rayCaster
來確定intersects
數組中是否存在snap
點。 它運作良好; 這是一個演示的小提琴 。
想法是將精靈隱藏在最終解決方案中,這樣就不會渲染它們,但是我的場景很大,因此仍然意味着向我的場景中添加很多精靈(每個頂點可能有數千個精靈)以進行檢測用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
結果進行數學運算的替代解決方案。 這種方法在這個小提琴中得到了證明。
這里的想法是從相交的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';
}
}
可悲的是,在第二種解決方案中,捕捉僅在鼠標從相交對象的表面移向頂點時才起作用。 萬一鼠標從對象外部移動(因此沒有交叉點),捕捉將不起作用。 在這方面,第一個使用Sprite的解決方案更加實用...
我的問題是,我是否使事情復雜化了,是否有更好/更簡單/更有效的方式來做到這一點? 歡迎對替代方法提出任何建議。
我調查了@meepzh他對使用八叉樹的建議,並使用了來自github的Threeoctree存儲庫提出了以下解決方案。 THREE.Octree
類不能立即解決我的所有問題,因此我向THREE.Octree
類添加了自定義方法findClosestVertex
,可以像這樣使用。
var snap = octree.findClosestVertex(position, radius);
如果position
radius
內沒有頂點,則snap
為null
,否則返回世界空間中的最近點( THREE.Vector3
)。
我在github上為新方法發出了Pull-Request。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.