Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGermano Cavalcante <germano.costa@ig.com.br>2016-05-05 21:49:21 +0300
committerCampbell Barton <ideasman42@gmail.com>2016-05-05 22:01:51 +0300
commit0b5a0d84126e629394b198508789378eb5663561 (patch)
tree0b0614ef8cdd83d7f1578c82f5f22ffb44461f57 /source/blender
parent88b72925d0ef59dc0d67df05f4ad74742175653c (diff)
Transform/Snap: EditMesh/BKE_bvhutils API improvements
Separate the creation of trees from EditMesh from the creation of trees from DerivedMesh. This was meant to simplify the API, but didn't work out so well. `bvhtree_from_mesh_*` actually is working as `bvhtree_from_derivedmesh_*`. This is inconsistent with the trees created from EditMesh. Since for create them does not use the DerivedMesh. In such cases the dm is being used only to cache the tree in the struct DerivedMesh. What is immediately released once bvhtree is being used in functions that change(tag) the DM cleaning the cache. - Use a filter function so users of SnapObjectContext can define how edit-mesh elements are handled. - Remove em_evil. - bvhtree of EditMesh is now really cached in the snap functions. - Code becomes organized and easier to maintain. This is an important patch for future improvements in snapping functions.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h51
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c637
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c91
-rw-r--r--source/blender/blenlib/intern/math_base_inline.c1
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.c50
-rw-r--r--source/blender/bmesh/intern/bmesh_iterators.h12
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c1
-rw-r--r--source/blender/editors/curve/editcurve.c1
-rw-r--r--source/blender/editors/include/ED_transform.h63
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h107
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c2
-rw-r--r--source/blender/editors/transform/transform.h3
-rw-r--r--source/blender/editors/transform/transform_snap.c126
-rw-r--r--source/blender/editors/transform/transform_snap_object.c389
-rw-r--r--source/blender/editors/util/CMakeLists.txt1
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c1
18 files changed, 1007 insertions, 531 deletions
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index 08c0fcc0f3c..856923b7b0f 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -39,10 +39,30 @@
*/
struct DerivedMesh;
+struct BMEditMesh;
struct MVert;
struct MFace;
/**
+* struct that kepts basic information about a BVHTree build from a editmesh
+*/
+typedef struct BVHTreeFromEditMesh {
+ struct BVHTree *tree;
+
+ /* default callbacks to bvh nearest and raycast */
+ BVHTree_NearestPointCallback nearest_callback;
+ BVHTree_RayCastCallback raycast_callback;
+ BVHTree_NearestToRayCallback nearest_to_ray_callback;
+
+ /* radius for raycast */
+ float sphere_radius;
+
+ /* Private data */
+ struct BMEditMesh *em;
+
+} BVHTreeFromEditMesh;
+
+/**
* struct that kepts basic information about a BVHTree build from a mesh
*/
typedef struct BVHTreeFromMesh {
@@ -69,8 +89,6 @@ typedef struct BVHTreeFromMesh {
float sphere_radius;
/* Private data */
- void *em_evil;
- bool em_evil_all; /* ignore selection/hidden state, adding all loops to the tree */
bool cached;
} BVHTreeFromMesh;
@@ -85,11 +103,19 @@ typedef struct BVHTreeFromMesh {
*
* free_bvhtree_from_mesh should be called when the tree is no longer needed.
*/
+BVHTree *bvhtree_from_editmesh_verts(
+ BVHTreeFromEditMesh *data, struct BMEditMesh *em,
+ float epsilon, int tree_type, int axis);
+BVHTree *bvhtree_from_editmesh_verts_ex(
+ BVHTreeFromEditMesh *data, struct BMEditMesh *em,
+ const BLI_bitmap *mask, int verts_num_active,
+ float epsilon, int tree_type, int axis);
+
BVHTree *bvhtree_from_mesh_verts(
struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
BVHTree *bvhtree_from_mesh_verts_ex(
struct BVHTreeFromMesh *data, struct MVert *vert, const int numVerts,
- const bool vert_allocated, BLI_bitmap *mask, int numVerts_active,
+ const bool vert_allocated, const BLI_bitmap *mask, int verts_num_active,
float epsilon, int tree_type, int axis);
BVHTree *bvhtree_from_mesh_edges(
@@ -103,7 +129,15 @@ BVHTree *bvhtree_from_mesh_faces_ex(
struct BVHTreeFromMesh *data,
struct MVert *vert, const bool vert_allocated,
struct MFace *face, const int numFaces, const bool face_allocated,
- BLI_bitmap *mask, int numFaces_active,
+ const BLI_bitmap *mask, int numFaces_active,
+ float epsilon, int tree_type, int axis);
+
+BVHTree *bvhtree_from_editmesh_looptri(
+ BVHTreeFromEditMesh *data, struct BMEditMesh *em, float epsilon,
+ int tree_type, int axis);
+BVHTree *bvhtree_from_editmesh_looptri_ex(
+ BVHTreeFromEditMesh *data, struct BMEditMesh *em,
+ const BLI_bitmap *mask, int looptri_num_active,
float epsilon, int tree_type, int axis);
BVHTree *bvhtree_from_mesh_looptri(
@@ -113,12 +147,13 @@ BVHTree *bvhtree_from_mesh_looptri_ex(
const struct MVert *vert, const bool vert_allocated,
const struct MLoop *mloop, const bool loop_allocated,
const struct MLoopTri *looptri, const int looptri_num, const bool looptri_allocated,
- BLI_bitmap *mask, int looptri_num_active,
+ const BLI_bitmap *mask, int looptri_num_active,
float epsilon, int tree_type, int axis);
/**
* Frees data allocated by a call to bvhtree_from_mesh_*.
*/
+void free_bvhtree_from_editmesh(struct BVHTreeFromEditMesh *data);
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data);
/**
@@ -144,12 +179,6 @@ enum {
BVHTREE_FROM_EDGES = 1,
BVHTREE_FROM_FACES = 2,
BVHTREE_FROM_LOOPTRI = 3,
- /* all faces */
- BVHTREE_FROM_FACES_EDITMESH_ALL = 4,
- /* visible unselected, only used for transform snapping */
- BVHTREE_FROM_FACES_EDITMESH_SNAP = 5,
- // BVHTREE_FROM_EDGES_EDITMESH_SNAP = 6,
- BVHTREE_FROM_VERTS_EDITMESH_SNAP = 7,
};
typedef struct LinkNode *BVHCache;
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index abba61310a4..5e9c18544b7 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -151,10 +151,10 @@ static void mesh_looptri_nearest_point(void *userdata, int index, const float co
}
}
/* copy of function above (warning, should de-duplicate with editmesh_bvh.c) */
-static void editmesh_faces_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
+static void editmesh_looptri_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
{
- const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
- BMEditMesh *em = data->em_evil;
+ const BVHTreeFromEditMesh *data = userdata;
+ BMEditMesh *em = data->em;
const BMLoop **ltri = (const BMLoop **)em->looptris[index];
const float *t0, *t1, *t2;
@@ -240,10 +240,10 @@ static void mesh_looptri_spherecast(void *userdata, int index, const BVHTreeRay
}
}
/* copy of function above (warning, should de-duplicate with editmesh_bvh.c) */
-static void editmesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+static void editmesh_looptri_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
- const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
- BMEditMesh *em = data->em_evil;
+ const BVHTreeFromEditMesh *data = (BVHTreeFromEditMesh *)userdata;
+ BMEditMesh *em = data->em;
const BMLoop **ltri = (const BMLoop **)em->looptris[index];
const float *t0, *t1, *t2;
@@ -296,7 +296,7 @@ static void mesh_edges_nearest_point(void *userdata, int index, const float co[3
/* Helper, does all the point-spherecast work actually. */
static void mesh_verts_spherecast_do(
- const BVHTreeFromMesh *UNUSED(data), int index, const float v[3], const BVHTreeRay *ray, BVHTreeRayHit *hit)
+ int index, const float v[3], const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
float dist;
const float *r1;
@@ -314,6 +314,14 @@ static void mesh_verts_spherecast_do(
}
}
+static void editmesh_verts_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ const BVHTreeFromEditMesh *data = userdata;
+ BMVert *eve = BM_vert_at_index(data->em->bm, index);
+
+ mesh_verts_spherecast_do(index, eve->co, ray, hit);
+}
+
/* Callback to bvh tree raycast. The tree must have been built using bvhtree_from_mesh_verts.
* userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
static void mesh_verts_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
@@ -321,7 +329,7 @@ static void mesh_verts_spherecast(void *userdata, int index, const BVHTreeRay *r
const BVHTreeFromMesh *data = (BVHTreeFromMesh *)userdata;
const float *v = data->vert[index].co;
- mesh_verts_spherecast_do(data, index, v, ray, hit);
+ mesh_verts_spherecast_do(index, v, ray, hit);
}
/* Callback to bvh tree raycast. The tree must have been built using bvhtree_from_mesh_edges.
@@ -341,7 +349,7 @@ static void mesh_edges_spherecast(void *userdata, int index, const BVHTreeRay *r
/* In case we get a zero-length edge, handle it as a point! */
if (equals_v3v3(v1, v2)) {
- mesh_verts_spherecast_do(data, index, v1, ray, hit);
+ mesh_verts_spherecast_do(index, v1, ray, hit);
return;
}
@@ -380,75 +388,70 @@ static void mesh_edges_spherecast(void *userdata, int index, const BVHTreeRay *r
/** \name Vertex Builder
* \{ */
-static BVHTree *bvhtree_from_mesh_verts_create_tree(
+static BVHTree *bvhtree_from_editmesh_verts_create_tree(
float epsilon, int tree_type, int axis,
- BMEditMesh *em, const int *index_array,
- MVert *vert, const int numVerts,
- BLI_bitmap *mask, int numVerts_active)
+ BMEditMesh *em, const int verts_num,
+ const BLI_bitmap *verts_mask, int verts_num_active)
{
BVHTree *tree = NULL;
- BMVert *eve = NULL;
int i;
- int index = 0;
- if (em != NULL) {
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ if (verts_mask && verts_num_active == -1) {
+ verts_num_active = 0;
+ for (i = 0; i < verts_num; i++) {
+ if (BLI_BITMAP_TEST_BOOL(verts_mask, i)) {
+ verts_num_active++;
+ }
+ }
+ }
+ else if (!verts_mask) {
+ verts_num_active = verts_num;
+ }
+
+ tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis);
+
+ if (tree) {
+ BMIter iter;
+ BMVert *eve;
+ BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ if (verts_mask && !BLI_BITMAP_TEST_BOOL(verts_mask, i)) {
+ continue;
+ }
+ BLI_bvhtree_insert(tree, i, eve->co, 1);
+ }
+ BLI_bvhtree_balance(tree);
}
+
+ return tree;
+}
+
+static BVHTree *bvhtree_from_mesh_verts_create_tree(
+ float epsilon, int tree_type, int axis,
+ MVert *vert, const int verts_num,
+ const BLI_bitmap *verts_mask, int verts_num_active)
+{
+ BVHTree *tree = NULL;
+ int i;
if (vert) {
- if (mask && numVerts_active < 0) {
- numVerts_active = 0;
- for (i = 0; i < numVerts; i++) {
- if (BLI_BITMAP_TEST_BOOL(mask, i)) {
- if (em != NULL) {
- if (index_array) {
- index = index_array[i];
- if (index == ORIGINDEX_NONE) {
- continue;
- }
- }
- else {
- index = i;
- }
-
- eve = BM_vert_at_index(em->bm, index);
- if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN) ||
- BM_elem_flag_test(eve, BM_ELEM_SELECT))
- {
- continue;
- }
- }
- numVerts_active++;
+ if (verts_mask && verts_num_active == -1) {
+ verts_num_active = 0;
+ for (i = 0; i < verts_num; i++) {
+ if (BLI_BITMAP_TEST_BOOL(verts_mask, i)) {
+ verts_num_active++;
}
}
}
- else if (!mask) {
- numVerts_active = numVerts;
+ else if (!verts_mask) {
+ verts_num_active = verts_num;
}
- tree = BLI_bvhtree_new(numVerts_active, epsilon, tree_type, axis);
+ tree = BLI_bvhtree_new(verts_num_active, epsilon, tree_type, axis);
if (tree) {
- for (i = 0; i < numVerts; i++) {
- if (mask && !BLI_BITMAP_TEST_BOOL(mask, i)) {
+ for (i = 0; i < verts_num; i++) {
+ if (verts_mask && !BLI_BITMAP_TEST_BOOL(verts_mask, i)) {
continue;
}
- if (em != NULL) {
- if (index_array) {
- index = index_array[i];
- if (index == ORIGINDEX_NONE) {
- continue;
- }
- }
- else {
- index = i;
- }
-
- eve = BM_vert_at_index(em->bm, index);
- if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN) ||
- BM_elem_flag_test(eve, BM_ELEM_SELECT))
- {
- continue;
- }
- }
BLI_bvhtree_insert(tree, i, vert[i].co, 1);
}
@@ -488,17 +491,51 @@ static void bvhtree_from_mesh_verts_setup_data(
}
}
+/* Builds a bvh tree where nodes are the vertices of the given em */
+BVHTree *bvhtree_from_editmesh_verts_ex(
+ BVHTreeFromEditMesh *data, BMEditMesh *em,
+ const BLI_bitmap *verts_mask, int verts_num_active,
+ float epsilon, int tree_type, int axis)
+{
+ int vert_num = em->bm->totvert;
+
+ BVHTree *tree = bvhtree_from_editmesh_verts_create_tree(
+ epsilon, tree_type, axis,
+ em, vert_num, verts_mask, verts_num_active);
+
+ if (tree) {
+ memset(data, 0, sizeof(*data));
+ data->tree = tree;
+ data->em = em;
+ data->nearest_callback = NULL;
+ data->raycast_callback = editmesh_verts_spherecast;
+ data->nearest_to_ray_callback = NULL;
+ }
+
+ return tree;
+}
+BVHTree *bvhtree_from_editmesh_verts(
+ BVHTreeFromEditMesh *data, BMEditMesh *em,
+ float epsilon, int tree_type, int axis)
+{
+ return bvhtree_from_editmesh_verts_ex(
+ data, em,
+ NULL, -1,
+ epsilon, tree_type, axis);
+}
+
+
/* Builds a bvh tree where nodes are the vertices of the given dm */
-BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
+BVHTree *bvhtree_from_mesh_verts(
+ BVHTreeFromMesh *data, DerivedMesh *dm,
+ float epsilon, int tree_type, int axis)
{
- BMEditMesh *em = data->em_evil;
- const int bvhcache_type = em ? BVHTREE_FROM_VERTS_EDITMESH_SNAP : BVHTREE_FROM_VERTS;
BVHTree *tree;
MVert *vert;
bool vert_allocated;
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
+ tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTS);
BLI_rw_mutex_unlock(&cache_rwlock);
vert = DM_get_vert_array(dm, &vert_allocated);
@@ -506,26 +543,20 @@ BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *dm, float e
/* Not in cache */
if (tree == NULL) {
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
+ tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_VERTS);
if (tree == NULL) {
- int vert_num, *index_array = NULL;
- if (em != NULL) {
- vert_num = em->bm->totvert;
- index_array = dm->getVertDataArray(dm, CD_ORIGINDEX);
- }
- else {
- vert_num = dm->getNumVerts(dm);
- BLI_assert(vert_num != 0);
- }
+
+ int vert_num = dm->getNumVerts(dm);
+ BLI_assert(vert_num != 0);
+
tree = bvhtree_from_mesh_verts_create_tree(
epsilon, tree_type, axis,
- em, index_array,
vert, vert_num, NULL, -1);
if (tree) {
/* Save on cache for later use */
/* printf("BVHTree built and saved on cache\n"); */
- bvhcache_insert(&dm->bvhCache, tree, bvhcache_type);
+ bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_VERTS);
}
}
BLI_rw_mutex_unlock(&cache_rwlock);
@@ -544,14 +575,15 @@ BVHTree *bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *dm, float e
* Builds a bvh tree where nodes are the given vertices (note: does not copy given mverts!).
* \param vert_allocated if true, vert freeing will be done when freeing data.
* \param mask if not null, true elements give which vert to add to BVH tree.
- * \param numVerts_active if >= 0, number of active verts to add to BVH tree (else will be computed from mask).
+ * \param verts_num_active if >= 0, number of active verts to add to BVH tree (else will be computed from mask).
*/
BVHTree *bvhtree_from_mesh_verts_ex(
- BVHTreeFromMesh *data, MVert *vert, const int numVerts, const bool vert_allocated,
- BLI_bitmap *mask, int numVerts_active,
+ BVHTreeFromMesh *data, MVert *vert, const int verts_num, const bool vert_allocated,
+ const BLI_bitmap *verts_mask, int verts_num_active,
float epsilon, int tree_type, int axis)
{
- BVHTree *tree = bvhtree_from_mesh_verts_create_tree(epsilon, tree_type, axis, NULL, NULL, vert, numVerts, mask, numVerts_active);
+ BVHTree *tree = bvhtree_from_mesh_verts_create_tree(
+ epsilon, tree_type, axis, vert, verts_num, verts_mask, verts_num_active);
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_verts_setup_data(data, tree, false, epsilon, vert, vert_allocated);
@@ -568,7 +600,9 @@ BVHTree *bvhtree_from_mesh_verts_ex(
* \{ */
/* Builds a bvh tree where nodes are the edges of the given dm */
-BVHTree *bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
+BVHTree *bvhtree_from_mesh_edges(
+ BVHTreeFromMesh *data, DerivedMesh *dm,
+ float epsilon, int tree_type, int axis)
{
BVHTree *tree;
MVert *vert;
@@ -655,107 +689,43 @@ BVHTree *bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *dm, float e
static BVHTree *bvhtree_from_mesh_faces_create_tree(
float epsilon, int tree_type, int axis,
- BMEditMesh *em, const bool em_all,
- MVert *vert, MFace *face, const int numFaces,
- BLI_bitmap *mask, int numFaces_active)
+ MVert *vert, MFace *face, const int faces_num,
+ const BLI_bitmap *faces_mask, int faces_num_active)
{
BVHTree *tree = NULL;
int i;
- if (numFaces) {
- if (mask && numFaces_active < 0) {
- numFaces_active = 0;
- for (i = 0; i < numFaces; i++) {
- if (BLI_BITMAP_TEST_BOOL(mask, i)) {
- numFaces_active++;
+ if (faces_num) {
+ if (faces_mask && faces_num_active == -1) {
+ faces_num_active = 0;
+ for (i = 0; i < faces_num; i++) {
+ if (BLI_BITMAP_TEST_BOOL(faces_mask, i)) {
+ faces_num_active++;
}
}
}
- else if (!mask) {
- numFaces_active = numFaces;
+ else if (!faces_mask) {
+ faces_num_active = faces_num;
}
/* Create a bvh-tree of the given target */
/* printf("%s: building BVH, total=%d\n", __func__, numFaces); */
- tree = BLI_bvhtree_new(numFaces_active, epsilon, tree_type, axis);
+ tree = BLI_bvhtree_new(faces_num_active, epsilon, tree_type, axis);
if (tree) {
- if (em) {
- const struct BMLoop *(*looptris)[3] = (void *)em->looptris;
-
- /* avoid double-up on face searches for quads-ngons */
- bool insert_prev = false;
- BMFace *f_prev = NULL;
-
- /* 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). */
-
- /* Insert BMesh-tessellation 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 tessellated
- * triangles) will be moving and will not be a good snap targets. */
- for (i = 0; i < numFaces; i++) {
- const BMLoop **ltri = looptris[i];
- BMFace *f = ltri[0]->f;
- bool insert = mask ? BLI_BITMAP_TEST_BOOL(mask, i) : true;
-
- /* Start with the assumption the triangle should be included for snapping. */
- if (f == f_prev) {
- insert = insert_prev;
- }
- else if (insert) {
- if (em_all) {
- /* pass */
- }
- else if (BM_elem_flag_test(f, BM_ELEM_SELECT) || BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- /* Don't insert triangles tessellated from faces that are hidden or selected */
- insert = false;
- }
- else {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
- /* Don't insert triangles tessellated from faces that have any selected verts */
- insert = false;
- break;
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- /* skip if face doesn't change */
- f_prev = f;
- insert_prev = insert;
+ if (vert && face) {
+ for (i = 0; i < faces_num; i++) {
+ float co[4][3];
+ if (faces_mask && !BLI_BITMAP_TEST_BOOL(faces_mask, i)) {
+ continue;
}
- if (insert) {
- /* No reason found to block hit-testing the triangle for snap, so insert it now.*/
- float co[3][3];
- copy_v3_v3(co[0], ltri[0]->v->co);
- copy_v3_v3(co[1], ltri[1]->v->co);
- copy_v3_v3(co[2], ltri[2]->v->co);
+ 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], 3);
- }
- }
- }
- else {
- if (vert && face) {
- for (i = 0; i < numFaces; i++) {
- float co[4][3];
- if (mask && !BLI_BITMAP_TEST_BOOL(mask, i)) {
- continue;
- }
-
- 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_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
}
}
BLI_bvhtree_balance(tree);
@@ -766,33 +736,24 @@ static BVHTree *bvhtree_from_mesh_faces_create_tree(
}
static void bvhtree_from_mesh_faces_setup_data(
- BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached,
- float epsilon, BMEditMesh *em,
+ BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, float epsilon,
MVert *vert, const bool vert_allocated,
MFace *face, const bool face_allocated)
{
memset(data, 0, sizeof(*data));
- data->em_evil = em;
if (tree) {
data->tree = tree;
data->cached = is_cached;
- if (em) {
- data->nearest_callback = editmesh_faces_nearest_point;
- data->raycast_callback = editmesh_faces_spherecast;
- data->nearest_to_ray_callback = NULL;
- }
- else {
- data->nearest_callback = mesh_faces_nearest_point;
- data->raycast_callback = mesh_faces_spherecast;
- data->nearest_to_ray_callback = NULL;
-
- data->vert = vert;
- data->vert_allocated = vert_allocated;
- data->face = face;
- data->face_allocated = face_allocated;
- }
+ data->nearest_callback = mesh_faces_nearest_point;
+ data->raycast_callback = mesh_faces_spherecast;
+ data->nearest_to_ray_callback = NULL;
+
+ data->vert = vert;
+ data->vert_allocated = vert_allocated;
+ data->face = face;
+ data->face_allocated = face_allocated;
data->sphere_radius = epsilon;
}
@@ -807,54 +768,37 @@ static void bvhtree_from_mesh_faces_setup_data(
}
/* Builds a bvh tree where nodes are the tesselated faces of the given dm */
-BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
+BVHTree *bvhtree_from_mesh_faces(
+ BVHTreeFromMesh *data, DerivedMesh *dm,
+ float epsilon, int tree_type, int axis)
{
- BMEditMesh *em = data->em_evil;
- const int bvhcache_type = em ?
- (data->em_evil_all ? BVHTREE_FROM_FACES_EDITMESH_ALL : BVHTREE_FROM_FACES_EDITMESH_SNAP) :
- BVHTREE_FROM_FACES;
BVHTree *tree;
MVert *vert = NULL;
MFace *face = NULL;
bool vert_allocated = false, face_allocated = false;
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
+ tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_FACES);
BLI_rw_mutex_unlock(&cache_rwlock);
- if (em == NULL) {
- vert = DM_get_vert_array(dm, &vert_allocated);
- face = DM_get_tessface_array(dm, &face_allocated);
- }
+ vert = DM_get_vert_array(dm, &vert_allocated);
+ face = DM_get_tessface_array(dm, &face_allocated);
/* Not in cache */
if (tree == NULL) {
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
+ tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_FACES);
if (tree == NULL) {
- int numFaces;
-
- /* BMESH specific check that we have tessfaces,
- * we _could_ tessellate here but rather not - campbell
- *
- * this assert checks we have tessfaces,
- * if not caller should use DM_ensure_tessface() */
- if (em) {
- numFaces = em->tottri;
- }
- else {
- numFaces = dm->getNumTessFaces(dm);
- BLI_assert(!(numFaces == 0 && dm->getNumPolys(dm) != 0));
- }
+ int numFaces = dm->getNumTessFaces(dm);
+ BLI_assert(!(numFaces == 0 && dm->getNumPolys(dm) != 0));
tree = bvhtree_from_mesh_faces_create_tree(
epsilon, tree_type, axis,
- em, (bvhcache_type == BVHTREE_FROM_FACES_EDITMESH_ALL),
vert, face, numFaces, NULL, -1);
if (tree) {
/* Save on cache for later use */
/* printf("BVHTree built and saved on cache\n"); */
- bvhcache_insert(&dm->bvhCache, tree, bvhcache_type);
+ bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_FACES);
}
}
BLI_rw_mutex_unlock(&cache_rwlock);
@@ -864,7 +808,7 @@ BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *dm, float e
}
/* Setup BVHTreeFromMesh */
- bvhtree_from_mesh_faces_setup_data(data, tree, true, epsilon, em, vert, vert_allocated, face, face_allocated);
+ bvhtree_from_mesh_faces_setup_data(data, tree, true, epsilon, vert, vert_allocated, face, face_allocated);
return data->tree;
}
@@ -879,16 +823,16 @@ BVHTree *bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *dm, float e
BVHTree *bvhtree_from_mesh_faces_ex(
BVHTreeFromMesh *data, MVert *vert, const bool vert_allocated,
MFace *face, const int numFaces, const bool face_allocated,
- BLI_bitmap *mask, int numFaces_active, float epsilon, int tree_type, int axis)
+ const BLI_bitmap *faces_mask, int faces_num_active,
+ float epsilon, int tree_type, int axis)
{
BVHTree *tree = bvhtree_from_mesh_faces_create_tree(
epsilon, tree_type, axis,
- NULL, false,
vert, face, numFaces,
- mask, numFaces_active);
+ faces_mask, faces_num_active);
/* Setup BVHTreeFromMesh */
- bvhtree_from_mesh_faces_setup_data(data, tree, false, epsilon, NULL, vert, vert_allocated, face, face_allocated);
+ bvhtree_from_mesh_faces_setup_data(data, tree, false, epsilon, vert, vert_allocated, face, face_allocated);
return data->tree;
}
@@ -901,25 +845,24 @@ BVHTree *bvhtree_from_mesh_faces_ex(
/** \name LoopTri Face Builder
* \{ */
-static BVHTree *bvhtree_from_mesh_looptri_create_tree(
+static BVHTree *bvhtree_from_editmesh_looptri_create_tree(
float epsilon, int tree_type, int axis,
- BMEditMesh *em, const bool em_all,
- const MVert *vert, const MLoop *mloop, const MLoopTri *looptri, const int looptri_num,
- BLI_bitmap *mask, int looptri_num_active)
+ BMEditMesh *em, const int looptri_num,
+ const BLI_bitmap *looptri_mask, int looptri_num_active)
{
BVHTree *tree = NULL;
int i;
if (looptri_num) {
- if (mask && looptri_num_active < 0) {
+ if (looptri_mask && looptri_num_active == -1) {
looptri_num_active = 0;
for (i = 0; i < looptri_num; i++) {
- if (BLI_BITMAP_TEST_BOOL(mask, i)) {
+ if (BLI_BITMAP_TEST_BOOL(looptri_mask, i)) {
looptri_num_active++;
}
}
}
- else if (!mask) {
+ else if (!looptri_mask) {
looptri_num_active = looptri_num;
}
@@ -930,52 +873,13 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(
if (em) {
const struct BMLoop *(*looptris)[3] = (void *)em->looptris;
- /* avoid double-up on face searches for quads-ngons */
- bool insert_prev = false;
- BMFace *f_prev = NULL;
-
- /* 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). */
-
/* Insert BMesh-tessellation 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 tessellated
* triangles) will be moving and will not be a good snap targets. */
for (i = 0; i < looptri_num; i++) {
const BMLoop **ltri = looptris[i];
- BMFace *f = ltri[0]->f;
- bool insert = mask ? BLI_BITMAP_TEST_BOOL(mask, i) : true;
-
- /* Start with the assumption the triangle should be included for snapping. */
- if (f == f_prev) {
- insert = insert_prev;
- }
- else if (insert) {
- if (em_all) {
- /* pass */
- }
- else if (BM_elem_flag_test(f, BM_ELEM_SELECT) || BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- /* Don't insert triangles tessellated from faces that are hidden or selected */
- insert = false;
- }
- else {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- do {
- if (BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) {
- /* Don't insert triangles tessellated from faces that have any selected verts */
- insert = false;
- break;
- }
- } while ((l_iter = l_iter->next) != l_first);
- }
-
- /* skip if face doesn't change */
- f_prev = f;
- insert_prev = insert;
- }
+ bool insert = looptri_mask ? BLI_BITMAP_TEST_BOOL(looptri_mask, i) : true;
if (insert) {
/* No reason found to block hit-testing the triangle for snap, so insert it now.*/
@@ -988,20 +892,50 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(
}
}
}
- else {
- if (vert && looptri) {
- for (i = 0; i < looptri_num; i++) {
- float co[3][3];
- if (mask && !BLI_BITMAP_TEST_BOOL(mask, i)) {
- continue;
- }
+ BLI_bvhtree_balance(tree);
+ }
+ }
- copy_v3_v3(co[0], vert[mloop[looptri[i].tri[0]].v].co);
- copy_v3_v3(co[1], vert[mloop[looptri[i].tri[1]].v].co);
- copy_v3_v3(co[2], vert[mloop[looptri[i].tri[2]].v].co);
+ return tree;
+}
- BLI_bvhtree_insert(tree, i, co[0], 3);
+static BVHTree *bvhtree_from_mesh_looptri_create_tree(
+ float epsilon, int tree_type, int axis,
+ const MVert *vert, const MLoop *mloop, const MLoopTri *looptri, const int looptri_num,
+ const BLI_bitmap *looptri_mask, int looptri_num_active)
+{
+ BVHTree *tree = NULL;
+ int i;
+
+ if (looptri_num) {
+ if (looptri_mask && looptri_num_active == -1) {
+ looptri_num_active = 0;
+ for (i = 0; i < looptri_num; i++) {
+ if (BLI_BITMAP_TEST_BOOL(looptri_mask, i)) {
+ looptri_num_active++;
+ }
+ }
+ }
+ else if (!looptri_mask) {
+ looptri_num_active = looptri_num;
+ }
+
+ /* Create a bvh-tree of the given target */
+ /* printf("%s: building BVH, total=%d\n", __func__, numFaces); */
+ tree = BLI_bvhtree_new(looptri_num_active, epsilon, tree_type, axis);
+ if (tree) {
+ if (vert && looptri) {
+ for (i = 0; i < looptri_num; i++) {
+ float co[3][3];
+ if (looptri_mask && !BLI_BITMAP_TEST_BOOL(looptri_mask, i)) {
+ continue;
}
+
+ copy_v3_v3(co[0], vert[mloop[looptri[i].tri[0]].v].co);
+ copy_v3_v3(co[1], vert[mloop[looptri[i].tri[1]].v].co);
+ copy_v3_v3(co[2], vert[mloop[looptri[i].tri[2]].v].co);
+
+ BLI_bvhtree_insert(tree, i, co[0], 3);
}
}
BLI_bvhtree_balance(tree);
@@ -1012,36 +946,27 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(
}
static void bvhtree_from_mesh_looptri_setup_data(
- BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached,
- float epsilon, BMEditMesh *em,
+ BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, float epsilon,
const MVert *vert, const bool vert_allocated,
const MLoop *mloop, const bool loop_allocated,
const MLoopTri *looptri, const bool looptri_allocated)
{
memset(data, 0, sizeof(*data));
- data->em_evil = em;
if (tree) {
data->tree = tree;
data->cached = is_cached;
- if (em) {
- data->nearest_callback = editmesh_faces_nearest_point;
- data->raycast_callback = editmesh_faces_spherecast;
- data->nearest_to_ray_callback = NULL;
- }
- else {
- data->nearest_callback = mesh_looptri_nearest_point;
- data->raycast_callback = mesh_looptri_spherecast;
- data->nearest_to_ray_callback = NULL;
-
- data->vert = vert;
- data->vert_allocated = vert_allocated;
- data->loop = mloop;
- data->loop_allocated = loop_allocated;
- data->looptri = looptri;
- data->looptri_allocated = looptri_allocated;
- }
+ data->nearest_callback = mesh_looptri_nearest_point;
+ data->raycast_callback = mesh_looptri_spherecast;
+ data->nearest_to_ray_callback = NULL;
+
+ data->vert = vert;
+ data->vert_allocated = vert_allocated;
+ data->loop = mloop;
+ data->loop_allocated = loop_allocated;
+ data->looptri = looptri;
+ data->looptri_allocated = looptri_allocated;
data->sphere_radius = epsilon;
}
@@ -1059,16 +984,52 @@ static void bvhtree_from_mesh_looptri_setup_data(
}
/**
+ * Builds a bvh tree where nodes are the looptri faces of the given bm
+ */
+BVHTree *bvhtree_from_editmesh_looptri_ex(
+ BVHTreeFromEditMesh *data, BMEditMesh *em,
+ const BLI_bitmap *looptri_mask, int looptri_num_active,
+ float epsilon, int tree_type, int axis)
+{
+ /* BMESH specific check that we have tessfaces,
+ * we _could_ tessellate here but rather not - campbell
+ *
+ * this assert checks we have tessfaces,
+ * if not caller should use DM_ensure_tessface() */
+
+ BVHTree *tree = bvhtree_from_editmesh_looptri_create_tree(
+ epsilon, tree_type, axis,
+ em, em->tottri, looptri_mask, looptri_num_active);
+
+ if (tree) {
+ data->tree = tree;
+ data->nearest_callback = editmesh_looptri_nearest_point;
+ data->raycast_callback = editmesh_looptri_spherecast;
+ data->nearest_to_ray_callback = NULL;
+ data->sphere_radius = 0.0f;
+ data->em = em;
+ }
+ return tree;
+}
+
+BVHTree *bvhtree_from_editmesh_looptri(
+ BVHTreeFromEditMesh *data, BMEditMesh *em,
+ float epsilon, int tree_type, int axis)
+{
+ return bvhtree_from_editmesh_looptri_ex(
+ data, em, NULL, -1,
+ epsilon, tree_type, axis);
+}
+
+/**
* Builds a bvh tree where nodes are the looptri faces of the given dm
*
* \note for editmesh this is currently a duplicate of bvhtree_from_mesh_faces
*/
-BVHTree *bvhtree_from_mesh_looptri(BVHTreeFromMesh *data, DerivedMesh *dm, float epsilon, int tree_type, int axis)
+BVHTree *bvhtree_from_mesh_looptri(
+ BVHTreeFromMesh *data, DerivedMesh *dm,
+ float epsilon, int tree_type, int axis)
{
- BMEditMesh *em = data->em_evil;
- const int bvhcache_type = em ?
- (data->em_evil_all ? BVHTREE_FROM_FACES_EDITMESH_ALL : BVHTREE_FROM_FACES_EDITMESH_SNAP) :
- BVHTREE_FROM_LOOPTRI;
BVHTree *tree;
MVert *mvert = NULL;
MLoop *mloop = NULL;
@@ -1078,58 +1039,42 @@ BVHTree *bvhtree_from_mesh_looptri(BVHTreeFromMesh *data, DerivedMesh *dm, float
bool looptri_allocated = false;
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
+ tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_LOOPTRI);
BLI_rw_mutex_unlock(&cache_rwlock);
- if (em == NULL) {
- MPoly *mpoly;
- bool poly_allocated = false;
+ MPoly *mpoly;
+ bool poly_allocated = false;
- mvert = DM_get_vert_array(dm, &vert_allocated);
- mpoly = DM_get_poly_array(dm, &poly_allocated);
+ mvert = DM_get_vert_array(dm, &vert_allocated);
+ mpoly = DM_get_poly_array(dm, &poly_allocated);
- mloop = DM_get_loop_array(dm, &loop_allocated);
- looptri = DM_get_looptri_array(
- dm,
- mvert,
- mpoly, dm->getNumPolys(dm),
- mloop, dm->getNumLoops(dm),
- &looptri_allocated);
-
- if (poly_allocated) {
- MEM_freeN(mpoly);
- }
+ mloop = DM_get_loop_array(dm, &loop_allocated);
+ looptri = DM_get_looptri_array(
+ dm,
+ mvert,
+ mpoly, dm->getNumPolys(dm),
+ mloop, dm->getNumLoops(dm),
+ &looptri_allocated);
+ if (poly_allocated) {
+ MEM_freeN(mpoly);
}
/* Not in cache */
if (tree == NULL) {
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- tree = bvhcache_find(&dm->bvhCache, bvhcache_type);
+ tree = bvhcache_find(&dm->bvhCache, BVHTREE_FROM_LOOPTRI);
if (tree == NULL) {
- int looptri_num;
-
- /* BMESH specific check that we have tessfaces,
- * we _could_ tessellate here but rather not - campbell
- *
- * this assert checks we have tessfaces,
- * if not caller should use DM_ensure_tessface() */
- if (em) {
- looptri_num = em->tottri;
- }
- else {
- looptri_num = dm->getNumLoopTri(dm);
- BLI_assert(!(looptri_num == 0 && dm->getNumPolys(dm) != 0));
- }
+ int looptri_num = dm->getNumLoopTri(dm);
+ BLI_assert(!(looptri_num == 0 && dm->getNumPolys(dm) != 0));
tree = bvhtree_from_mesh_looptri_create_tree(
epsilon, tree_type, axis,
- em, (bvhcache_type == BVHTREE_FROM_FACES_EDITMESH_ALL),
mvert, mloop, looptri, looptri_num, NULL, -1);
if (tree) {
/* Save on cache for later use */
/* printf("BVHTree built and saved on cache\n"); */
- bvhcache_insert(&dm->bvhCache, tree, bvhcache_type);
+ bvhcache_insert(&dm->bvhCache, tree, BVHTREE_FROM_LOOPTRI);
}
}
BLI_rw_mutex_unlock(&cache_rwlock);
@@ -1140,7 +1085,7 @@ BVHTree *bvhtree_from_mesh_looptri(BVHTreeFromMesh *data, DerivedMesh *dm, float
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_looptri_setup_data(
- data, tree, true, epsilon, em,
+ data, tree, true, epsilon,
mvert, vert_allocated,
mloop, loop_allocated,
looptri, looptri_allocated);
@@ -1153,18 +1098,17 @@ BVHTree *bvhtree_from_mesh_looptri_ex(
const struct MVert *vert, const bool vert_allocated,
const struct MLoop *mloop, const bool loop_allocated,
const struct MLoopTri *looptri, const int looptri_num, const bool looptri_allocated,
- BLI_bitmap *mask, int looptri_num_active,
+ const BLI_bitmap *looptri_mask, int looptri_num_active,
float epsilon, int tree_type, int axis)
{
BVHTree *tree = bvhtree_from_mesh_looptri_create_tree(
epsilon, tree_type, axis,
- NULL, false,
vert, mloop, looptri, looptri_num,
- mask, looptri_num_active);
+ looptri_mask, looptri_num_active);
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_looptri_setup_data(
- data, tree, false, epsilon, NULL,
+ data, tree, false, epsilon,
vert, vert_allocated,
mloop, loop_allocated,
looptri, looptri_allocated);
@@ -1175,6 +1119,15 @@ BVHTree *bvhtree_from_mesh_looptri_ex(
/** \} */
+/* Frees data allocated by a call to bvhtree_from_editmesh_*. */
+void free_bvhtree_from_editmesh(struct BVHTreeFromEditMesh *data)
+{
+ if (data->tree) {
+ BLI_bvhtree_free(data->tree);
+ memset(data, 0, sizeof(*data));
+ }
+}
+
/* Frees data allocated by a call to bvhtree_from_mesh_*. */
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
{
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index badf78edfb1..e855f6faa22 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -245,11 +245,11 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for
* for finding the best hit, to get the real dist,
* measure the len_v3v3() from the input coord to hit.co */
BVHTreeRayHit hit;
- BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh;
+ void *treeData = NULL;
/* auxiliary target */
DerivedMesh *auxMesh = NULL;
- BVHTreeFromMesh auxData = NULL_BVHTreeFromMesh;
+ void *auxData = NULL;
SpaceTransform local2aux;
/* If the user doesn't allows to project in any direction of projection axis
@@ -285,19 +285,44 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for
}
/* use editmesh to avoid array allocation */
+ BMEditMesh *emtarget = NULL, *emaux = NULL;
+ BVHTreeFromEditMesh emtreedata_stack, emauxdata_stack;
+ BVHTreeFromMesh dmtreedata_stack, dmauxdata_stack;
+ BVHTree *targ_tree;
+ void *targ_callback;
if (calc->smd->target && calc->target->type == DM_TYPE_EDITBMESH) {
- treeData.em_evil = BKE_editmesh_from_object(calc->smd->target);
- treeData.em_evil_all = true;
+ emtarget = BKE_editmesh_from_object(calc->smd->target);
+ if ((targ_tree = bvhtree_from_editmesh_looptri(&emtreedata_stack, emtarget, 0.0, 4, 6))) {
+ targ_callback = emtreedata_stack.raycast_callback;
+ treeData = &emtreedata_stack;
+ }
}
- if (calc->smd->auxTarget && auxMesh->type == DM_TYPE_EDITBMESH) {
- auxData.em_evil = BKE_editmesh_from_object(calc->smd->auxTarget);
- auxData.em_evil_all = true;
+ else {
+ if ((targ_tree = bvhtree_from_mesh_looptri(&dmtreedata_stack, calc->target, 0.0, 4, 6))) {
+ targ_callback = dmtreedata_stack.raycast_callback;
+ treeData = &dmtreedata_stack;
+ }
}
-
- /* After sucessufuly build the trees, start projection vertexs */
- if (bvhtree_from_mesh_looptri(&treeData, calc->target, 0.0, 4, 6) &&
- (auxMesh == NULL || bvhtree_from_mesh_looptri(&auxData, auxMesh, 0.0, 4, 6)))
- {
+ if (targ_tree) {
+ BVHTree *aux_tree = NULL;
+ void *aux_callback;
+ if (auxMesh != NULL) {
+ /* use editmesh to avoid array allocation */
+ if (calc->smd->auxTarget && auxMesh->type == DM_TYPE_EDITBMESH) {
+ emaux = BKE_editmesh_from_object(calc->smd->auxTarget);
+ if ((aux_tree = bvhtree_from_editmesh_looptri(&emauxdata_stack, emaux, 0.0, 4, 6)) != NULL) {
+ aux_callback = emauxdata_stack.raycast_callback;
+ auxData = &emauxdata_stack;
+ }
+ }
+ else {
+ if ((aux_tree = bvhtree_from_mesh_looptri(&dmauxdata_stack, calc->target, 0.0, 4, 6)) != NULL) {
+ aux_callback = dmauxdata_stack.raycast_callback;
+ auxData = &dmauxdata_stack;
+ }
+ }
+ }
+ /* After sucessufuly build the trees, start projection vertexs */
#ifndef __APPLE__
#pragma omp parallel for private(i, hit) schedule(static) if (calc->numVerts > BKE_MESH_OMP_LIMIT)
@@ -340,15 +365,17 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for
/* Project over positive direction of axis */
if (calc->smd->shrinkOpts & MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR) {
- if (auxData.tree) {
- BKE_shrinkwrap_project_normal(0, tmp_co, tmp_no,
- &local2aux, auxData.tree, &hit,
- auxData.raycast_callback, &auxData);
+ if (aux_tree) {
+ BKE_shrinkwrap_project_normal(
+ 0, tmp_co, tmp_no,
+ &local2aux, aux_tree, &hit,
+ aux_callback, auxData);
}
- BKE_shrinkwrap_project_normal(calc->smd->shrinkOpts, tmp_co, tmp_no,
- &calc->local2target, treeData.tree, &hit,
- treeData.raycast_callback, &treeData);
+ BKE_shrinkwrap_project_normal(
+ calc->smd->shrinkOpts, tmp_co, tmp_no,
+ &calc->local2target, targ_tree, &hit,
+ targ_callback, treeData);
}
/* Project over negative direction of axis */
@@ -356,15 +383,17 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for
float inv_no[3];
negate_v3_v3(inv_no, tmp_no);
- if (auxData.tree) {
- BKE_shrinkwrap_project_normal(0, tmp_co, inv_no,
- &local2aux, auxData.tree, &hit,
- auxData.raycast_callback, &auxData);
+ if (aux_tree) {
+ BKE_shrinkwrap_project_normal(
+ 0, tmp_co, inv_no,
+ &local2aux, aux_tree, &hit,
+ aux_callback, auxData);
}
- BKE_shrinkwrap_project_normal(calc->smd->shrinkOpts, tmp_co, inv_no,
- &calc->local2target, treeData.tree, &hit,
- treeData.raycast_callback, &treeData);
+ BKE_shrinkwrap_project_normal(
+ calc->smd->shrinkOpts, tmp_co, inv_no,
+ &calc->local2target, targ_tree, &hit,
+ targ_callback, treeData);
}
/* don't set the initial dist (which is more efficient),
@@ -383,8 +412,14 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool for
}
/* free data structures */
- free_bvhtree_from_mesh(&treeData);
- free_bvhtree_from_mesh(&auxData);
+ if (treeData) {
+ if (emtarget) free_bvhtree_from_editmesh(treeData);
+ else free_bvhtree_from_mesh(treeData);
+ }
+ if (auxData) {
+ if (emaux) free_bvhtree_from_editmesh(auxData);
+ else free_bvhtree_from_mesh(auxData);
+ }
}
/*
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index 7ab2b784812..fcd35de0bb3 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -33,7 +33,6 @@
#include <float.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#ifdef __SSE2__
# include <emmintrin.h>
diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c
index 4014d29966a..1ee629d203b 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.c
+++ b/source/blender/bmesh/intern/bmesh_iterators.c
@@ -31,6 +31,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
+#include "BLI_bitmap.h"
#include "bmesh.h"
#include "intern/bmesh_private.h"
@@ -250,6 +251,55 @@ void *BMO_iter_as_arrayN(
}
}
+int BM_iter_mesh_bitmap_from_filter(
+ const char itype, BMesh *bm,
+ BLI_bitmap *bitmap,
+ bool (*test_fn)(BMElem *, void *user_data),
+ void *user_data)
+{
+ BMIter iter;
+ BMElem *ele;
+ int i;
+
+ BM_ITER_MESH_INDEX (ele, &iter, bm, itype, i) {
+ BLI_BITMAP_SET(bitmap, i, test_fn(ele, user_data));
+ }
+
+ return i;
+}
+
+/**
+ * Needed when we want to check faces, but return a loop aligned array.
+ */
+int BM_iter_mesh_bitmap_from_filter_tessface(
+ BMesh *bm,
+ BLI_bitmap *bitmap,
+ bool (*test_fn)(BMFace *, void *user_data),
+ void *user_data)
+{
+ BMIter iter;
+ BMFace *f;
+ int i;
+ int j = 0;
+
+ BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
+ if (test_fn(f, user_data)) {
+ for (int A = 2; A < f->len; A++) {
+ BLI_BITMAP_ENABLE(bitmap, j);
+ j++;
+ }
+ }
+ else {
+ for (int A = 2; A < f->len; A++) {
+ BLI_BITMAP_DISABLE(bitmap, j);
+ j++;
+ }
+ }
+ }
+
+ return j;
+}
+
/**
* \brief Elem Iter Flag Count
*
diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h
index 336e9d88dea..0551d824131 100644
--- a/source/blender/bmesh/intern/bmesh_iterators.h
+++ b/source/blender/bmesh/intern/bmesh_iterators.h
@@ -208,6 +208,18 @@ void *BMO_iter_as_arrayN(
int *r_len,
/* optional args to avoid an alloc (normally stack array) */
void **stack_array, int stack_array_size);
+
+int BM_iter_mesh_bitmap_from_filter(
+ const char itype, BMesh *bm,
+ unsigned int *bitmap,
+ bool (*test_fn)(BMElem *, void *user_data),
+ void *user_data);
+int BM_iter_mesh_bitmap_from_filter_tessface(
+ BMesh *bm,
+ unsigned int *bitmap,
+ bool (*test_fn)(BMFace *, void *user_data),
+ void *user_data);
+
int BM_iter_elem_count_flag(const char itype, void *data, const char hflag, const bool value);
int BMO_iter_elem_count_flag(BMesh *bm, const char itype, void *data, const short oflag, const bool value);
int BM_iter_mesh_count(const char itype, BMesh *bm);
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index b62714700fa..7401a213496 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -47,6 +47,7 @@
#include "BIF_generate.h"
#include "ED_transform.h"
+#include "ED_transform_snap_object_context.h"
#include "WM_api.h"
#include "WM_types.h"
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index aedfbd4f774..91927fbc793 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -64,6 +64,7 @@
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_transform.h"
+#include "ED_transform_snap_object_context.h"
#include "ED_types.h"
#include "ED_util.h"
#include "ED_view3d.h"
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index 39df52e5f68..c881e849cf5 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -201,67 +201,4 @@ bool snapNodesContext(
/* return args */
float r_loc[2], float *r_dist_px, char *r_node_border);
-
-/* transform_snap_object.c */
-
-/* ED_transform_snap_object_*** API */
-struct SnapObjectParams {
- SnapSelect snap_select;
- union {
- unsigned int snap_to : 4;
- /* snap_target_flag: Snap to vert/edge/face. */
- unsigned int snap_to_flag : 4;
- };
- /* use editmode cage */
- unsigned int use_object_edit : 1;
- /* special context sensitive handling for the active object */
- unsigned int use_object_active : 1;
-};
-
-enum {
- SNAP_OBJECT_USE_CACHE = (1 << 0),
-};
-
-typedef struct SnapObjectContext SnapObjectContext;
-SnapObjectContext *ED_transform_snap_object_context_create(
- struct Main *bmain, struct Scene *scene, int flag);
-SnapObjectContext *ED_transform_snap_object_context_create_view3d(
- struct Main *bmain, struct Scene *scene, int flag,
- /* extra args for view3d */
- struct ARegion *ar, struct View3D *v3d);
-void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx);
-
-bool ED_transform_snap_object_project_ray_ex(
- struct SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_start[3], const float ray_normal[3], float *ray_depth,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- struct Object **r_ob, float r_obmat[4][4]);
-bool ED_transform_snap_object_project_ray(
- SnapObjectContext *sctx,
- const float ray_origin[3], const float ray_direction[3], float *ray_dist,
- float r_co[3], float r_no[3]);
-
-bool ED_transform_snap_object_project_view3d_ex(
- struct SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float mval[2], float *dist_px,
- float *ray_depth,
- float r_loc[3], float r_no[3], int *r_index);
-bool ED_transform_snap_object_project_view3d(
- struct SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float mval[2], float *dist_px,
- float *ray_depth,
- /* return args */
- float r_loc[3], float r_no[3]);
-bool ED_transform_snap_object_project_view3d_mixed(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float mval_fl[2], float *dist_px,
- bool use_depth,
- float r_co[3], float r_no[3]);
-
-
#endif /* __ED_TRANSFORM_H__ */
diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h
new file mode 100644
index 00000000000..e591a91a90f
--- /dev/null
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -0,0 +1,107 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ED_transform_snap_object_context.h
+ * \ingroup editors
+ */
+
+#ifndef __ED_TRANSFORM_SNAP_OBJECT_CONTEXT_H__
+#define __ED_TRANSFORM_SNAP_OBJECT_CONTEXT_H__
+
+struct BMVert;
+struct BMEdge;
+struct BMFace;
+
+struct Scene;
+struct Main;
+struct Object;
+struct ARegion;
+struct View3D;
+
+/* transform_snap_object.c */
+
+/* ED_transform_snap_object_*** API */
+struct SnapObjectParams {
+ int snap_select; /* SnapSelect */
+ union {
+ unsigned int snap_to : 4;
+ /* snap_target_flag: Snap to vert/edge/face. */
+ unsigned int snap_to_flag : 4;
+ };
+ /* use editmode cage */
+ unsigned int use_object_edit : 1;
+ /* special context sensitive handling for the active object */
+ unsigned int use_object_active : 1;
+};
+
+enum {
+ SNAP_OBJECT_USE_CACHE = (1 << 0),
+};
+
+typedef struct SnapObjectContext SnapObjectContext;
+SnapObjectContext *ED_transform_snap_object_context_create(
+ struct Main *bmain, struct Scene *scene, int flag);
+SnapObjectContext *ED_transform_snap_object_context_create_view3d(
+ struct Main *bmain, struct Scene *scene, int flag,
+ /* extra args for view3d */
+ struct ARegion *ar, struct View3D *v3d);
+void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx);
+
+/* callbacks to filter how snap works */
+void ED_transform_snap_object_context_set_editmesh_callbacks(
+ SnapObjectContext *sctx,
+ bool (*test_vert_fn)(struct BMVert *, void *user_data),
+ bool (*test_edge_fn)(struct BMEdge *, void *user_data),
+ bool (*test_face_fn)(struct BMFace *, void *user_data),
+ void *user_data);
+
+bool ED_transform_snap_object_project_ray_ex(
+ struct SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_start[3], const float ray_normal[3], float *ray_depth,
+ /* return args */
+ float r_loc[3], float r_no[3], int *r_index,
+ struct Object **r_ob, float r_obmat[4][4]);
+bool ED_transform_snap_object_project_ray(
+ SnapObjectContext *sctx,
+ const float ray_origin[3], const float ray_direction[3], float *ray_dist,
+ float r_co[3], float r_no[3]);
+
+bool ED_transform_snap_object_project_view3d_ex(
+ struct SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float mval[2], float *dist_px,
+ float *ray_depth,
+ float r_loc[3], float r_no[3], int *r_index);
+bool ED_transform_snap_object_project_view3d(
+ struct SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float mval[2], float *dist_px,
+ float *ray_depth,
+ /* return args */
+ float r_loc[3], float r_no[3]);
+bool ED_transform_snap_object_project_view3d_mixed(
+ SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float mval_fl[2], float *dist_px,
+ bool use_depth,
+ float r_co[3], float r_no[3]);
+
+#endif /* __ED_TRANSFORM_SNAP_OBJECT_CONTEXT_H__ */
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 49794d2e5cd..dc8e7bbb545 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -68,6 +68,7 @@
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_transform.h"
+#include "ED_transform_snap_object_context.h"
#include "ED_uvedit.h"
#include "ED_view3d.h"
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
index 26eb707624a..6789970d00f 100644
--- a/source/blender/editors/space_view3d/view3d_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -47,6 +47,7 @@
#include "ED_screen.h"
#include "ED_view3d.h"
#include "ED_transform.h"
+#include "ED_transform_snap_object_context.h"
#include "ED_space_api.h"
#include "BLF_api.h"
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 73ec0f664da..47f81678699 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -49,7 +49,7 @@
#include "ED_screen.h"
#include "ED_space_api.h"
-#include "ED_transform.h"
+#include "ED_transform_snap_object_context.h"
#include "PIL_time.h" /* smoothview */
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 5858210cd4f..11151a9c65a 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -59,6 +59,7 @@ struct wmTimer;
struct ARegion;
struct ReportList;
struct EditBone;
+struct SnapObjectContext;
/* transinfo->redraw */
typedef enum {
@@ -105,7 +106,7 @@ typedef struct TransSnap {
/**
* Re-usable snap context data.
*/
- SnapObjectContext *object_context;
+ struct SnapObjectContext *object_context;
} TransSnap;
typedef struct TransCon {
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 9e8454bf6fb..24b4b16e13f 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -68,6 +68,7 @@
#include "ED_node.h"
#include "ED_uvedit.h"
#include "ED_view3d.h"
+#include "ED_transform_snap_object_context.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -571,6 +572,13 @@ static void initSnappingMode(TransInfo *t)
t->tsnap.object_context = ED_transform_snap_object_context_create_view3d(
G.main, t->scene, SNAP_OBJECT_USE_CACHE,
t->ar, t->view);
+
+ ED_transform_snap_object_context_set_editmesh_callbacks(
+ t->tsnap.object_context,
+ (bool (*)(BMVert *, void *))BM_elem_cb_check_hflag_disabled,
+ (bool (*)(BMEdge *, void *))BM_elem_cb_check_hflag_disabled,
+ (bool (*)(BMFace *, void *))BM_elem_cb_check_hflag_disabled,
+ SET_UINT_IN_POINTER((BM_ELEM_SELECT | BM_ELEM_HIDDEN)));
}
}
}
@@ -1335,6 +1343,20 @@ struct PeelRayCast_Data {
ListBase *depth_peels;
};
+struct PeelEditMeshRayCast_Data {
+ BVHTreeFromEditMesh bvhdata;
+
+ /* internal vars for adding peel */
+ Object *ob;
+ const float(*obmat)[4];
+ const float(*timat)[3];
+
+ const float *ray_start; /* globalspace */
+
+ /* output list */
+ ListBase *depth_peels;
+};
+
static void peelRayCast_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
struct PeelRayCast_Data *data = userdata;
@@ -1359,8 +1381,32 @@ static void peelRayCast_cb(void *userdata, int index, const BVHTreeRay *ray, BVH
}
}
+static void peelEditMeshRayCast_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+ struct PeelEditMeshRayCast_Data *data = userdata;
+
+ data->bvhdata.raycast_callback(&data->bvhdata, index, ray, hit);
+
+ if (hit->index != -1) {
+ /* get all values in worldspace */
+ float location[3], normal[3];
+ float depth;
+
+ /* worldspace location */
+ mul_v3_m4v3(location, (float(*)[4])data->obmat, hit->co);
+ depth = len_v3v3(location, data->ray_start);
+
+ /* worldspace normal */
+ copy_v3_v3(normal, hit->no);
+ mul_m3_v3((float(*)[3])data->timat, normal);
+ normalize_v3(normal);
+
+ addDepthPeel(data->depth_peels, depth, location, normal, data->ob);
+ }
+}
+
static bool peelDerivedMesh(
- Object *ob, DerivedMesh *dm, BMEditMesh *em, float obmat[4][4],
+ Object *ob, DerivedMesh *dm, float obmat[4][4],
const float ray_start[3], const float ray_normal[3], const float UNUSED(mval[2]),
ListBase *depth_peels)
{
@@ -1402,8 +1448,6 @@ static bool peelDerivedMesh(
if (test == true) {
struct PeelRayCast_Data data;
- data.bvhdata.em_evil = em;
- data.bvhdata.em_evil_all = false;
bvhtree_from_mesh_looptri(&data.bvhdata, dm, 0.0f, 4, 6);
if (data.bvhdata.tree != NULL) {
@@ -1415,8 +1459,9 @@ static bool peelDerivedMesh(
data.polynors = dm->getPolyDataArray(dm, CD_NORMAL); /* can be NULL */
data.depth_peels = depth_peels;
- BLI_bvhtree_ray_cast_all(data.bvhdata.tree, ray_start_local, ray_normal_local, 0.0f,
- peelRayCast_cb, &data);
+ BLI_bvhtree_ray_cast_all(
+ data.bvhdata.tree, ray_start_local, ray_normal_local, 0.0f,
+ peelRayCast_cb, &data);
}
free_bvhtree_from_mesh(&data.bvhdata);
@@ -1424,7 +1469,59 @@ static bool peelDerivedMesh(
}
return retval;
-}
+}
+
+static bool peelEditMesh(
+ Object *ob, BMEditMesh *em, float obmat[4][4],
+ const float ray_start[3], const float ray_normal[3],
+ ListBase *depth_peels)
+{
+ bool retval = false;
+ int totvert = em->bm->totvert;
+
+ if (totvert > 0) {
+ float imat[4][4];
+ float timat[3][3]; /* transpose inverse matrix for normals */
+ float ray_start_local[3], ray_normal_local[3];
+ bool test = true;
+
+ invert_m4_m4(imat, obmat);
+
+ transpose_m3_m4(timat, imat);
+
+ mul_v3_m4v3(ray_start_local, imat, ray_start);
+ mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
+
+ if (test == true) {
+ struct PeelEditMeshRayCast_Data data;
+
+ BLI_bitmap *looptri_mask = BLI_BITMAP_NEW(em->tottri, __func__);
+ int looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
+ em->bm, looptri_mask,
+ BM_elem_cb_check_hflag_enabled_simple(BMFace *, (BM_ELEM_SELECT | BM_ELEM_HIDDEN)));
+
+ bvhtree_from_editmesh_looptri_ex(&data.bvhdata, em, looptri_mask, looptri_num_active, 0.0f, 4, 6);
+
+ MEM_freeN(looptri_mask);
+
+ if (data.bvhdata.tree != NULL) {
+ data.ob = ob;
+ data.obmat = (const float(*)[4])obmat;
+ data.timat = (const float(*)[3])timat;
+ data.ray_start = ray_start;
+ data.depth_peels = depth_peels;
+
+ BLI_bvhtree_ray_cast_all(
+ data.bvhdata.tree, ray_start_local, ray_normal_local, 0.0f,
+ peelEditMeshRayCast_cb, &data);
+ }
+
+ free_bvhtree_from_editmesh(&data.bvhdata);
+ }
+ }
+
+ return retval;
+}
static bool peelObjects(
Scene *scene, View3D *v3d, ARegion *ar, Object *obedit,
@@ -1452,24 +1549,21 @@ static bool peelObjects(
if (dob->type == OB_MESH) {
BMEditMesh *em;
- DerivedMesh *dm = NULL;
bool val;
if (dob != obedit) {
+ DerivedMesh *dm;
dm = mesh_get_derived_final(scene, dob, CD_MASK_BAREMESH);
-
- val = peelDerivedMesh(dob, dm, NULL, dob->obmat, ray_start, ray_normal, mval, r_depth_peels);
+ val = peelDerivedMesh(dob, dm, dob->obmat, ray_start, ray_normal, mval, r_depth_peels);
+
+ dm->release(dm);
}
else {
em = BKE_editmesh_from_object(dob);
- dm = editbmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH);
-
- val = peelDerivedMesh(dob, dm, em, dob->obmat, ray_start, ray_normal, mval, r_depth_peels);
+ val = peelEditMesh(dob, em, dob->obmat, ray_start, ray_normal, r_depth_peels);
}
retval = retval || val;
-
- dm->release(dm);
}
}
@@ -1482,14 +1576,14 @@ static bool peelObjects(
if (ob != obedit && ((snap_select == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL)) == 0) || ELEM(snap_select, SNAP_ALL, SNAP_NOT_OBEDIT))) {
DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
- val = peelDerivedMesh(ob, dm, NULL, ob->obmat, ray_start, ray_normal, mval, r_depth_peels);
+ val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, r_depth_peels);
dm->release(dm);
}
else if (ob == obedit && snap_select != SNAP_NOT_OBEDIT) {
BMEditMesh *em = BKE_editmesh_from_object(ob);
DerivedMesh *dm = editbmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH);
- val = peelDerivedMesh(ob, dm, NULL, ob->obmat, ray_start, ray_normal, mval, r_depth_peels);
+ val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, r_depth_peels);
dm->release(dm);
}
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 074d79457d5..5174c2477b4 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -51,15 +51,30 @@
#include "BKE_tracking.h"
#include "ED_transform.h"
+#include "ED_transform_snap_object_context.h"
#include "ED_view3d.h"
#include "ED_armature.h"
#include "transform.h"
typedef struct SnapObjectData {
- BVHTreeFromMesh *bvh_trees[2];
+ enum {
+ SNAP_MESH = 1,
+ SNAP_EDIT_MESH,
+ } type;
} SnapObjectData;
+typedef struct SnapObjectData_Mesh {
+ SnapObjectData sd;
+ BVHTreeFromMesh *bvh_trees[2];
+
+} SnapObjectData_Mesh;
+
+typedef struct SnapObjectData_EditMesh {
+ SnapObjectData sd;
+ BVHTreeFromEditMesh *bvh_trees[2];
+
+} SnapObjectData_EditMesh;
struct SnapObjectContext {
Main *bmain;
@@ -81,8 +96,19 @@ struct SnapObjectContext {
MemArena *mem_arena;
} cache;
+ /* Filter data, returns true to check this value */
+ struct {
+ struct {
+ bool (*test_vert_fn)(BMVert *, void *user_data);
+ bool (*test_edge_fn)(BMEdge *, void *user_data);
+ bool (*test_face_fn)(BMFace *, void *user_data);
+ void *user_data;
+ } edit_mesh;
+ } callbacks;
+
};
+
/* -------------------------------------------------------------------- */
/** \name Internal Object Snapping API
@@ -179,7 +205,7 @@ static bool snapEdge(
}
static bool snapVertex(
- ARegion *ar, const float vco[3], const short vno[3],
+ ARegion *ar, const float vco[3], const float vno[3],
float obmat[4][4], float timat[3][3], const float mval_fl[2], float *dist_px,
const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], float *ray_depth,
float r_loc[3], float r_no[3])
@@ -216,7 +242,7 @@ static bool snapVertex(
copy_v3_v3(r_loc, location);
if (r_no) {
- normal_short_to_float_v3(r_no, vno);
+ copy_v3_v3(r_no, vno);
mul_m3_v3(timat, r_no);
normalize_v3(r_no);
}
@@ -543,7 +569,7 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt)
static bool snapDerivedMesh(
SnapObjectContext *sctx,
- Object *ob, DerivedMesh *dm, BMEditMesh *em, float obmat[4][4],
+ Object *ob, DerivedMesh *dm, float obmat[4][4],
const float mval[2], float *dist_px, const short snap_to, bool do_bb,
const float ray_start[3], const float ray_normal[3], const float ray_origin[3], float *ray_depth,
float r_loc[3], float r_no[3], int *r_index)
@@ -579,19 +605,6 @@ static bool snapDerivedMesh(
local_depth *= local_scale;
}
- SnapObjectData *sod = NULL;
-
- if (sctx->flag & SNAP_OBJECT_USE_CACHE) {
- void **sod_p;
- if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
- sod = *sod_p;
- }
- else {
- sod = *sod_p = BLI_memarena_alloc(sctx->cache.mem_arena, sizeof(*sod));
- memset(sod, 0, sizeof(*sod));
- }
- }
-
if (do_bb) {
BoundBox *bb = BKE_object_boundbox_get(ob);
@@ -619,9 +632,19 @@ static bool snapDerivedMesh(
}
}
+ SnapObjectData_Mesh *sod = NULL;
BVHTreeFromMesh *treedata = NULL, treedata_stack;
if (sctx->flag & SNAP_OBJECT_USE_CACHE) {
+ void **sod_p;
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
+ sod = *sod_p;
+ }
+ else {
+ sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ sod->sd.type = SNAP_MESH;
+ }
+
int tree_index = -1;
switch (snap_to) {
case SCE_SNAP_MODE_FACE:
@@ -633,7 +656,7 @@ static bool snapDerivedMesh(
}
if (tree_index != -1) {
if (sod->bvh_trees[tree_index] == NULL) {
- sod->bvh_trees[tree_index] = BLI_memarena_alloc(sctx->cache.mem_arena, sizeof(*treedata));
+ sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata));
}
treedata = sod->bvh_trees[tree_index];
}
@@ -646,8 +669,6 @@ static bool snapDerivedMesh(
}
if (treedata) {
- treedata->em_evil = em;
- treedata->em_evil_all = false;
switch (snap_to) {
case SCE_SNAP_MODE_FACE:
bvhtree_from_mesh_looptri(treedata, dm, 0.0f, 4, 6);
@@ -741,8 +762,10 @@ static bool snapDerivedMesh(
&nearest, NULL, NULL) != -1)
{
const MVert *v = &treedata->vert[nearest.index];
+ float vno[3];
+ normal_short_to_float_v3(vno, v->no);
retval = snapVertex(
- ar, v->co, v->no, obmat, timat, mval, dist_px,
+ ar, v->co, vno, obmat, timat, mval, dist_px,
ray_start, ray_start_local, ray_normal_local, ray_depth,
r_loc, r_no);
}
@@ -753,45 +776,247 @@ static bool snapDerivedMesh(
MVert *verts = dm->getVertArray(dm);
MEdge *edges = dm->getEdgeArray(dm);
int totedge = dm->getNumEdges(dm);
- const int *index_array = NULL;
- int index = 0;
- int i;
- if (em != NULL) {
- index_array = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
- BM_mesh_elem_table_ensure(em->bm, BM_EDGE);
+ for (int i = 0; i < totedge; i++) {
+ MEdge *e = edges + i;
+ retval |= snapEdge(
+ ar, verts[e->v1].co, verts[e->v1].no, verts[e->v2].co, verts[e->v2].no,
+ obmat, timat, mval, dist_px,
+ ray_start, ray_start_local, ray_normal_local, ray_depth,
+ r_loc, r_no);
}
- for (i = 0; i < totedge; i++) {
- MEdge *e = edges + i;
- bool test = true;
+ break;
+ }
+ }
- if (em != NULL) {
- if (index_array) {
- index = index_array[i];
- }
- else {
- index = i;
- }
+ if ((sctx->flag & SNAP_OBJECT_USE_CACHE) == 0) {
+ if (treedata) {
+ free_bvhtree_from_mesh(treedata);
+ }
+ }
+ }
- if (index == ORIGINDEX_NONE) {
- test = false;
- }
- else {
- BMEdge *eed = BM_edge_at_index(em->bm, index);
+ return retval;
+}
- if (BM_elem_flag_test(eed, BM_ELEM_HIDDEN) ||
- BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
- BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))
- {
- test = false;
- }
+
+static bool snapEditMesh(
+ SnapObjectContext *sctx,
+ Object *ob, BMEditMesh *em, float obmat[4][4],
+ const float mval[2], float *dist_px, const short snap_to,
+ const float ray_start[3], const float ray_normal[3], const float ray_origin[3], float *ray_depth,
+ float r_loc[3], float r_no[3], int *r_index)
+{
+ ARegion *ar = sctx->v3d_data.ar;
+ bool retval = false;
+ int totvert = em->bm->totvert;
+
+ if (totvert > 0) {
+ const bool do_ray_start_correction = (
+ ELEM(snap_to, SCE_SNAP_MODE_FACE, SCE_SNAP_MODE_VERTEX) &&
+ (sctx->use_v3d && !((RegionView3D *)sctx->v3d_data.ar->regiondata)->is_persp));
+
+ float imat[4][4];
+ float timat[3][3]; /* transpose inverse matrix for normals */
+ float ray_start_local[3], ray_normal_local[3];
+ float local_scale, local_depth, len_diff;
+
+ invert_m4_m4(imat, obmat);
+ transpose_m3_m4(timat, imat);
+
+ copy_v3_v3(ray_start_local, ray_start);
+ copy_v3_v3(ray_normal_local, ray_normal);
+
+ mul_m4_v3(imat, ray_start_local);
+ mul_mat3_m4_v3(imat, ray_normal_local);
+
+ /* local scale in normal direction */
+ local_scale = normalize_v3(ray_normal_local);
+ local_depth = *ray_depth;
+ if (local_depth != BVH_RAYCAST_DIST_MAX) {
+ local_depth *= local_scale;
+ }
+
+ SnapObjectData_EditMesh *sod = NULL;
+
+ BVHTreeFromEditMesh *treedata = NULL, treedata_stack;
+
+ if (sctx->flag & SNAP_OBJECT_USE_CACHE) {
+ void **sod_p;
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
+ sod = *sod_p;
+ }
+ else {
+ sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ sod->sd.type = SNAP_EDIT_MESH;
+ }
+
+ int tree_index = -1;
+ switch (snap_to) {
+ case SCE_SNAP_MODE_FACE:
+ tree_index = 1;
+ break;
+ case SCE_SNAP_MODE_VERTEX:
+ tree_index = 0;
+ break;
+ }
+ if (tree_index != -1) {
+ if (sod->bvh_trees[tree_index] == NULL) {
+ sod->bvh_trees[tree_index] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*treedata));
+ }
+ treedata = sod->bvh_trees[tree_index];
+ }
+ }
+ else {
+ if (ELEM(snap_to, SCE_SNAP_MODE_FACE, SCE_SNAP_MODE_VERTEX)) {
+ treedata = &treedata_stack;
+ memset(treedata, 0, sizeof(*treedata));
+ }
+ }
+
+ if (treedata && treedata->tree == NULL) {
+ switch (snap_to) {
+ case SCE_SNAP_MODE_FACE:
+ {
+ BLI_bitmap *looptri_mask = NULL;
+ int looptri_num_active = -1;
+ if (sctx->callbacks.edit_mesh.test_face_fn) {
+ looptri_mask = BLI_BITMAP_NEW(em->tottri, __func__);
+ looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
+ em->bm, looptri_mask,
+ sctx->callbacks.edit_mesh.test_face_fn, sctx->callbacks.edit_mesh.user_data);
+ }
+ bvhtree_from_editmesh_looptri_ex(treedata, em, looptri_mask, looptri_num_active, 0.0f, 4, 6);
+ if (looptri_mask) {
+ MEM_freeN(looptri_mask);
+ }
+ break;
+ }
+ case SCE_SNAP_MODE_VERTEX:
+ {
+ BLI_bitmap *verts_mask = NULL;
+ int verts_num_active = -1;
+ if (sctx->callbacks.edit_mesh.test_vert_fn) {
+ verts_mask = BLI_BITMAP_NEW(em->bm->totvert, __func__);
+ verts_num_active = BM_iter_mesh_bitmap_from_filter(
+ BM_VERTS_OF_MESH, em->bm, verts_mask,
+ (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_vert_fn,
+ sctx->callbacks.edit_mesh.user_data);
+ }
+ bvhtree_from_editmesh_verts_ex(treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6);
+ if (verts_mask) {
+ MEM_freeN(verts_mask);
+ }
+ break;
+ }
+ }
+ }
+
+ /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already
+ * been *inside* boundbox, leading to snap failures (see T38409).
+ * Note also ar might be null (see T38435), in this case we assume ray_start is ok!
+ */
+ if (do_ray_start_correction) {
+ /* We *need* a reasonably valid len_diff in this case.
+ * Use BHVTree to find the closest face from ray_start_local.
+ */
+ if (treedata && treedata->tree != NULL) {
+ BVHTreeNearest nearest;
+ nearest.index = -1;
+ nearest.dist_sq = FLT_MAX;
+ /* Compute and store result. */
+ BLI_bvhtree_find_nearest(
+ treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata);
+ if (nearest.index != -1) {
+ len_diff = sqrtf(nearest.dist_sq);
+ }
+ }
+ float ray_org_local[3];
+
+ copy_v3_v3(ray_org_local, ray_origin);
+ mul_m4_v3(imat, ray_org_local);
+
+ /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with very far
+ * away ray_start values (as returned in case of ortho view3d), see T38358.
+ */
+ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
+ madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local,
+ len_diff - len_v3v3(ray_start_local, ray_org_local));
+ local_depth -= len_diff;
+ }
+ else {
+ len_diff = 0.0f;
+ }
+
+ switch (snap_to) {
+ case SCE_SNAP_MODE_FACE:
+ {
+ BVHTreeRayHit hit;
+
+ hit.index = -1;
+ hit.dist = local_depth;
+
+ if (treedata->tree &&
+ BLI_bvhtree_ray_cast(treedata->tree, ray_start_local, ray_normal_local, 0.0f,
+ &hit, treedata->raycast_callback, treedata) != -1)
+ {
+ hit.dist += len_diff;
+ hit.dist /= local_scale;
+ if (hit.dist <= *ray_depth) {
+ *ray_depth = hit.dist;
+ copy_v3_v3(r_loc, hit.co);
+ copy_v3_v3(r_no, hit.no);
+
+ /* back to worldspace */
+ mul_m4_v3(obmat, r_loc);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+
+ retval = true;
+
+ if (r_index) {
+ *r_index = hit.index;
}
}
+ }
+ break;
+ }
+ case SCE_SNAP_MODE_VERTEX:
+ {
+ BVHTreeNearest nearest;
- if (test) {
+ nearest.index = -1;
+ nearest.dist_sq = local_depth * local_depth;
+ if (treedata->tree &&
+ BLI_bvhtree_find_nearest_to_ray(
+ treedata->tree, ray_start_local, ray_normal_local,
+ &nearest, NULL, NULL) != -1)
+ {
+ const BMVert *v = BM_vert_at_index(em->bm, nearest.index);
+ retval = snapVertex(
+ ar, v->co, v->no, obmat, timat, mval, dist_px,
+ ray_start, ray_start_local, ray_normal_local, ray_depth,
+ r_loc, r_no);
+ }
+ break;
+ }
+ case SCE_SNAP_MODE_EDGE:
+ {
+ BM_mesh_elem_table_ensure(em->bm, BM_EDGE);
+ int totedge = em->bm->totvert;
+ for (int i = 0; i < totedge; i++) {
+ BMEdge *eed = BM_edge_at_index(em->bm, i);
+
+ if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN) &&
+ !BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) &&
+ !BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))
+ {
+ short v1no[3], v2no[3];
+ normal_float_to_short_v3(v1no, eed->v1->no);
+ normal_float_to_short_v3(v2no, eed->v2->no);
retval |= snapEdge(
- ar, verts[e->v1].co, verts[e->v1].no, verts[e->v2].co, verts[e->v2].no,
+ ar, eed->v1->co, v1no, eed->v2->co, v2no,
obmat, timat, mval, dist_px,
ray_start, ray_start_local, ray_normal_local, ray_depth,
r_loc, r_no);
@@ -804,7 +1029,7 @@ static bool snapDerivedMesh(
if ((sctx->flag & SNAP_OBJECT_USE_CACHE) == 0) {
if (treedata) {
- free_bvhtree_from_mesh(treedata);
+ free_bvhtree_from_editmesh(treedata);
}
}
}
@@ -826,17 +1051,18 @@ static bool snapObject(
if (ob->type == OB_MESH) {
BMEditMesh *em;
- DerivedMesh *dm;
- bool do_bb = true;
if (use_obedit) {
em = BKE_editmesh_from_object(ob);
- dm = editbmesh_get_derived_cage(sctx->scene, ob, em, CD_MASK_BAREMESH);
- do_bb = false;
+ retval = snapEditMesh(
+ sctx, ob, em, obmat, mval, dist_px, snap_to,
+ ray_start, ray_normal, ray_origin, ray_depth,
+ r_loc, r_no, r_index);
}
else {
/* in this case we want the mesh from the editmesh, avoids stale data. see: T45978.
* still set the 'em' to NULL, since we only want the 'dm'. */
+ DerivedMesh *dm;
em = BKE_editmesh_from_object(ob);
if (em) {
editbmesh_get_derived_cage_and_final(sctx->scene, ob, em, CD_MASK_BAREMESH, &dm);
@@ -844,15 +1070,13 @@ static bool snapObject(
else {
dm = mesh_get_derived_final(sctx->scene, ob, CD_MASK_BAREMESH);
}
- em = NULL;
- }
-
- retval = snapDerivedMesh(
- sctx, ob, dm, em, obmat, mval, dist_px, snap_to, do_bb,
- ray_start, ray_normal, ray_origin, ray_depth,
- r_loc, r_no, r_index);
+ retval = snapDerivedMesh(
+ sctx, ob, dm, obmat, mval, dist_px, snap_to, true,
+ ray_start, ray_normal, ray_origin, ray_depth,
+ r_loc, r_no, r_index);
- dm->release(dm);
+ dm->release(dm);
+ }
}
else if (ob->type == OB_ARMATURE) {
retval = snapArmature(
@@ -1014,12 +1238,28 @@ SnapObjectContext *ED_transform_snap_object_context_create_view3d(
return sctx;
}
-static void snap_object_data_free(void *val)
+static void snap_object_data_free(void *sod_v)
{
- SnapObjectData *sod = val;
- for (int i = 0; i < ARRAY_SIZE(sod->bvh_trees); i++) {
- if (sod->bvh_trees[i]) {
- free_bvhtree_from_mesh(sod->bvh_trees[i]);
+ switch (((SnapObjectData *)sod_v)->type) {
+ case SNAP_MESH:
+ {
+ SnapObjectData_Mesh *sod = sod_v;
+ for (int i = 0; i < ARRAY_SIZE(sod->bvh_trees); i++) {
+ if (sod->bvh_trees[i]) {
+ free_bvhtree_from_mesh(sod->bvh_trees[i]);
+ }
+ }
+ break;
+ }
+ case SNAP_EDIT_MESH:
+ {
+ SnapObjectData_EditMesh *sod = sod_v;
+ for (int i = 0; i < ARRAY_SIZE(sod->bvh_trees); i++) {
+ if (sod->bvh_trees[i]) {
+ free_bvhtree_from_editmesh(sod->bvh_trees[i]);
+ }
+ }
+ break;
}
}
}
@@ -1034,6 +1274,19 @@ void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)
MEM_freeN(sctx);
}
+void ED_transform_snap_object_context_set_editmesh_callbacks(
+ SnapObjectContext *sctx,
+ bool (*test_vert_fn)(BMVert *, void *user_data),
+ bool (*test_edge_fn)(BMEdge *, void *user_data),
+ bool (*test_face_fn)(BMFace *, void *user_data),
+ void *user_data)
+{
+ sctx->callbacks.edit_mesh.test_vert_fn = test_vert_fn;
+ sctx->callbacks.edit_mesh.test_edge_fn = test_edge_fn;
+ sctx->callbacks.edit_mesh.test_face_fn = test_face_fn;
+
+ sctx->callbacks.edit_mesh.user_data = user_data;
+}
bool ED_transform_snap_object_project_ray_ex(
SnapObjectContext *sctx,
diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt
index 7de788dca56..c0b30f93939 100644
--- a/source/blender/editors/util/CMakeLists.txt
+++ b/source/blender/editors/util/CMakeLists.txt
@@ -83,6 +83,7 @@ set(SRC
../include/ED_space_api.h
../include/ED_text.h
../include/ED_transform.h
+ ../include/ED_transform_snap_object_context.h
../include/ED_transverts.h
../include/ED_types.h
../include/ED_util.h
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index 9ba50641cc0..74fb4a08eda 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -55,6 +55,7 @@
#include "BKE_writeavi.h"
#include "ED_transform.h"
+#include "ED_transform_snap_object_context.h"
#include "ED_uvedit.h"
#ifdef WITH_PYTHON