簡體   English   中英

高效地捕捉Threejs中的頂點

[英]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內沒有頂點,則snapnull ,否則返回世界空間中的最近點( THREE.Vector3 )。

在github上為新方法發出了Pull-Request。

這是一個小提琴中的演示

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM