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:
authorCampbell Barton <ideasman42@gmail.com>2019-04-17 07:17:24 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-04-17 07:21:24 +0300
commite12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch)
tree8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/editors/transform/transform_snap_object.c
parentb3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff)
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/editors/transform/transform_snap_object.c')
-rw-r--r--source/blender/editors/transform/transform_snap_object.c4654
1 files changed, 2381 insertions, 2273 deletions
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index f2692f57a35..93f89c1919e 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -45,7 +45,7 @@
#include "BKE_armature.h"
#include "BKE_curve.h"
#include "BKE_object.h"
-#include "BKE_anim.h" /* for duplis */
+#include "BKE_anim.h" /* for duplis */
#include "BKE_editmesh.h"
#include "BKE_main.h"
#include "BKE_tracking.h"
@@ -70,78 +70,76 @@
#define MAX_CLIPPLANE_LEN 3
enum eViewProj {
- VIEW_PROJ_NONE = -1,
- VIEW_PROJ_ORTHO = 0,
- VIEW_PROJ_PERSP = -1,
+ VIEW_PROJ_NONE = -1,
+ VIEW_PROJ_ORTHO = 0,
+ VIEW_PROJ_PERSP = -1,
};
typedef struct SnapData {
- short snap_to_flag;
- float mval[2];
- float pmat[4][4]; /* perspective matrix */
- float win_size[2];/* win x and y */
- enum eViewProj view_proj;
- float clip_plane[MAX_CLIPPLANE_LEN][4];
- short clip_plane_len;
+ short snap_to_flag;
+ float mval[2];
+ float pmat[4][4]; /* perspective matrix */
+ float win_size[2]; /* win x and y */
+ enum eViewProj view_proj;
+ float clip_plane[MAX_CLIPPLANE_LEN][4];
+ short clip_plane_len;
} SnapData;
typedef struct SnapObjectData {
- enum {
- SNAP_MESH = 1,
- SNAP_EDIT_MESH,
- } type;
+ enum {
+ SNAP_MESH = 1,
+ SNAP_EDIT_MESH,
+ } type;
} SnapObjectData;
typedef struct SnapObjectData_Mesh {
- SnapObjectData sd;
- BVHTreeFromMesh treedata;
- const struct MPoly *poly;
- BVHTree *bvhtree[2]; /* from loose verts and from loose edges */
- uint has_looptris : 1;
- uint has_loose_edge : 1;
- uint has_loose_vert : 1;
+ SnapObjectData sd;
+ BVHTreeFromMesh treedata;
+ const struct MPoly *poly;
+ BVHTree *bvhtree[2]; /* from loose verts and from loose edges */
+ uint has_looptris : 1;
+ uint has_loose_edge : 1;
+ uint has_loose_vert : 1;
} SnapObjectData_Mesh;
typedef struct SnapObjectData_EditMesh {
- SnapObjectData sd;
- BVHTreeFromEditMesh *bvh_trees[3];
- float min[3], max[3];
+ SnapObjectData sd;
+ BVHTreeFromEditMesh *bvh_trees[3];
+ float min[3], max[3];
} SnapObjectData_EditMesh;
struct SnapObjectContext {
- Main *bmain;
- Scene *scene;
- Depsgraph *depsgraph;
-
- int flag;
-
- /* Optional: when performing screen-space projection.
- * otherwise this doesn't take viewport into account. */
- bool use_v3d;
- struct {
- const struct View3D *v3d;
- const struct ARegion *ar;
- } v3d_data;
-
-
- /* Object -> SnapObjectData map */
- struct {
- GHash *object_map;
- 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;
-
+ Main *bmain;
+ Scene *scene;
+ Depsgraph *depsgraph;
+
+ int flag;
+
+ /* Optional: when performing screen-space projection.
+ * otherwise this doesn't take viewport into account. */
+ bool use_v3d;
+ struct {
+ const struct View3D *v3d;
+ const struct ARegion *ar;
+ } v3d_data;
+
+ /* Object -> SnapObjectData map */
+ struct {
+ GHash *object_map;
+ 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;
};
/** \} */
@@ -155,51 +153,54 @@ struct SnapObjectContext {
*/
static void bm_mesh_minmax(BMesh *bm, float r_min[3], float r_max[3])
{
- INIT_MINMAX(r_min, r_max);
- BMIter iter;
- BMVert *v;
+ INIT_MINMAX(r_min, r_max);
+ BMIter iter;
+ BMVert *v;
- BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
- minmax_v3v3_v3(r_min, r_max, v->co);
- }
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ minmax_v3v3_v3(r_min, r_max, v->co);
+ }
}
static SnapObjectData_Mesh *snap_object_data_mesh_get(SnapObjectContext *sctx, Object *ob)
{
- void **sod_p;
- if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
- BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_MESH);
- }
- else {
- SnapObjectData_Mesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
- sod->sd.type = SNAP_MESH;
- /* start assuming that it has each of these element types */
- sod->has_looptris = true;
- sod->has_loose_edge = true;
- sod->has_loose_vert = true;
- }
-
- return *sod_p;
+ void **sod_p;
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, ob, &sod_p)) {
+ BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_MESH);
+ }
+ else {
+ SnapObjectData_Mesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
+ sod->sd.type = SNAP_MESH;
+ /* start assuming that it has each of these element types */
+ sod->has_looptris = true;
+ sod->has_loose_edge = true;
+ sod->has_loose_vert = true;
+ }
+
+ return *sod_p;
}
/* Use `em->ob` as the key in ghash since the editmesh is used
* to create bvhtree and is the same for each linked object. */
-static SnapObjectData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext *sctx, BMEditMesh *em)
+static SnapObjectData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext *sctx,
+ BMEditMesh *em)
{
- void **sod_p;
- if (BLI_ghash_ensure_p(sctx->cache.object_map, em->ob, &sod_p)) {
- BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_EDIT_MESH);
- }
- else {
- SnapObjectData_EditMesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(*sod));
- sod->sd.type = SNAP_EDIT_MESH;
- bm_mesh_minmax(em->bm, sod->min, sod->max);
- }
-
- return *sod_p;
+ void **sod_p;
+ if (BLI_ghash_ensure_p(sctx->cache.object_map, em->ob, &sod_p)) {
+ BLI_assert(((SnapObjectData *)*sod_p)->type == SNAP_EDIT_MESH);
+ }
+ else {
+ SnapObjectData_EditMesh *sod = *sod_p = BLI_memarena_calloc(sctx->cache.mem_arena,
+ sizeof(*sod));
+ sod->sd.type = SNAP_EDIT_MESH;
+ bm_mesh_minmax(em->bm, sod->min, sod->max);
+ }
+
+ return *sod_p;
}
-typedef void(*IterSnapObjsCallback)(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data);
+typedef void (*IterSnapObjsCallback)(
+ SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data);
/**
* Walks through all objects in the scene to create the list of objects to snap.
@@ -207,36 +208,35 @@ typedef void(*IterSnapObjsCallback)(SnapObjectContext *sctx, bool is_obedit, Obj
* \param sctx: Snap context to store data.
* \param snap_select: from enum #eSnapSelect.
*/
-static void iter_snap_objects(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- IterSnapObjsCallback sob_callback,
- void *data)
+static void iter_snap_objects(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ IterSnapObjsCallback sob_callback,
+ void *data)
{
- ViewLayer *view_layer = DEG_get_input_view_layer(sctx->depsgraph);
- const View3D *v3d = sctx->v3d_data.v3d;
- const eSnapSelect snap_select = params->snap_select;
- const bool use_object_edit_cage = params->use_object_edit_cage;
-
- Base *base_act = view_layer->basact;
- for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
- if ((BASE_VISIBLE(v3d, base)) && (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) == 0 &&
- !((snap_select == SNAP_NOT_SELECTED && ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) ||
- (snap_select == SNAP_NOT_ACTIVE && base == base_act)))
- {
- Object *obj_eval = DEG_get_evaluated_object(sctx->depsgraph, base->object);
- if (obj_eval->transflag & OB_DUPLI) {
- DupliObject *dupli_ob;
- ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj_eval);
- for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
- sob_callback(sctx, use_object_edit_cage, dupli_ob->ob, dupli_ob->mat, data);
- }
- free_object_duplilist(lb);
- }
-
- sob_callback(sctx, use_object_edit_cage, obj_eval, obj_eval->obmat, data);
- }
- }
+ ViewLayer *view_layer = DEG_get_input_view_layer(sctx->depsgraph);
+ const View3D *v3d = sctx->v3d_data.v3d;
+ const eSnapSelect snap_select = params->snap_select;
+ const bool use_object_edit_cage = params->use_object_edit_cage;
+
+ Base *base_act = view_layer->basact;
+ for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
+ if ((BASE_VISIBLE(v3d, base)) && (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) == 0 &&
+ !((snap_select == SNAP_NOT_SELECTED &&
+ ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) ||
+ (snap_select == SNAP_NOT_ACTIVE && base == base_act))) {
+ Object *obj_eval = DEG_get_evaluated_object(sctx->depsgraph, base->object);
+ if (obj_eval->transflag & OB_DUPLI) {
+ DupliObject *dupli_ob;
+ ListBase *lb = object_duplilist(sctx->depsgraph, sctx->scene, obj_eval);
+ for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
+ sob_callback(sctx, use_object_edit_cage, dupli_ob->ob, dupli_ob->mat, data);
+ }
+ free_object_duplilist(lb);
+ }
+
+ sob_callback(sctx, use_object_edit_cage, obj_eval, obj_eval->obmat, data);
+ }
+ }
}
/** \} */
@@ -249,516 +249,567 @@ static void iter_snap_objects(
* Support for storing all depths, not just the first (raycast 'all') */
struct RayCastAll_Data {
- void *bvhdata;
+ void *bvhdata;
- /* internal vars for adding depths */
- BVHTree_RayCastCallback raycast_callback;
+ /* internal vars for adding depths */
+ BVHTree_RayCastCallback raycast_callback;
- const float(*obmat)[4];
- const float(*timat)[3];
+ const float (*obmat)[4];
+ const float (*timat)[3];
- float len_diff;
- float local_scale;
+ float len_diff;
+ float local_scale;
- Object *ob;
- unsigned int ob_uuid;
+ Object *ob;
+ unsigned int ob_uuid;
- /* output data */
- ListBase *hit_list;
- bool retval;
+ /* output data */
+ ListBase *hit_list;
+ bool retval;
};
-
-static struct SnapObjectHitDepth *hit_depth_create(
- const float depth, const float co[3], const float no[3], int index,
- Object *ob, const float obmat[4][4], unsigned int ob_uuid)
+static struct SnapObjectHitDepth *hit_depth_create(const float depth,
+ const float co[3],
+ const float no[3],
+ int index,
+ Object *ob,
+ const float obmat[4][4],
+ unsigned int ob_uuid)
{
- struct SnapObjectHitDepth *hit = MEM_mallocN(sizeof(*hit), __func__);
+ struct SnapObjectHitDepth *hit = MEM_mallocN(sizeof(*hit), __func__);
- hit->depth = depth;
- copy_v3_v3(hit->co, co);
- copy_v3_v3(hit->no, no);
- hit->index = index;
+ hit->depth = depth;
+ copy_v3_v3(hit->co, co);
+ copy_v3_v3(hit->no, no);
+ hit->index = index;
- hit->ob = ob;
- copy_m4_m4(hit->obmat, (float(*)[4])obmat);
- hit->ob_uuid = ob_uuid;
+ hit->ob = ob;
+ copy_m4_m4(hit->obmat, (float(*)[4])obmat);
+ hit->ob_uuid = ob_uuid;
- return hit;
+ return hit;
}
static int hit_depth_cmp(const void *arg1, const void *arg2)
{
- const struct SnapObjectHitDepth *h1 = arg1;
- const struct SnapObjectHitDepth *h2 = arg2;
- int val = 0;
-
- if (h1->depth < h2->depth) {
- val = -1;
- }
- else if (h1->depth > h2->depth) {
- val = 1;
- }
-
- return val;
+ const struct SnapObjectHitDepth *h1 = arg1;
+ const struct SnapObjectHitDepth *h2 = arg2;
+ int val = 0;
+
+ if (h1->depth < h2->depth) {
+ val = -1;
+ }
+ else if (h1->depth > h2->depth) {
+ val = 1;
+ }
+
+ return val;
}
static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
- struct RayCastAll_Data *data = userdata;
- data->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 = (hit->dist + data->len_diff) / data->local_scale;
-
- /* worldspace normal */
- copy_v3_v3(normal, hit->no);
- mul_m3_v3((float(*)[3])data->timat, normal);
- normalize_v3(normal);
-
- struct SnapObjectHitDepth *hit_item = hit_depth_create(
- depth, location, normal, hit->index,
- data->ob, data->obmat, data->ob_uuid);
- BLI_addtail(data->hit_list, hit_item);
- }
+ struct RayCastAll_Data *data = userdata;
+ data->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 = (hit->dist + data->len_diff) / data->local_scale;
+
+ /* worldspace normal */
+ copy_v3_v3(normal, hit->no);
+ mul_m3_v3((float(*)[3])data->timat, normal);
+ normalize_v3(normal);
+
+ struct SnapObjectHitDepth *hit_item = hit_depth_create(
+ depth, location, normal, hit->index, data->ob, data->obmat, data->ob_uuid);
+ BLI_addtail(data->hit_list, hit_item);
+ }
}
-
-static bool raycastMesh(
- SnapObjectContext *sctx,
- const float ray_start[3], const float ray_dir[3],
- Object *ob, Mesh *me, float obmat[4][4], const unsigned int ob_index,
- /* read/write args */
- float *ray_depth,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- ListBase *r_hit_list)
+static bool raycastMesh(SnapObjectContext *sctx,
+ const float ray_start[3],
+ const float ray_dir[3],
+ Object *ob,
+ Mesh *me,
+ float obmat[4][4],
+ const unsigned int ob_index,
+ /* read/write args */
+ float *ray_depth,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ ListBase *r_hit_list)
{
- bool retval = false;
-
- if (me->totpoly == 0) {
- return retval;
- }
-
- float imat[4][4];
- float ray_start_local[3], ray_normal_local[3];
- float local_scale, local_depth, len_diff = 0.0f;
-
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(ray_start_local, ray_start);
- copy_v3_v3(ray_normal_local, ray_dir);
-
- 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;
- }
-
- /* Test BoundBox */
- BoundBox *bb = BKE_mesh_boundbox_get(ob);
- if (bb) {
- /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
- if (!isect_ray_aabb_v3_simple(
- ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &len_diff, NULL))
- {
- return retval;
- }
- }
- /* 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 T50486, T38358.
- */
- if (len_diff > 400.0f) {
- len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
- madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
- local_depth -= len_diff;
- }
- else {
- len_diff = 0.0f;
- }
-
- SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob);
-
- BVHTreeFromMesh *treedata = &sod->treedata;
-
- /* The tree is owned by the Mesh and may have been freed since we last used. */
- if (treedata->tree) {
- BLI_assert(treedata->cached);
- if (!bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) {
- free_bvhtree_from_mesh(treedata);
- }
- else {
- /* Update Pointers. */
- if (treedata->vert && treedata->vert_allocated == false) {
- treedata->vert = me->mvert;
- }
- if (treedata->loop && treedata->loop_allocated == false) {
- treedata->loop = me->mloop;
- }
- if (treedata->looptri && treedata->looptri_allocated == false) {
- treedata->looptri = BKE_mesh_runtime_looptri_ensure(me);
- }
- /* required for snapping with occlusion. */
- treedata->edge = me->medge;
- sod->poly = me->mpoly;
- }
- }
-
- if (treedata->tree == NULL) {
- BKE_bvhtree_from_mesh_get(treedata, me, BVHTREE_FROM_LOOPTRI, 4);
-
- /* required for snapping with occlusion. */
- treedata->edge = me->medge;
- sod->poly = me->mpoly;
-
- if (treedata->tree == NULL) {
- return retval;
- }
- }
-
- float timat[3][3]; /* transpose inverse matrix for normals */
- transpose_m3_m4(timat, imat);
-
- if (r_hit_list) {
- struct RayCastAll_Data data;
-
- data.bvhdata = treedata;
- data.raycast_callback = treedata->raycast_callback;
- data.obmat = obmat;
- data.timat = timat;
- data.len_diff = len_diff;
- data.local_scale = local_scale;
- data.ob = ob;
- data.ob_uuid = ob_index;
- data.hit_list = r_hit_list;
- data.retval = retval;
-
- BLI_bvhtree_ray_cast_all(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- *ray_depth, raycast_all_cb, &data);
-
- retval = data.retval;
- }
- else {
- BVHTreeRayHit hit = { .index = -1, .dist = local_depth, };
-
- if (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);
-
- /* back to worldspace */
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- copy_v3_v3(r_no, hit.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
-
- retval = true;
-
- if (r_index) {
- *r_index = treedata->looptri[hit.index].poly;
- }
- }
- }
- }
-
- return retval;
+ bool retval = false;
+
+ if (me->totpoly == 0) {
+ return retval;
+ }
+
+ float imat[4][4];
+ float ray_start_local[3], ray_normal_local[3];
+ float local_scale, local_depth, len_diff = 0.0f;
+
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(ray_start_local, ray_start);
+ copy_v3_v3(ray_normal_local, ray_dir);
+
+ 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;
+ }
+
+ /* Test BoundBox */
+ BoundBox *bb = BKE_mesh_boundbox_get(ob);
+ if (bb) {
+ /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
+ if (!isect_ray_aabb_v3_simple(
+ ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], &len_diff, NULL)) {
+ return retval;
+ }
+ }
+ /* 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 T50486, T38358.
+ */
+ if (len_diff > 400.0f) {
+ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
+ madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
+ local_depth -= len_diff;
+ }
+ else {
+ len_diff = 0.0f;
+ }
+
+ SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob);
+
+ BVHTreeFromMesh *treedata = &sod->treedata;
+
+ /* The tree is owned by the Mesh and may have been freed since we last used. */
+ if (treedata->tree) {
+ BLI_assert(treedata->cached);
+ if (!bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) {
+ free_bvhtree_from_mesh(treedata);
+ }
+ else {
+ /* Update Pointers. */
+ if (treedata->vert && treedata->vert_allocated == false) {
+ treedata->vert = me->mvert;
+ }
+ if (treedata->loop && treedata->loop_allocated == false) {
+ treedata->loop = me->mloop;
+ }
+ if (treedata->looptri && treedata->looptri_allocated == false) {
+ treedata->looptri = BKE_mesh_runtime_looptri_ensure(me);
+ }
+ /* required for snapping with occlusion. */
+ treedata->edge = me->medge;
+ sod->poly = me->mpoly;
+ }
+ }
+
+ if (treedata->tree == NULL) {
+ BKE_bvhtree_from_mesh_get(treedata, me, BVHTREE_FROM_LOOPTRI, 4);
+
+ /* required for snapping with occlusion. */
+ treedata->edge = me->medge;
+ sod->poly = me->mpoly;
+
+ if (treedata->tree == NULL) {
+ return retval;
+ }
+ }
+
+ float timat[3][3]; /* transpose inverse matrix for normals */
+ transpose_m3_m4(timat, imat);
+
+ if (r_hit_list) {
+ struct RayCastAll_Data data;
+
+ data.bvhdata = treedata;
+ data.raycast_callback = treedata->raycast_callback;
+ data.obmat = obmat;
+ data.timat = timat;
+ data.len_diff = len_diff;
+ data.local_scale = local_scale;
+ data.ob = ob;
+ data.ob_uuid = ob_index;
+ data.hit_list = r_hit_list;
+ data.retval = retval;
+
+ BLI_bvhtree_ray_cast_all(treedata->tree,
+ ray_start_local,
+ ray_normal_local,
+ 0.0f,
+ *ray_depth,
+ raycast_all_cb,
+ &data);
+
+ retval = data.retval;
+ }
+ else {
+ BVHTreeRayHit hit = {
+ .index = -1,
+ .dist = local_depth,
+ };
+
+ if (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);
+
+ /* back to worldspace */
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ copy_v3_v3(r_no, hit.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
+
+ retval = true;
+
+ if (r_index) {
+ *r_index = treedata->looptri[hit.index].poly;
+ }
+ }
+ }
+ }
+
+ return retval;
}
-static bool raycastEditMesh(
- SnapObjectContext *sctx,
- const float ray_start[3], const float ray_dir[3],
- Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index,
- /* read/write args */
- float *ray_depth,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- ListBase *r_hit_list)
+static bool raycastEditMesh(SnapObjectContext *sctx,
+ const float ray_start[3],
+ const float ray_dir[3],
+ Object *ob,
+ BMEditMesh *em,
+ float obmat[4][4],
+ const unsigned int ob_index,
+ /* read/write args */
+ float *ray_depth,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ ListBase *r_hit_list)
{
- bool retval = false;
- if (em->bm->totface == 0) {
- return retval;
- }
-
- BLI_assert(BKE_object_get_pre_modified_mesh(em->ob) == BKE_object_get_pre_modified_mesh(ob));
-
- float imat[4][4];
- float ray_start_local[3], ray_normal_local[3];
- float local_scale, local_depth, len_diff = 0.0f;
-
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(ray_start_local, ray_start);
- copy_v3_v3(ray_normal_local, ray_dir);
-
- 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 = snap_object_data_editmesh_get(sctx, em);
-
- /* Test BoundBox */
-
- /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
- if (!isect_ray_aabb_v3_simple(
- ray_start_local, ray_normal_local, sod->min, sod->max, &len_diff, NULL))
- {
- return retval;
- }
-
- /* 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 T50486, T38358.
- */
- if (len_diff > 400.0f) {
- len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
- madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
- local_depth -= len_diff;
- }
- else {
- len_diff = 0.0f;
- }
-
- if (sod->bvh_trees[2] == NULL) {
- sod->bvh_trees[2] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(BVHTreeFromEditMesh));
- }
-
- BVHTreeFromEditMesh *treedata = sod->bvh_trees[2];
-
- BVHCache *em_bvh_cache = ((Mesh *)em->ob->data)->runtime.bvh_cache;
-
- if (sctx->callbacks.edit_mesh.test_face_fn == NULL) {
- /* The tree is owned by the Mesh and may have been freed since we last used! */
- if (!bvhcache_has_tree(em_bvh_cache, treedata->tree)) {
- free_bvhtree_from_editmesh(treedata);
- }
- }
-
- if (treedata->tree == NULL) {
- BVHCache **bvh_cache = NULL;
- BLI_bitmap *elem_mask = NULL;
- BMEditMesh *em_orig;
- int looptri_num_active = -1;
-
- /* Get original version of the edit_mesh. */
- em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
-
- if (sctx->callbacks.edit_mesh.test_face_fn) {
- BMesh *bm = em_orig->bm;
- BLI_assert(poly_to_tri_count(bm->totface, bm->totloop) == em_orig->tottri);
-
- elem_mask = BLI_BITMAP_NEW(em_orig->tottri, __func__);
- looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
- bm, elem_mask,
- sctx->callbacks.edit_mesh.test_face_fn,
- sctx->callbacks.edit_mesh.user_data);
- }
- else {
- /* Only cache if bvhtree is created without a mask.
- * This helps keep a standardized bvhtree in cache. */
- bvh_cache = &em_bvh_cache;
- }
-
- bvhtree_from_editmesh_looptri_ex(
- treedata, em_orig, elem_mask, looptri_num_active,
- 0.0f, 4, 6, bvh_cache);
-
- if (elem_mask) {
- MEM_freeN(elem_mask);
- }
- if (treedata->tree == NULL) {
- return retval;
- }
- }
-
- float timat[3][3]; /* transpose inverse matrix for normals */
- transpose_m3_m4(timat, imat);
-
- if (r_hit_list) {
- struct RayCastAll_Data data;
-
- data.bvhdata = treedata;
- data.raycast_callback = treedata->raycast_callback;
- data.obmat = obmat;
- data.timat = timat;
- data.len_diff = len_diff;
- data.local_scale = local_scale;
- data.ob = ob;
- data.ob_uuid = ob_index;
- data.hit_list = r_hit_list;
- data.retval = retval;
-
- BLI_bvhtree_ray_cast_all(
- treedata->tree, ray_start_local, ray_normal_local, 0.0f,
- *ray_depth, raycast_all_cb, &data);
-
- retval = data.retval;
- }
- else {
- BVHTreeRayHit hit = { .index = -1, .dist = local_depth, };
-
- if (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);
-
- /* back to worldspace */
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- copy_v3_v3(r_no, hit.no);
- mul_m3_v3(timat, r_no);
- normalize_v3(r_no);
- }
-
- retval = true;
-
- if (r_index) {
- /* Get original version of the edit_mesh. */
- BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
-
- *r_index = BM_elem_index_get(em_orig->looptris[hit.index][0]->f);
- }
- }
- }
- }
-
- return retval;
+ bool retval = false;
+ if (em->bm->totface == 0) {
+ return retval;
+ }
+
+ BLI_assert(BKE_object_get_pre_modified_mesh(em->ob) == BKE_object_get_pre_modified_mesh(ob));
+
+ float imat[4][4];
+ float ray_start_local[3], ray_normal_local[3];
+ float local_scale, local_depth, len_diff = 0.0f;
+
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(ray_start_local, ray_start);
+ copy_v3_v3(ray_normal_local, ray_dir);
+
+ 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 = snap_object_data_editmesh_get(sctx, em);
+
+ /* Test BoundBox */
+
+ /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
+ if (!isect_ray_aabb_v3_simple(
+ ray_start_local, ray_normal_local, sod->min, sod->max, &len_diff, NULL)) {
+ return retval;
+ }
+
+ /* 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 T50486, T38358.
+ */
+ if (len_diff > 400.0f) {
+ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
+ madd_v3_v3fl(ray_start_local, ray_normal_local, len_diff);
+ local_depth -= len_diff;
+ }
+ else {
+ len_diff = 0.0f;
+ }
+
+ if (sod->bvh_trees[2] == NULL) {
+ sod->bvh_trees[2] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(BVHTreeFromEditMesh));
+ }
+
+ BVHTreeFromEditMesh *treedata = sod->bvh_trees[2];
+
+ BVHCache *em_bvh_cache = ((Mesh *)em->ob->data)->runtime.bvh_cache;
+
+ if (sctx->callbacks.edit_mesh.test_face_fn == NULL) {
+ /* The tree is owned by the Mesh and may have been freed since we last used! */
+ if (!bvhcache_has_tree(em_bvh_cache, treedata->tree)) {
+ free_bvhtree_from_editmesh(treedata);
+ }
+ }
+
+ if (treedata->tree == NULL) {
+ BVHCache **bvh_cache = NULL;
+ BLI_bitmap *elem_mask = NULL;
+ BMEditMesh *em_orig;
+ int looptri_num_active = -1;
+
+ /* Get original version of the edit_mesh. */
+ em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
+
+ if (sctx->callbacks.edit_mesh.test_face_fn) {
+ BMesh *bm = em_orig->bm;
+ BLI_assert(poly_to_tri_count(bm->totface, bm->totloop) == em_orig->tottri);
+
+ elem_mask = BLI_BITMAP_NEW(em_orig->tottri, __func__);
+ looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
+ bm,
+ elem_mask,
+ sctx->callbacks.edit_mesh.test_face_fn,
+ sctx->callbacks.edit_mesh.user_data);
+ }
+ else {
+ /* Only cache if bvhtree is created without a mask.
+ * This helps keep a standardized bvhtree in cache. */
+ bvh_cache = &em_bvh_cache;
+ }
+
+ bvhtree_from_editmesh_looptri_ex(
+ treedata, em_orig, elem_mask, looptri_num_active, 0.0f, 4, 6, bvh_cache);
+
+ if (elem_mask) {
+ MEM_freeN(elem_mask);
+ }
+ if (treedata->tree == NULL) {
+ return retval;
+ }
+ }
+
+ float timat[3][3]; /* transpose inverse matrix for normals */
+ transpose_m3_m4(timat, imat);
+
+ if (r_hit_list) {
+ struct RayCastAll_Data data;
+
+ data.bvhdata = treedata;
+ data.raycast_callback = treedata->raycast_callback;
+ data.obmat = obmat;
+ data.timat = timat;
+ data.len_diff = len_diff;
+ data.local_scale = local_scale;
+ data.ob = ob;
+ data.ob_uuid = ob_index;
+ data.hit_list = r_hit_list;
+ data.retval = retval;
+
+ BLI_bvhtree_ray_cast_all(treedata->tree,
+ ray_start_local,
+ ray_normal_local,
+ 0.0f,
+ *ray_depth,
+ raycast_all_cb,
+ &data);
+
+ retval = data.retval;
+ }
+ else {
+ BVHTreeRayHit hit = {
+ .index = -1,
+ .dist = local_depth,
+ };
+
+ if (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);
+
+ /* back to worldspace */
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ copy_v3_v3(r_no, hit.no);
+ mul_m3_v3(timat, r_no);
+ normalize_v3(r_no);
+ }
+
+ retval = true;
+
+ if (r_index) {
+ /* Get original version of the edit_mesh. */
+ BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
+
+ *r_index = BM_elem_index_get(em_orig->looptris[hit.index][0]->f);
+ }
+ }
+ }
+ }
+
+ return retval;
}
-
/**
* \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping;
*
* \note Duplicate args here are documented at #snapObjectsRay
*/
-static bool raycastObj(
- SnapObjectContext *sctx,
- const float ray_start[3], const float ray_dir[3],
- Object *ob, float obmat[4][4], const unsigned int ob_index,
- bool use_obedit, bool use_occlusion_test,
- /* read/write args */
- float *ray_depth,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4],
- ListBase *r_hit_list)
+static bool raycastObj(SnapObjectContext *sctx,
+ const float ray_start[3],
+ const float ray_dir[3],
+ Object *ob,
+ float obmat[4][4],
+ const unsigned int ob_index,
+ bool use_obedit,
+ bool use_occlusion_test,
+ /* read/write args */
+ float *ray_depth,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4],
+ ListBase *r_hit_list)
{
- bool retval = false;
-
- switch (ob->type) {
- case OB_MESH:
- {
- if (use_occlusion_test) {
- if (use_obedit && sctx->use_v3d &&
- XRAY_ENABLED(sctx->v3d_data.v3d))
- {
- /* Use of occlude geometry in editing mode disabled. */
- return false;
- }
-
- if (ELEM(ob->dt, OB_BOUNDBOX, OB_WIRE)) {
- /* Do not hit objects that are in wire or bounding box
- * display mode. */
- return false;
- }
- }
-
- Mesh *me = ob->data;
- if (BKE_object_is_in_editmode(ob)) {
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- if (use_obedit) {
- retval = raycastEditMesh(
- sctx,
- ray_start, ray_dir,
- ob, em, obmat, ob_index,
- ray_depth, r_loc, r_no, r_index, r_hit_list);
- break;
- }
- else if (em->mesh_eval_final) {
- me = em->mesh_eval_final;
- }
- }
- retval = raycastMesh(
- sctx,
- ray_start, ray_dir,
- ob, me, obmat, ob_index,
- ray_depth, r_loc, r_no, r_index, r_hit_list);
- break;
- }
- }
-
- if (retval) {
- if (r_ob) {
- *r_ob = ob;
- }
- if (r_obmat) {
- copy_m4_m4(r_obmat, obmat);
- }
- return true;
- }
-
- return false;
+ bool retval = false;
+
+ switch (ob->type) {
+ case OB_MESH: {
+ if (use_occlusion_test) {
+ if (use_obedit && sctx->use_v3d && XRAY_ENABLED(sctx->v3d_data.v3d)) {
+ /* Use of occlude geometry in editing mode disabled. */
+ return false;
+ }
+
+ if (ELEM(ob->dt, OB_BOUNDBOX, OB_WIRE)) {
+ /* Do not hit objects that are in wire or bounding box
+ * display mode. */
+ return false;
+ }
+ }
+
+ Mesh *me = ob->data;
+ if (BKE_object_is_in_editmode(ob)) {
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ if (use_obedit) {
+ retval = raycastEditMesh(sctx,
+ ray_start,
+ ray_dir,
+ ob,
+ em,
+ obmat,
+ ob_index,
+ ray_depth,
+ r_loc,
+ r_no,
+ r_index,
+ r_hit_list);
+ break;
+ }
+ else if (em->mesh_eval_final) {
+ me = em->mesh_eval_final;
+ }
+ }
+ retval = raycastMesh(sctx,
+ ray_start,
+ ray_dir,
+ ob,
+ me,
+ obmat,
+ ob_index,
+ ray_depth,
+ r_loc,
+ r_no,
+ r_index,
+ r_hit_list);
+ break;
+ }
+ }
+
+ if (retval) {
+ if (r_ob) {
+ *r_ob = ob;
+ }
+ if (r_obmat) {
+ copy_m4_m4(r_obmat, obmat);
+ }
+ return true;
+ }
+
+ return false;
}
-
struct RaycastObjUserData {
- const float *ray_start;
- const float *ray_dir;
- unsigned int ob_index;
- /* read/write args */
- float *ray_depth;
- /* return args */
- float *r_loc;
- float *r_no;
- int *r_index;
- Object **r_ob;
- float (*r_obmat)[4];
- ListBase *r_hit_list;
- bool use_occlusion_test;
- bool ret;
+ const float *ray_start;
+ const float *ray_dir;
+ unsigned int ob_index;
+ /* read/write args */
+ float *ray_depth;
+ /* return args */
+ float *r_loc;
+ float *r_no;
+ int *r_index;
+ Object **r_ob;
+ float (*r_obmat)[4];
+ ListBase *r_hit_list;
+ bool use_occlusion_test;
+ bool ret;
};
-static void raycast_obj_cb(SnapObjectContext *sctx, bool use_obedit, Object *ob, float obmat[4][4], void *data)
+static void raycast_obj_cb(
+ SnapObjectContext *sctx, bool use_obedit, Object *ob, float obmat[4][4], void *data)
{
- struct RaycastObjUserData *dt = data;
-
- dt->ret |= raycastObj(
- sctx,
- dt->ray_start, dt->ray_dir,
- ob, obmat, dt->ob_index++,
- use_obedit, dt->use_occlusion_test,
- dt->ray_depth,
- dt->r_loc, dt->r_no, dt->r_index,
- dt->r_ob, dt->r_obmat,
- dt->r_hit_list);
+ struct RaycastObjUserData *dt = data;
+
+ dt->ret |= raycastObj(sctx,
+ dt->ray_start,
+ dt->ray_dir,
+ ob,
+ obmat,
+ dt->ob_index++,
+ use_obedit,
+ dt->use_occlusion_test,
+ dt->ray_depth,
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index,
+ dt->r_ob,
+ dt->r_obmat,
+ dt->r_hit_list);
}
/**
@@ -788,202 +839,194 @@ static void raycast_obj_cb(SnapObjectContext *sctx, bool use_obedit, Object *ob,
* \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances).
* \param r_hit_list: List of #SnapObjectHitDepth (caller must free).
*/
-static bool raycastObjects(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_start[3], const float ray_dir[3],
- /* read/write args */
- float *ray_depth,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4],
- ListBase *r_hit_list)
+static bool raycastObjects(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_start[3],
+ const float ray_dir[3],
+ /* read/write args */
+ float *ray_depth,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4],
+ ListBase *r_hit_list)
{
- struct RaycastObjUserData data = {
- .ray_start = ray_start,
- .ray_dir = ray_dir,
- .ob_index = 0,
- .ray_depth = ray_depth,
- .r_loc = r_loc,
- .r_no = r_no,
- .r_index = r_index,
- .r_ob = r_ob,
- .r_obmat = r_obmat,
- .r_hit_list = r_hit_list,
- .use_occlusion_test = params->use_occlusion_test,
- .ret = false,
- };
-
- iter_snap_objects(sctx, params, raycast_obj_cb, &data);
-
- return data.ret;
+ struct RaycastObjUserData data = {
+ .ray_start = ray_start,
+ .ray_dir = ray_dir,
+ .ob_index = 0,
+ .ray_depth = ray_depth,
+ .r_loc = r_loc,
+ .r_no = r_no,
+ .r_index = r_index,
+ .r_ob = r_ob,
+ .r_obmat = r_obmat,
+ .r_hit_list = r_hit_list,
+ .use_occlusion_test = params->use_occlusion_test,
+ .ret = false,
+ };
+
+ iter_snap_objects(sctx, params, raycast_obj_cb, &data);
+
+ return data.ret;
}
-
/** \} */
/* -------------------------------------------------------------------- */
/** Snap Nearest utilities
* \{ */
- /* Test BoundBox */
-static bool snap_bound_box_check_dist(
- float min[3], float max[3], float lpmat[4][4],
- float win_size[2], float mval[2], float dist_px_sq)
+/* Test BoundBox */
+static bool snap_bound_box_check_dist(float min[3],
+ float max[3],
+ float lpmat[4][4],
+ float win_size[2],
+ float mval[2],
+ float dist_px_sq)
{
- /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
+ /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
- struct DistProjectedAABBPrecalc data_precalc;
- dist_squared_to_projected_aabb_precalc(
- &data_precalc, lpmat, win_size, mval);
+ struct DistProjectedAABBPrecalc data_precalc;
+ dist_squared_to_projected_aabb_precalc(&data_precalc, lpmat, win_size, mval);
- bool dummy[3];
- float bb_dist_px_sq = dist_squared_to_projected_aabb(
- &data_precalc, min, max, dummy);
+ bool dummy[3];
+ float bb_dist_px_sq = dist_squared_to_projected_aabb(&data_precalc, min, max, dummy);
- if (bb_dist_px_sq > dist_px_sq) {
- return false;
- }
- return true;
+ if (bb_dist_px_sq > dist_px_sq) {
+ return false;
+ }
+ return true;
}
-static void cb_mvert_co_get(
- const int index, const float **co, const BVHTreeFromMesh *data)
+static void cb_mvert_co_get(const int index, const float **co, const BVHTreeFromMesh *data)
{
- *co = data->vert[index].co;
+ *co = data->vert[index].co;
}
-static void cb_bvert_co_get(
- const int index, const float **co, const BMEditMesh *data)
+static void cb_bvert_co_get(const int index, const float **co, const BMEditMesh *data)
{
- BMVert *eve = BM_vert_at_index(data->bm, index);
- *co = eve->co;
+ BMVert *eve = BM_vert_at_index(data->bm, index);
+ *co = eve->co;
}
-static void cb_mvert_no_copy(
- const int index, float r_no[3], const BVHTreeFromMesh *data)
+static void cb_mvert_no_copy(const int index, float r_no[3], const BVHTreeFromMesh *data)
{
- const MVert *vert = data->vert + index;
+ const MVert *vert = data->vert + index;
- normal_short_to_float_v3(r_no, vert->no);
+ normal_short_to_float_v3(r_no, vert->no);
}
-static void cb_bvert_no_copy(
- const int index, float r_no[3], const BMEditMesh *data)
+static void cb_bvert_no_copy(const int index, float r_no[3], const BMEditMesh *data)
{
- BMVert *eve = BM_vert_at_index(data->bm, index);
+ BMVert *eve = BM_vert_at_index(data->bm, index);
- copy_v3_v3(r_no, eve->no);
+ copy_v3_v3(r_no, eve->no);
}
-static void cb_medge_verts_get(
- const int index, int v_index[2], const BVHTreeFromMesh *data)
+static void cb_medge_verts_get(const int index, int v_index[2], const BVHTreeFromMesh *data)
{
- const MEdge *edge = &data->edge[index];
-
- v_index[0] = edge->v1;
- v_index[1] = edge->v2;
+ const MEdge *edge = &data->edge[index];
+ v_index[0] = edge->v1;
+ v_index[1] = edge->v2;
}
-static void cb_bedge_verts_get(
- const int index, int v_index[2], const BMEditMesh *data)
+static void cb_bedge_verts_get(const int index, int v_index[2], const BMEditMesh *data)
{
- BMEdge *eed = BM_edge_at_index(data->bm, index);
+ BMEdge *eed = BM_edge_at_index(data->bm, index);
- v_index[0] = BM_elem_index_get(eed->v1);
- v_index[1] = BM_elem_index_get(eed->v2);
+ v_index[0] = BM_elem_index_get(eed->v1);
+ v_index[1] = BM_elem_index_get(eed->v2);
}
-static void cb_mlooptri_edges_get(
- const int index, int v_index[3], const BVHTreeFromMesh *data)
+static void cb_mlooptri_edges_get(const int index, int v_index[3], const BVHTreeFromMesh *data)
{
- const MEdge *medge = data->edge;
- const MLoop *mloop = data->loop;
- const MLoopTri *lt = &data->looptri[index];
- for (int j = 2, j_next = 0; j_next < 3; j = j_next++) {
- const MEdge *ed = &medge[mloop[lt->tri[j]].e];
- unsigned int tri_edge[2] = {mloop[lt->tri[j]].v, mloop[lt->tri[j_next]].v};
- if (ELEM(ed->v1, tri_edge[0], tri_edge[1]) &&
- ELEM(ed->v2, tri_edge[0], tri_edge[1]))
- {
- //printf("real edge found\n");
- v_index[j] = mloop[lt->tri[j]].e;
- }
- else
- v_index[j] = -1;
- }
+ const MEdge *medge = data->edge;
+ const MLoop *mloop = data->loop;
+ const MLoopTri *lt = &data->looptri[index];
+ for (int j = 2, j_next = 0; j_next < 3; j = j_next++) {
+ const MEdge *ed = &medge[mloop[lt->tri[j]].e];
+ unsigned int tri_edge[2] = {mloop[lt->tri[j]].v, mloop[lt->tri[j_next]].v};
+ if (ELEM(ed->v1, tri_edge[0], tri_edge[1]) && ELEM(ed->v2, tri_edge[0], tri_edge[1])) {
+ //printf("real edge found\n");
+ v_index[j] = mloop[lt->tri[j]].e;
+ }
+ else
+ v_index[j] = -1;
+ }
}
-static void cb_mlooptri_verts_get(
- const int index, int v_index[3], const BVHTreeFromMesh *data)
+static void cb_mlooptri_verts_get(const int index, int v_index[3], const BVHTreeFromMesh *data)
{
- const MLoop *loop = data->loop;
- const MLoopTri *looptri = &data->looptri[index];
+ const MLoop *loop = data->loop;
+ const MLoopTri *looptri = &data->looptri[index];
- v_index[0] = loop[looptri->tri[0]].v;
- v_index[1] = loop[looptri->tri[1]].v;
- v_index[2] = loop[looptri->tri[2]].v;
+ v_index[0] = loop[looptri->tri[0]].v;
+ v_index[1] = loop[looptri->tri[1]].v;
+ v_index[2] = loop[looptri->tri[2]].v;
}
-static bool test_projected_vert_dist(
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- const bool is_persp, const float co[3],
- float *dist_px_sq, float r_co[3])
+static bool test_projected_vert_dist(const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ const bool is_persp,
+ const float co[3],
+ float *dist_px_sq,
+ float r_co[3])
{
- if (!isect_point_planes_v3_negated(clip_plane, clip_plane_len, co)) {
- return false;
- }
-
- float co2d[2] = {
- (dot_m4_v3_row_x(precalc->pmat, co) + precalc->pmat[3][0]),
- (dot_m4_v3_row_y(precalc->pmat, co) + precalc->pmat[3][1]),
- };
-
- if (is_persp) {
- float w = mul_project_m4_v3_zfac(precalc->pmat, co);
- mul_v2_fl(co2d, 1.0f / w);
- }
-
- const float dist_sq = len_squared_v2v2(precalc->mval, co2d);
- if (dist_sq < *dist_px_sq) {
- copy_v3_v3(r_co, co);
- *dist_px_sq = dist_sq;
- return true;
- }
- return false;
+ if (!isect_point_planes_v3_negated(clip_plane, clip_plane_len, co)) {
+ return false;
+ }
+
+ float co2d[2] = {
+ (dot_m4_v3_row_x(precalc->pmat, co) + precalc->pmat[3][0]),
+ (dot_m4_v3_row_y(precalc->pmat, co) + precalc->pmat[3][1]),
+ };
+
+ if (is_persp) {
+ float w = mul_project_m4_v3_zfac(precalc->pmat, co);
+ mul_v2_fl(co2d, 1.0f / w);
+ }
+
+ const float dist_sq = len_squared_v2v2(precalc->mval, co2d);
+ if (dist_sq < *dist_px_sq) {
+ copy_v3_v3(r_co, co);
+ *dist_px_sq = dist_sq;
+ return true;
+ }
+ return false;
}
-static bool test_projected_edge_dist(
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- const bool is_persp, const float va[3], const float vb[3],
- float *dist_px_sq, float r_co[3])
+static bool test_projected_edge_dist(const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ const bool is_persp,
+ const float va[3],
+ const float vb[3],
+ float *dist_px_sq,
+ float r_co[3])
{
- float near_co[3], lambda;
- if (!isect_ray_seg_v3(
- precalc->ray_origin,
- precalc->ray_direction,
- va, vb, &lambda))
- {
- copy_v3_v3(near_co, va);
- }
- else {
- if (lambda <= 0.0f) {
- copy_v3_v3(near_co, va);
- }
- else if (lambda >= 1.0f) {
- copy_v3_v3(near_co, vb);
- }
- else {
- interp_v3_v3v3(near_co, va, vb, lambda);
- }
- }
-
- return test_projected_vert_dist(
- precalc, clip_plane, clip_plane_len,
- is_persp, near_co, dist_px_sq, r_co);
+ float near_co[3], lambda;
+ if (!isect_ray_seg_v3(precalc->ray_origin, precalc->ray_direction, va, vb, &lambda)) {
+ copy_v3_v3(near_co, va);
+ }
+ else {
+ if (lambda <= 0.0f) {
+ copy_v3_v3(near_co, va);
+ }
+ else if (lambda >= 1.0f) {
+ copy_v3_v3(near_co, vb);
+ }
+ else {
+ interp_v3_v3v3(near_co, va, vb, lambda);
+ }
+ }
+
+ return test_projected_vert_dist(
+ precalc, clip_plane, clip_plane_len, is_persp, near_co, dist_px_sq, r_co);
}
/** \} */
@@ -1000,132 +1043,128 @@ typedef void (*Nearest2DGetTriEdgesCallback)(const int index, int e_index[3], vo
typedef void (*Nearest2DCopyVertNoCallback)(const int index, float r_no[3], void *data);
typedef struct Nearest2dUserData {
- bool is_persp;
+ bool is_persp;
- void *userdata;
- Nearest2DGetVertCoCallback get_vert_co;
- Nearest2DGetEdgeVertsCallback get_edge_verts_index;
- Nearest2DGetTriVertsCallback get_tri_verts_index;
- Nearest2DGetTriEdgesCallback get_tri_edges_index;
- Nearest2DCopyVertNoCallback copy_vert_no;
+ void *userdata;
+ Nearest2DGetVertCoCallback get_vert_co;
+ Nearest2DGetEdgeVertsCallback get_edge_verts_index;
+ Nearest2DGetTriVertsCallback get_tri_verts_index;
+ Nearest2DGetTriEdgesCallback get_tri_edges_index;
+ Nearest2DCopyVertNoCallback copy_vert_no;
} Nearest2dUserData;
-
-static void cb_snap_vert(
- void *userdata, int index,
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- BVHTreeNearest *nearest)
+static void cb_snap_vert(void *userdata,
+ int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ BVHTreeNearest *nearest)
{
- struct Nearest2dUserData *data = userdata;
-
- const float *co;
- data->get_vert_co(index, &co, data->userdata);
-
- if (test_projected_vert_dist(
- precalc,
- clip_plane,
- clip_plane_len,
- data->is_persp, co,
- &nearest->dist_sq,
- nearest->co))
- {
- data->copy_vert_no(index, nearest->no, data->userdata);
- nearest->index = index;
- }
+ struct Nearest2dUserData *data = userdata;
+
+ const float *co;
+ data->get_vert_co(index, &co, data->userdata);
+
+ if (test_projected_vert_dist(precalc,
+ clip_plane,
+ clip_plane_len,
+ data->is_persp,
+ co,
+ &nearest->dist_sq,
+ nearest->co)) {
+ data->copy_vert_no(index, nearest->no, data->userdata);
+ nearest->index = index;
+ }
}
-static void cb_snap_edge(
- void *userdata, int index,
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- BVHTreeNearest *nearest)
+static void cb_snap_edge(void *userdata,
+ int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ BVHTreeNearest *nearest)
{
- struct Nearest2dUserData *data = userdata;
-
- int vindex[2];
- data->get_edge_verts_index(index, vindex, data->userdata);
-
- const float *v_pair[2];
- data->get_vert_co(vindex[0], &v_pair[0], data->userdata);
- data->get_vert_co(vindex[1], &v_pair[1], data->userdata);
-
- if (test_projected_edge_dist(
- precalc,
- clip_plane,
- clip_plane_len,
- data->is_persp,
- v_pair[0], v_pair[1],
- &nearest->dist_sq,
- nearest->co))
- {
- sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]);
- nearest->index = index;
- }
+ struct Nearest2dUserData *data = userdata;
+
+ int vindex[2];
+ data->get_edge_verts_index(index, vindex, data->userdata);
+
+ const float *v_pair[2];
+ data->get_vert_co(vindex[0], &v_pair[0], data->userdata);
+ data->get_vert_co(vindex[1], &v_pair[1], data->userdata);
+
+ if (test_projected_edge_dist(precalc,
+ clip_plane,
+ clip_plane_len,
+ data->is_persp,
+ v_pair[0],
+ v_pair[1],
+ &nearest->dist_sq,
+ nearest->co)) {
+ sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]);
+ nearest->index = index;
+ }
}
-static void cb_snap_edge_verts(
- void *userdata, int index,
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- BVHTreeNearest *nearest)
+static void cb_snap_edge_verts(void *userdata,
+ int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ BVHTreeNearest *nearest)
{
- struct Nearest2dUserData *data = userdata;
-
- int vindex[2];
- data->get_edge_verts_index(index, vindex, data->userdata);
-
- for (int i = 2; i--;) {
- if (vindex[i] == nearest->index) {
- continue;
- }
- cb_snap_vert(
- userdata, vindex[i], precalc,
- clip_plane, clip_plane_len, nearest);
- }
+ struct Nearest2dUserData *data = userdata;
+
+ int vindex[2];
+ data->get_edge_verts_index(index, vindex, data->userdata);
+
+ for (int i = 2; i--;) {
+ if (vindex[i] == nearest->index) {
+ continue;
+ }
+ cb_snap_vert(userdata, vindex[i], precalc, clip_plane, clip_plane_len, nearest);
+ }
}
-static void cb_snap_tri_edges(
- void *userdata, int index,
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- BVHTreeNearest *nearest)
+static void cb_snap_tri_edges(void *userdata,
+ int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ BVHTreeNearest *nearest)
{
- struct Nearest2dUserData *data = userdata;
-
- int eindex[3];
- data->get_tri_edges_index(index, eindex, data->userdata);
- for (int i = 3; i--;) {
- if (eindex[i] != -1) {
- if (eindex[i] == nearest->index) {
- continue;
- }
- cb_snap_edge(
- userdata, eindex[i], precalc,
- clip_plane, clip_plane_len, nearest);
- }
- }
+ struct Nearest2dUserData *data = userdata;
+
+ int eindex[3];
+ data->get_tri_edges_index(index, eindex, data->userdata);
+ for (int i = 3; i--;) {
+ if (eindex[i] != -1) {
+ if (eindex[i] == nearest->index) {
+ continue;
+ }
+ cb_snap_edge(userdata, eindex[i], precalc, clip_plane, clip_plane_len, nearest);
+ }
+ }
}
-static void cb_snap_tri_verts(
- void *userdata, int index,
- const struct DistProjectedAABBPrecalc *precalc,
- const float (*clip_plane)[4], const int clip_plane_len,
- BVHTreeNearest *nearest)
+static void cb_snap_tri_verts(void *userdata,
+ int index,
+ const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4],
+ const int clip_plane_len,
+ BVHTreeNearest *nearest)
{
- struct Nearest2dUserData *data = userdata;
-
- int vindex[3];
- data->get_tri_verts_index(index, vindex, data->userdata);
- for (int i = 3; i--;) {
- if (vindex[i] == nearest->index) {
- continue;
- }
- cb_snap_vert(
- userdata, vindex[i], precalc,
- clip_plane, clip_plane_len, nearest);
- }
+ struct Nearest2dUserData *data = userdata;
+
+ int vindex[3];
+ data->get_tri_verts_index(index, vindex, data->userdata);
+ for (int i = 3; i--;) {
+ if (vindex[i] == nearest->index) {
+ continue;
+ }
+ cb_snap_vert(userdata, vindex[i], precalc, clip_plane, clip_plane_len, nearest);
+ }
}
/** \} */
@@ -1134,1028 +1173,1124 @@ static void cb_snap_tri_verts(
/** \name Internal Object Snapping API
* \{ */
-static short snap_mesh_polygon(
- SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, float obmat[4][4],
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index)
+static short snap_mesh_polygon(SnapObjectContext *sctx,
+ SnapData *snapdata,
+ Object *ob,
+ float obmat[4][4],
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index)
{
- short elem = 0;
-
- float lpmat[4][4];
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
-
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- Nearest2dUserData nearest2d = {
- .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
- };
-
- BVHTreeNearest nearest = {
- .index = -1,
- .dist_sq = SQUARE(*dist_px),
- };
-
- SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
- if (sod == NULL) {
- /* The object is in edit mode, and the key used
- * was the object referenced in BMEditMesh */
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- sod = BLI_ghash_lookup(sctx->cache.object_map, em->ob);
- }
-
- BLI_assert(sod != NULL);
-
- if (sod->type == SNAP_MESH) {
- BVHTreeFromMesh *treedata = &((SnapObjectData_Mesh *)sod)->treedata;
-
- nearest2d.userdata = treedata;
- nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
- nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
- nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
-
- const MPoly *mp = &((SnapObjectData_Mesh *)sod)->poly[*r_index];
- const MLoop *ml = &treedata->loop[mp->loopstart];
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- elem = SCE_SNAP_MODE_EDGE;
- BLI_assert(treedata->edge != NULL);
- for (int i = mp->totloop; i--; ml++) {
- cb_snap_edge(
- &nearest2d, ml->e, &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest);
- }
- }
- else {
- elem = SCE_SNAP_MODE_VERTEX;
- for (int i = mp->totloop; i--; ml++) {
- cb_snap_vert(
- &nearest2d, ml->v, &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest);
- }
- }
- }
- else {
- BLI_assert(sod->type == SNAP_EDIT_MESH);
- BMEditMesh *em = BKE_editmesh_from_object(ob);
-
- nearest2d.userdata = em;
- nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get;
- nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get;
- nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy;
-
- BM_mesh_elem_table_ensure(em->bm, BM_FACE);
- BMFace *f = BM_face_at_index(em->bm, *r_index);
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- elem = SCE_SNAP_MODE_EDGE;
- BM_mesh_elem_index_ensure(em->bm, BM_EDGE);
- BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE);
- do {
- cb_snap_edge(
- &nearest2d, BM_elem_index_get(l_iter->e),
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest);
- } while ((l_iter = l_iter->next) != l_first);
- }
- else {
- elem = SCE_SNAP_MODE_VERTEX;
- BM_mesh_elem_index_ensure(em->bm, BM_VERT);
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
- do {
- cb_snap_vert(
- &nearest2d, BM_elem_index_get(l_iter->v),
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest);
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
-
- if (nearest.index != -1) {
- *dist_px = sqrtf(nearest.dist_sq);
-
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- float imat[4][4];
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(r_no, nearest.no);
- mul_transposed_mat3_m4_v3(imat, r_no);
- normalize_v3(r_no);
- }
-
- *r_index = nearest.index;
- return elem;
- }
-
- return 0;
+ short elem = 0;
+
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ Nearest2dUserData nearest2d = {
+ .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
+ };
+
+ BVHTreeNearest nearest = {
+ .index = -1,
+ .dist_sq = SQUARE(*dist_px),
+ };
+
+ SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
+ if (sod == NULL) {
+ /* The object is in edit mode, and the key used
+ * was the object referenced in BMEditMesh */
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ sod = BLI_ghash_lookup(sctx->cache.object_map, em->ob);
+ }
+
+ BLI_assert(sod != NULL);
+
+ if (sod->type == SNAP_MESH) {
+ BVHTreeFromMesh *treedata = &((SnapObjectData_Mesh *)sod)->treedata;
+
+ nearest2d.userdata = treedata;
+ nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
+ nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
+ nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
+
+ const MPoly *mp = &((SnapObjectData_Mesh *)sod)->poly[*r_index];
+ const MLoop *ml = &treedata->loop[mp->loopstart];
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ elem = SCE_SNAP_MODE_EDGE;
+ BLI_assert(treedata->edge != NULL);
+ for (int i = mp->totloop; i--; ml++) {
+ cb_snap_edge(&nearest2d,
+ ml->e,
+ &neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest);
+ }
+ }
+ else {
+ elem = SCE_SNAP_MODE_VERTEX;
+ for (int i = mp->totloop; i--; ml++) {
+ cb_snap_vert(&nearest2d,
+ ml->v,
+ &neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest);
+ }
+ }
+ }
+ else {
+ BLI_assert(sod->type == SNAP_EDIT_MESH);
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+
+ nearest2d.userdata = em;
+ nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get;
+ nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get;
+ nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy;
+
+ BM_mesh_elem_table_ensure(em->bm, BM_FACE);
+ BMFace *f = BM_face_at_index(em->bm, *r_index);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ elem = SCE_SNAP_MODE_EDGE;
+ BM_mesh_elem_index_ensure(em->bm, BM_EDGE);
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE);
+ do {
+ cb_snap_edge(&nearest2d,
+ BM_elem_index_get(l_iter->e),
+ &neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ else {
+ elem = SCE_SNAP_MODE_VERTEX;
+ BM_mesh_elem_index_ensure(em->bm, BM_VERT);
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ do {
+ cb_snap_vert(&nearest2d,
+ BM_elem_index_get(l_iter->v),
+ &neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+ }
+
+ if (nearest.index != -1) {
+ *dist_px = sqrtf(nearest.dist_sq);
+
+ copy_v3_v3(r_loc, nearest.co);
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ float imat[4][4];
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(r_no, nearest.no);
+ mul_transposed_mat3_m4_v3(imat, r_no);
+ normalize_v3(r_no);
+ }
+
+ *r_index = nearest.index;
+ return elem;
+ }
+
+ return 0;
}
-
-static short snap_mesh_edge_verts_mixed(
- SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, float obmat[4][4], float original_dist_px,
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index)
+static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
+ SnapData *snapdata,
+ Object *ob,
+ float obmat[4][4],
+ float original_dist_px,
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index)
{
- short elem = SCE_SNAP_MODE_EDGE;
-
- if (ob->type != OB_MESH) {
- return elem;
- }
-
- float lpmat[4][4];
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
-
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
-
- Nearest2dUserData nearest2d = {
- .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
- };
-
- BVHTreeNearest nearest = {
- .index = -1,
- .dist_sq = SQUARE(original_dist_px),
- };
-
- SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
- BLI_assert(sod != NULL);
-
- if (sod->type == SNAP_MESH) {
- nearest2d.userdata = &((SnapObjectData_Mesh *)sod)->treedata;
- nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
- nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
- nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
- }
- else {
- BLI_assert(sod->type == SNAP_EDIT_MESH);
- nearest2d.userdata = BKE_editmesh_from_object(ob);
- nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get;
- nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get;
- nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy;
- }
-
- int vindex[2];
- nearest2d.get_edge_verts_index(*r_index, vindex, nearest2d.userdata);
-
- const float *v_pair[2];
- nearest2d.get_vert_co(vindex[0], &v_pair[0], nearest2d.userdata);
- nearest2d.get_vert_co(vindex[1], &v_pair[1], nearest2d.userdata);
-
- float lambda;
- if (!isect_ray_seg_v3(
- neasrest_precalc.ray_origin,
- neasrest_precalc.ray_direction,
- v_pair[0], v_pair[1], &lambda))
- {
- /* do nothing */
- }
- else if (lambda < 0.25f || 0.75f < lambda) {
- int v_id = lambda < 0.5f ? 0 : 1;
-
- if (test_projected_vert_dist(
- &neasrest_precalc, NULL, 0,
- nearest2d.is_persp, v_pair[v_id],
- &nearest.dist_sq, nearest.co))
- {
- nearest.index = vindex[v_id];
- nearest2d.copy_vert_no(vindex[v_id], nearest.no, nearest2d.userdata);
- elem = SCE_SNAP_MODE_VERTEX;
- }
- }
-
- if (nearest.index != -1) {
- *dist_px = sqrtf(nearest.dist_sq);
-
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- float imat[4][4];
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(r_no, nearest.no);
- mul_transposed_mat3_m4_v3(imat, r_no);
- normalize_v3(r_no);
- }
-
- *r_index = nearest.index;
- }
-
- return elem;
+ short elem = SCE_SNAP_MODE_EDGE;
+
+ if (ob->type != OB_MESH) {
+ return elem;
+ }
+
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
+
+ Nearest2dUserData nearest2d = {
+ .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
+ };
+
+ BVHTreeNearest nearest = {
+ .index = -1,
+ .dist_sq = SQUARE(original_dist_px),
+ };
+
+ SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
+ BLI_assert(sod != NULL);
+
+ if (sod->type == SNAP_MESH) {
+ nearest2d.userdata = &((SnapObjectData_Mesh *)sod)->treedata;
+ nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get;
+ nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get;
+ nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy;
+ }
+ else {
+ BLI_assert(sod->type == SNAP_EDIT_MESH);
+ nearest2d.userdata = BKE_editmesh_from_object(ob);
+ nearest2d.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get;
+ nearest2d.get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get;
+ nearest2d.copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy;
+ }
+
+ int vindex[2];
+ nearest2d.get_edge_verts_index(*r_index, vindex, nearest2d.userdata);
+
+ const float *v_pair[2];
+ nearest2d.get_vert_co(vindex[0], &v_pair[0], nearest2d.userdata);
+ nearest2d.get_vert_co(vindex[1], &v_pair[1], nearest2d.userdata);
+
+ float lambda;
+ if (!isect_ray_seg_v3(neasrest_precalc.ray_origin,
+ neasrest_precalc.ray_direction,
+ v_pair[0],
+ v_pair[1],
+ &lambda)) {
+ /* do nothing */
+ }
+ else if (lambda < 0.25f || 0.75f < lambda) {
+ int v_id = lambda < 0.5f ? 0 : 1;
+
+ if (test_projected_vert_dist(&neasrest_precalc,
+ NULL,
+ 0,
+ nearest2d.is_persp,
+ v_pair[v_id],
+ &nearest.dist_sq,
+ nearest.co)) {
+ nearest.index = vindex[v_id];
+ nearest2d.copy_vert_no(vindex[v_id], nearest.no, nearest2d.userdata);
+ elem = SCE_SNAP_MODE_VERTEX;
+ }
+ }
+
+ if (nearest.index != -1) {
+ *dist_px = sqrtf(nearest.dist_sq);
+
+ copy_v3_v3(r_loc, nearest.co);
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ float imat[4][4];
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(r_no, nearest.no);
+ mul_transposed_mat3_m4_v3(imat, r_no);
+ normalize_v3(r_no);
+ }
+
+ *r_index = nearest.index;
+ }
+
+ return elem;
}
-static short snapArmature(
- SnapData *snapdata,
- Object *ob, float obmat[4][4], bool use_obedit,
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float *UNUSED(r_no), int *r_index)
+static short snapArmature(SnapData *snapdata,
+ Object *ob,
+ float obmat[4][4],
+ bool use_obedit,
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float *UNUSED(r_no),
+ int *r_index)
{
- short retval = 0;
-
- if (snapdata->snap_to_flag == SCE_SNAP_MODE_FACE) { /* Currently only edge and vert */
- return retval;
- }
-
- float lpmat[4][4], dist_px_sq = SQUARE(*dist_px);
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
-
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
-
- use_obedit = use_obedit && BKE_object_is_in_editmode(ob);
-
- if (use_obedit == false) {
- /* Test BoundBox */
- BoundBox *bb = BKE_armature_boundbox_get(ob);
- if (bb && !snap_bound_box_check_dist(
- bb->vec[0], bb->vec[6], lpmat,
- snapdata->win_size, snapdata->mval, dist_px_sq))
- {
- return retval;
- }
- }
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
-
- bArmature *arm = ob->data;
- if (arm->edbo) {
- for (EditBone *eBone = arm->edbo->first; eBone; eBone = eBone->next) {
- if (eBone->layer & arm->layer) {
- /* skip hidden or moving (selected) bones */
- if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
- bool has_vert_snap = false;
-
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- has_vert_snap = test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, eBone->head, &dist_px_sq, r_loc);
- has_vert_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, eBone->tail, &dist_px_sq, r_loc);
-
- if (has_vert_snap) {
- retval = SCE_SNAP_MODE_VERTEX;
- }
- }
- if (!has_vert_snap && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- if (test_projected_edge_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, eBone->head, eBone->tail,
- &dist_px_sq, r_loc))
- {
- retval = SCE_SNAP_MODE_EDGE;
- }
- }
- }
- }
- }
- }
- else if (ob->pose && ob->pose->chanbase.first) {
- for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- Bone *bone = pchan->bone;
- /* skip hidden bones */
- if (bone && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
- bool has_vert_snap = false;
- const float *head_vec = pchan->pose_head;
- const float *tail_vec = pchan->pose_tail;
-
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- has_vert_snap = test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, head_vec, &dist_px_sq, r_loc);
- has_vert_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, tail_vec, &dist_px_sq, r_loc);
-
- if (has_vert_snap) {
- retval = SCE_SNAP_MODE_VERTEX;
- }
- }
- if (!has_vert_snap && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- if (test_projected_edge_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, head_vec, tail_vec,
- &dist_px_sq, r_loc))
- {
- retval = SCE_SNAP_MODE_EDGE;
- }
- }
- }
- }
- }
-
- if (retval) {
- *dist_px = sqrtf(dist_px_sq);
- mul_m4_v3(obmat, r_loc);
- if (r_index) {
- /* Does not support index. */
- *r_index = -1;
- }
- return retval;
- }
-
- return 0;
+ short retval = 0;
+
+ if (snapdata->snap_to_flag == SCE_SNAP_MODE_FACE) { /* Currently only edge and vert */
+ return retval;
+ }
+
+ float lpmat[4][4], dist_px_sq = SQUARE(*dist_px);
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
+
+ use_obedit = use_obedit && BKE_object_is_in_editmode(ob);
+
+ if (use_obedit == false) {
+ /* Test BoundBox */
+ BoundBox *bb = BKE_armature_boundbox_get(ob);
+ if (bb && !snap_bound_box_check_dist(
+ bb->vec[0], bb->vec[6], lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
+ return retval;
+ }
+ }
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+
+ bArmature *arm = ob->data;
+ if (arm->edbo) {
+ for (EditBone *eBone = arm->edbo->first; eBone; eBone = eBone->next) {
+ if (eBone->layer & arm->layer) {
+ /* skip hidden or moving (selected) bones */
+ if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) {
+ bool has_vert_snap = false;
+
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ has_vert_snap = test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ eBone->head,
+ &dist_px_sq,
+ r_loc);
+ has_vert_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ eBone->tail,
+ &dist_px_sq,
+ r_loc);
+
+ if (has_vert_snap) {
+ retval = SCE_SNAP_MODE_VERTEX;
+ }
+ }
+ if (!has_vert_snap && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ if (test_projected_edge_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ eBone->head,
+ eBone->tail,
+ &dist_px_sq,
+ r_loc)) {
+ retval = SCE_SNAP_MODE_EDGE;
+ }
+ }
+ }
+ }
+ }
+ }
+ else if (ob->pose && ob->pose->chanbase.first) {
+ for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ Bone *bone = pchan->bone;
+ /* skip hidden bones */
+ if (bone && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) {
+ bool has_vert_snap = false;
+ const float *head_vec = pchan->pose_head;
+ const float *tail_vec = pchan->pose_tail;
+
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ has_vert_snap = test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ head_vec,
+ &dist_px_sq,
+ r_loc);
+ has_vert_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ tail_vec,
+ &dist_px_sq,
+ r_loc);
+
+ if (has_vert_snap) {
+ retval = SCE_SNAP_MODE_VERTEX;
+ }
+ }
+ if (!has_vert_snap && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ if (test_projected_edge_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ head_vec,
+ tail_vec,
+ &dist_px_sq,
+ r_loc)) {
+ retval = SCE_SNAP_MODE_EDGE;
+ }
+ }
+ }
+ }
+ }
+
+ if (retval) {
+ *dist_px = sqrtf(dist_px_sq);
+ mul_m4_v3(obmat, r_loc);
+ if (r_index) {
+ /* Does not support index. */
+ *r_index = -1;
+ }
+ return retval;
+ }
+
+ return 0;
}
-static short snapCurve(
- SnapData *snapdata,
- Object *ob, float obmat[4][4], bool use_obedit,
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float *UNUSED(r_no), int *r_index)
+static short snapCurve(SnapData *snapdata,
+ Object *ob,
+ float obmat[4][4],
+ bool use_obedit,
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float *UNUSED(r_no),
+ int *r_index)
{
- bool has_snap = false;
-
- /* only vertex snapping mode (eg control points and handles) supported for now) */
- if (snapdata->snap_to_flag != SCE_SNAP_MODE_VERTEX) {
- return 0;
- }
-
- Curve *cu = ob->data;
- float dist_px_sq = SQUARE(*dist_px);
-
- float lpmat[4][4];
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
-
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
-
- use_obedit = use_obedit && BKE_object_is_in_editmode(ob);
-
- if (use_obedit == false) {
- /* Test BoundBox */
- BoundBox *bb = BKE_curve_texspace_get(cu, NULL, NULL, NULL);
- if (bb && !snap_bound_box_check_dist(
- bb->vec[0], bb->vec[6], lpmat,
- snapdata->win_size, snapdata->mval, dist_px_sq))
- {
- return 0;
- }
- }
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
-
- for (Nurb *nu = (use_obedit ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
- for (int u = 0; u < nu->pntsu; u++) {
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- if (use_obedit) {
- if (nu->bezt) {
- /* don't snap to selected (moving) or hidden */
- if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) {
- continue;
- }
- has_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, nu->bezt[u].vec[1], &dist_px_sq,
- r_loc);
- /* don't snap if handle is selected (moving), or if it is aligning to a moving handle */
- if (!(nu->bezt[u].f1 & SELECT) &&
- !(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT))
- {
- has_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, nu->bezt[u].vec[0], &dist_px_sq,
- r_loc);
- }
- if (!(nu->bezt[u].f3 & SELECT) &&
- !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT))
- {
- has_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, nu->bezt[u].vec[2], &dist_px_sq,
- r_loc);
- }
- }
- else {
- /* don't snap to selected (moving) or hidden */
- if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) {
- continue;
- }
- has_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, nu->bp[u].vec, &dist_px_sq,
- r_loc);
- }
- }
- else {
- /* curve is not visible outside editmode if nurb length less than two */
- if (nu->pntsu > 1) {
- if (nu->bezt) {
- has_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, nu->bezt[u].vec[1], &dist_px_sq,
- r_loc);
- }
- else {
- has_snap |= test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, nu->bp[u].vec, &dist_px_sq,
- r_loc);
- }
- }
- }
- }
- }
- }
- if (has_snap) {
- *dist_px = sqrtf(dist_px_sq);
- mul_m4_v3(obmat, r_loc);
- if (r_index) {
- /* Does not support index yet. */
- *r_index = -1;
- }
- return SCE_SNAP_MODE_VERTEX;
- }
-
- return 0;
+ bool has_snap = false;
+
+ /* only vertex snapping mode (eg control points and handles) supported for now) */
+ if (snapdata->snap_to_flag != SCE_SNAP_MODE_VERTEX) {
+ return 0;
+ }
+
+ Curve *cu = ob->data;
+ float dist_px_sq = SQUARE(*dist_px);
+
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
+
+ use_obedit = use_obedit && BKE_object_is_in_editmode(ob);
+
+ if (use_obedit == false) {
+ /* Test BoundBox */
+ BoundBox *bb = BKE_curve_texspace_get(cu, NULL, NULL, NULL);
+ if (bb && !snap_bound_box_check_dist(
+ bb->vec[0], bb->vec[6], lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
+ return 0;
+ }
+ }
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+
+ for (Nurb *nu = (use_obedit ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
+ for (int u = 0; u < nu->pntsu; u++) {
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ if (use_obedit) {
+ if (nu->bezt) {
+ /* don't snap to selected (moving) or hidden */
+ if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) {
+ continue;
+ }
+ has_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ nu->bezt[u].vec[1],
+ &dist_px_sq,
+ r_loc);
+ /* don't snap if handle is selected (moving), or if it is aligning to a moving handle */
+ if (!(nu->bezt[u].f1 & SELECT) &&
+ !(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT)) {
+ has_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ nu->bezt[u].vec[0],
+ &dist_px_sq,
+ r_loc);
+ }
+ if (!(nu->bezt[u].f3 & SELECT) &&
+ !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT)) {
+ has_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ nu->bezt[u].vec[2],
+ &dist_px_sq,
+ r_loc);
+ }
+ }
+ else {
+ /* don't snap to selected (moving) or hidden */
+ if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) {
+ continue;
+ }
+ has_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ nu->bp[u].vec,
+ &dist_px_sq,
+ r_loc);
+ }
+ }
+ else {
+ /* curve is not visible outside editmode if nurb length less than two */
+ if (nu->pntsu > 1) {
+ if (nu->bezt) {
+ has_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ nu->bezt[u].vec[1],
+ &dist_px_sq,
+ r_loc);
+ }
+ else {
+ has_snap |= test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ nu->bp[u].vec,
+ &dist_px_sq,
+ r_loc);
+ }
+ }
+ }
+ }
+ }
+ }
+ if (has_snap) {
+ *dist_px = sqrtf(dist_px_sq);
+ mul_m4_v3(obmat, r_loc);
+ if (r_index) {
+ /* Does not support index yet. */
+ *r_index = -1;
+ }
+ return SCE_SNAP_MODE_VERTEX;
+ }
+
+ return 0;
}
/* may extend later (for now just snaps to empty center) */
-static short snapEmpty(
- SnapData *snapdata,
- Object *ob, float obmat[4][4],
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float *UNUSED(r_no), int *r_index)
+static short snapEmpty(SnapData *snapdata,
+ Object *ob,
+ float obmat[4][4],
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float *UNUSED(r_no),
+ int *r_index)
{
- short retval = 0;
-
- if (ob->transflag & OB_DUPLI) {
- return retval;
- }
-
- /* for now only vertex supported */
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
- float dist_px_sq = SQUARE(*dist_px);
- float co[3];
- copy_v3_v3(co, obmat[3]);
- if (test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, co, &dist_px_sq, r_loc))
- {
- *dist_px = sqrtf(dist_px_sq);
- retval = SCE_SNAP_MODE_VERTEX;
- }
- }
-
- if (retval) {
- if (r_index) {
- /* Does not support index. */
- *r_index = -1;
- }
- return retval;
- }
-
- return 0;
+ short retval = 0;
+
+ if (ob->transflag & OB_DUPLI) {
+ return retval;
+ }
+
+ /* for now only vertex supported */
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+ float dist_px_sq = SQUARE(*dist_px);
+ float co[3];
+ copy_v3_v3(co, obmat[3]);
+ if (test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ co,
+ &dist_px_sq,
+ r_loc)) {
+ *dist_px = sqrtf(dist_px_sq);
+ retval = SCE_SNAP_MODE_VERTEX;
+ }
+ }
+
+ if (retval) {
+ if (r_index) {
+ /* Does not support index. */
+ *r_index = -1;
+ }
+ return retval;
+ }
+
+ return 0;
}
-static short snapCamera(
- const SnapObjectContext *sctx, SnapData *snapdata,
- Object *object, float obmat[4][4],
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float *UNUSED(r_no), int *r_index)
+static short snapCamera(const SnapObjectContext *sctx,
+ SnapData *snapdata,
+ Object *object,
+ float obmat[4][4],
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float *UNUSED(r_no),
+ int *r_index)
{
- short retval = 0;
-
- Scene *scene = sctx->scene;
-
- bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
- float dist_px_sq = SQUARE(*dist_px);
-
- float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4];
- MovieClip *clip = BKE_object_movieclip_get(scene, object, false);
- MovieTracking *tracking;
-
- if (clip == NULL) {
- return retval;
- }
- if (object->transflag & OB_DUPLI) {
- return retval;
- }
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- tracking = &clip->tracking;
-
- BKE_tracking_get_camera_object_matrix(scene, object, orig_camera_mat);
-
- invert_m4_m4(orig_camera_imat, orig_camera_mat);
- invert_m4_m4(imat, obmat);
-
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- struct DistProjectedAABBPrecalc neasrest_precalc;
- dist_squared_to_projected_aabb_precalc(
- &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
-
- MovieTrackingObject *tracking_object;
- for (tracking_object = tracking->objects.first;
- tracking_object;
- tracking_object = tracking_object->next)
- {
- ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
- MovieTrackingTrack *track;
- float reconstructed_camera_mat[4][4],
- reconstructed_camera_imat[4][4];
- float (*vertex_obmat)[4];
-
- if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) {
- BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object,
- CFRA, reconstructed_camera_mat);
-
- invert_m4_m4(reconstructed_camera_imat, reconstructed_camera_mat);
- }
-
- for (track = tracksbase->first; track; track = track->next) {
- float bundle_pos[3];
-
- if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
- continue;
- }
-
- copy_v3_v3(bundle_pos, track->bundle_pos);
- if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
- vertex_obmat = orig_camera_mat;
- }
- else {
- mul_m4_v3(reconstructed_camera_imat, bundle_pos);
- vertex_obmat = obmat;
- }
-
- mul_m4_v3(vertex_obmat, bundle_pos);
- if (test_projected_vert_dist(
- &neasrest_precalc,
- clip_planes_local, snapdata->clip_plane_len,
- is_persp, bundle_pos, &dist_px_sq, r_loc))
- {
- retval = SCE_SNAP_MODE_VERTEX;
- }
- }
- }
- }
-
- if (retval) {
- *dist_px = sqrtf(dist_px_sq);
- if (r_index) {
- /* Does not support index. */
- *r_index = -1;
- }
- return retval;
- }
-
- return 0;
+ short retval = 0;
+
+ Scene *scene = sctx->scene;
+
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+ float dist_px_sq = SQUARE(*dist_px);
+
+ float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4];
+ MovieClip *clip = BKE_object_movieclip_get(scene, object, false);
+ MovieTracking *tracking;
+
+ if (clip == NULL) {
+ return retval;
+ }
+ if (object->transflag & OB_DUPLI) {
+ return retval;
+ }
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ tracking = &clip->tracking;
+
+ BKE_tracking_get_camera_object_matrix(scene, object, orig_camera_mat);
+
+ invert_m4_m4(orig_camera_imat, orig_camera_mat);
+ invert_m4_m4(imat, obmat);
+
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
+
+ MovieTrackingObject *tracking_object;
+ for (tracking_object = tracking->objects.first; tracking_object;
+ tracking_object = tracking_object->next) {
+ ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object);
+ MovieTrackingTrack *track;
+ float reconstructed_camera_mat[4][4], reconstructed_camera_imat[4][4];
+ float(*vertex_obmat)[4];
+
+ if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) {
+ BKE_tracking_camera_get_reconstructed_interpolate(
+ tracking, tracking_object, CFRA, reconstructed_camera_mat);
+
+ invert_m4_m4(reconstructed_camera_imat, reconstructed_camera_mat);
+ }
+
+ for (track = tracksbase->first; track; track = track->next) {
+ float bundle_pos[3];
+
+ if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
+ continue;
+ }
+
+ copy_v3_v3(bundle_pos, track->bundle_pos);
+ if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
+ vertex_obmat = orig_camera_mat;
+ }
+ else {
+ mul_m4_v3(reconstructed_camera_imat, bundle_pos);
+ vertex_obmat = obmat;
+ }
+
+ mul_m4_v3(vertex_obmat, bundle_pos);
+ if (test_projected_vert_dist(&neasrest_precalc,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ is_persp,
+ bundle_pos,
+ &dist_px_sq,
+ r_loc)) {
+ retval = SCE_SNAP_MODE_VERTEX;
+ }
+ }
+ }
+ }
+
+ if (retval) {
+ *dist_px = sqrtf(dist_px_sq);
+ if (r_index) {
+ /* Does not support index. */
+ *r_index = -1;
+ }
+ return retval;
+ }
+
+ return 0;
}
-static short snapMesh(
- SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, Mesh *me, float obmat[4][4],
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index)
+static short snapMesh(SnapObjectContext *sctx,
+ SnapData *snapdata,
+ Object *ob,
+ Mesh *me,
+ float obmat[4][4],
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index)
{
- BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
-
- if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) {
- if (me->totedge == 0) {
- return 0;
- }
- }
- else {
- if (me->totvert == 0) {
- return 0;
- }
- }
-
- float lpmat[4][4];
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
-
- float dist_px_sq = SQUARE(*dist_px);
-
- /* Test BoundBox */
- BoundBox *bb = BKE_mesh_boundbox_get(ob);
- if (bb && !snap_bound_box_check_dist(
- bb->vec[0], bb->vec[6], lpmat, snapdata->win_size,
- snapdata->mval, dist_px_sq))
- {
- return 0;
- }
-
- SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob);
-
- BVHTreeFromMesh *treedata, dummy_treedata;
- BVHTree **bvhtree;
- treedata = &sod->treedata;
- bvhtree = sod->bvhtree;
-
- /* The tree is owned by the Mesh and may have been freed since we last used! */
- if ((sod->has_looptris && treedata->tree && !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) ||
- (sod->has_loose_edge && bvhtree[0] && !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0])) ||
- (sod->has_loose_vert && bvhtree[1] && !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1])))
- {
- BLI_assert(!treedata->tree || !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree));
- BLI_assert(!bvhtree[0] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0]));
- BLI_assert(!bvhtree[1] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1]));
-
- free_bvhtree_from_mesh(treedata);
- bvhtree[0] = NULL;
- bvhtree[1] = NULL;
- }
-
- if (sod->has_looptris && treedata->tree == NULL) {
- BKE_bvhtree_from_mesh_get(treedata, me, BVHTREE_FROM_LOOPTRI, 4);
- sod->has_looptris = (treedata->tree != NULL);
- if (sod->has_looptris) {
- /* Make sure that the array of edges is referenced in the callbacks. */
- treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */
- }
- }
- if (sod->has_loose_edge && bvhtree[0] == NULL) {
- bvhtree[0] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEEDGES, 2);
- sod->has_loose_edge = bvhtree[0] != NULL;
-
- if (sod->has_loose_edge) {
- BLI_assert(treedata->vert_allocated == false);
- treedata->vert = dummy_treedata.vert;
- treedata->vert_allocated = dummy_treedata.vert_allocated;
-
- BLI_assert(treedata->edge_allocated == false);
- treedata->edge = dummy_treedata.edge;
- treedata->edge_allocated = dummy_treedata.edge_allocated;
- }
- }
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- if (sod->has_loose_vert && bvhtree[1] == NULL) {
- bvhtree[1] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEVERTS, 2);
- sod->has_loose_vert = bvhtree[1] != NULL;
-
- if (sod->has_loose_vert) {
- BLI_assert(treedata->vert_allocated == false);
- treedata->vert = dummy_treedata.vert;
- treedata->vert_allocated = dummy_treedata.vert_allocated;
- }
- }
- }
- else {
- /* Not necessary, just to keep the data more consistent. */
- sod->has_loose_vert = false;
- }
-
- /* Update pointers. */
- if (treedata->vert_allocated == false) {
- treedata->vert = me->mvert; /* CustomData_get_layer(&me->vdata, CD_MVERT);? */
- }
- if (treedata->tree || bvhtree[0]) {
- if (treedata->edge_allocated == false) {
- /* If raycast has been executed before, `treedata->edge` can be NULL. */
- treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */
- }
- if (treedata->loop && treedata->loop_allocated == false) {
- treedata->loop = me->mloop; /* CustomData_get_layer(&me->edata, CD_MLOOP);? */
- }
- if (treedata->looptri && treedata->looptri_allocated == false) {
- treedata->looptri = BKE_mesh_runtime_looptri_ensure(me);
- }
- }
-
- Nearest2dUserData nearest2d = {
- .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
- .userdata = treedata,
- .get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get,
- .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get,
- .get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get,
- .get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get,
- .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy,
- };
-
- BVHTreeNearest nearest = {
- .index = -1,
- .dist_sq = dist_px_sq,
- };
- int last_index = nearest.index;
- short elem = SCE_SNAP_MODE_VERTEX;
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- if (bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
- /* snap to loose verts */
- BLI_bvhtree_find_nearest_projected(
- bvhtree[1], lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_vert, &nearest2d);
-
- last_index = nearest.index;
- }
-
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- if (bvhtree[0]) {
- /* snap to loose edges */
- BLI_bvhtree_find_nearest_projected(
- bvhtree[0], lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_edge, &nearest2d);
- }
-
- if (treedata->tree) {
- /* snap to looptris */
- BLI_bvhtree_find_nearest_projected(
- treedata->tree, lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_tri_edges, &nearest2d);
- }
-
- if (last_index != nearest.index) {
- elem = SCE_SNAP_MODE_EDGE;
- }
- }
- else {
- BLI_assert(snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX);
- if (bvhtree[0]) {
- /* snap to loose edges */
- BLI_bvhtree_find_nearest_projected(
- bvhtree[0], lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_edge_verts, &nearest2d);
- }
-
- if (treedata->tree) {
- /* snap to looptris */
- BLI_bvhtree_find_nearest_projected(
- treedata->tree, lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_tri_verts, &nearest2d);
- }
- }
-
- if (nearest.index != -1) {
- *dist_px = sqrtf(nearest.dist_sq);
-
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
-
- if (r_no) {
- float imat[4][4];
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(r_no, nearest.no);
- mul_transposed_mat3_m4_v3(imat, r_no);
- normalize_v3(r_no);
- }
- if (r_index) {
- *r_index = nearest.index;
- }
-
- return elem;
- }
-
- return 0;
+ BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
+
+ if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) {
+ if (me->totedge == 0) {
+ return 0;
+ }
+ }
+ else {
+ if (me->totvert == 0) {
+ return 0;
+ }
+ }
+
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+
+ float dist_px_sq = SQUARE(*dist_px);
+
+ /* Test BoundBox */
+ BoundBox *bb = BKE_mesh_boundbox_get(ob);
+ if (bb && !snap_bound_box_check_dist(
+ bb->vec[0], bb->vec[6], lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
+ return 0;
+ }
+
+ SnapObjectData_Mesh *sod = snap_object_data_mesh_get(sctx, ob);
+
+ BVHTreeFromMesh *treedata, dummy_treedata;
+ BVHTree **bvhtree;
+ treedata = &sod->treedata;
+ bvhtree = sod->bvhtree;
+
+ /* The tree is owned by the Mesh and may have been freed since we last used! */
+ if ((sod->has_looptris && treedata->tree &&
+ !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree)) ||
+ (sod->has_loose_edge && bvhtree[0] &&
+ !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0])) ||
+ (sod->has_loose_vert && bvhtree[1] &&
+ !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1]))) {
+ BLI_assert(!treedata->tree || !bvhcache_has_tree(me->runtime.bvh_cache, treedata->tree));
+ BLI_assert(!bvhtree[0] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[0]));
+ BLI_assert(!bvhtree[1] || !bvhcache_has_tree(me->runtime.bvh_cache, bvhtree[1]));
+
+ free_bvhtree_from_mesh(treedata);
+ bvhtree[0] = NULL;
+ bvhtree[1] = NULL;
+ }
+
+ if (sod->has_looptris && treedata->tree == NULL) {
+ BKE_bvhtree_from_mesh_get(treedata, me, BVHTREE_FROM_LOOPTRI, 4);
+ sod->has_looptris = (treedata->tree != NULL);
+ if (sod->has_looptris) {
+ /* Make sure that the array of edges is referenced in the callbacks. */
+ treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */
+ }
+ }
+ if (sod->has_loose_edge && bvhtree[0] == NULL) {
+ bvhtree[0] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEEDGES, 2);
+ sod->has_loose_edge = bvhtree[0] != NULL;
+
+ if (sod->has_loose_edge) {
+ BLI_assert(treedata->vert_allocated == false);
+ treedata->vert = dummy_treedata.vert;
+ treedata->vert_allocated = dummy_treedata.vert_allocated;
+
+ BLI_assert(treedata->edge_allocated == false);
+ treedata->edge = dummy_treedata.edge;
+ treedata->edge_allocated = dummy_treedata.edge_allocated;
+ }
+ }
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ if (sod->has_loose_vert && bvhtree[1] == NULL) {
+ bvhtree[1] = BKE_bvhtree_from_mesh_get(&dummy_treedata, me, BVHTREE_FROM_LOOSEVERTS, 2);
+ sod->has_loose_vert = bvhtree[1] != NULL;
+
+ if (sod->has_loose_vert) {
+ BLI_assert(treedata->vert_allocated == false);
+ treedata->vert = dummy_treedata.vert;
+ treedata->vert_allocated = dummy_treedata.vert_allocated;
+ }
+ }
+ }
+ else {
+ /* Not necessary, just to keep the data more consistent. */
+ sod->has_loose_vert = false;
+ }
+
+ /* Update pointers. */
+ if (treedata->vert_allocated == false) {
+ treedata->vert = me->mvert; /* CustomData_get_layer(&me->vdata, CD_MVERT);? */
+ }
+ if (treedata->tree || bvhtree[0]) {
+ if (treedata->edge_allocated == false) {
+ /* If raycast has been executed before, `treedata->edge` can be NULL. */
+ treedata->edge = me->medge; /* CustomData_get_layer(&me->edata, CD_MEDGE);? */
+ }
+ if (treedata->loop && treedata->loop_allocated == false) {
+ treedata->loop = me->mloop; /* CustomData_get_layer(&me->edata, CD_MLOOP);? */
+ }
+ if (treedata->looptri && treedata->looptri_allocated == false) {
+ treedata->looptri = BKE_mesh_runtime_looptri_ensure(me);
+ }
+ }
+
+ Nearest2dUserData nearest2d = {
+ .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
+ .userdata = treedata,
+ .get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get,
+ .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_medge_verts_get,
+ .get_tri_verts_index = (Nearest2DGetTriVertsCallback)cb_mlooptri_verts_get,
+ .get_tri_edges_index = (Nearest2DGetTriEdgesCallback)cb_mlooptri_edges_get,
+ .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_mvert_no_copy,
+ };
+
+ BVHTreeNearest nearest = {
+ .index = -1,
+ .dist_sq = dist_px_sq,
+ };
+ int last_index = nearest.index;
+ short elem = SCE_SNAP_MODE_VERTEX;
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ if (bvhtree[1] && (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
+ /* snap to loose verts */
+ BLI_bvhtree_find_nearest_projected(bvhtree[1],
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_vert,
+ &nearest2d);
+
+ last_index = nearest.index;
+ }
+
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ if (bvhtree[0]) {
+ /* snap to loose edges */
+ BLI_bvhtree_find_nearest_projected(bvhtree[0],
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_edge,
+ &nearest2d);
+ }
+
+ if (treedata->tree) {
+ /* snap to looptris */
+ BLI_bvhtree_find_nearest_projected(treedata->tree,
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_tri_edges,
+ &nearest2d);
+ }
+
+ if (last_index != nearest.index) {
+ elem = SCE_SNAP_MODE_EDGE;
+ }
+ }
+ else {
+ BLI_assert(snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX);
+ if (bvhtree[0]) {
+ /* snap to loose edges */
+ BLI_bvhtree_find_nearest_projected(bvhtree[0],
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_edge_verts,
+ &nearest2d);
+ }
+
+ if (treedata->tree) {
+ /* snap to looptris */
+ BLI_bvhtree_find_nearest_projected(treedata->tree,
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_tri_verts,
+ &nearest2d);
+ }
+ }
+
+ if (nearest.index != -1) {
+ *dist_px = sqrtf(nearest.dist_sq);
+
+ copy_v3_v3(r_loc, nearest.co);
+ mul_m4_v3(obmat, r_loc);
+
+ if (r_no) {
+ float imat[4][4];
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(r_no, nearest.no);
+ mul_transposed_mat3_m4_v3(imat, r_no);
+ normalize_v3(r_no);
+ }
+ if (r_index) {
+ *r_index = nearest.index;
+ }
+
+ return elem;
+ }
+
+ return 0;
}
-static short snapEditMesh(
- SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, BMEditMesh *em, float obmat[4][4],
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index)
+static short snapEditMesh(SnapObjectContext *sctx,
+ SnapData *snapdata,
+ Object *ob,
+ BMEditMesh *em,
+ float obmat[4][4],
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index)
{
- BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
-
- if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) {
- if (em->bm->totedge == 0) {
- return 0;
- }
- }
- else {
- if (em->bm->totvert == 0) {
- return 0;
- }
- }
-
- BVHTreeFromEditMesh *treedata_vert = NULL, *treedata_edge = NULL;
-
- BLI_assert(BKE_object_get_pre_modified_mesh(ob) == BKE_object_get_pre_modified_mesh(ob));
- UNUSED_VARS_NDEBUG(ob);
-
- float lpmat[4][4];
- mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
-
- float dist_px_sq = SQUARE(*dist_px);
-
- SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, em);
-
- /* Test BoundBox */
-
- /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
- if (!snap_bound_box_check_dist(
- sod->min, sod->max, lpmat, snapdata->win_size, snapdata->mval, dist_px_sq))
- {
- return 0;
- }
-
- BVHCache *em_bvh_cache = ((Mesh *)em->ob->data)->runtime.bvh_cache;
-
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- if (sod->bvh_trees[0] == NULL) {
- sod->bvh_trees[0] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
- }
- treedata_vert = sod->bvh_trees[0];
-
- if (sctx->callbacks.edit_mesh.test_vert_fn == NULL) {
- /* The tree is owned by the Mesh and may have been freed since we last used! */
- if (!bvhcache_has_tree(em_bvh_cache, treedata_vert->tree)) {
- free_bvhtree_from_editmesh(treedata_vert);
- }
- }
-
- if (treedata_vert->tree == NULL) {
- 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_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6);
- MEM_freeN(verts_mask);
- }
- else {
- bvhtree_from_editmesh_verts(treedata_vert, em, 0.0f, 2, 6, &em_bvh_cache);
- }
- }
- }
-
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- if (sod->bvh_trees[1] == NULL) {
- sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
- }
- treedata_edge = sod->bvh_trees[1];
-
- if (sctx->callbacks.edit_mesh.test_edge_fn == NULL) {
- /* The tree is owned by the Mesh and may have been freed since we last used! */
- if (!bvhcache_has_tree(em_bvh_cache, treedata_edge->tree)) {
- free_bvhtree_from_editmesh(treedata_edge);
- }
- }
-
- if (treedata_edge->tree == NULL) {
- BLI_bitmap *edges_mask = NULL;
- int edges_num_active = -1;
- if (sctx->callbacks.edit_mesh.test_edge_fn) {
- edges_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
- edges_num_active = BM_iter_mesh_bitmap_from_filter(
- BM_EDGES_OF_MESH, em->bm, edges_mask,
- (bool(*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
- sctx->callbacks.edit_mesh.user_data);
-
- bvhtree_from_editmesh_edges_ex(treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6);
- MEM_freeN(edges_mask);
- }
- else {
- bvhtree_from_editmesh_edges(treedata_edge, em, 0.0f, 2, 6, &em_bvh_cache);
- }
- }
- }
-
- Nearest2dUserData nearest2d = {
- .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
- .userdata = em,
- .get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get,
- .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get,
- .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy,
- };
-
- BVHTreeNearest nearest = {
- .index = -1,
- .dist_sq = dist_px_sq,
- };
- int last_index = nearest.index;
- short elem = SCE_SNAP_MODE_VERTEX;
-
- float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
- transpose_m4_m4(tobmat, obmat);
-
- for (int i = snapdata->clip_plane_len; i--;) {
- mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
- }
-
- if (treedata_vert && snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
- BM_mesh_elem_table_ensure(em->bm, BM_VERT);
- BLI_bvhtree_find_nearest_projected(
- treedata_vert->tree, lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_vert, &nearest2d);
-
- last_index = nearest.index;
- }
-
- if (treedata_edge && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
- BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT);
- BLI_bvhtree_find_nearest_projected(
- treedata_edge->tree, lpmat, snapdata->win_size, snapdata->mval,
- clip_planes_local, snapdata->clip_plane_len,
- &nearest, cb_snap_edge, &nearest2d);
-
- if (last_index != nearest.index) {
- elem = SCE_SNAP_MODE_EDGE;
- }
- }
-
- if (nearest.index != -1) {
- *dist_px = sqrtf(nearest.dist_sq);
-
- copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
- if (r_no) {
- float imat[4][4];
- invert_m4_m4(imat, obmat);
-
- copy_v3_v3(r_no, nearest.no);
- mul_transposed_mat3_m4_v3(imat, r_no);
- normalize_v3(r_no);
- }
- if (r_index) {
- *r_index = nearest.index;
- }
-
- return elem;
- }
-
- return 0;
+ BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
+
+ if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) {
+ if (em->bm->totedge == 0) {
+ return 0;
+ }
+ }
+ else {
+ if (em->bm->totvert == 0) {
+ return 0;
+ }
+ }
+
+ BVHTreeFromEditMesh *treedata_vert = NULL, *treedata_edge = NULL;
+
+ BLI_assert(BKE_object_get_pre_modified_mesh(ob) == BKE_object_get_pre_modified_mesh(ob));
+ UNUSED_VARS_NDEBUG(ob);
+
+ float lpmat[4][4];
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+
+ float dist_px_sq = SQUARE(*dist_px);
+
+ SnapObjectData_EditMesh *sod = snap_object_data_editmesh_get(sctx, em);
+
+ /* Test BoundBox */
+
+ /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
+ if (!snap_bound_box_check_dist(
+ sod->min, sod->max, lpmat, snapdata->win_size, snapdata->mval, dist_px_sq)) {
+ return 0;
+ }
+
+ BVHCache *em_bvh_cache = ((Mesh *)em->ob->data)->runtime.bvh_cache;
+
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ if (sod->bvh_trees[0] == NULL) {
+ sod->bvh_trees[0] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
+ }
+ treedata_vert = sod->bvh_trees[0];
+
+ if (sctx->callbacks.edit_mesh.test_vert_fn == NULL) {
+ /* The tree is owned by the Mesh and may have been freed since we last used! */
+ if (!bvhcache_has_tree(em_bvh_cache, treedata_vert->tree)) {
+ free_bvhtree_from_editmesh(treedata_vert);
+ }
+ }
+
+ if (treedata_vert->tree == NULL) {
+ 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_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6);
+ MEM_freeN(verts_mask);
+ }
+ else {
+ bvhtree_from_editmesh_verts(treedata_vert, em, 0.0f, 2, 6, &em_bvh_cache);
+ }
+ }
+ }
+
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ if (sod->bvh_trees[1] == NULL) {
+ sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
+ }
+ treedata_edge = sod->bvh_trees[1];
+
+ if (sctx->callbacks.edit_mesh.test_edge_fn == NULL) {
+ /* The tree is owned by the Mesh and may have been freed since we last used! */
+ if (!bvhcache_has_tree(em_bvh_cache, treedata_edge->tree)) {
+ free_bvhtree_from_editmesh(treedata_edge);
+ }
+ }
+
+ if (treedata_edge->tree == NULL) {
+ BLI_bitmap *edges_mask = NULL;
+ int edges_num_active = -1;
+ if (sctx->callbacks.edit_mesh.test_edge_fn) {
+ edges_mask = BLI_BITMAP_NEW(em->bm->totedge, __func__);
+ edges_num_active = BM_iter_mesh_bitmap_from_filter(
+ BM_EDGES_OF_MESH,
+ em->bm,
+ edges_mask,
+ (bool (*)(BMElem *, void *))sctx->callbacks.edit_mesh.test_edge_fn,
+ sctx->callbacks.edit_mesh.user_data);
+
+ bvhtree_from_editmesh_edges_ex(
+ treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6);
+ MEM_freeN(edges_mask);
+ }
+ else {
+ bvhtree_from_editmesh_edges(treedata_edge, em, 0.0f, 2, 6, &em_bvh_cache);
+ }
+ }
+ }
+
+ Nearest2dUserData nearest2d = {
+ .is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
+ .userdata = em,
+ .get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get,
+ .get_edge_verts_index = (Nearest2DGetEdgeVertsCallback)cb_bedge_verts_get,
+ .copy_vert_no = (Nearest2DCopyVertNoCallback)cb_bvert_no_copy,
+ };
+
+ BVHTreeNearest nearest = {
+ .index = -1,
+ .dist_sq = dist_px_sq,
+ };
+ int last_index = nearest.index;
+ short elem = SCE_SNAP_MODE_VERTEX;
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ if (treedata_vert && snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ BLI_bvhtree_find_nearest_projected(treedata_vert->tree,
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_vert,
+ &nearest2d);
+
+ last_index = nearest.index;
+ }
+
+ if (treedata_edge && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT);
+ BLI_bvhtree_find_nearest_projected(treedata_edge->tree,
+ lpmat,
+ snapdata->win_size,
+ snapdata->mval,
+ clip_planes_local,
+ snapdata->clip_plane_len,
+ &nearest,
+ cb_snap_edge,
+ &nearest2d);
+
+ if (last_index != nearest.index) {
+ elem = SCE_SNAP_MODE_EDGE;
+ }
+ }
+
+ if (nearest.index != -1) {
+ *dist_px = sqrtf(nearest.dist_sq);
+
+ copy_v3_v3(r_loc, nearest.co);
+ mul_m4_v3(obmat, r_loc);
+ if (r_no) {
+ float imat[4][4];
+ invert_m4_m4(imat, obmat);
+
+ copy_v3_v3(r_no, nearest.no);
+ mul_transposed_mat3_m4_v3(imat, r_no);
+ normalize_v3(r_no);
+ }
+ if (r_index) {
+ *r_index = nearest.index;
+ }
+
+ return elem;
+ }
+
+ return 0;
}
/**
@@ -2163,127 +2298,112 @@ static short snapEditMesh(
*
* \note Duplicate args here are documented at #snapObjectsRay
*/
-static short snapObject(
- SnapObjectContext *sctx, SnapData *snapdata,
- Object *ob, float obmat[4][4], bool use_obedit,
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4])
+static short snapObject(SnapObjectContext *sctx,
+ SnapData *snapdata,
+ Object *ob,
+ float obmat[4][4],
+ bool use_obedit,
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4])
{
- short retval = 0;
-
- switch (ob->type) {
- case OB_MESH:
- {
- Mesh *me = ob->data;
- if (BKE_object_is_in_editmode(ob)) {
- BMEditMesh *em = BKE_editmesh_from_object(ob);
- if (use_obedit) {
- retval = snapEditMesh(
- sctx, snapdata, ob, em, obmat,
- dist_px,
- r_loc, r_no, r_index);
- break;
- }
- else if (em->mesh_eval_final) {
- me = em->mesh_eval_final;
- }
- }
- else if (ob->dt == OB_BOUNDBOX) {
- /* Do not snap to objects that are in bounding box display mode */
- return 0;
- }
-
- retval = snapMesh(
- sctx, snapdata, ob, me, obmat,
- dist_px,
- r_loc, r_no, r_index);
- break;
- }
- case OB_ARMATURE:
- retval = snapArmature(
- snapdata,
- ob, obmat, use_obedit,
- dist_px,
- r_loc, r_no, r_index);
- break;
-
- case OB_CURVE:
- retval = snapCurve(
- snapdata,
- ob, obmat, use_obedit,
- dist_px,
- r_loc, r_no, r_index);
- break;
-
- case OB_EMPTY:
- retval = snapEmpty(
- snapdata, ob, obmat,
- dist_px,
- r_loc, r_no, r_index);
- break;
- case OB_GPENCIL:
- retval = snapEmpty(
- snapdata, ob, obmat,
- dist_px,
- r_loc, r_no, r_index);
- break;
- case OB_CAMERA:
- retval = snapCamera(
- sctx, snapdata, ob, obmat,
- dist_px,
- r_loc, r_no, r_index);
- break;
- }
-
- if (retval) {
- if (r_ob) {
- *r_ob = ob;
- }
- if (r_obmat) {
- copy_m4_m4(r_obmat, obmat);
- }
- return retval;
- }
-
- return 0;
+ short retval = 0;
+
+ switch (ob->type) {
+ case OB_MESH: {
+ Mesh *me = ob->data;
+ if (BKE_object_is_in_editmode(ob)) {
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ if (use_obedit) {
+ retval = snapEditMesh(sctx, snapdata, ob, em, obmat, dist_px, r_loc, r_no, r_index);
+ break;
+ }
+ else if (em->mesh_eval_final) {
+ me = em->mesh_eval_final;
+ }
+ }
+ else if (ob->dt == OB_BOUNDBOX) {
+ /* Do not snap to objects that are in bounding box display mode */
+ return 0;
+ }
+
+ retval = snapMesh(sctx, snapdata, ob, me, obmat, dist_px, r_loc, r_no, r_index);
+ break;
+ }
+ case OB_ARMATURE:
+ retval = snapArmature(snapdata, ob, obmat, use_obedit, dist_px, r_loc, r_no, r_index);
+ break;
+
+ case OB_CURVE:
+ retval = snapCurve(snapdata, ob, obmat, use_obedit, dist_px, r_loc, r_no, r_index);
+ break;
+
+ case OB_EMPTY:
+ retval = snapEmpty(snapdata, ob, obmat, dist_px, r_loc, r_no, r_index);
+ break;
+ case OB_GPENCIL:
+ retval = snapEmpty(snapdata, ob, obmat, dist_px, r_loc, r_no, r_index);
+ break;
+ case OB_CAMERA:
+ retval = snapCamera(sctx, snapdata, ob, obmat, dist_px, r_loc, r_no, r_index);
+ break;
+ }
+
+ if (retval) {
+ if (r_ob) {
+ *r_ob = ob;
+ }
+ if (r_obmat) {
+ copy_m4_m4(r_obmat, obmat);
+ }
+ return retval;
+ }
+
+ return 0;
}
-
struct SnapObjUserData {
- SnapData *snapdata;
- /* read/write args */
- float *dist_px;
- /* return args */
- float *r_loc;
- float *r_no;
- int *r_index;
- Object **r_ob;
- float (*r_obmat)[4];
- short ret;
+ SnapData *snapdata;
+ /* read/write args */
+ float *dist_px;
+ /* return args */
+ float *r_loc;
+ float *r_no;
+ int *r_index;
+ Object **r_ob;
+ float (*r_obmat)[4];
+ short ret;
};
-static void sanp_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data)
+static void sanp_obj_cb(
+ SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data)
{
- struct SnapObjUserData *dt = data;
-
- short elem = snapObject(
- sctx, dt->snapdata,
- ob, obmat, is_obedit,
- /* read/write args */
- dt->dist_px,
- /* return args */
- dt->r_loc, dt->r_no, dt->r_index,
- dt->r_ob, dt->r_obmat);
-
- if (elem) {
- dt->ret = elem;
- }
+ struct SnapObjUserData *dt = data;
+
+ short elem = snapObject(sctx,
+ dt->snapdata,
+ ob,
+ obmat,
+ is_obedit,
+ /* read/write args */
+ dt->dist_px,
+ /* return args */
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index,
+ dt->r_ob,
+ dt->r_obmat);
+
+ if (elem) {
+ dt->ret = elem;
+ }
}
-
/**
* Main Snapping Function
* ======================
@@ -2309,29 +2429,32 @@ static void sanp_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, flo
* \param r_ob: Hit object.
* \param r_obmat: Object matrix (may not be #Object.obmat with dupli-instances).
*/
-static short snapObjectsRay(
- SnapObjectContext *sctx, SnapData *snapdata,
- const struct SnapObjectParams *params,
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4])
+static short snapObjectsRay(SnapObjectContext *sctx,
+ SnapData *snapdata,
+ const struct SnapObjectParams *params,
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4])
{
- struct SnapObjUserData data = {
- .snapdata = snapdata,
- .dist_px = dist_px,
- .r_loc = r_loc,
- .r_no = r_no,
- .r_ob = r_ob,
- .r_index = r_index,
- .r_obmat = r_obmat,
- .ret = 0,
- };
-
- iter_snap_objects(sctx, params, sanp_obj_cb, &data);
-
- return data.ret;
+ struct SnapObjUserData data = {
+ .snapdata = snapdata,
+ .dist_px = dist_px,
+ .r_loc = r_loc,
+ .r_no = r_no,
+ .r_ob = r_ob,
+ .r_index = r_index,
+ .r_obmat = r_obmat,
+ .ret = 0,
+ };
+
+ iter_snap_objects(sctx, params, sanp_obj_cb, &data);
+
+ return data.ret;
}
/** \} */
@@ -2340,95 +2463,99 @@ static short snapObjectsRay(
/** \name Public Object Snapping API
* \{ */
-SnapObjectContext *ED_transform_snap_object_context_create(
- Main *bmain, Scene *scene, Depsgraph *depsgraph, int flag)
+SnapObjectContext *ED_transform_snap_object_context_create(Main *bmain,
+ Scene *scene,
+ Depsgraph *depsgraph,
+ int flag)
{
- SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__);
+ SnapObjectContext *sctx = MEM_callocN(sizeof(*sctx), __func__);
- sctx->flag = flag;
+ sctx->flag = flag;
- sctx->bmain = bmain;
- sctx->scene = scene;
- sctx->depsgraph = depsgraph;
+ sctx->bmain = bmain;
+ sctx->scene = scene;
+ sctx->depsgraph = depsgraph;
- sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
- sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ sctx->cache.object_map = BLI_ghash_ptr_new(__func__);
+ sctx->cache.mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- return sctx;
+ return sctx;
}
-SnapObjectContext *ED_transform_snap_object_context_create_view3d(
- Main *bmain, Scene *scene, Depsgraph *depsgraph, int flag,
- /* extra args for view3d */
- const ARegion *ar, const View3D *v3d)
+SnapObjectContext *ED_transform_snap_object_context_create_view3d(Main *bmain,
+ Scene *scene,
+ Depsgraph *depsgraph,
+ int flag,
+ /* extra args for view3d */
+ const ARegion *ar,
+ const View3D *v3d)
{
- SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, depsgraph, flag);
+ SnapObjectContext *sctx = ED_transform_snap_object_context_create(bmain, scene, depsgraph, flag);
- sctx->use_v3d = true;
- sctx->v3d_data.ar = ar;
- sctx->v3d_data.v3d = v3d;
+ sctx->use_v3d = true;
+ sctx->v3d_data.ar = ar;
+ sctx->v3d_data.v3d = v3d;
- return sctx;
+ return sctx;
}
static void snap_object_data_free(void *sod_v)
{
- switch (((SnapObjectData *)sod_v)->type) {
- case SNAP_MESH:
- {
- SnapObjectData_Mesh *sod = sod_v;
- if (sod->treedata.tree) {
- free_bvhtree_from_mesh(&sod->treedata);
- }
- 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;
- }
- }
+ switch (((SnapObjectData *)sod_v)->type) {
+ case SNAP_MESH: {
+ SnapObjectData_Mesh *sod = sod_v;
+ if (sod->treedata.tree) {
+ free_bvhtree_from_mesh(&sod->treedata);
+ }
+ 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;
+ }
+ }
}
void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx)
{
- BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free);
- BLI_memarena_free(sctx->cache.mem_arena);
+ BLI_ghash_free(sctx->cache.object_map, NULL, snap_object_data_free);
+ BLI_memarena_free(sctx->cache.mem_arena);
- MEM_freeN(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)
+ 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.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;
+ sctx->callbacks.edit_mesh.user_data = user_data;
}
-bool ED_transform_snap_object_project_ray_ex(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_start[3], const float ray_normal[3],
- float *ray_depth,
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4])
+bool ED_transform_snap_object_project_ray_ex(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_start[3],
+ const float ray_normal[3],
+ float *ray_depth,
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4])
{
- return raycastObjects(
- sctx, params,
- ray_start, ray_normal,
- ray_depth, r_loc, r_no, r_index, r_ob, r_obmat, NULL);
+ return raycastObjects(
+ sctx, params, ray_start, ray_normal, ray_depth, r_loc, r_no, r_index, r_ob, r_obmat, NULL);
}
/**
@@ -2438,37 +2565,35 @@ bool ED_transform_snap_object_project_ray_ex(
* \param sort: Optionally sort the hits by depth.
* \param r_hit_list: List of #SnapObjectHitDepth (caller must free).
*/
-bool ED_transform_snap_object_project_ray_all(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_start[3], const float ray_normal[3],
- float ray_depth, bool sort,
- ListBase *r_hit_list)
+bool ED_transform_snap_object_project_ray_all(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_start[3],
+ const float ray_normal[3],
+ float ray_depth,
+ bool sort,
+ ListBase *r_hit_list)
{
- if (ray_depth == -1.0f) {
- ray_depth = BVH_RAYCAST_DIST_MAX;
- }
+ if (ray_depth == -1.0f) {
+ ray_depth = BVH_RAYCAST_DIST_MAX;
+ }
#ifdef DEBUG
- float ray_depth_prev = ray_depth;
+ float ray_depth_prev = ray_depth;
#endif
- bool retval = raycastObjects(
- sctx, params,
- ray_start, ray_normal,
- &ray_depth, NULL, NULL, NULL, NULL, NULL,
- r_hit_list);
+ bool retval = raycastObjects(
+ sctx, params, ray_start, ray_normal, &ray_depth, NULL, NULL, NULL, NULL, NULL, r_hit_list);
- /* meant to be readonly for 'all' hits, ensure it is */
+ /* meant to be readonly for 'all' hits, ensure it is */
#ifdef DEBUG
- BLI_assert(ray_depth_prev == ray_depth);
+ BLI_assert(ray_depth_prev == ray_depth);
#endif
- if (sort) {
- BLI_listbase_sort(r_hit_list, hit_depth_cmp);
- }
+ if (sort) {
+ BLI_listbase_sort(r_hit_list, hit_depth_cmp);
+ }
- return retval;
+ return retval;
}
/**
@@ -2478,196 +2603,183 @@ bool ED_transform_snap_object_project_ray_all(
*
* \return Snap success
*/
-static bool transform_snap_context_project_ray_impl(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_start[3], const float ray_normal[3], float *ray_depth,
- float r_co[3], float r_no[3])
+static bool transform_snap_context_project_ray_impl(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_start[3],
+ const float ray_normal[3],
+ float *ray_depth,
+ float r_co[3],
+ float r_no[3])
{
- bool ret;
+ bool ret;
- /* try snap edge, then face if it fails */
- ret = ED_transform_snap_object_project_ray_ex(
- sctx,
- params,
- ray_start, ray_normal, ray_depth,
- r_co, r_no, NULL,
- NULL, NULL);
+ /* try snap edge, then face if it fails */
+ ret = ED_transform_snap_object_project_ray_ex(
+ sctx, params, ray_start, ray_normal, ray_depth, r_co, r_no, NULL, NULL, NULL);
- return ret;
+ return ret;
}
-bool ED_transform_snap_object_project_ray(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float ray_origin[3], const float ray_direction[3], float *ray_depth,
- float r_co[3], float r_no[3])
+bool ED_transform_snap_object_project_ray(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float ray_origin[3],
+ const float ray_direction[3],
+ float *ray_depth,
+ float r_co[3],
+ float r_no[3])
{
- float ray_depth_fallback;
- if (ray_depth == NULL) {
- ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
- ray_depth = &ray_depth_fallback;
- }
-
- return transform_snap_context_project_ray_impl(
- sctx,
- params,
- ray_origin, ray_direction, ray_depth,
- r_co, r_no);
+ float ray_depth_fallback;
+ if (ray_depth == NULL) {
+ ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
+ ray_depth = &ray_depth_fallback;
+ }
+
+ return transform_snap_context_project_ray_impl(
+ sctx, params, ray_origin, ray_direction, ray_depth, r_co, r_no);
}
static short transform_snap_context_project_view3d_mixed_impl(
- SnapObjectContext *sctx,
- const unsigned short snap_to_flag,
- const struct SnapObjectParams *params,
- const float mval[2], float *dist_px,
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4])
+ SnapObjectContext *sctx,
+ const unsigned short snap_to_flag,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float *dist_px,
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4])
{
- BLI_assert(
- (snap_to_flag & (
- SCE_SNAP_MODE_VERTEX |
- SCE_SNAP_MODE_EDGE |
- SCE_SNAP_MODE_FACE)) != 0);
-
- short retval = 0;
- bool has_hit = false;
- int index = -1;
-
- float loc[3], no[3], obmat[4][4];
- Object *ob = NULL;
-
- const ARegion *ar = sctx->v3d_data.ar;
- const RegionView3D *rv3d = ar->regiondata;
-
- bool use_occlusion_test =
- params->use_occlusion_test && !XRAY_ENABLED(sctx->v3d_data.v3d);
-
- if (snap_to_flag & SCE_SNAP_MODE_FACE || use_occlusion_test) {
- float ray_start[3], ray_normal[3];
-
- if (!ED_view3d_win_to_ray_clipped_ex(
- sctx->depsgraph,
- sctx->v3d_data.ar, sctx->v3d_data.v3d,
- mval, NULL, ray_normal, ray_start, true))
- {
- return false;
- }
-
- float dummy_ray_depth = BVH_RAYCAST_DIST_MAX;
-
- has_hit = raycastObjects(
- sctx, params,
- ray_start, ray_normal,
- &dummy_ray_depth, loc, no,
- &index, &ob, obmat, NULL);
-
- if (has_hit && (snap_to_flag & SCE_SNAP_MODE_FACE)) {
- retval = SCE_SNAP_MODE_FACE;
- }
- }
-
- if (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE)) {
- short elem;
- float dist_px_tmp = *dist_px;
-
- SnapData snapdata;
- copy_m4_m4(snapdata.pmat, rv3d->persmat);
- snapdata.win_size[0] = ar->winx;
- snapdata.win_size[1] = ar->winy;
- copy_v2_v2(snapdata.mval, mval);
- snapdata.snap_to_flag = snap_to_flag;
- snapdata.view_proj = rv3d->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO;
-
- planes_from_projmat(
- snapdata.pmat,
- NULL, NULL, NULL, NULL,
- snapdata.clip_plane[0], snapdata.clip_plane[1]);
-
- snapdata.clip_plane_len = 2;
-
- if (has_hit) {
- /* Compute the new clip_pane but do not add it yet. */
- float new_clipplane[4];
- plane_from_point_normal_v3(new_clipplane, loc, no);
- if (dot_v3v3(snapdata.clip_plane[0], new_clipplane) > 0.0f) {
- /* The plane is facing the wrong direction. */
- negate_v4(new_clipplane);
- }
-
- /* Small offset to simulate a kind of volume for edges and vertices. */
- new_clipplane[3] += 0.01f;
-
- /* Try to snap only to the polygon. */
- elem = snap_mesh_polygon(
- sctx, &snapdata, ob, obmat,
- &dist_px_tmp, loc, no, &index);
-
- if (elem) {
- retval = elem;
- }
-
- /* Add the new clip plane to the beginning of the list. */
- for (int i = snapdata.clip_plane_len; i != 0; i--) {
- copy_v4_v4(snapdata.clip_plane[i], snapdata.clip_plane[i - 1]);
- }
- copy_v4_v4(snapdata.clip_plane[0], new_clipplane);
- snapdata.clip_plane_len++;
- }
-
- elem = snapObjectsRay(
- sctx, &snapdata, params,
- &dist_px_tmp, loc, no, &index, &ob, obmat);
-
- if (elem) {
- retval = elem;
- }
-
- if ((retval == SCE_SNAP_MODE_EDGE) &&
- (snapdata.snap_to_flag & SCE_SNAP_MODE_VERTEX))
- {
- retval = snap_mesh_edge_verts_mixed(
- sctx, &snapdata,
- ob, obmat, *dist_px,
- &dist_px_tmp, loc, no, &index);
- }
-
- *dist_px = dist_px_tmp;
- }
-
- if (retval) {
- copy_v3_v3(r_loc, loc);
- if (r_no) {
- copy_v3_v3(r_no, no);
- }
- if (r_ob) {
- *r_ob = ob;
- }
- if (r_obmat) {
- copy_m4_m4(r_obmat, obmat);
- }
- if (r_index) {
- *r_index = index;
- }
- return retval;
- }
-
- return 0;
+ BLI_assert((snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE)) !=
+ 0);
+
+ short retval = 0;
+ bool has_hit = false;
+ int index = -1;
+
+ float loc[3], no[3], obmat[4][4];
+ Object *ob = NULL;
+
+ const ARegion *ar = sctx->v3d_data.ar;
+ const RegionView3D *rv3d = ar->regiondata;
+
+ bool use_occlusion_test = params->use_occlusion_test && !XRAY_ENABLED(sctx->v3d_data.v3d);
+
+ if (snap_to_flag & SCE_SNAP_MODE_FACE || use_occlusion_test) {
+ float ray_start[3], ray_normal[3];
+
+ if (!ED_view3d_win_to_ray_clipped_ex(sctx->depsgraph,
+ sctx->v3d_data.ar,
+ sctx->v3d_data.v3d,
+ mval,
+ NULL,
+ ray_normal,
+ ray_start,
+ true)) {
+ return false;
+ }
+
+ float dummy_ray_depth = BVH_RAYCAST_DIST_MAX;
+
+ has_hit = raycastObjects(
+ sctx, params, ray_start, ray_normal, &dummy_ray_depth, loc, no, &index, &ob, obmat, NULL);
+
+ if (has_hit && (snap_to_flag & SCE_SNAP_MODE_FACE)) {
+ retval = SCE_SNAP_MODE_FACE;
+ }
+ }
+
+ if (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE)) {
+ short elem;
+ float dist_px_tmp = *dist_px;
+
+ SnapData snapdata;
+ copy_m4_m4(snapdata.pmat, rv3d->persmat);
+ snapdata.win_size[0] = ar->winx;
+ snapdata.win_size[1] = ar->winy;
+ copy_v2_v2(snapdata.mval, mval);
+ snapdata.snap_to_flag = snap_to_flag;
+ snapdata.view_proj = rv3d->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO;
+
+ planes_from_projmat(
+ snapdata.pmat, NULL, NULL, NULL, NULL, snapdata.clip_plane[0], snapdata.clip_plane[1]);
+
+ snapdata.clip_plane_len = 2;
+
+ if (has_hit) {
+ /* Compute the new clip_pane but do not add it yet. */
+ float new_clipplane[4];
+ plane_from_point_normal_v3(new_clipplane, loc, no);
+ if (dot_v3v3(snapdata.clip_plane[0], new_clipplane) > 0.0f) {
+ /* The plane is facing the wrong direction. */
+ negate_v4(new_clipplane);
+ }
+
+ /* Small offset to simulate a kind of volume for edges and vertices. */
+ new_clipplane[3] += 0.01f;
+
+ /* Try to snap only to the polygon. */
+ elem = snap_mesh_polygon(sctx, &snapdata, ob, obmat, &dist_px_tmp, loc, no, &index);
+
+ if (elem) {
+ retval = elem;
+ }
+
+ /* Add the new clip plane to the beginning of the list. */
+ for (int i = snapdata.clip_plane_len; i != 0; i--) {
+ copy_v4_v4(snapdata.clip_plane[i], snapdata.clip_plane[i - 1]);
+ }
+ copy_v4_v4(snapdata.clip_plane[0], new_clipplane);
+ snapdata.clip_plane_len++;
+ }
+
+ elem = snapObjectsRay(sctx, &snapdata, params, &dist_px_tmp, loc, no, &index, &ob, obmat);
+
+ if (elem) {
+ retval = elem;
+ }
+
+ if ((retval == SCE_SNAP_MODE_EDGE) && (snapdata.snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
+ retval = snap_mesh_edge_verts_mixed(
+ sctx, &snapdata, ob, obmat, *dist_px, &dist_px_tmp, loc, no, &index);
+ }
+
+ *dist_px = dist_px_tmp;
+ }
+
+ if (retval) {
+ copy_v3_v3(r_loc, loc);
+ if (r_no) {
+ copy_v3_v3(r_no, no);
+ }
+ if (r_ob) {
+ *r_ob = ob;
+ }
+ if (r_obmat) {
+ copy_m4_m4(r_obmat, obmat);
+ }
+ if (r_index) {
+ *r_index = index;
+ }
+ return retval;
+ }
+
+ return 0;
}
-bool ED_transform_snap_object_project_view3d_ex(
- SnapObjectContext *sctx,
- const unsigned short snap_to,
- const struct SnapObjectParams *params,
- const float mval[2], float *dist_px,
- float r_loc[3], float r_no[3], int *r_index,
- Object **r_ob, float r_obmat[4][4])
+bool ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx,
+ const unsigned short snap_to,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float *dist_px,
+ float r_loc[3],
+ float r_no[3],
+ int *r_index,
+ Object **r_ob,
+ float r_obmat[4][4])
{
- return transform_snap_context_project_view3d_mixed_impl(
- sctx,
- snap_to, params,
- mval, dist_px,
- r_loc, r_no, r_index, r_ob, r_obmat) != 0;
+ return transform_snap_context_project_view3d_mixed_impl(
+ sctx, snap_to, params, mval, dist_px, r_loc, r_no, r_index, r_ob, r_obmat) != 0;
}
/**
@@ -2682,47 +2794,43 @@ bool ED_transform_snap_object_project_view3d_ex(
* \param r_no: hit normal (optional).
* \return Snap success
*/
-bool ED_transform_snap_object_project_view3d(
- SnapObjectContext *sctx,
- const unsigned short snap_to,
- const struct SnapObjectParams *params,
- const float mval[2], float *dist_px,
- float r_loc[3], float r_no[3])
+bool ED_transform_snap_object_project_view3d(SnapObjectContext *sctx,
+ const unsigned short snap_to,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float *dist_px,
+ float r_loc[3],
+ float r_no[3])
{
- return ED_transform_snap_object_project_view3d_ex(
- sctx,
- snap_to,
- params,
- mval, dist_px,
- r_loc, r_no, NULL,
- NULL, NULL);
+ return ED_transform_snap_object_project_view3d_ex(
+ sctx, snap_to, params, mval, dist_px, r_loc, r_no, NULL, NULL, NULL);
}
/**
* see: #ED_transform_snap_object_project_ray_all
*/
-bool ED_transform_snap_object_project_all_view3d_ex(
- SnapObjectContext *sctx,
- const struct SnapObjectParams *params,
- const float mval[2],
- float ray_depth, bool sort,
- ListBase *r_hit_list)
+bool ED_transform_snap_object_project_all_view3d_ex(SnapObjectContext *sctx,
+ const struct SnapObjectParams *params,
+ const float mval[2],
+ float ray_depth,
+ bool sort,
+ ListBase *r_hit_list)
{
- float ray_start[3], ray_normal[3];
-
- if (!ED_view3d_win_to_ray_clipped_ex(
- sctx->depsgraph,
- sctx->v3d_data.ar, sctx->v3d_data.v3d,
- mval, NULL, ray_normal, ray_start, true))
- {
- return false;
- }
-
- return ED_transform_snap_object_project_ray_all(
- sctx,
- params,
- ray_start, ray_normal, ray_depth, sort,
- r_hit_list);
+ float ray_start[3], ray_normal[3];
+
+ if (!ED_view3d_win_to_ray_clipped_ex(sctx->depsgraph,
+ sctx->v3d_data.ar,
+ sctx->v3d_data.v3d,
+ mval,
+ NULL,
+ ray_normal,
+ ray_start,
+ true)) {
+ return false;
+ }
+
+ return ED_transform_snap_object_project_ray_all(
+ sctx, params, ray_start, ray_normal, ray_depth, sort, r_hit_list);
}
/** \} */