diff options
Diffstat (limited to 'source/blender/blenkernel/intern/bvhutils.c')
-rw-r--r-- | source/blender/blenkernel/intern/bvhutils.c | 96 |
1 files changed, 71 insertions, 25 deletions
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index 1100c1c0ef5..19838a634f8 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -41,7 +41,7 @@ #include "BLI_linklist.h" #include "BKE_DerivedMesh.h" - +#include "BKE_tessmesh.h" #include "BLI_math.h" #include "MEM_guardedalloc.h" @@ -555,7 +555,7 @@ BVHTree* bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float data->mesh = mesh; data->vert = mesh->getVertDataArray(mesh, CD_MVERT); - data->face = mesh->getFaceDataArray(mesh, CD_MFACE); + data->face = mesh->getTessFaceDataArray(mesh, CD_MFACE); data->sphere_radius = epsilon; } @@ -572,45 +572,91 @@ BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float if(tree == NULL) { int i; - int numFaces= mesh->getNumFaces(mesh); - MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT); - MFace *face = mesh->getFaceDataArray(mesh, CD_MFACE); + int numFaces= mesh->getNumTessFaces(mesh); - if(vert != NULL && face != NULL) + if(numFaces != 0) { /* Create a bvh-tree of the given target */ tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis); if(tree != NULL) { - /* XXX, for snap only, em & dm are assumed to be aligned, since dm is the em's cage */ - EditMesh *em= data->em_evil; + BMEditMesh *em= data->em_evil; if(em) { - EditFace *efa= em->faces.first; - for(i = 0; i < numFaces; i++, efa= efa->next) { - if(!(efa->f & 1) && efa->h==0 && !((efa->v1->f&1)+(efa->v2->f&1)+(efa->v3->f&1)+(efa->v4?efa->v4->f&1:0))) { + /*data->em_evil is only set for snapping, and only for the mesh of the object + which is currently open in edit mode. When set, the bvhtree should not contain + faces that will interfere with snapping (e.g. faces that are hidden/selected + or faces that have selected verts).*/ + + /* XXX, for snap only, em & dm are assumed to be aligned, since dm is the em's cage */ + + /*Insert BMesh-tesselation triangles into the bvh tree, unless they are hidden + and/or selected. Even if the faces themselves are not selected for the snapped + transform, having a vertex selected means the face (and thus it's tesselated + triangles) will be moving and will not be a good snap targets.*/ + for (i = 0; i < em->tottri; i++) { + BMLoop **tri = em->looptris[i]; + BMFace *f; + BMVert *v; + BMIter iter; + int insert; + + /*Each loop of the triangle points back to the BMFace it was tesselated from. + All three should point to the same face, so just use the face from the first + loop.*/ + f = tri[0]->f; + + /*If the looptris is ordered such that all triangles tesselated from a single + faces are consecutive elements in the array, then we could speed up the tests + below by using the insert value from the previous iteration.*/ + + /*Start with the assumption the triangle should be included for snapping.*/ + insert = 1; + + if (BM_TestHFlag(f, BM_SELECT) || BM_TestHFlag(f, BM_HIDDEN)) { + /*Don't insert triangles tesselated from faces that are hidden + or selected*/ + insert = 0; + } + else { + BM_ITER(v, &iter, em->bm, BM_VERTS_OF_FACE, f) { + if (BM_TestHFlag(v, BM_SELECT)) { + /*Don't insert triangles tesselated from faces that have + any selected verts.*/ + insert = 0; + } + } + } + + if (insert) + { + /*No reason found to block hit-testing the triangle for snap, + so insert it now.*/ + float co[4][3]; + copy_v3_v3(co[0], tri[0]->v->co); + copy_v3_v3(co[1], tri[1]->v->co); + copy_v3_v3(co[2], tri[2]->v->co); + + BLI_bvhtree_insert(tree, i, co[0], 3); + } + } + } + else { + MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT); + MFace *face = mesh->getTessFaceDataArray(mesh, CD_MFACE); + + if (vert != NULL && face != NULL) { + for(i = 0; i < numFaces; i++) { float co[4][3]; copy_v3_v3(co[0], vert[ face[i].v1 ].co); copy_v3_v3(co[1], vert[ face[i].v2 ].co); copy_v3_v3(co[2], vert[ face[i].v3 ].co); if(face[i].v4) copy_v3_v3(co[3], vert[ face[i].v4 ].co); - + BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3); } } } - else { - for(i = 0; i < numFaces; i++) { - float co[4][3]; - copy_v3_v3(co[0], vert[ face[i].v1 ].co); - copy_v3_v3(co[1], vert[ face[i].v2 ].co); - copy_v3_v3(co[2], vert[ face[i].v3 ].co); - if(face[i].v4) - copy_v3_v3(co[3], vert[ face[i].v4 ].co); - - BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3); - } - } BLI_bvhtree_balance(tree); //Save on cache for later use @@ -638,7 +684,7 @@ BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float data->mesh = mesh; data->vert = mesh->getVertDataArray(mesh, CD_MVERT); - data->face = mesh->getFaceDataArray(mesh, CD_MFACE); + data->face = mesh->getTessFaceDataArray(mesh, CD_MFACE); data->sphere_radius = epsilon; } |