Transform Volume rewrite/refactor
Take advantage of the efficiency provided by the snap_context. Also fixes errors: - volume snap fails based on view angle (T48394). - multiple instances of dupli-objects break volume calculation.
This commit is contained in:

committed by
Campbell Barton

parent
4a135ad2b7
commit
67d2de8828
@@ -82,7 +82,6 @@ typedef struct SK_Intersection {
|
|||||||
|
|
||||||
typedef struct SK_Sketch {
|
typedef struct SK_Sketch {
|
||||||
ListBase strokes;
|
ListBase strokes;
|
||||||
ListBase depth_peels;
|
|
||||||
SK_Stroke *active_stroke;
|
SK_Stroke *active_stroke;
|
||||||
SK_Stroke *gesture;
|
SK_Stroke *gesture;
|
||||||
SK_Point next_point;
|
SK_Point next_point;
|
||||||
|
@@ -50,8 +50,6 @@ void freeSketch(SK_Sketch *sketch)
|
|||||||
sk_freeStroke(stk);
|
sk_freeStroke(stk);
|
||||||
}
|
}
|
||||||
|
|
||||||
BLI_freelistN(&sketch->depth_peels);
|
|
||||||
|
|
||||||
MEM_freeN(sketch);
|
MEM_freeN(sketch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -970,100 +970,30 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S
|
|||||||
ToolSettings *ts = CTX_data_tool_settings(C);
|
ToolSettings *ts = CTX_data_tool_settings(C);
|
||||||
int point_added = 0;
|
int point_added = 0;
|
||||||
|
|
||||||
|
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
|
||||||
|
CTX_data_main(C), CTX_data_scene(C), 0,
|
||||||
|
CTX_wm_region(C), CTX_wm_view3d(C));
|
||||||
|
|
||||||
|
float mvalf[2] = {UNPACK2(dd->mval)};
|
||||||
|
float r_loc[3], dummy_no[3];
|
||||||
|
|
||||||
if (ts->snap_mode == SCE_SNAP_MODE_VOLUME) {
|
if (ts->snap_mode == SCE_SNAP_MODE_VOLUME) {
|
||||||
DepthPeel *p1, *p2;
|
float size;
|
||||||
float *last_p = NULL;
|
if (peelObjectsSnapContext(
|
||||||
float dist = FLT_MAX;
|
snap_context, mvalf, SNAP_ALL,
|
||||||
float p[3] = {0};
|
(ts->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0,
|
||||||
float size = 0;
|
r_loc, dummy_no, &size))
|
||||||
float mvalf[2];
|
{
|
||||||
|
|
||||||
BLI_freelistN(&sketch->depth_peels);
|
|
||||||
BLI_listbase_clear(&sketch->depth_peels);
|
|
||||||
|
|
||||||
mvalf[0] = dd->mval[0];
|
|
||||||
mvalf[1] = dd->mval[1];
|
|
||||||
peelObjectsContext(C, mvalf, SNAP_ALL, &sketch->depth_peels);
|
|
||||||
|
|
||||||
if (stk->nb_points > 0 && stk->points[stk->nb_points - 1].type == PT_CONTINUOUS) {
|
|
||||||
last_p = stk->points[stk->nb_points - 1].p;
|
|
||||||
}
|
|
||||||
else if (LAST_SNAP_POINT_VALID) {
|
|
||||||
last_p = LAST_SNAP_POINT;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for (p1 = sketch->depth_peels.first; p1; p1 = p1->next) {
|
|
||||||
if (p1->flag == 0) {
|
|
||||||
float vec[3];
|
|
||||||
float new_dist;
|
|
||||||
float new_size = 0;
|
|
||||||
|
|
||||||
p2 = NULL;
|
|
||||||
p1->flag = 1;
|
|
||||||
|
|
||||||
/* if peeling objects, take the first and last from each object */
|
|
||||||
if (ts->snap_flag & SCE_SNAP_PEEL_OBJECT) {
|
|
||||||
DepthPeel *peel;
|
|
||||||
for (peel = p1->next; peel; peel = peel->next) {
|
|
||||||
if (peel->ob == p1->ob) {
|
|
||||||
peel->flag = 1;
|
|
||||||
p2 = peel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* otherwise, pair first with second and so on */
|
|
||||||
else {
|
|
||||||
for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next) {
|
|
||||||
/* nothing to do here */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p2) {
|
|
||||||
p2->flag = 1;
|
|
||||||
|
|
||||||
add_v3_v3v3(vec, p1->p, p2->p);
|
|
||||||
mul_v3_fl(vec, 0.5f);
|
|
||||||
new_size = len_v3v3(p1->p, p2->p);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
copy_v3_v3(vec, p1->p);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (last_p == NULL) {
|
|
||||||
copy_v3_v3(p, vec);
|
|
||||||
size = new_size;
|
|
||||||
dist = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_dist = len_v3v3(last_p, vec);
|
|
||||||
|
|
||||||
if (new_dist < dist) {
|
|
||||||
copy_v3_v3(p, vec);
|
|
||||||
dist = new_dist;
|
|
||||||
size = new_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dist != FLT_MAX) {
|
|
||||||
pt->type = dd->type;
|
pt->type = dd->type;
|
||||||
pt->mode = PT_SNAP;
|
pt->mode = PT_SNAP;
|
||||||
pt->size = size / 2;
|
pt->size = size / 2;
|
||||||
copy_v3_v3(pt->p, p);
|
copy_v3_v3(pt->p, r_loc);
|
||||||
|
|
||||||
point_added = 1;
|
point_added = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//BLI_freelistN(&depth_peels);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SK_Stroke *snap_stk;
|
SK_Stroke *snap_stk;
|
||||||
float vec[3];
|
|
||||||
float no[3];
|
|
||||||
float mval[2];
|
|
||||||
int found = 0;
|
|
||||||
float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
|
float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
|
||||||
|
|
||||||
/* snap to strokes */
|
/* snap to strokes */
|
||||||
@@ -1082,37 +1012,28 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S
|
|||||||
point_added = 1;
|
point_added = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mval[0] = dd->mval[0];
|
|
||||||
mval[1] = dd->mval[1];
|
|
||||||
|
|
||||||
/* try to snap to closer object */
|
/* try to snap to closer object */
|
||||||
{
|
{
|
||||||
struct SnapObjectContext *snap_context = ED_transform_snap_object_context_create_view3d(
|
if (ED_transform_snap_object_project_view3d(
|
||||||
CTX_data_main(C), CTX_data_scene(C), 0,
|
|
||||||
CTX_wm_region(C), CTX_wm_view3d(C));
|
|
||||||
|
|
||||||
found = ED_transform_snap_object_project_view3d(
|
|
||||||
snap_context,
|
snap_context,
|
||||||
&(const struct SnapObjectParams){
|
&(const struct SnapObjectParams){
|
||||||
.snap_select = SNAP_NOT_SELECTED,
|
.snap_select = SNAP_NOT_SELECTED,
|
||||||
.snap_to = ts->snap_mode,
|
.snap_to = ts->snap_mode,
|
||||||
},
|
},
|
||||||
mval, &dist_px, NULL,
|
mvalf, &dist_px, NULL,
|
||||||
vec, no);
|
r_loc, dummy_no))
|
||||||
|
{
|
||||||
|
pt->type = dd->type;
|
||||||
|
pt->mode = PT_SNAP;
|
||||||
|
copy_v3_v3(pt->p, r_loc);
|
||||||
|
|
||||||
ED_transform_snap_object_context_destroy(snap_context);
|
point_added = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found == 1) {
|
|
||||||
pt->type = dd->type;
|
|
||||||
pt->mode = PT_SNAP;
|
|
||||||
copy_v3_v3(pt->p, vec);
|
|
||||||
|
|
||||||
point_added = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ED_transform_snap_object_context_destroy(snap_context);
|
||||||
return point_added;
|
return point_added;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -158,19 +158,6 @@ void BIF_draw_manipulator(const struct bContext *C);
|
|||||||
|
|
||||||
/* Snapping */
|
/* Snapping */
|
||||||
|
|
||||||
|
|
||||||
typedef struct DepthPeel {
|
|
||||||
struct DepthPeel *next, *prev;
|
|
||||||
|
|
||||||
float depth;
|
|
||||||
float p[3];
|
|
||||||
float no[3];
|
|
||||||
struct Object *ob;
|
|
||||||
int flag;
|
|
||||||
} DepthPeel;
|
|
||||||
|
|
||||||
struct ListBase;
|
|
||||||
|
|
||||||
typedef enum SnapSelect {
|
typedef enum SnapSelect {
|
||||||
SNAP_ALL = 0,
|
SNAP_ALL = 0,
|
||||||
SNAP_NOT_SELECTED = 1,
|
SNAP_NOT_SELECTED = 1,
|
||||||
@@ -179,14 +166,18 @@ typedef enum SnapSelect {
|
|||||||
|
|
||||||
#define SNAP_MIN_DISTANCE 30
|
#define SNAP_MIN_DISTANCE 30
|
||||||
|
|
||||||
bool peelObjectsTransForm(
|
bool peelObjectsTransform(
|
||||||
struct TransInfo *t, const float mval[2], SnapSelect snap_select,
|
struct TransInfo *t, const float mval[2],
|
||||||
|
SnapSelect snap_select, bool use_peel_object,
|
||||||
/* return args */
|
/* return args */
|
||||||
struct ListBase *r_depth_peels);
|
float r_loc[3], float r_no[3], float *r_thickness);
|
||||||
bool peelObjectsContext(
|
bool peelObjectsSnapContext(
|
||||||
struct bContext *C, const float mval[2], SnapSelect snap_select,
|
struct SnapObjectContext *sctx,
|
||||||
|
const float mval[2],
|
||||||
|
SnapSelect snap_select, bool use_peel_object,
|
||||||
/* return args */
|
/* return args */
|
||||||
struct ListBase *r_depth_peels);
|
float r_loc[3], float r_no[3], float *r_thickness);
|
||||||
|
|
||||||
bool snapObjectsTransform(
|
bool snapObjectsTransform(
|
||||||
struct TransInfo *t, const float mval[2], SnapSelect snap_select,
|
struct TransInfo *t, const float mval[2], SnapSelect snap_select,
|
||||||
float *dist_px,
|
float *dist_px,
|
||||||
|
@@ -29,6 +29,7 @@ struct BMVert;
|
|||||||
struct BMEdge;
|
struct BMEdge;
|
||||||
struct BMFace;
|
struct BMFace;
|
||||||
|
|
||||||
|
struct ListBase;
|
||||||
struct Scene;
|
struct Scene;
|
||||||
struct Main;
|
struct Main;
|
||||||
struct Object;
|
struct Object;
|
||||||
@@ -38,6 +39,24 @@ struct View3D;
|
|||||||
/* transform_snap_object.c */
|
/* transform_snap_object.c */
|
||||||
|
|
||||||
/* ED_transform_snap_object_*** API */
|
/* ED_transform_snap_object_*** API */
|
||||||
|
|
||||||
|
/** used for storing multiple hits */
|
||||||
|
struct SnapObjectHitDepth {
|
||||||
|
struct SnapObjectHitDepth *next, *prev;
|
||||||
|
|
||||||
|
float depth;
|
||||||
|
float co[3];
|
||||||
|
float no[3];
|
||||||
|
int index;
|
||||||
|
|
||||||
|
struct Object *ob;
|
||||||
|
float obmat[4][4];
|
||||||
|
|
||||||
|
/* needed to tell which ray-cast this was part of,
|
||||||
|
* the same object may be part of many ray-casts when dupli's are used. */
|
||||||
|
unsigned int ob_uuid;
|
||||||
|
};
|
||||||
|
|
||||||
struct SnapObjectParams {
|
struct SnapObjectParams {
|
||||||
int snap_select; /* SnapSelect */
|
int snap_select; /* SnapSelect */
|
||||||
union {
|
union {
|
||||||
@@ -81,9 +100,16 @@ bool ED_transform_snap_object_project_ray_ex(
|
|||||||
struct Object **r_ob, float r_obmat[4][4]);
|
struct Object **r_ob, float r_obmat[4][4]);
|
||||||
bool ED_transform_snap_object_project_ray(
|
bool ED_transform_snap_object_project_ray(
|
||||||
SnapObjectContext *sctx,
|
SnapObjectContext *sctx,
|
||||||
const float ray_origin[3], const float ray_direction[3], float *ray_dist,
|
const float ray_origin[3], const float ray_direction[3], float *ray_depth,
|
||||||
float r_co[3], float r_no[3]);
|
float r_co[3], float r_no[3]);
|
||||||
|
|
||||||
|
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,
|
||||||
|
struct ListBase *r_hit_list);
|
||||||
|
|
||||||
bool ED_transform_snap_object_project_view3d_ex(
|
bool ED_transform_snap_object_project_view3d_ex(
|
||||||
struct SnapObjectContext *sctx,
|
struct SnapObjectContext *sctx,
|
||||||
const struct SnapObjectParams *params,
|
const struct SnapObjectParams *params,
|
||||||
@@ -104,4 +130,11 @@ bool ED_transform_snap_object_project_view3d_mixed(
|
|||||||
bool use_depth,
|
bool use_depth,
|
||||||
float r_co[3], float r_no[3]);
|
float r_co[3], float r_no[3]);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
#endif /* __ED_TRANSFORM_SNAP_OBJECT_CONTEXT_H__ */
|
#endif /* __ED_TRANSFORM_SNAP_OBJECT_CONTEXT_H__ */
|
||||||
|
@@ -963,86 +963,10 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
|
|||||||
mval[1] = t->mval[1];
|
mval[1] = t->mval[1];
|
||||||
|
|
||||||
if (t->tsnap.mode == SCE_SNAP_MODE_VOLUME) {
|
if (t->tsnap.mode == SCE_SNAP_MODE_VOLUME) {
|
||||||
ListBase depth_peels;
|
found = peelObjectsTransform(
|
||||||
DepthPeel *p1, *p2;
|
t, mval, t->tsnap.modeSelect,
|
||||||
const float *last_p = NULL;
|
(t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0,
|
||||||
float max_dist = FLT_MAX;
|
loc, no, NULL);
|
||||||
float p[3] = {0.0f, 0.0f, 0.0f};
|
|
||||||
|
|
||||||
BLI_listbase_clear(&depth_peels);
|
|
||||||
|
|
||||||
peelObjectsTransForm(t, mval, t->tsnap.modeSelect, &depth_peels);
|
|
||||||
|
|
||||||
// if (LAST_SNAP_POINT_VALID)
|
|
||||||
// {
|
|
||||||
// last_p = LAST_SNAP_POINT;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
{
|
|
||||||
last_p = t->tsnap.snapPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for (p1 = depth_peels.first; p1; p1 = p1->next) {
|
|
||||||
if (p1->flag == 0) {
|
|
||||||
float vec[3];
|
|
||||||
float new_dist;
|
|
||||||
|
|
||||||
p2 = NULL;
|
|
||||||
p1->flag = 1;
|
|
||||||
|
|
||||||
/* if peeling objects, take the first and last from each object */
|
|
||||||
if (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) {
|
|
||||||
DepthPeel *peel;
|
|
||||||
for (peel = p1->next; peel; peel = peel->next) {
|
|
||||||
if (peel->ob == p1->ob) {
|
|
||||||
peel->flag = 1;
|
|
||||||
p2 = peel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* otherwise, pair first with second and so on */
|
|
||||||
else {
|
|
||||||
for (p2 = p1->next; p2 && p2->ob != p1->ob; p2 = p2->next) {
|
|
||||||
/* nothing to do here */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p2) {
|
|
||||||
p2->flag = 1;
|
|
||||||
|
|
||||||
add_v3_v3v3(vec, p1->p, p2->p);
|
|
||||||
mul_v3_fl(vec, 0.5f);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
copy_v3_v3(vec, p1->p);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (last_p == NULL) {
|
|
||||||
copy_v3_v3(p, vec);
|
|
||||||
max_dist = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_dist = len_squared_v3v3(last_p, vec);
|
|
||||||
|
|
||||||
if (new_dist < max_dist) {
|
|
||||||
copy_v3_v3(p, vec);
|
|
||||||
max_dist = new_dist;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (max_dist != FLT_MAX) {
|
|
||||||
copy_v3_v3(loc, p);
|
|
||||||
/* XXX, is there a correct normal in this case ???, for now just z up */
|
|
||||||
no[0] = 0.0;
|
|
||||||
no[1] = 0.0;
|
|
||||||
no[2] = 1.0;
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
BLI_freelistN(&depth_peels);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
zero_v3(no); /* objects won't set this */
|
zero_v3(no); /* objects won't set this */
|
||||||
@@ -1302,347 +1226,87 @@ bool snapObjectsTransform(
|
|||||||
|
|
||||||
/******************** PEELING *********************************/
|
/******************** PEELING *********************************/
|
||||||
|
|
||||||
|
bool peelObjectsSnapContext(
|
||||||
static int cmpPeel(const void *arg1, const void *arg2)
|
SnapObjectContext *sctx,
|
||||||
|
const float mval[2], SnapSelect snap_select, bool use_peel_object,
|
||||||
|
/* return args */
|
||||||
|
float r_loc[3], float r_no[3], float *r_thickness)
|
||||||
{
|
{
|
||||||
const DepthPeel *p1 = arg1;
|
ListBase depths_peel = {0};
|
||||||
const DepthPeel *p2 = arg2;
|
ED_transform_snap_object_project_all_view3d_ex(
|
||||||
int val = 0;
|
sctx,
|
||||||
|
&(const struct SnapObjectParams){
|
||||||
if (p1->depth < p2->depth) {
|
.snap_to = SCE_SNAP_MODE_FACE,
|
||||||
val = -1;
|
.snap_select = snap_select,
|
||||||
}
|
.use_object_edit = true,
|
||||||
else if (p1->depth > p2->depth) {
|
},
|
||||||
val = 1;
|
mval, -1.0f, false,
|
||||||
}
|
&depths_peel);
|
||||||
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void removeDoublesPeel(ListBase *depth_peels)
|
if (!BLI_listbase_is_empty(&depths_peel)) {
|
||||||
{
|
/* At the moment we only use the hits of the first object */
|
||||||
DepthPeel *peel;
|
struct SnapObjectHitDepth *hit_min = depths_peel.first;
|
||||||
|
for (struct SnapObjectHitDepth *iter = hit_min->next; iter; iter = iter->next) {
|
||||||
for (peel = depth_peels->first; peel; peel = peel->next) {
|
if (iter->depth < hit_min->depth) {
|
||||||
DepthPeel *next_peel = peel->next;
|
hit_min = iter;
|
||||||
|
|
||||||
if (next_peel && fabsf(peel->depth - next_peel->depth) < 0.0015f) {
|
|
||||||
peel->next = next_peel->next;
|
|
||||||
|
|
||||||
if (next_peel->next) {
|
|
||||||
next_peel->next->prev = peel;
|
|
||||||
}
|
|
||||||
|
|
||||||
MEM_freeN(next_peel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float no[3], Object *ob)
|
|
||||||
{
|
|
||||||
DepthPeel *peel = MEM_callocN(sizeof(DepthPeel), "DepthPeel");
|
|
||||||
|
|
||||||
peel->depth = depth;
|
|
||||||
peel->ob = ob;
|
|
||||||
copy_v3_v3(peel->p, p);
|
|
||||||
copy_v3_v3(peel->no, no);
|
|
||||||
|
|
||||||
BLI_addtail(depth_peels, peel);
|
|
||||||
|
|
||||||
peel->flag = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PeelRayCast_Data {
|
|
||||||
BVHTreeFromMesh bvhdata;
|
|
||||||
|
|
||||||
/* internal vars for adding peel */
|
|
||||||
Object *ob;
|
|
||||||
const float (*obmat)[4];
|
|
||||||
const float (*timat)[3];
|
|
||||||
|
|
||||||
const float *ray_start; /* globalspace */
|
|
||||||
|
|
||||||
const MLoopTri *looptri;
|
|
||||||
const float (*polynors)[3]; /* optional, can be NULL */
|
|
||||||
|
|
||||||
/* output list */
|
|
||||||
ListBase *depth_peels;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PeelEditMeshRayCast_Data {
|
|
||||||
BVHTreeFromEditMesh bvhdata;
|
|
||||||
|
|
||||||
/* internal vars for adding peel */
|
|
||||||
Object *ob;
|
|
||||||
const float(*obmat)[4];
|
|
||||||
const float(*timat)[3];
|
|
||||||
|
|
||||||
const float *ray_start; /* globalspace */
|
|
||||||
|
|
||||||
/* output list */
|
|
||||||
ListBase *depth_peels;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void peelRayCast_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
|
|
||||||
{
|
|
||||||
struct PeelRayCast_Data *data = userdata;
|
|
||||||
|
|
||||||
data->bvhdata.raycast_callback(&data->bvhdata, index, ray, hit);
|
|
||||||
|
|
||||||
if (hit->index != -1) {
|
|
||||||
/* get all values in worldspace */
|
|
||||||
float location[3], normal[3];
|
|
||||||
float depth;
|
|
||||||
|
|
||||||
/* worldspace location */
|
|
||||||
mul_v3_m4v3(location, (float (*)[4])data->obmat, hit->co);
|
|
||||||
depth = len_v3v3(location, data->ray_start);
|
|
||||||
|
|
||||||
/* worldspace normal */
|
|
||||||
copy_v3_v3(normal, data->polynors ? data->polynors[data->looptri[hit->index].poly] : hit->no);
|
|
||||||
mul_m3_v3((float (*)[3])data->timat, normal);
|
|
||||||
normalize_v3(normal);
|
|
||||||
|
|
||||||
addDepthPeel(data->depth_peels, depth, location, normal, data->ob);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void peelEditMeshRayCast_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
|
|
||||||
{
|
|
||||||
struct PeelEditMeshRayCast_Data *data = userdata;
|
|
||||||
|
|
||||||
data->bvhdata.raycast_callback(&data->bvhdata, index, ray, hit);
|
|
||||||
|
|
||||||
if (hit->index != -1) {
|
|
||||||
/* get all values in worldspace */
|
|
||||||
float location[3], normal[3];
|
|
||||||
float depth;
|
|
||||||
|
|
||||||
/* worldspace location */
|
|
||||||
mul_v3_m4v3(location, (float(*)[4])data->obmat, hit->co);
|
|
||||||
depth = len_v3v3(location, data->ray_start);
|
|
||||||
|
|
||||||
/* worldspace normal */
|
|
||||||
copy_v3_v3(normal, hit->no);
|
|
||||||
mul_m3_v3((float(*)[3])data->timat, normal);
|
|
||||||
normalize_v3(normal);
|
|
||||||
|
|
||||||
addDepthPeel(data->depth_peels, depth, location, normal, data->ob);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool peelDerivedMesh(
|
|
||||||
Object *ob, DerivedMesh *dm, float obmat[4][4],
|
|
||||||
const float ray_start[3], const float ray_normal[3], const float UNUSED(mval[2]),
|
|
||||||
ListBase *depth_peels)
|
|
||||||
{
|
|
||||||
bool retval = false;
|
|
||||||
int totvert = dm->getNumVerts(dm);
|
|
||||||
|
|
||||||
if (totvert > 0) {
|
|
||||||
const MLoopTri *looptri = dm->getLoopTriArray(dm);
|
|
||||||
const int looptri_num = dm->getNumLoopTri(dm);
|
|
||||||
float imat[4][4];
|
|
||||||
float timat[3][3]; /* transpose inverse matrix for normals */
|
|
||||||
float ray_start_local[3], ray_normal_local[3];
|
|
||||||
bool test = true;
|
|
||||||
|
|
||||||
invert_m4_m4(imat, obmat);
|
|
||||||
|
|
||||||
transpose_m3_m4(timat, imat);
|
|
||||||
|
|
||||||
mul_v3_m4v3(ray_start_local, imat, ray_start);
|
|
||||||
mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
|
|
||||||
|
|
||||||
/* If number of vert is more than an arbitrary limit,
|
|
||||||
* test against boundbox first
|
|
||||||
* */
|
|
||||||
if (looptri_num > 16) {
|
|
||||||
BoundBox *bb = BKE_object_boundbox_get(ob);
|
|
||||||
|
|
||||||
if (bb) {
|
|
||||||
BoundBox bb_temp;
|
|
||||||
|
|
||||||
/* We cannot aford a bbox with some null dimension, which may happen in some cases...
|
|
||||||
* Threshold is rather high, but seems to be needed to get good behavior, see T46099. */
|
|
||||||
bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f);
|
|
||||||
|
|
||||||
test = BKE_boundbox_ray_hit_check(bb, ray_start_local, ray_normal_local, NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
struct SnapObjectHitDepth *hit_max = NULL;
|
||||||
if (test == true) {
|
|
||||||
struct PeelRayCast_Data data;
|
|
||||||
|
|
||||||
bvhtree_from_mesh_looptri(&data.bvhdata, dm, 0.0f, 4, 6);
|
if (use_peel_object) {
|
||||||
|
/* if peeling objects, take the first and last from each object */
|
||||||
if (data.bvhdata.tree != NULL) {
|
hit_max = hit_min;
|
||||||
data.ob = ob;
|
for (struct SnapObjectHitDepth *iter = depths_peel.first; iter; iter = iter->next) {
|
||||||
data.obmat = (const float (*)[4])obmat;
|
if ((iter->depth > hit_max->depth) && (iter->ob_uuid == hit_min->ob_uuid)) {
|
||||||
data.timat = (const float (*)[3])timat;
|
hit_max = iter;
|
||||||
data.ray_start = ray_start;
|
}
|
||||||
data.looptri = looptri;
|
|
||||||
data.polynors = dm->getPolyDataArray(dm, CD_NORMAL); /* can be NULL */
|
|
||||||
data.depth_peels = depth_peels;
|
|
||||||
|
|
||||||
BLI_bvhtree_ray_cast_all(
|
|
||||||
data.bvhdata.tree, ray_start_local, ray_normal_local, 0.0f, BVH_RAYCAST_DIST_MAX,
|
|
||||||
peelRayCast_cb, &data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free_bvhtree_from_mesh(&data.bvhdata);
|
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
|
/* otherwise, pair first with second and so on */
|
||||||
return retval;
|
for (struct SnapObjectHitDepth *iter = depths_peel.first; iter; iter = iter->next) {
|
||||||
}
|
if ((iter != hit_min) && (iter->ob_uuid == hit_min->ob_uuid)) {
|
||||||
|
if (hit_max == NULL) {
|
||||||
static bool peelEditMesh(
|
hit_max = iter;
|
||||||
Object *ob, BMEditMesh *em, float obmat[4][4],
|
}
|
||||||
const float ray_start[3], const float ray_normal[3],
|
else if (iter->depth < hit_max->depth) {
|
||||||
ListBase *depth_peels)
|
hit_max = iter;
|
||||||
{
|
|
||||||
bool retval = false;
|
|
||||||
int totvert = em->bm->totvert;
|
|
||||||
|
|
||||||
if (totvert > 0) {
|
|
||||||
float imat[4][4];
|
|
||||||
float timat[3][3]; /* transpose inverse matrix for normals */
|
|
||||||
float ray_start_local[3], ray_normal_local[3];
|
|
||||||
bool test = true;
|
|
||||||
|
|
||||||
invert_m4_m4(imat, obmat);
|
|
||||||
|
|
||||||
transpose_m3_m4(timat, imat);
|
|
||||||
|
|
||||||
mul_v3_m4v3(ray_start_local, imat, ray_start);
|
|
||||||
mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal);
|
|
||||||
|
|
||||||
if (test == true) {
|
|
||||||
struct PeelEditMeshRayCast_Data data;
|
|
||||||
|
|
||||||
BLI_bitmap *looptri_mask = BLI_BITMAP_NEW(em->tottri, __func__);
|
|
||||||
int looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
|
|
||||||
em->bm, looptri_mask,
|
|
||||||
BM_elem_cb_check_hflag_enabled_simple(BMFace *, (BM_ELEM_SELECT | BM_ELEM_HIDDEN)));
|
|
||||||
|
|
||||||
bvhtree_from_editmesh_looptri_ex(&data.bvhdata, em, looptri_mask, looptri_num_active, 0.0f, 4, 6);
|
|
||||||
|
|
||||||
MEM_freeN(looptri_mask);
|
|
||||||
|
|
||||||
if (data.bvhdata.tree != NULL) {
|
|
||||||
data.ob = ob;
|
|
||||||
data.obmat = (const float(*)[4])obmat;
|
|
||||||
data.timat = (const float(*)[3])timat;
|
|
||||||
data.ray_start = ray_start;
|
|
||||||
data.depth_peels = depth_peels;
|
|
||||||
|
|
||||||
BLI_bvhtree_ray_cast_all(
|
|
||||||
data.bvhdata.tree, ray_start_local, ray_normal_local, 0.0f, BVH_RAYCAST_DIST_MAX,
|
|
||||||
peelEditMeshRayCast_cb, &data);
|
|
||||||
}
|
|
||||||
|
|
||||||
free_bvhtree_from_editmesh(&data.bvhdata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool peelObjects(
|
|
||||||
Scene *scene, View3D *v3d, ARegion *ar, Object *obedit,
|
|
||||||
const float mval[2], SnapSelect snap_select,
|
|
||||||
ListBase *r_depth_peels)
|
|
||||||
{
|
|
||||||
Base *base;
|
|
||||||
bool retval = false;
|
|
||||||
float ray_start[3], ray_normal[3];
|
|
||||||
|
|
||||||
if (ED_view3d_win_to_ray(ar, v3d, mval, ray_start, ray_normal, true) == false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (base = scene->base.first; base != NULL; base = base->next) {
|
|
||||||
if (BASE_SELECTABLE(v3d, base)) {
|
|
||||||
Object *ob = base->object;
|
|
||||||
|
|
||||||
if (ob->transflag & OB_DUPLI) {
|
|
||||||
DupliObject *dupli_ob;
|
|
||||||
ListBase *lb = object_duplilist(G.main->eval_ctx, scene, ob);
|
|
||||||
|
|
||||||
for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
|
|
||||||
Object *dob = dupli_ob->ob;
|
|
||||||
|
|
||||||
if (dob->type == OB_MESH) {
|
|
||||||
BMEditMesh *em;
|
|
||||||
bool val;
|
|
||||||
|
|
||||||
if (dob != obedit) {
|
|
||||||
DerivedMesh *dm;
|
|
||||||
dm = mesh_get_derived_final(scene, dob, CD_MASK_BAREMESH);
|
|
||||||
val = peelDerivedMesh(dob, dm, dob->obmat, ray_start, ray_normal, mval, r_depth_peels);
|
|
||||||
|
|
||||||
dm->release(dm);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
em = BKE_editmesh_from_object(dob);
|
|
||||||
val = peelEditMesh(dob, em, dob->obmat, ray_start, ray_normal, r_depth_peels);
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = retval || val;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free_object_duplilist(lb);
|
|
||||||
}
|
}
|
||||||
|
/* in this case has only one hit. treat as raycast */
|
||||||
if (ob->type == OB_MESH) {
|
if (hit_max == NULL) {
|
||||||
bool val = false;
|
hit_max = hit_min;
|
||||||
|
|
||||||
if (ob != obedit && ((snap_select == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL)) == 0) || ELEM(snap_select, SNAP_ALL, SNAP_NOT_OBEDIT))) {
|
|
||||||
DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
|
|
||||||
|
|
||||||
val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, r_depth_peels);
|
|
||||||
dm->release(dm);
|
|
||||||
}
|
|
||||||
else if (ob == obedit && snap_select != SNAP_NOT_OBEDIT) {
|
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(ob);
|
|
||||||
DerivedMesh *dm = editbmesh_get_derived_cage(scene, obedit, em, CD_MASK_BAREMESH);
|
|
||||||
|
|
||||||
val = peelDerivedMesh(ob, dm, ob->obmat, ray_start, ray_normal, mval, r_depth_peels);
|
|
||||||
dm->release(dm);
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = retval || val;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mid_v3_v3v3(r_loc, hit_min->co, hit_max->co);
|
||||||
|
|
||||||
|
if (r_thickness) {
|
||||||
|
*r_thickness = hit_max->depth - hit_min->depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX, is there a correct normal in this case ???, for now just z up */
|
||||||
|
r_no[0] = 0.0;
|
||||||
|
r_no[1] = 0.0;
|
||||||
|
r_no[2] = 1.0;
|
||||||
|
|
||||||
|
BLI_freelistN(&depths_peel);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
BLI_listbase_sort(r_depth_peels, cmpPeel);
|
|
||||||
removeDoublesPeel(r_depth_peels);
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool peelObjectsTransForm(
|
bool peelObjectsTransform(
|
||||||
TransInfo *t, const float mval[2], SnapSelect snap_select,
|
TransInfo *t,
|
||||||
ListBase *r_depth_peels)
|
const float mval[2], SnapSelect snap_select, bool use_peel_object,
|
||||||
|
/* return args */
|
||||||
|
float r_loc[3], float r_no[3], float *r_thickness)
|
||||||
{
|
{
|
||||||
return peelObjects(t->scene, t->view, t->ar, t->obedit, mval, snap_select, r_depth_peels);
|
return peelObjectsSnapContext(
|
||||||
}
|
t->tsnap.object_context,
|
||||||
|
mval, snap_select, use_peel_object,
|
||||||
bool peelObjectsContext(
|
r_loc, r_no, r_thickness);
|
||||||
bContext *C, const float mval[2], SnapSelect snap_select,
|
|
||||||
ListBase *r_depth_peels)
|
|
||||||
{
|
|
||||||
Scene *scene = CTX_data_scene(C);
|
|
||||||
ScrArea *sa = CTX_wm_area(C);
|
|
||||||
View3D *v3d = sa->spacedata.first;
|
|
||||||
ARegion *ar = CTX_wm_region(C);
|
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
|
||||||
|
|
||||||
return peelObjects(scene, v3d, ar, obedit, mval, snap_select, r_depth_peels);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************** NODES ***********************************/
|
/******************** NODES ***********************************/
|
||||||
|
@@ -34,6 +34,7 @@
|
|||||||
#include "BLI_memarena.h"
|
#include "BLI_memarena.h"
|
||||||
#include "BLI_ghash.h"
|
#include "BLI_ghash.h"
|
||||||
#include "BLI_linklist.h"
|
#include "BLI_linklist.h"
|
||||||
|
#include "BLI_listbase.h"
|
||||||
#include "BLI_utildefines.h"
|
#include "BLI_utildefines.h"
|
||||||
|
|
||||||
#include "DNA_armature_types.h"
|
#include "DNA_armature_types.h"
|
||||||
@@ -109,6 +110,111 @@ struct SnapObjectContext {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt);
|
||||||
|
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/** \name Support for storing all depths, not just the first (raycast 'all')
|
||||||
|
*
|
||||||
|
* This uses a list of #SnapObjectHitDepth structs.
|
||||||
|
*
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
/* Store all ray-hits */
|
||||||
|
struct RayCastAll_Data {
|
||||||
|
void *bvhdata;
|
||||||
|
|
||||||
|
/* internal vars for adding depths */
|
||||||
|
BVHTree_RayCastCallback raycast_callback;
|
||||||
|
|
||||||
|
const float(*obmat)[4];
|
||||||
|
const float(*timat)[3];
|
||||||
|
|
||||||
|
float len_diff;
|
||||||
|
float local_scale;
|
||||||
|
|
||||||
|
Object *ob;
|
||||||
|
unsigned int ob_uuid;
|
||||||
|
|
||||||
|
/* DerivedMesh only */
|
||||||
|
DerivedMesh *dm;
|
||||||
|
const struct MLoopTri *dm_looptri;
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
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->ob = ob;
|
||||||
|
copy_m4_m4(hit->obmat, (float(*)[4])obmat);
|
||||||
|
hit->ob_uuid = ob_uuid;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* currently unused, and causes issues when looptri's havn't been calculated.
|
||||||
|
* since theres some overhead in ensuring this data is valid, it may need to be optional. */
|
||||||
|
#if 0
|
||||||
|
if (data->dm) {
|
||||||
|
hit->index = dm_looptri_to_poly_index(data->dm, &data->dm_looptri[hit->index]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
@@ -572,8 +678,10 @@ static bool snapDerivedMesh(
|
|||||||
SnapObjectContext *sctx,
|
SnapObjectContext *sctx,
|
||||||
Object *ob, DerivedMesh *dm, float obmat[4][4],
|
Object *ob, DerivedMesh *dm, float obmat[4][4],
|
||||||
const float mval[2], float *dist_px, const short snap_to, bool do_bb,
|
const float mval[2], float *dist_px, const short snap_to, bool do_bb,
|
||||||
const float ray_start[3], const float ray_normal[3], const float ray_origin[3], float *ray_depth,
|
const float ray_start[3], const float ray_normal[3], const float ray_origin[3],
|
||||||
float r_loc[3], float r_no[3], int *r_index)
|
float *ray_depth, unsigned int ob_index,
|
||||||
|
float r_loc[3], float r_no[3], int *r_index,
|
||||||
|
ListBase *r_hit_list)
|
||||||
{
|
{
|
||||||
ARegion *ar = sctx->v3d_data.ar;
|
ARegion *ar = sctx->v3d_data.ar;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
@@ -729,31 +837,55 @@ static bool snapDerivedMesh(
|
|||||||
switch (snap_to) {
|
switch (snap_to) {
|
||||||
case SCE_SNAP_MODE_FACE:
|
case SCE_SNAP_MODE_FACE:
|
||||||
{
|
{
|
||||||
BVHTreeRayHit hit;
|
if (r_hit_list) {
|
||||||
|
struct RayCastAll_Data data;
|
||||||
|
|
||||||
hit.index = -1;
|
data.bvhdata = treedata;
|
||||||
hit.dist = local_depth;
|
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.dm = dm;
|
||||||
|
data.hit_list = r_hit_list;
|
||||||
|
data.retval = retval;
|
||||||
|
|
||||||
if (treedata->tree &&
|
BLI_bvhtree_ray_cast_all(
|
||||||
BLI_bvhtree_ray_cast(treedata->tree, ray_start_local, ray_normal_local, 0.0f,
|
treedata->tree, ray_start_local, ray_normal_local, 0.0f,
|
||||||
&hit, treedata->raycast_callback, treedata) != -1)
|
*ray_depth, raycast_all_cb, &data);
|
||||||
{
|
|
||||||
hit.dist += len_diff;
|
|
||||||
hit.dist /= local_scale;
|
|
||||||
if (hit.dist <= *ray_depth) {
|
|
||||||
*ray_depth = hit.dist;
|
|
||||||
copy_v3_v3(r_loc, hit.co);
|
|
||||||
copy_v3_v3(r_no, hit.no);
|
|
||||||
|
|
||||||
/* back to worldspace */
|
retval = data.retval;
|
||||||
mul_m4_v3(obmat, r_loc);
|
}
|
||||||
mul_m3_v3(timat, r_no);
|
else {
|
||||||
normalize_v3(r_no);
|
BVHTreeRayHit hit;
|
||||||
|
|
||||||
retval = true;
|
hit.index = -1;
|
||||||
|
hit.dist = local_depth;
|
||||||
|
|
||||||
if (r_index) {
|
if (treedata->tree &&
|
||||||
*r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]);
|
BLI_bvhtree_ray_cast(
|
||||||
|
treedata->tree, ray_start_local, ray_normal_local, 0.0f,
|
||||||
|
&hit, treedata->raycast_callback, treedata) != -1)
|
||||||
|
{
|
||||||
|
hit.dist += len_diff;
|
||||||
|
hit.dist /= local_scale;
|
||||||
|
if (hit.dist <= *ray_depth) {
|
||||||
|
*ray_depth = hit.dist;
|
||||||
|
copy_v3_v3(r_loc, hit.co);
|
||||||
|
copy_v3_v3(r_no, hit.no);
|
||||||
|
|
||||||
|
/* back to worldspace */
|
||||||
|
mul_m4_v3(obmat, r_loc);
|
||||||
|
mul_m3_v3(timat, r_no);
|
||||||
|
normalize_v3(r_no);
|
||||||
|
|
||||||
|
retval = true;
|
||||||
|
|
||||||
|
if (r_index) {
|
||||||
|
*r_index = dm_looptri_to_poly_index(dm, &treedata->looptri[hit.index]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -814,8 +946,10 @@ static bool snapEditMesh(
|
|||||||
SnapObjectContext *sctx,
|
SnapObjectContext *sctx,
|
||||||
Object *ob, BMEditMesh *em, float obmat[4][4],
|
Object *ob, BMEditMesh *em, float obmat[4][4],
|
||||||
const float mval[2], float *dist_px, const short snap_to,
|
const float mval[2], float *dist_px, const short snap_to,
|
||||||
const float ray_start[3], const float ray_normal[3], const float ray_origin[3], float *ray_depth,
|
const float ray_start[3], const float ray_normal[3], const float ray_origin[3],
|
||||||
float r_loc[3], float r_no[3], int *r_index)
|
float *ray_depth, const unsigned int ob_index,
|
||||||
|
float r_loc[3], float r_no[3], int *r_index,
|
||||||
|
ListBase *r_hit_list)
|
||||||
{
|
{
|
||||||
ARegion *ar = sctx->v3d_data.ar;
|
ARegion *ar = sctx->v3d_data.ar;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
@@ -951,7 +1085,7 @@ static bool snapEditMesh(
|
|||||||
*/
|
*/
|
||||||
len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
|
len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */
|
||||||
madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local,
|
madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local,
|
||||||
len_diff - len_v3v3(ray_start_local, ray_org_local));
|
len_diff - len_v3v3(ray_start_local, ray_org_local));
|
||||||
local_depth -= len_diff;
|
local_depth -= len_diff;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -961,32 +1095,55 @@ static bool snapEditMesh(
|
|||||||
switch (snap_to) {
|
switch (snap_to) {
|
||||||
case SCE_SNAP_MODE_FACE:
|
case SCE_SNAP_MODE_FACE:
|
||||||
{
|
{
|
||||||
BVHTreeRayHit hit;
|
if (r_hit_list) {
|
||||||
|
struct RayCastAll_Data data;
|
||||||
|
|
||||||
hit.index = -1;
|
data.bvhdata = treedata;
|
||||||
hit.dist = local_depth;
|
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.dm = NULL;
|
||||||
|
data.hit_list = r_hit_list;
|
||||||
|
data.retval = retval;
|
||||||
|
|
||||||
if (treedata->tree &&
|
BLI_bvhtree_ray_cast_all(
|
||||||
BLI_bvhtree_ray_cast(
|
treedata->tree, ray_start_local, ray_normal_local, 0.0f,
|
||||||
treedata->tree, ray_start_local, ray_normal_local, 0.0f,
|
*ray_depth, raycast_all_cb, &data);
|
||||||
&hit, treedata->raycast_callback, treedata) != -1)
|
|
||||||
{
|
|
||||||
hit.dist += len_diff;
|
|
||||||
hit.dist /= local_scale;
|
|
||||||
if (hit.dist <= *ray_depth) {
|
|
||||||
*ray_depth = hit.dist;
|
|
||||||
copy_v3_v3(r_loc, hit.co);
|
|
||||||
copy_v3_v3(r_no, hit.no);
|
|
||||||
|
|
||||||
/* back to worldspace */
|
retval = data.retval;
|
||||||
mul_m4_v3(obmat, r_loc);
|
}
|
||||||
mul_m3_v3(timat, r_no);
|
else {
|
||||||
normalize_v3(r_no);
|
BVHTreeRayHit hit;
|
||||||
|
|
||||||
retval = true;
|
hit.index = -1;
|
||||||
|
hit.dist = local_depth;
|
||||||
|
|
||||||
if (r_index) {
|
if (treedata->tree &&
|
||||||
*r_index = hit.index;
|
BLI_bvhtree_ray_cast(
|
||||||
|
treedata->tree, ray_start_local, ray_normal_local, 0.0f,
|
||||||
|
&hit, treedata->raycast_callback, treedata) != -1)
|
||||||
|
{
|
||||||
|
hit.dist += len_diff;
|
||||||
|
hit.dist /= local_scale;
|
||||||
|
if (hit.dist <= *ray_depth) {
|
||||||
|
*ray_depth = hit.dist;
|
||||||
|
copy_v3_v3(r_loc, hit.co);
|
||||||
|
copy_v3_v3(r_no, hit.no);
|
||||||
|
|
||||||
|
/* back to worldspace */
|
||||||
|
mul_m4_v3(obmat, r_loc);
|
||||||
|
mul_m3_v3(timat, r_no);
|
||||||
|
normalize_v3(r_no);
|
||||||
|
|
||||||
|
retval = true;
|
||||||
|
|
||||||
|
if (r_index) {
|
||||||
|
*r_index = hit.index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1050,11 +1207,13 @@ static bool snapEditMesh(
|
|||||||
static bool snapObject(
|
static bool snapObject(
|
||||||
SnapObjectContext *sctx,
|
SnapObjectContext *sctx,
|
||||||
Object *ob, float obmat[4][4], bool use_obedit, const short snap_to,
|
Object *ob, float obmat[4][4], bool use_obedit, const short snap_to,
|
||||||
const float mval[2], float *dist_px,
|
const float mval[2], float *dist_px, const unsigned int ob_index,
|
||||||
const float ray_start[3], const float ray_normal[3], const float ray_origin[3], float *ray_depth,
|
const float ray_start[3], const float ray_normal[3], const float ray_origin[3],
|
||||||
|
float *ray_depth,
|
||||||
/* return args */
|
/* return args */
|
||||||
float r_loc[3], float r_no[3], int *r_index,
|
float r_loc[3], float r_no[3], int *r_index,
|
||||||
Object **r_ob, float r_obmat[4][4])
|
Object **r_ob, float r_obmat[4][4],
|
||||||
|
ListBase *r_hit_list)
|
||||||
{
|
{
|
||||||
ARegion *ar = sctx->v3d_data.ar;
|
ARegion *ar = sctx->v3d_data.ar;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
@@ -1066,8 +1225,10 @@ static bool snapObject(
|
|||||||
em = BKE_editmesh_from_object(ob);
|
em = BKE_editmesh_from_object(ob);
|
||||||
retval = snapEditMesh(
|
retval = snapEditMesh(
|
||||||
sctx, ob, em, obmat, mval, dist_px, snap_to,
|
sctx, ob, em, obmat, mval, dist_px, snap_to,
|
||||||
ray_start, ray_normal, ray_origin, ray_depth,
|
ray_start, ray_normal, ray_origin,
|
||||||
r_loc, r_no, r_index);
|
ray_depth, ob_index,
|
||||||
|
r_loc, r_no, r_index,
|
||||||
|
r_hit_list);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* in this case we want the mesh from the editmesh, avoids stale data. see: T45978.
|
/* in this case we want the mesh from the editmesh, avoids stale data. see: T45978.
|
||||||
@@ -1082,8 +1243,9 @@ static bool snapObject(
|
|||||||
}
|
}
|
||||||
retval = snapDerivedMesh(
|
retval = snapDerivedMesh(
|
||||||
sctx, ob, dm, obmat, mval, dist_px, snap_to, true,
|
sctx, ob, dm, obmat, mval, dist_px, snap_to, true,
|
||||||
ray_start, ray_normal, ray_origin, ray_depth,
|
ray_start, ray_normal, ray_origin,
|
||||||
r_loc, r_no, r_index);
|
ray_depth, ob_index,
|
||||||
|
r_loc, r_no, r_index, r_hit_list);
|
||||||
|
|
||||||
dm->release(dm);
|
dm->release(dm);
|
||||||
}
|
}
|
||||||
@@ -1132,19 +1294,22 @@ static bool snapObjectsRay(
|
|||||||
const float ray_start[3], const float ray_normal[3], const float ray_origin[3], float *ray_depth,
|
const float ray_start[3], const float ray_normal[3], const float ray_origin[3], float *ray_depth,
|
||||||
/* return args */
|
/* return args */
|
||||||
float r_loc[3], float r_no[3], int *r_index,
|
float r_loc[3], float r_no[3], int *r_index,
|
||||||
Object **r_ob, float r_obmat[4][4])
|
Object **r_ob, float r_obmat[4][4],
|
||||||
|
ListBase *r_hit_list)
|
||||||
{
|
{
|
||||||
Base *base;
|
Base *base;
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
bool snap_obedit_first = snap_select == SNAP_ALL && obedit;
|
||||||
|
unsigned int ob_index = 0;
|
||||||
|
|
||||||
if (snap_select == SNAP_ALL && obedit) {
|
if (snap_obedit_first) {
|
||||||
Object *ob = obedit;
|
Object *ob = obedit;
|
||||||
|
|
||||||
retval |= snapObject(
|
retval |= snapObject(
|
||||||
sctx, ob, ob->obmat, true, snap_to,
|
sctx, ob, ob->obmat, true, snap_to,
|
||||||
mval, dist_px,
|
mval, dist_px, ob_index++,
|
||||||
ray_start, ray_normal, ray_origin, ray_depth,
|
ray_start, ray_normal, ray_origin, ray_depth,
|
||||||
r_loc, r_no, r_index, r_ob, r_obmat);
|
r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA
|
/* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA
|
||||||
@@ -1157,9 +1322,9 @@ static bool snapObjectsRay(
|
|||||||
Object *ob = base->object;
|
Object *ob = base->object;
|
||||||
retval |= snapObject(
|
retval |= snapObject(
|
||||||
sctx, ob, ob->obmat, false, snap_to,
|
sctx, ob, ob->obmat, false, snap_to,
|
||||||
mval, dist_px,
|
mval, dist_px, ob_index++,
|
||||||
ray_start, ray_normal, ray_origin, ray_depth,
|
ray_start, ray_normal, ray_origin, ray_depth,
|
||||||
r_loc, r_no, r_index, r_ob, r_obmat);
|
r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (base = sctx->scene->base.first; base != NULL; base = base->next) {
|
for (base = sctx->scene->base.first; base != NULL; base = base->next) {
|
||||||
@@ -1173,12 +1338,6 @@ static bool snapObjectsRay(
|
|||||||
Object *ob_snap = ob;
|
Object *ob_snap = ob;
|
||||||
bool use_obedit = false;
|
bool use_obedit = false;
|
||||||
|
|
||||||
/* for linked objects, use the same object but a different matrix */
|
|
||||||
if (obedit && ob->data == obedit->data) {
|
|
||||||
use_obedit = true;
|
|
||||||
ob_snap = obedit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ob->transflag & OB_DUPLI) {
|
if (ob->transflag & OB_DUPLI) {
|
||||||
DupliObject *dupli_ob;
|
DupliObject *dupli_ob;
|
||||||
ListBase *lb = object_duplilist(sctx->bmain->eval_ctx, sctx->scene, ob);
|
ListBase *lb = object_duplilist(sctx->bmain->eval_ctx, sctx->scene, ob);
|
||||||
@@ -1189,19 +1348,33 @@ static bool snapObjectsRay(
|
|||||||
|
|
||||||
retval |= snapObject(
|
retval |= snapObject(
|
||||||
sctx, dupli_snap, dupli_ob->mat, use_obedit_dupli, snap_to,
|
sctx, dupli_snap, dupli_ob->mat, use_obedit_dupli, snap_to,
|
||||||
mval, dist_px,
|
mval, dist_px, ob_index++,
|
||||||
ray_start, ray_normal, ray_origin, ray_depth,
|
ray_start, ray_normal, ray_origin, ray_depth,
|
||||||
r_loc, r_no, r_index, r_ob, r_obmat);
|
r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
free_object_duplilist(lb);
|
free_object_duplilist(lb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (obedit) {
|
||||||
|
if ((ob == obedit) &&
|
||||||
|
(snap_obedit_first || (snap_select == SNAP_NOT_OBEDIT)))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ob->data == obedit->data) {
|
||||||
|
/* for linked objects, use the same object but a different matrix */
|
||||||
|
use_obedit = true;
|
||||||
|
ob_snap = obedit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
retval |= snapObject(
|
retval |= snapObject(
|
||||||
sctx, ob_snap, ob->obmat, use_obedit, snap_to,
|
sctx, ob_snap, ob->obmat, use_obedit, snap_to,
|
||||||
mval, dist_px,
|
mval, dist_px, ob_index++,
|
||||||
ray_start, ray_normal, ray_origin, ray_depth,
|
ray_start, ray_normal, ray_origin, ray_depth,
|
||||||
r_loc, r_no, r_index, r_ob, r_obmat);
|
r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1315,7 +1488,53 @@ bool ED_transform_snap_object_project_ray_ex(
|
|||||||
base_act, obedit,
|
base_act, obedit,
|
||||||
ray_start, ray_normal, ray_start, ray_depth,
|
ray_start, ray_normal, ray_start, ray_depth,
|
||||||
r_loc, r_no, r_index,
|
r_loc, r_no, r_index,
|
||||||
r_ob, r_obmat);
|
r_ob, r_obmat, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill in a list of all hits.
|
||||||
|
*
|
||||||
|
* \param ray_depth: Only depths in this range are considered, -1.0 for maximum.
|
||||||
|
* \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)
|
||||||
|
{
|
||||||
|
Base *base_act = params->use_object_active ? sctx->scene->basact : NULL;
|
||||||
|
Object *obedit = params->use_object_edit ? sctx->scene->obedit : NULL;
|
||||||
|
|
||||||
|
if (ray_depth == -1.0f) {
|
||||||
|
ray_depth = BVH_RAYCAST_DIST_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
float ray_depth_prev = ray_depth;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool retval = snapObjectsRay(
|
||||||
|
sctx,
|
||||||
|
params->snap_select, params->snap_to,
|
||||||
|
NULL, NULL,
|
||||||
|
base_act, obedit,
|
||||||
|
ray_start, ray_normal, ray_start, &ray_depth,
|
||||||
|
NULL, NULL, NULL, NULL, NULL,
|
||||||
|
r_hit_list);
|
||||||
|
|
||||||
|
/* meant to be readonly for 'all' hits, ensure it is */
|
||||||
|
#ifdef DEBUG
|
||||||
|
BLI_assert(ray_depth_prev == ray_depth);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (sort) {
|
||||||
|
BLI_listbase_sort(r_hit_list, hit_depth_cmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1327,7 +1546,7 @@ bool ED_transform_snap_object_project_ray_ex(
|
|||||||
*/
|
*/
|
||||||
static bool transform_snap_context_project_ray_impl(
|
static bool transform_snap_context_project_ray_impl(
|
||||||
SnapObjectContext *sctx,
|
SnapObjectContext *sctx,
|
||||||
const float ray_start[3], const float ray_normal[3], float *ray_dist,
|
const float ray_start[3], const float ray_normal[3], float *ray_depth,
|
||||||
float r_co[3], float r_no[3])
|
float r_co[3], float r_no[3])
|
||||||
{
|
{
|
||||||
bool ret;
|
bool ret;
|
||||||
@@ -1340,7 +1559,7 @@ static bool transform_snap_context_project_ray_impl(
|
|||||||
.snap_to = SCE_SNAP_MODE_FACE,
|
.snap_to = SCE_SNAP_MODE_FACE,
|
||||||
.use_object_edit = (sctx->scene->obedit != NULL),
|
.use_object_edit = (sctx->scene->obedit != NULL),
|
||||||
},
|
},
|
||||||
ray_start, ray_normal, ray_dist,
|
ray_start, ray_normal, ray_depth,
|
||||||
r_co, r_no, NULL,
|
r_co, r_no, NULL,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
|
|
||||||
@@ -1349,13 +1568,13 @@ static bool transform_snap_context_project_ray_impl(
|
|||||||
|
|
||||||
bool ED_transform_snap_object_project_ray(
|
bool ED_transform_snap_object_project_ray(
|
||||||
SnapObjectContext *sctx,
|
SnapObjectContext *sctx,
|
||||||
const float ray_origin[3], const float ray_direction[3], float *ray_dist,
|
const float ray_origin[3], const float ray_direction[3], float *ray_depth,
|
||||||
float r_co[3], float r_no[3])
|
float r_co[3], float r_no[3])
|
||||||
{
|
{
|
||||||
float ray_dist_fallback;
|
float ray_depth_fallback;
|
||||||
if (ray_dist == NULL) {
|
if (ray_depth == NULL) {
|
||||||
ray_dist_fallback = BVH_RAYCAST_DIST_MAX;
|
ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
|
||||||
ray_dist = &ray_dist_fallback;
|
ray_depth = &ray_depth_fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
float no_fallback[3];
|
float no_fallback[3];
|
||||||
@@ -1365,7 +1584,7 @@ bool ED_transform_snap_object_project_ray(
|
|||||||
|
|
||||||
return transform_snap_context_project_ray_impl(
|
return transform_snap_context_project_ray_impl(
|
||||||
sctx,
|
sctx,
|
||||||
ray_origin, ray_direction, ray_dist,
|
ray_origin, ray_direction, ray_depth,
|
||||||
r_co, r_no);
|
r_co, r_no);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1376,7 +1595,7 @@ static bool transform_snap_context_project_view3d_mixed_impl(
|
|||||||
bool use_depth,
|
bool use_depth,
|
||||||
float r_co[3], float r_no[3])
|
float r_co[3], float r_no[3])
|
||||||
{
|
{
|
||||||
float ray_dist = BVH_RAYCAST_DIST_MAX;
|
float ray_depth = BVH_RAYCAST_DIST_MAX;
|
||||||
bool is_hit = false;
|
bool is_hit = false;
|
||||||
|
|
||||||
float r_no_dummy[3];
|
float r_no_dummy[3];
|
||||||
@@ -1394,7 +1613,7 @@ static bool transform_snap_context_project_view3d_mixed_impl(
|
|||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
if ((params->snap_to_flag & (1 << i)) && (is_hit == false || use_depth)) {
|
if ((params->snap_to_flag & (1 << i)) && (is_hit == false || use_depth)) {
|
||||||
if (use_depth == false) {
|
if (use_depth == false) {
|
||||||
ray_dist = BVH_RAYCAST_DIST_MAX;
|
ray_depth = BVH_RAYCAST_DIST_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
params_temp.snap_to = elem_type[i];
|
params_temp.snap_to = elem_type[i];
|
||||||
@@ -1402,7 +1621,7 @@ static bool transform_snap_context_project_view3d_mixed_impl(
|
|||||||
if (ED_transform_snap_object_project_view3d(
|
if (ED_transform_snap_object_project_view3d(
|
||||||
sctx,
|
sctx,
|
||||||
¶ms_temp,
|
¶ms_temp,
|
||||||
mval, dist_px, &ray_dist,
|
mval, dist_px, &ray_depth,
|
||||||
r_co, r_no))
|
r_co, r_no))
|
||||||
{
|
{
|
||||||
is_hit = true;
|
is_hit = true;
|
||||||
@@ -1470,7 +1689,7 @@ bool ED_transform_snap_object_project_view3d_ex(
|
|||||||
mval, dist_px,
|
mval, dist_px,
|
||||||
base_act, obedit,
|
base_act, obedit,
|
||||||
ray_start, ray_normal, ray_orgigin, ray_depth,
|
ray_start, ray_normal, ray_orgigin, ray_depth,
|
||||||
r_loc, r_no, r_index, NULL, NULL);
|
r_loc, r_no, r_index, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ED_transform_snap_object_project_view3d(
|
bool ED_transform_snap_object_project_view3d(
|
||||||
@@ -1488,4 +1707,32 @@ bool ED_transform_snap_object_project_view3d(
|
|||||||
r_loc, r_no, NULL);
|
r_loc, r_no, 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)
|
||||||
|
{
|
||||||
|
float ray_start[3], ray_normal[3];
|
||||||
|
|
||||||
|
BLI_assert(params->snap_to == SCE_SNAP_MODE_FACE);
|
||||||
|
|
||||||
|
if (!ED_view3d_win_to_ray_ex(
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
Reference in New Issue
Block a user