UI: Asset Shelf (Experimental Feature) #104831

Closed
Julian Eisel wants to merge 399 commits from asset-shelf into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
12 changed files with 860 additions and 956 deletions
Showing only changes of commit 7bca31aeab - Show all commits

View File

@ -360,6 +360,7 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
info.has_nanovdb = true;
info.has_light_tree = true;
info.has_mnee = true;
info.has_osl = true;
info.has_guiding = true;
info.has_profiling = true;
@ -409,6 +410,7 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
/* Accumulate device info. */
info.has_nanovdb &= device.has_nanovdb;
info.has_light_tree &= device.has_light_tree;
info.has_mnee &= device.has_mnee;
info.has_osl &= device.has_osl;
info.has_guiding &= device.has_guiding;
info.has_profiling &= device.has_profiling;

View File

@ -76,6 +76,7 @@ class DeviceInfo {
bool display_device; /* GPU is used as a display device. */
bool has_nanovdb; /* Support NanoVDB volumes. */
bool has_light_tree; /* Support light tree. */
bool has_mnee; /* Support MNEE. */
bool has_osl; /* Support Open Shading Language. */
bool has_guiding; /* Support path guiding. */
bool has_profiling; /* Supports runtime collection of profiling info. */
@ -98,6 +99,7 @@ class DeviceInfo {
display_device = false;
has_nanovdb = false;
has_light_tree = true;
has_mnee = true;
has_osl = false;
has_guiding = false;
has_profiling = false;

View File

@ -156,6 +156,7 @@ void device_hip_info(vector<DeviceInfo> &devices)
info.has_nanovdb = true;
info.has_light_tree = true;
info.has_mnee = true;
info.denoisers = 0;
info.has_gpu_queue = true;

View File

@ -60,6 +60,7 @@ void device_metal_info(vector<DeviceInfo> &devices)
info.has_nanovdb = vendor == METAL_GPU_APPLE;
info.has_light_tree = vendor != METAL_GPU_AMD;
info.has_mnee = vendor != METAL_GPU_AMD;
info.use_hardware_raytracing = vendor != METAL_GPU_INTEL;
if (info.use_hardware_raytracing) {

View File

@ -85,11 +85,6 @@ CCL_NAMESPACE_BEGIN
#define __VISIBILITY_FLAG__
#define __VOLUME__
/* TODO: solve internal compiler perf issue and enable light tree on Metal/AMD. */
#if defined(__KERNEL_METAL_AMD__)
# undef __LIGHT_TREE__
#endif
/* Device specific features */
#ifdef WITH_OSL
# define __OSL__
@ -111,6 +106,13 @@ CCL_NAMESPACE_BEGIN
# define __MNEE__
#endif
#if defined(__KERNEL_METAL_AMD__)
/* Disabled due to internal compiler perf issue and enable light tree on Metal/AMD. */
# undef __LIGHT_TREE__
/* Disabled due to compiler crash on Metal/AMD. */
# undef __MNEE__
#endif
/* Scene-based selective features compilation. */
#ifdef __KERNEL_FEATURES__
# if !(__KERNEL_FEATURES & KERNEL_FEATURE_OBJECT_MOTION)

View File

@ -819,7 +819,65 @@ static bool fcurve_can_use_simple_bezt_drawing(FCurve *fcu)
return true;
}
/* helper func - draw one repeat of an F-Curve (using Bezier curve approximations) */
static int calculate_bezt_draw_resolution(BezTriple *bezt,
BezTriple *prevbezt,
const int max_bez_resolution,
const bool is_driver)
{
if (is_driver) {
return max_bez_resolution;
}
const int resolution = (int)(5.0f * len_v2v2(bezt->vec[1], prevbezt->vec[1]));
/* NOTE: higher values will crash */
/* TODO: view scale should factor into this someday too... */
return min_ii(resolution, max_bez_resolution);
}
/** Draw a segment from \param prevbezt to \param bezt at the given \param resolution.
* immBeginAtMost is expected to be called with enough space for this function to run.
*/
static void draw_bezt(BezTriple *bezt, BezTriple *prevbezt, int resolution, uint pos)
{
float prev_key[2], prev_handle[2], bez_handle[2], bez_key[2];
float data[120];
if (resolution < 2) {
prev_key[0] = prevbezt->vec[1][0];
prev_key[1] = prevbezt->vec[1][1];
immVertex2fv(pos, prev_key);
return;
}
prev_key[0] = prevbezt->vec[1][0];
prev_key[1] = prevbezt->vec[1][1];
prev_handle[0] = prevbezt->vec[2][0];
prev_handle[1] = prevbezt->vec[2][1];
bez_handle[0] = bezt->vec[0][0];
bez_handle[1] = bezt->vec[0][1];
bez_key[0] = bezt->vec[1][0];
bez_key[1] = bezt->vec[1][1];
BKE_fcurve_correct_bezpart(prev_key, prev_handle, bez_handle, bez_key);
BKE_curve_forward_diff_bezier(
prev_key[0], prev_handle[0], bez_handle[0], bez_key[0], data, resolution, sizeof(float[3]));
BKE_curve_forward_diff_bezier(prev_key[1],
prev_handle[1],
bez_handle[1],
bez_key[1],
data + 1,
resolution,
sizeof(float[3]));
for (float *fp = data; resolution; resolution--, fp += 3) {
immVertex2fv(pos, fp);
}
}
/* Helper function - draw one repeat of an F-Curve (using Bezier curve approximations). */
static void draw_fcurve_curve_bezts(
bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, uint pos, const bool draw_extrapolation)
{
@ -827,178 +885,136 @@ static void draw_fcurve_curve_bezts(
return;
}
BezTriple *prevbezt = fcu->bezt;
BezTriple *bezt = prevbezt + 1;
float v1[2], v2[2], v3[2], v4[2];
float *fp, data[120];
float fac = 0.0f;
int b = fcu->totvert - 1;
int resol;
float unit_scale, offset;
short mapping_flag = ANIM_get_normalization_flags(ac);
/* apply unit mapping */
/* Apply unit mapping. */
GPU_matrix_push();
unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
float offset;
short mapping_flag = ANIM_get_normalization_flags(ac);
const float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
GPU_matrix_scale_2f(1.0f, unit_scale);
GPU_matrix_translate_2f(0.0f, offset);
/* For now, this assumes the worst case scenario, where all the keyframes have
* bezier interpolation, and are drawn at full res.
* This is tricky to optimize, but maybe can be improved at some point... */
immBeginAtMost(GPU_PRIM_LINE_STRIP, (b * 32 + 3));
int b = fcu->totvert - 1;
const int max_bezt_resolution = 32;
immBeginAtMost(GPU_PRIM_LINE_STRIP, (b * max_bezt_resolution + 3));
/* extrapolate to left? */
BezTriple *prevbezt = fcu->bezt;
BezTriple *bezt = prevbezt + 1;
float vertex_position[2];
float fac = 0.0f;
/* Extrapolate to the left? */
if (draw_extrapolation && prevbezt->vec[1][0] > v2d->cur.xmin) {
/* left-side of view comes before first keyframe, so need to extend as not cyclic */
v1[0] = v2d->cur.xmin;
vertex_position[0] = v2d->cur.xmin;
/* y-value depends on the interpolation */
if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (prevbezt->ipo == BEZT_IPO_CONST) ||
(prevbezt->ipo == BEZT_IPO_LIN && fcu->totvert == 1))
{
/* just extend across the first keyframe's value */
v1[1] = prevbezt->vec[1][1];
vertex_position[1] = prevbezt->vec[1][1];
}
else if (prevbezt->ipo == BEZT_IPO_LIN) {
/* extrapolate linear doesn't use the handle, use the next points center instead */
fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - vertex_position[0]);
if (fac) {
fac = 1.0f / fac;
}
v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]);
vertex_position[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]);
}
else {
/* based on angle of handle 1 (relative to keyframe) */
fac = (prevbezt->vec[0][0] - prevbezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
fac = (prevbezt->vec[0][0] - prevbezt->vec[1][0]) /
(prevbezt->vec[1][0] - vertex_position[0]);
if (fac) {
fac = 1.0f / fac;
}
v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[0][1] - prevbezt->vec[1][1]);
vertex_position[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[0][1] - prevbezt->vec[1][1]);
}
immVertex2fv(pos, v1);
immVertex2fv(pos, vertex_position);
}
/* if only one keyframe, add it now */
/* If only one keyframe, add it now. */
if (fcu->totvert == 1) {
v1[0] = prevbezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
immVertex2fv(pos, v1);
vertex_position[0] = prevbezt->vec[1][0];
vertex_position[1] = prevbezt->vec[1][1];
immVertex2fv(pos, vertex_position);
}
/* draw curve between first and last keyframe (if there are enough to do so) */
/* Draw curve between first and last keyframe (if there are enough to do so). */
/* TODO: optimize this to not have to calc stuff out of view too? */
while (b--) {
if (prevbezt->ipo == BEZT_IPO_CONST) {
/* Constant-Interpolation: draw segment between previous keyframe and next,
* but holding same value */
v1[0] = prevbezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
immVertex2fv(pos, v1);
vertex_position[0] = prevbezt->vec[1][0];
vertex_position[1] = prevbezt->vec[1][1];
immVertex2fv(pos, vertex_position);
v1[0] = bezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
immVertex2fv(pos, v1);
vertex_position[0] = bezt->vec[1][0];
vertex_position[1] = prevbezt->vec[1][1];
immVertex2fv(pos, vertex_position);
}
else if (prevbezt->ipo == BEZT_IPO_LIN) {
/* Linear interpolation: just add one point (which should add a new line segment) */
v1[0] = prevbezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
immVertex2fv(pos, v1);
vertex_position[0] = prevbezt->vec[1][0];
vertex_position[1] = prevbezt->vec[1][1];
immVertex2fv(pos, vertex_position);
}
else if (prevbezt->ipo == BEZT_IPO_BEZ) {
/* Bezier-Interpolation: draw curve as series of segments between keyframes
* - resol determines number of points to sample in between keyframes
*/
/* resol depends on distance between points
* (not just horizontal) OR is a fixed high res */
/* TODO: view scale should factor into this someday too... */
if (fcu->driver) {
resol = 32;
}
else {
resol = (int)(5.0f * len_v2v2(bezt->vec[1], prevbezt->vec[1]));
}
if (resol < 2) {
/* only draw one */
v1[0] = prevbezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
immVertex2fv(pos, v1);
}
else {
/* clamp resolution to max of 32 */
/* NOTE: higher values will crash */
if (resol > 32) {
resol = 32;
}
v1[0] = prevbezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
v2[0] = prevbezt->vec[2][0];
v2[1] = prevbezt->vec[2][1];
v3[0] = bezt->vec[0][0];
v3[1] = bezt->vec[0][1];
v4[0] = bezt->vec[1][0];
v4[1] = bezt->vec[1][1];
BKE_fcurve_correct_bezpart(v1, v2, v3, v4);
BKE_curve_forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float[3]));
BKE_curve_forward_diff_bezier(
v1[1], v2[1], v3[1], v4[1], data + 1, resol, sizeof(float[3]));
for (fp = data; resol; resol--, fp += 3) {
immVertex2fv(pos, fp);
}
}
int resolution = calculate_bezt_draw_resolution(
bezt, prevbezt, max_bezt_resolution, fcu->driver != NULL);
draw_bezt(bezt, prevbezt, resolution, pos);
}
/* get next pointers */
/* Get next pointers. */
prevbezt = bezt;
bezt++;
/* last point? */
/* Last point? */
if (b == 0) {
v1[0] = prevbezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
immVertex2fv(pos, v1);
vertex_position[0] = prevbezt->vec[1][0];
vertex_position[1] = prevbezt->vec[1][1];
immVertex2fv(pos, vertex_position);
}
}
/* extrapolate to right? (see code for left-extrapolation above too) */
/* Extrapolate to the right? (see code for left-extrapolation above too) */
if (draw_extrapolation && prevbezt->vec[1][0] < v2d->cur.xmax) {
v1[0] = v2d->cur.xmax;
vertex_position[0] = v2d->cur.xmax;
/* y-value depends on the interpolation */
/* y-value depends on the interpolation. */
if ((fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) || (fcu->flag & FCURVE_INT_VALUES) ||
(prevbezt->ipo == BEZT_IPO_CONST) || (prevbezt->ipo == BEZT_IPO_LIN && fcu->totvert == 1))
{
/* based on last keyframe's value */
v1[1] = prevbezt->vec[1][1];
vertex_position[1] = prevbezt->vec[1][1];
}
else if (prevbezt->ipo == BEZT_IPO_LIN) {
/* extrapolate linear doesn't use the handle, use the previous points center instead */
/* Extrapolate linear doesn't use the handle, use the previous points center instead. */
bezt = prevbezt - 1;
fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
fac = (prevbezt->vec[1][0] - bezt->vec[1][0]) / (prevbezt->vec[1][0] - vertex_position[0]);
if (fac) {
fac = 1.0f / fac;
}
v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]);
vertex_position[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[1][1] - bezt->vec[1][1]);
}
else {
/* based on angle of handle 1 (relative to keyframe) */
fac = (prevbezt->vec[2][0] - prevbezt->vec[1][0]) / (prevbezt->vec[1][0] - v1[0]);
/* Based on angle of handle 1 (relative to keyframe). */
fac = (prevbezt->vec[2][0] - prevbezt->vec[1][0]) /
(prevbezt->vec[1][0] - vertex_position[0]);
if (fac) {
fac = 1.0f / fac;
}
v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[2][1] - prevbezt->vec[1][1]);
vertex_position[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[2][1] - prevbezt->vec[1][1]);
}
immVertex2fv(pos, v1);
immVertex2fv(pos, vertex_position);
}
immEnd();

