有效地捕捉到三个顶点

时间:2016-06-30 16:38:17

标签: javascript three.js

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

一种解决方案是为场景中的所有顶点添加THREE.Sprite个实例,然后使用rayCaster来确定snap数组中是否存在intersects点。它工作得很好;这里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
这里的想法是从相交的vertices(网格)的几何中测试所有object,然后检查交叉distancepoint之间的vertices是否threshold来自几何体的1}}小于快照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'; } }

import csv
from xml.dom import minidom

def getAttribute(node,attribute,default=None):
    attr = node.getElementsByTagName(attribute)[0]
    return attr.firstChild.data if attr.firstChild else default

xml_doc = minidom.parse(open("users.xml"))
persons = xml_doc.getElementsByTagName('user')

users = []
attrs = ['name','screen_name','location','description','profile_image_url','friends_count','url']

mapping = {'user_id': 'user_id:ID(User)',
           'name': 'name:string',
           'screen_name': 'screen_name:string',
           'location': 'location:string',
           'description': 'description:string',
           'profile_image_url': 'profile_image_url:string',
           'friends_count': 'friends_count:int',
           'url': 'url:string'}

with open('users.csv','w') as csvfile:
    writer = csv.DictWriter(csvfile, fieldnames=mapping.values())
    writer.writeheader()
    for person in persons:
        user = {mapping[attr]: getAttribute(person, attr) for attr in attrs}
        user[mapping['user_id']] = getAttribute(person, 'id')

        writer.writerow(user)

令人遗憾的是,在第二个解决方案中,只有当鼠标从相交对象的表面移向顶点时,捕捉才会起作用。如果鼠标从对象外部移动(因此没有交叉点),则捕捉不起作用。在这方面,第一个带有精灵的解决方案更加实用......

我的问题是,我是否过于复杂,是否有更好/更简单/更有效的方法来做到这一点?欢迎任何有关替代方法的建议。

1 个答案:

答案 0 :(得分:2)

我查看了@meepzh他建议使用八叉树并使用this threeoctree repository from github制作了以下解决方案。 THREE.Octree课程没有解决我所有的问题开箱即用所以 我将自定义方法findClosestVertex添加到可以像这样使用的THREE.Octree类中。

var snap = octree.findClosestVertex(position, radius);
如果snap null内没有顶点,则{p> radiusposition,否则返回世界空间中最近的点(THREE.Vector3)。

我为新方法做了一个Pull-Request here on github

<强> Here is a demo in a fiddle