34# pragma optimize("t", on)
47 if (
dot_v3v3(ray_dir, plane) > 0.0f) {
59 const float (*clip_plane)[4],
60 const int clip_plane_len,
80 if (dist_sq < nearest->dist_sq) {
82 nearest->dist_sq = dist_sq;
89 const float (*clip_plane)[4],
90 const int clip_plane_len,
104 is_persp(sctx->runtime.rv3d ? sctx->runtime.rv3d->is_persp :
false),
105 use_backface_culling(sctx->runtime.
params.use_backface_culling)
124 bool skip_occlusion_plane)
127 if (!skip_occlusion_plane) {
148#ifdef TEST_CLIPPLANES_IN_BOUNDBOX
150 reinterpret_cast<const float(*)[4]
>(this->
clip_planes.data()),
151 this->clip_planes.size(),
172 reinterpret_cast<const float(*)[4]
>(this->
clip_planes.data()),
173 this->clip_planes.size(),
176 &this->nearest_point))
187 reinterpret_cast<const float(*)[4]
>(this->
clip_planes.data()),
188 this->clip_planes.size(),
192 &this->nearest_point))
203 float dist_px_sq_orig)
210 const float *v_pair[2];
216 this->nearest_precalc.ray_direction,
231 float range = 1.0f / (2 * e_mode_len - 1);
234 range *= e_mode_len - 1;
235 if ((range) < lambda && lambda < (1.0f -
range)) {
247 float v_near[3], va_g[3], vb_g[3];
253 if (
IN_RANGE(lambda_perp, 0.0f, 1.0f)) {
265 if (lambda < (range) || (1.0f - range) < lambda) {
266 int v_id = lambda < 0.5f ? 0 : 1;
268 if (this->
snap_point(v_pair[v_id], vindex[v_id])) {
291 sctx->
ret.
ob = ob_eval;
301 r_nearest->
index = -2;
315 const bool is_in_front)
318 if (hit->dist <= depth_max) {
326 sctx->
ret.
ob = ob_eval;
353 bool use_hide =
false;
355 switch (ob_eval->
type) {
373 mesh_eval = editmesh_eval;
378 *r_use_hide = use_hide;
380 return (
ID *)mesh_eval;
386 *r_use_hide = use_hide;
388 return (
ID *)ob_eval->
data;
401 bool is_object_active,
406 const Base *base_act,
424 const bool is_active = (base_act == base);
429 const bool is_in_object_mode = (base_act ==
nullptr) ||
432 if (is_in_object_mode) {
479 const bool is_object_active = (base == base_act);
487 if ((tmp = sob_callback(sctx,
500 bool use_hide =
false;
502 if ((tmp = sob_callback(
503 sctx, obj_eval, ob_data, obj_eval->object_to_world(), is_object_active, use_hide)) !=
527 hit->ob_uuid = ob_uuid;
552 if (hit->index != -1) {
558 mul_v3_m4v3(location, (
float(*)[4])data->obmat, hit->co);
559 depth = (hit->dist + data->len_diff) / data->local_scale;
567 const float dir[3],
const float v0[3],
const float v1[3],
const float v2[3],
float no[3])
585 if (ob_data ==
nullptr) {
660 r_nearest->
index = -1;
682 vec =
float3(nearest.co) - init_co;
689 vec =
float3(nearest.co) - curr_co;
693 if (r_nearest->
dist_sq <= original_distance) {
701 float3 delta = (curr_co - init_co) * step_scale_factor;
710 *r_nearest = nearest;
712 r_nearest->
dist_sq = original_distance;
733 if (ob_data ==
nullptr) {
787 const float (*clip_plane)[4],
788 const int clip_plane_len,
797 data->copy_vert_no(index, nearest->no);
798 nearest->index = index;
805 const float (*clip_plane)[4],
806 const int clip_plane_len,
814 const float *v_pair[2];
815 data->get_vert_co(vindex[0], &v_pair[0]);
816 data->get_vert_co(vindex[1], &v_pair[1]);
819 precalc, clip_plane, clip_plane_len, data->is_persp, v_pair[0], v_pair[1], nearest))
822 nearest->index = index;
887 bool is_object_active,
890 if (ob_data ==
nullptr && (ob_eval->
type ==
OB_MESH)) {
895 if (ob_data ==
nullptr) {
916 switch (ob_eval->
type) {
921 retval =
snapArmature(sctx, ob_eval, obmat, is_object_active);
926 retval =
snapCurve(sctx, ob_eval, obmat);
981 for (
int i = 0; i < 4; i++) {
1031 bool (*test_vert_fn)(
BMVert *,
void *user_data),
1032 bool (*test_edge_fn)(
BMEdge *,
void *user_data),
1033 bool (*test_face_fn)(
BMFace *,
void *user_data),
1036 bool is_cache_dirty =
false;
1039 is_cache_dirty =
true;
1043 is_cache_dirty =
true;
1047 is_cache_dirty =
true;
1051 is_cache_dirty =
true;
1054 if (is_cache_dirty) {
1066 const float ray_start[3],
1067 const float ray_dir[3],
1068 const float ray_depth,
1069 const float mval[2],
1070 const float init_co[3],
1071 const float prev_co[3],
1072 const float dist_px_sq,
1084 snap_to_flag &= ~SCE_SNAP_INDIVIDUAL_NEAREST;
1143 if (
params->grid_size == 0.0f) {
1170 sctx->
ret.
ob =
nullptr;
1181 const float ray_start[3],
1182 const float ray_normal[3],
1188 float r_obmat[4][4])
1219 *r_ob = sctx->
ret.
ob;
1236 const float ray_start[3],
1237 const float ray_normal[3],
1281 const float ray_start[3],
1282 const float ray_normal[3],
1307 const float init_co[3],
1308 const float mval[2],
1309 const float prev_co[3],
1315 float r_obmat[4][4],
1316 float r_face_nor[3])
1320 bool use_occlusion_plane =
false;
1328 use_occlusion_plane =
true;
1357 snap_to_flag &= ~SCE_SNAP_TO_FACE;
1358 use_occlusion_plane =
false;
1368 use_occlusion_plane ?
params->occlusion_test :
1383#ifdef DEBUG_SNAP_TIME
1391 bool has_hit =
false;
1423 if (use_occlusion_plane && has_hit) {
1461 retval = elem & snap_to_flag;
1477 *r_ob = sctx->
ret.
ob;
1491#ifdef DEBUG_SNAP_TIME
1492 duration_ += timeit::Clock::now() - start_;
1505 const float init_co[3],
1506 const float mval[2],
1507 const float prev_co[3],
1535 const float mval[2],
1540 float3 ray_start, ray_normal, ray_end;
1544 depsgraph, region, v3d, mval,
false,
nullptr, ray_normal, ray_start, ray_end))
1552 float ray_depth_max =
math::dot(ray_end - ray_start, ray_normal);
1553 if ((ray_depth == -1.0f) || (ray_depth > ray_depth_max)) {
1554 ray_depth = ray_depth_max;
1559 sctx,
depsgraph, v3d,
params, ray_start, ray_normal, ray_depth, sort, r_hit_list);
1562#ifdef DEBUG_SNAP_TIME
1565 std::cout <<
"Average snapping time: ";
1566 std::cout << std::fixed << duration_.count() / 1.0e6 <<
" ms";
1569 duration_ = timeit::Nanoseconds::zero();
ListBase * object_duplilist(Depsgraph *depsgraph, Scene *sce, Object *ob)
void free_object_duplilist(ListBase *lb)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Base * BKE_view_layer_active_base_get(ViewLayer *view_layer)
ListBase * BKE_view_layer_object_bases_get(ViewLayer *view_layer)
General operations, lookup, etc. for blender objects.
const Mesh * BKE_object_get_editmesh_eval_cage(const Object *object)
bool BKE_object_is_in_editmode(const Object *ob)
Mesh * BKE_object_get_evaluated_mesh(const Object *object_eval)
const Mesh * BKE_object_get_editmesh_eval_final(const Object *object)
#define BVH_RAYCAST_DIST_MAX
void(* BVHTree_NearestPointCallback)(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
int BLI_bvhtree_find_nearest(const BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
#define LISTBASE_FOREACH(type, var, list)
void void BLI_listbase_sort(struct ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
MINLINE float max_ff(float a, float b)
MINLINE float square_f(float a)
#define BLI_ASSERT_UNIT_V3(v)
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
bool clip_segment_v3_plane_n(const float p1[3], const float p2[3], const float plane_array[][4], int plane_num, float r_p1[3], float r_p2[3])
bool isect_ray_plane_v3(const float ray_origin[3], const float ray_direction[3], const float plane[4], float *r_lambda, bool clip)
float dist_squared_to_projected_aabb(struct DistProjectedAABBPrecalc *data, const float bbmin[3], const float bbmax[3], bool r_axis_closest[3])
bool isect_ray_line_v3(const float ray_origin[3], const float ray_direction[3], const float v0[3], const float v1[3], float *r_lambda)
bool isect_point_planes_v3_negated(const float(*planes)[4], int totplane, const float p[3])
void cross_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
#define ISECT_AABB_PLANE_BEHIND_ANY
float closest_ray_to_segment_v3(const float ray_origin[3], const float ray_direction[3], const float v0[3], const float v1[3], float r_close[3])
void dist_squared_to_projected_aabb_precalc(struct DistProjectedAABBPrecalc *precalc, const float projmat[4][4], const float winsize[2], const float mval[2])
int isect_aabb_planes_v3(const float(*planes)[4], int totplane, const float bbmin[3], const float bbmax[3])
float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
void planes_from_projmat(const float mat[4][4], float left[4], float right[4], float bottom[4], float top[4], float near[4], float far[4])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool compare_m4m4(const float mat1[4][4], const float mat2[4][4], float limit)
MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_fl3(float v[3], float x, float y, float z)
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
MINLINE float mul_project_m4_v3_zfac(const float mat[4][4], const float co[3]) ATTR_WARN_UNUSED_RESULT
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE float dot_m4_v3_row_x(const float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float dot_m4_v3_row_y(const float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void negate_v4(float r[4])
#define IN_RANGE(a, b, c)
ViewLayer * DEG_get_input_view_layer(const Depsgraph *graph)
Scene * DEG_get_input_scene(const Depsgraph *graph)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
bool DEG_is_evaluated_object(const Object *object)
@ BA_TRANSFORM_LOCKED_IN_PLACE
@ BA_SNAP_FIX_DEPS_FIASCO
#define BASE_SELECTED(v3d, base)
@ SCE_SNAP_TARGET_NOT_ACTIVE
@ SCE_SNAP_TARGET_NOT_NONEDITED
@ SCE_SNAP_TARGET_ONLY_SELECTABLE
@ SCE_SNAP_TARGET_NOT_SELECTED
@ SCE_SNAP_TARGET_NOT_EDITED
#define BASE_SELECTABLE(v3d, base)
@ SCE_SNAP_INDIVIDUAL_NEAREST
@ SCE_SNAP_TO_EDGE_ENDPOINT
@ SCE_SNAP_TO_EDGE_MIDPOINT
@ SCE_SNAP_TO_EDGE_PERPENDICULAR
#define BASE_VISIBLE(v3d, base)
#define RV3D_VIEW_IS_AXIS(view)
#define ED_transform_snap_object_time_average_print()
#define XRAY_ENABLED(v3d)
float ED_view3d_grid_view_scale(const Scene *scene, const View3D *v3d, const ARegion *region, const char **r_grid_unit)
bool ED_view3d_win_to_ray_clipped_ex(Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const float mval[2], const bool do_clip_planes, float r_ray_co[3], float r_ray_normal[3], float r_ray_start[3], float r_ray_end[3])
ATTR_WARN_UNUSED_RESULT const BMVert * v2
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
blender::Vector< blender::float4, MAX_CLIPPLANE_LEN+1 > clip_planes
void clip_planes_enable(SnapObjectContext *sctx, const Object *ob_eval, bool skip_occlusion_plane=false)
blender::float4x4 pmat_local
bool snap_point(const blender::float3 &co, int index=-1)
static void register_result_raycast(SnapObjectContext *sctx, const Object *ob_eval, const ID *id_eval, const blender::float4x4 &obmat, const BVHTreeRayHit *hit, const bool is_in_front)
SnapData(SnapObjectContext *sctx, const blender::float4x4 &obmat=blender::float4x4::identity())
static void register_result(SnapObjectContext *sctx, const Object *ob_eval, const ID *id_eval, const blender::float4x4 &obmat, BVHTreeNearest *r_nearest)
virtual void copy_vert_no(const int, float[3])
DistProjectedAABBPrecalc nearest_precalc
BVHTreeNearest nearest_point
eSnapMode snap_edge_points_impl(SnapObjectContext *sctx, int edge_index, float dist_px_sq_orig)
virtual void get_vert_co(const int, const float **)
bool snap_boundbox(const blender::float3 &min, const blender::float3 &max)
virtual void get_edge_verts_index(const int, int[2])
bool snap_edge(const blender::float3 &va, const blender::float3 &vb, int edge_index=-1)
const Depsgraph * depsgraph
bool object_has_geometry_set_instances(const Object &object)
T length_squared(const VecBase< T, Size > &a)
MatBase< T, NumCol, NumRow > transpose(const MatBase< T, NumRow, NumCol > &mat)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
CartesianBasis invert(const CartesianBasis &basis)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
VecBase< T, 3 > transform_direction(const MatBase< T, 3, 3 > &mat, const VecBase< T, 3 > &direction)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
std::chrono::nanoseconds Nanoseconds
Clock::time_point TimePoint
MatBase< float, 4, 4 > float4x4
VecBase< float, 3 > float3
MeshRuntimeHandle * runtime
BVHTree_RayCastCallback raycast_callback
struct SnapObjectContext::@587::@591 edit_mesh
blender::float4 planes[4]
blender::float4 occlusion_plane_in_front
blender::float3 ray_start
struct SnapObjectContext::@588 grid
const RegionView3D * rv3d
blender::Vector< blender::float4, MAX_CLIPPLANE_LEN > clip_planes
struct SnapObjectContext::@590 ret
bool(* test_face_fn)(BMFace *, void *user_data)
bool(* test_edge_fn)(BMEdge *, void *user_data)
blender::Map< const ID *, std::unique_ptr< SnapCache > > editmesh_caches
bool(* test_vert_fn)(BMVert *, void *user_data)
eSnapOcclusionTest occlusion_test_edit
struct SnapObjectContext::@589 runtime
blender::float4 occlusion_plane
bool has_occlusion_plane_in_front
blender::float4x4 persmat
float ray_depth_max_in_front
struct SnapObjectContext::@587 callbacks
eSnapTargetOP snap_target_select
eSnapEditType edit_mode_type
eSnapOcclusionTest occlusion_test
const c_style_mat & ptr() const