View File

@ -39,6 +39,7 @@ struct SnapSouceCustomData {
void *customdata_mode_prev;
eSnapTargetOP target_operation_prev;
eSnapMode snap_mode_confirm;
struct {
void (*apply)(TransInfo *t, MouseInput *mi, const double mval[2], float output[3]);
@ -76,6 +77,9 @@ static void snapsource_confirm(TransInfo *t)
t->tsnap.status |= SNAP_SOURCE_FOUND;
t->flag |= T_DRAW_SNAP_SOURCE;
struct SnapSouceCustomData *customdata = t->custom.mode.data;
t->tsnap.mode = customdata->snap_mode_confirm;
int mval[2];
#ifndef RESET_TRANSFORMATION
if (true) {
@ -183,10 +187,17 @@ void transform_mode_snap_source_init(TransInfo *t, wmOperator *UNUSED(op))
t->tsnap.target_operation = SCE_SNAP_TARGET_ALL;
t->tsnap.status &= ~SNAP_SOURCE_FOUND;
customdata->snap_mode_confirm = t->tsnap.mode;
t->tsnap.mode &= ~(SCE_SNAP_MODE_EDGE_PERPENDICULAR);
if ((t->tsnap.mode & ~(SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) == 0) {
/* Initialize snap modes for geometry. */
t->tsnap.mode &= ~(SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID);
t->tsnap.mode |= SCE_SNAP_MODE_GEOM;
if (!(customdata->snap_mode_confirm & SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
customdata->snap_mode_confirm = t->tsnap.mode;
}
}
if (t->data_type == &TransConvertType_Mesh) {

View File

@ -1390,7 +1390,8 @@ eSnapMode snapObjectsTransform(
snap_object_params.use_occlusion_test = true;
snap_object_params.use_backface_culling = (t->tsnap.flag & SCE_SNAP_BACKFACE_CULLING) != 0;
float *prev_co = (t->tsnap.status & SNAP_SOURCE_FOUND) ? t->tsnap.snap_source : nullptr;
float *prev_co = (t->tsnap.status & SNAP_SOURCE_FOUND) ? t->tsnap.snap_source : t->center_global;
return ED_transform_snap_object_project_view3d(t->tsnap.object_context,
t->depsgraph,
t->region,

File diff suppressed because it is too large Load Diff

View File

@ -10,12 +10,6 @@
#define MAX_CLIPPLANE_LEN 3
enum eViewProj {
VIEW_PROJ_NONE = -1,
VIEW_PROJ_ORTHO = 0,
VIEW_PROJ_PERSP = -1,
};
/* -------------------------------------------------------------------- */
/** \name Internal Data Types
* \{ */
@ -58,8 +52,6 @@ struct SnapData_EditMesh {
struct SnapObjectContext {
struct Scene *scene;
int flag;
blender::Map<const BMEditMesh *, std::unique_ptr<SnapData_EditMesh>> editmesh_caches;
/* Filter data, returns true to check this value */
@ -77,14 +69,27 @@ struct SnapObjectContext {
const ARegion *region;
const View3D *v3d;
eSnapMode snap_to_flag;
SnapObjectParams params;
float ray_start[3];
float ray_dir[3];
float mval[2];
float init_co[3];
float curr_co[3];
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;
eSnapMode snap_to_flag;
int clip_plane_len;
/* read/write */
uint object_index;
bool is_persp;
bool has_occlusion_plane; /* Ignore plane of occlusion in curves. */
bool use_occlusion_test_edit;
} runtime;
/* Output. */
@ -104,7 +109,8 @@ struct SnapObjectContext {
/* Snapped data. */
ID *data;
float dist_sq;
float ray_depth_max;
float dist_px_sq;
bool is_edit;
} ret;
@ -203,7 +209,6 @@ void cb_snap_edge(void *userdata,
BVHTreeNearest *nearest);
bool nearest_world_tree(SnapObjectContext *sctx,
const struct SnapObjectParams *params,
BVHTree *tree,
BVHTree_NearestPointCallback nearest_cb,
void *treedata,
@ -217,57 +222,20 @@ bool nearest_world_tree(SnapObjectContext *sctx,
/* transform_snap_object_editmesh.cc */
bool raycastEditMesh(SnapObjectContext *sctx,
const struct SnapObjectParams *params,
const float ray_start[3],
const float ray_dir[3],
Object *ob_eval,
BMEditMesh *em,
const float obmat[4][4],
const uint 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);
eSnapMode snap_object_editmesh(SnapObjectContext *sctx,
Object *ob_eval,
ID *id,
const float obmat[4][4],
eSnapMode snap_to_flag,
bool use_hide);
eSnapMode snap_polygon_editmesh(SnapObjectContext *sctx,
const SnapObjectParams *params,
BMEditMesh *em,
Object *ob_eval,
ID *id,
const float obmat[4][4],
float clip_planes_local[MAX_CLIPPLANE_LEN][4],
/* read/write args */
float *dist_px,
/* return args */
float r_loc[3],
float r_no[3],
int *r_index);
eSnapMode snapEditMesh(struct SnapObjectContext *sctx,
const struct SnapObjectParams *params,
struct Object *ob_eval,
struct BMEditMesh *em,
const float obmat[4][4],
/* read/write args */
float *dist_px,
/* return args */
float r_loc[3],
float r_no[3],
int *r_index);
bool nearest_world_editmesh(struct SnapObjectContext *sctx,
const struct SnapObjectParams *params,
struct Object *ob_eval,
struct BMEditMesh *em,
const float (*obmat)[4],
const float init_co[3],
const float curr_co[3],
float *r_dist_sq,
float *r_loc,
float *r_no,
int *r_index);
eSnapMode snap_to_flag,
int polygon,
const float clip_planes_local[MAX_CLIPPLANE_LEN][4]);
void nearest2d_data_init_editmesh(struct BMEditMesh *em,
bool is_persp,
@ -276,60 +244,22 @@ void nearest2d_data_init_editmesh(struct BMEditMesh *em,
/* transform_snap_object_mesh.cc */
bool raycastMesh(const struct SnapObjectParams *params,
const float ray_start[3],
const float ray_dir[3],
struct Object *ob_eval,
const struct Mesh *me_eval,
const float obmat[4][4],
const uint ob_index,
bool use_hide,
/* read/write args */
float *ray_depth,
/* return args */
float r_loc[3],
float r_no[3],
int *r_index,
struct ListBase *r_hit_list);
eSnapMode snap_object_mesh(SnapObjectContext *sctx,
Object *ob_eval,
ID *id,
const float obmat[4][4],
eSnapMode snap_to_flag,
bool use_hide);
bool nearest_world_mesh(SnapObjectContext *sctx,
const SnapObjectParams *params,
const Mesh *me_eval,
const float (*obmat)[4],
bool use_hide,
const float init_co[3],
const float curr_co[3],
float *r_dist_sq,
float *r_loc,
float *r_no,
int *r_index);
eSnapMode snap_polygon_mesh(SnapObjectContext *sctx,
Object *ob_eval,
ID *id,
const float obmat[4][4],
eSnapMode snap_to_flag,
int polygon,
const float clip_planes_local[MAX_CLIPPLANE_LEN][4]);
void nearest2d_data_init_mesh(const Mesh *mesh,
bool is_persp,
bool use_backface_culling,
Nearest2dUserData *r_nearest2d);
eSnapMode snap_polygon_mesh(SnapObjectContext *sctx,
const SnapObjectParams *params,
const Mesh *mesh,
const float obmat[4][4],
float clip_planes_local[MAX_CLIPPLANE_LEN][4],
/* read/write args */
float *dist_px,
/* return args */
float r_loc[3],
float r_no[3],
int *r_index);
eSnapMode snapMesh(SnapObjectContext *sctx,
const SnapObjectParams *params,
Object *ob_eval,
const Mesh *me_eval,
const float obmat[4][4],
bool use_hide,
/* read/write args */
float *dist_px,
/* return args */
float r_loc[3],
float r_no[3],
int *r_index);

View File

@ -66,9 +66,10 @@ static blender::bke::MeshRuntime *snap_object_data_editmesh_runtime_get(Object *
static SnapData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext *sctx,
Object *ob_eval,
BMEditMesh *em)
BMEditMesh *em,
const bool create)
{
SnapData_EditMesh *sod;
SnapData_EditMesh *sod = nullptr;
bool init = false;
if (std::unique_ptr<SnapData_EditMesh> *sod_p = sctx->editmesh_caches.lookup_ptr(em)) {
@ -114,7 +115,7 @@ static SnapData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext *sctx,
init = true;
}
}
else {
else if (create) {
std::unique_ptr<SnapData_EditMesh> sod_ptr = std::make_unique<SnapData_EditMesh>();
sod = sod_ptr.get();
sctx->editmesh_caches.add_new(em, std::move(sod_ptr));
@ -122,6 +123,9 @@ static SnapData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext *sctx,
}
if (init) {
/* Operators only update the editmesh looptris of the original mesh. */
BLI_assert(em == BKE_editmesh_from_object(DEG_get_original_object(ob_eval)));
sod->treedata_editmesh.em = em;
sod->mesh_runtime = snap_object_data_editmesh_runtime_get(ob_eval);
snap_editmesh_minmax(sctx, em->bm, sod->min, sod->max);
@ -130,18 +134,13 @@ static SnapData_EditMesh *snap_object_data_editmesh_get(SnapObjectContext *sctx,
return sod;
}
static BVHTreeFromEditMesh *snap_object_data_editmesh_treedata_get(SnapObjectContext *sctx,
Object *ob_eval,
static BVHTreeFromEditMesh *snap_object_data_editmesh_treedata_get(SnapData_EditMesh *sod,
SnapObjectContext *sctx,
BMEditMesh *em)
{
SnapData_EditMesh *sod = snap_object_data_editmesh_get(sctx, ob_eval, em);
BVHTreeFromEditMesh *treedata = &sod->treedata_editmesh;
if (treedata->tree == nullptr) {
/* Operators only update the editmesh looptris of the original mesh. */
BLI_assert(sod->treedata_editmesh.em ==
BKE_editmesh_from_object(DEG_get_original_object(ob_eval)));
em = sod->treedata_editmesh.em;
if (sctx->callbacks.edit_mesh.test_face_fn) {
@ -178,6 +177,50 @@ static BVHTreeFromEditMesh *snap_object_data_editmesh_treedata_get(SnapObjectCon
/** \} */
/* -------------------------------------------------------------------- */
/** \name Snap Object Data
* \{ */
static eSnapMode editmesh_snap_mode_supported(BMEditMesh *em)
{
eSnapMode snap_mode_supported = SCE_SNAP_MODE_NONE;
if (em->bm->totface) {
snap_mode_supported |= SCE_SNAP_MODE_FACE | SCE_SNAP_MODE_FACE_NEAREST;
}
if (em->bm->totedge) {
snap_mode_supported |= SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT |
SCE_SNAP_MODE_EDGE_PERPENDICULAR;
}
if (em->bm->totvert) {
snap_mode_supported |= SCE_SNAP_MODE_VERTEX;
}
return snap_mode_supported;
}
static SnapData_EditMesh *editmesh_snapdata_init(SnapObjectContext *sctx,
Object *ob_eval,
eSnapMode snap_to_flag)
{
BMEditMesh *em = BKE_editmesh_from_object(ob_eval);
if (em == nullptr) {
return nullptr;
}
SnapData_EditMesh *sod = snap_object_data_editmesh_get(sctx, ob_eval, em, false);
if (sod != nullptr) {
return sod;
}
eSnapMode snap_mode_used = snap_to_flag & editmesh_snap_mode_supported(em);
if (snap_mode_used == SCE_SNAP_MODE_NONE) {
return nullptr;
}
return snap_object_data_editmesh_get(sctx, ob_eval, em, true);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Ray Cast Functions
* \{ */
@ -212,26 +255,21 @@ static void editmesh_looptri_raycast_backface_culling_cb(void *userdata,
}
}
bool raycastEditMesh(SnapObjectContext *sctx,
const SnapObjectParams *params,
const float ray_start[3],
const float ray_dir[3],
Object *ob_eval,
BMEditMesh *em,
const float obmat[4][4],
const uint 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(SnapData_EditMesh *sod,
SnapObjectContext *sctx,
Object *ob_eval,
BMEditMesh *em,
const float obmat[4][4],
const uint 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;
}
float imat[4][4];
float ray_start_local[3], ray_normal_local[3];
@ -239,8 +277,8 @@ bool raycastEditMesh(SnapObjectContext *sctx,
invert_m4_m4(imat, obmat);
copy_v3_v3(ray_start_local, ray_start);
copy_v3_v3(ray_normal_local, ray_dir);
copy_v3_v3(ray_start_local, sctx->runtime.ray_start);
copy_v3_v3(ray_normal_local, sctx->runtime.ray_dir);
mul_m4_v3(imat, ray_start_local);
mul_mat3_m4_v3(imat, ray_normal_local);
@ -252,8 +290,6 @@ bool raycastEditMesh(SnapObjectContext *sctx,
local_depth *= local_scale;
}
SnapData_EditMesh *sod = snap_object_data_editmesh_get(sctx, ob_eval, em);
/* Test BoundBox */
/* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
@ -275,7 +311,7 @@ bool raycastEditMesh(SnapObjectContext *sctx,
len_diff = 0.0f;
}
BVHTreeFromEditMesh *treedata = snap_object_data_editmesh_treedata_get(sctx, ob_eval, em);
BVHTreeFromEditMesh *treedata = snap_object_data_editmesh_treedata_get(sod, sctx, em);
if (treedata == nullptr) {
return retval;
}
@ -317,7 +353,7 @@ bool raycastEditMesh(SnapObjectContext *sctx,
ray_normal_local,
0.0f,
&hit,
params->use_backface_culling ?
sctx->runtime.params.use_backface_culling ?
editmesh_looptri_raycast_backface_culling_cb :
treedata->raycast_callback,
treedata) != -1)
@ -355,25 +391,23 @@ bool raycastEditMesh(SnapObjectContext *sctx,
/** \name Surface Snap Functions
* \{ */
bool nearest_world_editmesh(SnapObjectContext *sctx,
const SnapObjectParams *params,
Object *ob_eval,
BMEditMesh *em,
const float (*obmat)[4],
const float init_co[3],
const float curr_co[3],
float *r_dist_sq,
float *r_loc,
float *r_no,
int *r_index)
static bool nearest_world_editmesh(SnapData_EditMesh *sod,
SnapObjectContext *sctx,
BMEditMesh *em,
const float (*obmat)[4],
const float init_co[3],
const float curr_co[3],
float *r_dist_sq,
float *r_loc,
float *r_no,
int *r_index)
{
BVHTreeFromEditMesh *treedata = snap_object_data_editmesh_treedata_get(sctx, ob_eval, em);
BVHTreeFromEditMesh *treedata = snap_object_data_editmesh_treedata_get(sod, sctx, em);
if (treedata == nullptr) {
return false;
}
return nearest_world_tree(sctx,
params,
treedata->tree,
treedata->nearest_callback,
treedata,
@ -437,21 +471,22 @@ void nearest2d_data_init_editmesh(BMEditMesh *em,
* \{ */
eSnapMode snap_polygon_editmesh(SnapObjectContext *sctx,
const SnapObjectParams *params,
BMEditMesh *em,
Object *ob_eval,
ID * /*id*/,
const float obmat[4][4],
float clip_planes_local[MAX_CLIPPLANE_LEN][4],
/* read/write args */
float *dist_px,
/* return args */
float r_loc[3],
float r_no[3],
int *r_index)
eSnapMode snap_to_flag,
int polygon,
const float clip_planes_local[MAX_CLIPPLANE_LEN][4])
{
BLI_assert(sctx->editmesh_caches.lookup(em).get()->treedata_editmesh.em == em);
eSnapMode elem = SCE_SNAP_MODE_NONE;
SnapData_EditMesh *sod = editmesh_snapdata_init(sctx, ob_eval, snap_to_flag);
if (sod == nullptr) {
return elem;
}
BMEditMesh *em = sod->treedata_editmesh.em;
float lpmat[4][4];
mul_m4_m4m4(lpmat, sctx->runtime.pmat, obmat);
@ -461,18 +496,18 @@ eSnapMode snap_polygon_editmesh(SnapObjectContext *sctx,
BVHTreeNearest nearest{};
nearest.index = -1;
nearest.dist_sq = square_f(*dist_px);
nearest.dist_sq = sctx->ret.dist_px_sq;
Nearest2dUserData nearest2d;
nearest2d_data_init_editmesh(
em, sctx->runtime.view_proj == VIEW_PROJ_PERSP, params->use_backface_culling, &nearest2d);
em, sctx->runtime.is_persp, sctx->runtime.params.use_backface_culling, &nearest2d);
BM_mesh_elem_table_ensure(em->bm, BM_FACE);
BMFace *f = BM_face_at_index(em->bm, sctx->ret.index);
BMFace *f = BM_face_at_index(em->bm, polygon);
BMLoop *l_iter, *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) {
if (snap_to_flag & SCE_SNAP_MODE_EDGE) {
elem = SCE_SNAP_MODE_EDGE;
BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_EDGE);
BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE);
@ -500,10 +535,10 @@ eSnapMode snap_polygon_editmesh(SnapObjectContext *sctx,
}
if (nearest.index != -1) {
*dist_px = sqrtf(nearest.dist_sq);
sctx->ret.dist_px_sq = nearest.dist_sq;
mul_m4_v3(obmat, nearest.co);
copy_v3_v3(r_loc, nearest.co);
copy_v3_v3(sctx->ret.loc, nearest.co);
{
float imat[4][4];
@ -511,58 +546,42 @@ eSnapMode snap_polygon_editmesh(SnapObjectContext *sctx,
mul_transposed_mat3_m4_v3(imat, nearest.no);
normalize_v3(nearest.no);
copy_v3_v3(r_no, nearest.no);
copy_v3_v3(sctx->ret.no, nearest.no);
}
*r_index = nearest.index;
sctx->ret.index = nearest.index;
return elem;
}
return SCE_SNAP_MODE_NONE;
}
eSnapMode snapEditMesh(SnapObjectContext *sctx,
const SnapObjectParams *params,
Object *ob_eval,
BMEditMesh *em,
const float obmat[4][4],
/* read/write args */
float *dist_px,
/* return args */
float r_loc[3],
float r_no[3],
int *r_index)
static eSnapMode snapEditMesh(SnapData_EditMesh *sod,
SnapObjectContext *sctx,
BMEditMesh *em,
const float obmat[4][4],
eSnapMode snap_to_flag,
/* read/write args */
float *dist_px_sq,
/* return args */
float r_loc[3],
float r_no[3],
int *r_index)
{
BLI_assert(sctx->runtime.snap_to_flag != SCE_SNAP_MODE_FACE);
if ((sctx->runtime.snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_VERTEX) {
if (em->bm->totvert == 0) {
return SCE_SNAP_MODE_NONE;
}
}
else {
if (em->bm->totedge == 0) {
return SCE_SNAP_MODE_NONE;
}
}
BLI_assert(snap_to_flag != SCE_SNAP_MODE_FACE);
float lpmat[4][4];
mul_m4_m4m4(lpmat, sctx->runtime.pmat, obmat);
float dist_px_sq = square_f(*dist_px);
SnapData_EditMesh *sod = snap_object_data_editmesh_get(sctx, ob_eval, em);
/* Test BoundBox */
/* Was BKE_boundbox_ray_hit_check, see: cf6ca226fa58. */
if (!snap_bound_box_check_dist(
sod->min, sod->max, lpmat, sctx->runtime.win_size, sctx->runtime.mval, dist_px_sq))
sod->min, sod->max, lpmat, sctx->runtime.win_size, sctx->runtime.mval, *dist_px_sq))
{
return SCE_SNAP_MODE_NONE;
}
if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX) {
if (snap_to_flag & SCE_SNAP_MODE_VERTEX) {
BVHTreeFromEditMesh treedata{};
treedata.tree = sod->bvhtree[0];
@ -592,7 +611,7 @@ eSnapMode snapEditMesh(SnapObjectContext *sctx,
}
}
if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) {
if (snap_to_flag & SCE_SNAP_MODE_EDGE) {
BVHTreeFromEditMesh treedata{};
treedata.tree = sod->bvhtree[1];
@ -624,13 +643,13 @@ eSnapMode snapEditMesh(SnapObjectContext *sctx,
Nearest2dUserData nearest2d;
nearest2d_data_init_editmesh(sod->treedata_editmesh.em,
sctx->runtime.view_proj == VIEW_PROJ_PERSP,
params->use_backface_culling,
sctx->runtime.is_persp,
sctx->runtime.params.use_backface_culling,
&nearest2d);
BVHTreeNearest nearest{};
nearest.index = -1;
nearest.dist_sq = dist_px_sq;
nearest.dist_sq = *dist_px_sq;
eSnapMode elem = SCE_SNAP_MODE_VERTEX;
@ -641,7 +660,7 @@ eSnapMode snapEditMesh(SnapObjectContext *sctx,
mul_v4_m4v4(clip_planes_local[i], tobmat, sctx->runtime.clip_plane[i]);
}
if (sod->bvhtree[0] && (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
if (sod->bvhtree[0] && (snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
BM_mesh_elem_table_ensure(em->bm, BM_VERT);
BM_mesh_elem_index_ensure(em->bm, BM_VERT);
BLI_bvhtree_find_nearest_projected(sod->bvhtree[0],
@ -655,7 +674,7 @@ eSnapMode snapEditMesh(SnapObjectContext *sctx,
&nearest2d);
}
if (sod->bvhtree[1] && (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE)) {
if (sod->bvhtree[1] && (snap_to_flag & SCE_SNAP_MODE_EDGE)) {
int last_index = nearest.index;
nearest.index = -1;
BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT);
@ -679,7 +698,7 @@ eSnapMode snapEditMesh(SnapObjectContext *sctx,
}
if (nearest.index != -1) {
*dist_px = sqrtf(nearest.dist_sq);
*dist_px_sq = nearest.dist_sq;
copy_v3_v3(r_loc, nearest.co);
mul_m4_v3(obmat, r_loc);
@ -702,3 +721,75 @@ eSnapMode snapEditMesh(SnapObjectContext *sctx,
}
/** \} */
eSnapMode snap_object_editmesh(SnapObjectContext *sctx,
Object *ob_eval,
ID * /*id*/,
const float obmat[4][4],
eSnapMode snap_to_flag,
bool /*use_hide*/)
{
eSnapMode elem = SCE_SNAP_MODE_NONE;
SnapData_EditMesh *sod = editmesh_snapdata_init(sctx, ob_eval, snap_to_flag);
if (sod == nullptr) {
return elem;
}
BMEditMesh *em = sod->treedata_editmesh.em;
eSnapMode snap_mode_used = snap_to_flag & editmesh_snap_mode_supported(em);
if (snap_mode_used & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT |
SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_VERTEX))
{
elem = snapEditMesh(sod,
sctx,
em,
obmat,
snap_to_flag,
&sctx->ret.dist_px_sq,
sctx->ret.loc,
sctx->ret.no,
&sctx->ret.index);
if (elem) {
return elem;
}
}
if (snap_mode_used & SCE_SNAP_MODE_FACE) {
if (raycastEditMesh(sod,
sctx,
ob_eval,
em,
obmat,
sctx->runtime.object_index++,
/* read/write args */
&sctx->ret.ray_depth_max,
/* return args */
sctx->ret.loc,
sctx->ret.no,
&sctx->ret.index,
sctx->ret.hit_list))
{
return SCE_SNAP_MODE_FACE;
}
}
if (snap_mode_used & SCE_SNAP_MODE_FACE_NEAREST) {
if (nearest_world_editmesh(sod,
sctx,
em,
obmat,
sctx->runtime.init_co,
sctx->runtime.curr_co,
&sctx->ret.dist_px_sq,
sctx->ret.loc,
sctx->ret.no,
&sctx->ret.index))
{
return SCE_SNAP_MODE_FACE_NEAREST;
}
}
return SCE_SNAP_MODE_NONE;
}

View File

@ -82,21 +82,19 @@ static void mesh_looptri_raycast_backface_culling_cb(void *userdata,
}
}
bool raycastMesh(const SnapObjectParams *params,
const float ray_start[3],
const float ray_dir[3],
Object *ob_eval,
const Mesh *me_eval,
const float obmat[4][4],
const uint ob_index,
bool use_hide,
/* 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,
Object *ob_eval,
const Mesh *me_eval,
const float obmat[4][4],
const uint ob_index,
bool use_hide,
/* 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;
@ -110,8 +108,8 @@ bool raycastMesh(const SnapObjectParams *params,
invert_m4_m4(imat, obmat);
copy_v3_v3(ray_start_local, ray_start);
copy_v3_v3(ray_normal_local, ray_dir);
copy_v3_v3(ray_start_local, sctx->runtime.ray_start);
copy_v3_v3(ray_normal_local, sctx->runtime.ray_dir);
mul_m4_v3(imat, ray_start_local);
mul_mat3_m4_v3(imat, ray_normal_local);
@ -191,7 +189,7 @@ bool raycastMesh(const SnapObjectParams *params,
ray_normal_local,
0.0f,
&hit,
params->use_backface_culling ?
sctx->runtime.params.use_backface_culling ?
mesh_looptri_raycast_backface_culling_cb :
treedata.raycast_callback,
&treedata) != -1)
@ -229,17 +227,16 @@ bool raycastMesh(const SnapObjectParams *params,
/** \name Surface Snap Functions
* \{ */
bool nearest_world_mesh(SnapObjectContext *sctx,
const SnapObjectParams *params,
const Mesh *me_eval,
const float (*obmat)[4],
bool use_hide,
const float init_co[3],
const float curr_co[3],
float *r_dist_sq,
float *r_loc,
float *r_no,
int *r_index)
static bool nearest_world_mesh(SnapObjectContext *sctx,
const Mesh *me_eval,
const float (*obmat)[4],
bool use_hide,
const float init_co[3],
const float curr_co[3],
float *r_dist_sq,
float *r_loc,
float *r_no,
int *r_index)
{
BVHTreeFromMesh treedata;
snap_object_data_mesh_get(me_eval, use_hide, &treedata);
@ -248,7 +245,6 @@ bool nearest_world_mesh(SnapObjectContext *sctx,
}
return nearest_world_tree(sctx,
params,
treedata.tree,
treedata.nearest_callback,
&treedata,
@ -429,19 +425,17 @@ void nearest2d_data_init_mesh(const Mesh *mesh,
* \{ */
eSnapMode snap_polygon_mesh(SnapObjectContext *sctx,
const SnapObjectParams *params,
const Mesh *mesh,
Object * /*ob_eval*/,
ID *id,
const float obmat[4][4],
float clip_planes_local[MAX_CLIPPLANE_LEN][4],
/* read/write args */
float *dist_px,
/* return args */
float r_loc[3],
float r_no[3],
int *r_index)
eSnapMode snap_to_flag,
int polygon,
const float clip_planes_local[MAX_CLIPPLANE_LEN][4])
{
eSnapMode elem = SCE_SNAP_MODE_NONE;
Mesh *mesh_eval = reinterpret_cast<Mesh *>(id);
float lpmat[4][4];
mul_m4_m4m4(lpmat, sctx->runtime.pmat, obmat);
@ -451,15 +445,15 @@ eSnapMode snap_polygon_mesh(SnapObjectContext *sctx,
BVHTreeNearest nearest{};
nearest.index = -1;
nearest.dist_sq = square_f(*dist_px);
nearest.dist_sq = sctx->ret.dist_px_sq;
Nearest2dUserData nearest2d;
nearest2d_data_init_mesh(
mesh, sctx->runtime.view_proj == VIEW_PROJ_PERSP, params->use_backface_culling, &nearest2d);
mesh_eval, sctx->runtime.is_persp, sctx->runtime.params.use_backface_culling, &nearest2d);
const blender::IndexRange poly = mesh->polys()[sctx->ret.index];
const blender::IndexRange poly = mesh_eval->polys()[polygon];
if (sctx->runtime.snap_to_flag & SCE_SNAP_MODE_EDGE) {
if (snap_to_flag & SCE_SNAP_MODE_EDGE) {
elem = SCE_SNAP_MODE_EDGE;
BLI_assert(nearest2d.edges != nullptr);
const int *poly_edges = &nearest2d.corner_edges[poly.start()];
@ -486,10 +480,10 @@ eSnapMode snap_polygon_mesh(SnapObjectContext *sctx,
}
if (nearest.index != -1) {
*dist_px = sqrtf(nearest.dist_sq);
sctx->ret.dist_px_sq = sqrtf(nearest.dist_sq);
mul_m4_v3(obmat, nearest.co);
copy_v3_v3(r_loc, nearest.co);
copy_v3_v3(sctx->ret.loc, nearest.co);
{
float imat[4][4];
@ -497,28 +491,27 @@ eSnapMode snap_polygon_mesh(SnapObjectContext *sctx,
mul_transposed_mat3_m4_v3(imat, nearest.no);
normalize_v3(nearest.no);
copy_v3_v3(r_no, nearest.no);
copy_v3_v3(sctx->ret.no, nearest.no);
}
*r_index = nearest.index;
sctx->ret.index = nearest.index;
return elem;
}
return SCE_SNAP_MODE_NONE;
}
eSnapMode snapMesh(SnapObjectContext *sctx,
const SnapObjectParams *params,
Object *ob_eval,
const Mesh *me_eval,
const float obmat[4][4],
bool use_hide,
/* read/write args */
float *dist_px,
/* return args */
float r_loc[3],
float r_no[3],
int *r_index)
static eSnapMode snapMesh(SnapObjectContext *sctx,
Object *ob_eval,
const Mesh *me_eval,
const float obmat[4][4],
bool use_hide,
/* read/write args */
float *dist_px_sq,
/* return args */
float r_loc[3],
float r_no[3],
int *r_index)
{
BLI_assert(sctx->runtime.snap_to_flag != SCE_SNAP_MODE_FACE);
if (me_eval->totvert == 0) {
@ -531,13 +524,15 @@ eSnapMode snapMesh(SnapObjectContext *sctx,
float lpmat[4][4];
mul_m4_m4m4(lpmat, sctx->runtime.pmat, obmat);
float dist_px_sq = square_f(*dist_px);
/* Test BoundBox */
if (ob_eval->data == me_eval) {
const BoundBox *bb = BKE_object_boundbox_get(ob_eval);
if (!snap_bound_box_check_dist(
bb->vec[0], bb->vec[6], lpmat, sctx->runtime.win_size, sctx->runtime.mval, dist_px_sq))
if (!snap_bound_box_check_dist(bb->vec[0],
bb->vec[6],
lpmat,
sctx->runtime.win_size,
sctx->runtime.mval,
*dist_px_sq))
{
return SCE_SNAP_MODE_NONE;
}
@ -555,14 +550,12 @@ eSnapMode snapMesh(SnapObjectContext *sctx,
}
Nearest2dUserData nearest2d;
nearest2d_data_init_mesh(me_eval,
sctx->runtime.view_proj == VIEW_PROJ_PERSP,
params->use_backface_culling,
&nearest2d);
nearest2d_data_init_mesh(
me_eval, sctx->runtime.is_persp, sctx->runtime.params.use_backface_culling, &nearest2d);
BVHTreeNearest nearest{};
nearest.index = -1;
nearest.dist_sq = dist_px_sq;
nearest.dist_sq = *dist_px_sq;
int last_index = nearest.index;
eSnapMode elem = SCE_SNAP_MODE_VERTEX;
@ -650,7 +643,7 @@ eSnapMode snapMesh(SnapObjectContext *sctx,
}
if (nearest.index != -1) {
*dist_px = sqrtf(nearest.dist_sq);
*dist_px_sq = nearest.dist_sq;
copy_v3_v3(r_loc, nearest.co);
mul_m4_v3(obmat, r_loc);
@ -674,3 +667,86 @@ eSnapMode snapMesh(SnapObjectContext *sctx,
}
/** \} */
static eSnapMode mesh_snap_mode_supported(Mesh *mesh)
{
eSnapMode snap_mode_supported = SCE_SNAP_MODE_NONE;
if (mesh->totpoly) {
snap_mode_supported |= SCE_SNAP_MODE_FACE | SCE_SNAP_MODE_FACE_NEAREST;
}
if (mesh->totedge) {
snap_mode_supported |= SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT |
SCE_SNAP_MODE_EDGE_PERPENDICULAR;
}
if (mesh->totvert) {
snap_mode_supported |= SCE_SNAP_MODE_VERTEX;
}
return snap_mode_supported;
}
eSnapMode snap_object_mesh(SnapObjectContext *sctx,
Object *ob_eval,
ID *id,
const float obmat[4][4],
eSnapMode snap_to_flag,
bool use_hide)
{
eSnapMode elem = SCE_SNAP_MODE_NONE;
Mesh *mesh_eval = reinterpret_cast<Mesh *>(id);
eSnapMode snap_mode_used = snap_to_flag & mesh_snap_mode_supported(mesh_eval);
if (snap_mode_used & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT |
SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_VERTEX))
{
elem = snapMesh(sctx,
ob_eval,
mesh_eval,
obmat,
use_hide,
&sctx->ret.dist_px_sq,
sctx->ret.loc,
sctx->ret.no,
&sctx->ret.index);
if (elem) {
return elem;
}
}
if (snap_mode_used & SCE_SNAP_MODE_FACE) {
if (raycastMesh(sctx,
ob_eval,
mesh_eval,
obmat,
sctx->runtime.object_index++,
use_hide,
/* read/write args */
&sctx->ret.ray_depth_max,
/* return args */
sctx->ret.loc,
sctx->ret.no,
&sctx->ret.index,
sctx->ret.hit_list))
{
return SCE_SNAP_MODE_FACE;
}
}
if (snap_mode_used & SCE_SNAP_MODE_FACE_NEAREST) {
if (nearest_world_mesh(sctx,
mesh_eval,
obmat,
use_hide,
sctx->runtime.init_co,
sctx->runtime.curr_co,
&sctx->ret.dist_px_sq,
sctx->ret.loc,
sctx->ret.no,
&sctx->ret.index))
{
return SCE_SNAP_MODE_FACE_NEAREST;
}
}
return SCE_SNAP_MODE_NONE;
}