我想制作一个捕捉功能来捕捉我的网格顶点。我尝试了几种解决方案。
一种解决方案是为场景中的所有顶点添加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
,然后检查交叉distance
和point
之间的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)
令人遗憾的是,在第二个解决方案中,只有当鼠标从相交对象的表面移向顶点时,捕捉才会起作用。如果鼠标从对象外部移动(因此没有交叉点),则捕捉不起作用。在这方面,第一个带有精灵的解决方案更加实用......
我的问题是,我是否过于复杂,是否有更好/更简单/更有效的方法来做到这一点?欢迎任何有关替代方法的建议。
答案 0 :(得分:2)
我查看了@meepzh他建议使用八叉树并使用this threeoctree repository from github制作了以下解决方案。 THREE.Octree
课程没有解决我所有的问题开箱即用所以
我将自定义方法findClosestVertex
添加到可以像这样使用的THREE.Octree
类中。
var snap = octree.findClosestVertex(position, radius);
如果snap
null
内没有顶点,则{p> radius
为position
,否则返回世界空间中最近的点(THREE.Vector3
)。
我为新方法做了一个Pull-Request here on github。
<强> Here is a demo in a fiddle 强>