49# define TIMEIT_BENCH(expr, id) (expr)
53#define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n"))
102 if (
mesh ==
nullptr) {
111 if (
mesh->verts_num <= 0) {
118 data->corner_edges =
mesh->corner_edges();
119 data->vert_normals =
mesh->vert_normals();
126 return data->bvh !=
nullptr;
129 if (
mesh->faces_num <= 0) {
133 data->treeData =
mesh->bvh_corner_tris();
136 if (
data->bvh ==
nullptr) {
141 data->face_normals =
mesh->face_normals();
143 data->corner_normals =
mesh->corner_normals();
162 const float edge_dir[3],
166 float *direction = vdata[index].
direction;
192 for (
const int edge : corner_edges) {
193 if (edge_mode[edge] < 2) {
201 int num_boundary_edges = 0;
203 if (edge_mode[
i] == 1) {
204 edge_is_boundary[
i].set();
205 num_boundary_edges++;
210 if (num_boundary_edges == 0) {
224 edges, corner_verts, corner_edges, corner_tris[
i]);
226 for (
int j = 0; j < 3; j++) {
227 if (real_edges[j] >= 0 && edge_is_boundary[real_edges[j]]) {
228 tri_has_boundary[
i].set();
238 if (edge_is_boundary[
i]) {
239 const int2 &edge = edges[
i];
240 vert_boundary_id[edge[0]] = 1;
241 vert_boundary_id[edge[1]] = 1;
245 int boundary_verts_num = 0;
247 vert_boundary_id[
i] = (vert_boundary_id[
i] != 0) ? boundary_verts_num++ : -1;
255 if (edge_is_boundary[
i]) {
256 const int2 &edge = edges[
i];
259 sub_v3_v3v3(dir, positions[edge[1]], positions[edge[0]]);
262 merge_vert_dir(boundary_verts.
data(), vert_status, vert_boundary_id[edge[0]], dir, 1);
263 merge_vert_dir(boundary_verts.
data(), vert_status, vert_boundary_id[edge[1]], dir, 2);
270 int bidx = vert_boundary_id[
i];
284 data.edge_is_boundary = std::move(edge_is_boundary);
285 data.tri_has_boundary = std::move(tri_has_boundary);
286 data.vert_boundary_id = std::move(vert_boundary_id);
287 data.boundary_verts = std::move(boundary_verts);
294 mesh.runtime->shrinkwrap_boundary_cache.ensure(
296 return mesh.runtime->shrinkwrap_boundary_cache.data();
322 if (weight == 0.0f) {
340 if (nearest->
index != -1) {
350 if (nearest->
index != -1) {
353 if (nearest->
dist_sq > FLT_EPSILON) {
355 weight *= (dist - calc->
keepDist) / dist;
389 const float ray_radius,
399 float tmp_co[3], tmp_no[3];
400 const float *co, *no;
404 memcpy(&hit_tmp, hit,
sizeof(hit_tmp));
416#ifdef USE_DIST_CORRECT
428 tree->bvh, co, no, ray_radius, &hit_tmp,
tree->treeData.raycast_callback, &
tree->treeData);
430 if (hit_tmp.
index != -1) {
449#ifdef USE_DIST_CORRECT
456 memcpy(hit, &hit_tmp,
sizeof(hit_tmp));
472 float *proj_axis =
data->proj_axis;
479 const float *tmp_co, *tmp_no;
483 if (weight == 0.0f) {
551 if (proj_limit_squared != 0.0f) {
557 if (hit->
index != -1) {
588 float proj_axis[3] = {0.0f, 0.0f, 0.0f};
598 Mesh *auxMesh =
nullptr;
649 aux_tree = &aux_tree_stack;
656 data.aux_tree = aux_tree;
657 data.proj_axis = proj_axis;
658 data.local2aux = &local2aux;
706 const float w[3] = {
x[0],
x[1], 1.0f -
x[0] -
x[1]};
730 x[0] = std::max(
x[0], 0.0f);
731 x[1] = std::max(
x[1], 0.0f);
732 if (
x[0] +
x[1] > 1.0f) {
733 x[0] =
x[0] / (
x[0] +
x[1]);
745 const float epsilon = 1e-5f;
747 const float dir_epsilon = 0.5f;
748 bool fixed =
false, locked =
false;
753 float sum =
x[0] +
x[1];
756 if (
sum + sstep > 1.0f) {
757 float ldist = 1.0f -
sum;
760 if (ldist < epsilon *
float(
M_SQRT2)) {
764 if (step_len > epsilon && sstep > step_len * dir_epsilon *
float(
M_SQRT2)) {
770 fixed = locked =
true;
780 for (
int i = 0;
i < 2;
i++) {
783 if (
x[
i] < epsilon) {
787 if (step_len > epsilon && (locked ||
step[
i] > step_len * dir_epsilon)) {
813 const float vtri_no[3][3],
814 const float point_co[3],
815 const float hit_co[3],
821 float dist =
sqrtf(hit_dist_sq);
824 float epsilon = magnitude_estimate * 1.0e-6f;
832 x[2] = (
dot_v3v3(tmp, r_hit_no) < 0) ? -dist : dist;
847#ifdef TRACE_TARGET_PROJECT
848 const bool trace =
true;
850 const bool trace =
false;
876 const float hit_co[3],
877 const float hit_no[3])
881 if (dist_sq < nearest->dist_sq) {
882#ifdef TRACE_TARGET_PROJECT
884 "#=#=#> %d (%.3f,%.3f,%.3f) %g < %g\n", index,
UNPACK3(hit_co), dist_sq, nearest->
dist_sq);
886 nearest->
index = index;
906 const float *vedge_co[2] = {
data->vert_positions[edge[0]],
data->vert_positions[edge[1]]};
908#ifdef TRACE_TARGET_PROJECT
909 printf(
"EDGE %d (%.3f,%.3f,%.3f) (%.3f,%.3f,%.3f)\n",
916 const int *vert_boundary_id =
tree->boundary->vert_boundary_id.data();
917 const int bid1 = vert_boundary_id[edge[0]], bid2 = vert_boundary_id[edge[1]];
919 if (bid1 < 0 || bid2 < 0) {
925 float vedge_dir[2][3], dir[3];
927 copy_v3_v3(vedge_dir[0], boundary_verts[bid1].normal_plane);
928 copy_v3_v3(vedge_dir[1], boundary_verts[bid2].normal_plane);
932 if (
dot_v3v3(boundary_verts[bid1].direction, dir) < 0) {
935 if (
dot_v3v3(boundary_verts[bid2].direction, dir) < 0) {
940 const float d0v0 =
dot_v3v3(vedge_dir[0], vedge_co[0]),
941 d0v1 =
dot_v3v3(vedge_dir[0], vedge_co[1]);
942 const float d1v0 =
dot_v3v3(vedge_dir[1], vedge_co[0]),
943 d1v1 =
dot_v3v3(vedge_dir[1], vedge_co[1]);
944 const float d0co =
dot_v3v3(vedge_dir[0], co);
947 const float a = d0v1 - d0v0 + d1v0 - d1v1;
949 const float b = 2 * d0v0 - d0v1 - d0co - d1v0 +
dot_v3v3(vedge_dir[1], co);
950 const float c = d0co - d0v0;
951 const float det =
b *
b - 4 * a * c;
954 const float epsilon = 1e-6f;
955 const float sdet =
sqrtf(det);
956 float hit_co[3], hit_no[3];
958 for (
int i = (det > 0 ? 2 : 0);
i >= 0;
i -= 2) {
959 float x = (-
b +
float(
i - 1) * sdet) / (2.0f * a);
961 if (
x >= -epsilon &&
x <= 1.0f + epsilon) {
964 float vedge_no[2][3];
971 update_hit(nearest, index, co, hit_co, hit_no);
987 const int3 &tri =
data->corner_tris[index];
988 const int tri_verts[3] = {
989 data->corner_verts[tri[0]],
990 data->corner_verts[tri[1]],
991 data->corner_verts[tri[2]],
993 const float *vtri_co[3] = {
994 data->vert_positions[tri_verts[0]],
995 data->vert_positions[tri_verts[1]],
996 data->vert_positions[tri_verts[2]],
998 float raw_hit_co[3], hit_co[3], hit_no[3], dist_sq, vtri_no[3][3];
1004#ifdef TRACE_TARGET_PROJECT
1005 printf(
"TRIANGLE %d (%.3f,%.3f,%.3f) (%.3f,%.3f,%.3f) (%.3f,%.3f,%.3f) %g %g\n",
1014 if (dist_sq >= nearest->
dist_sq) {
1025 update_hit(nearest, index, co, hit_co, hit_no);
1028 else if (
tree->boundary &&
tree->boundary->has_boundary() &&
1029 tree->boundary->tri_has_boundary[index])
1031 const BitSpan is_boundary =
tree->boundary->edge_is_boundary;
1033 tree->edges,
data->corner_verts,
tree->corner_edges, tri);
1035 for (
int i = 0;
i < 3;
i++) {
1036 if (edges[
i] >= 0 && is_boundary[edges[
i]]) {
1051#ifdef TRACE_TARGET_PROJECT
1052 printf(
"\n====== TARGET PROJECT START ======\n");
1058#ifdef TRACE_TARGET_PROJECT
1059 printf(
"====== TARGET PROJECT END: %d %g ======\n\n", nearest->
index, nearest->
dist_sq);
1062 if (nearest->
index < 0) {
1092 if (weight == 0.0f) {
1110 if (nearest->
index != -1) {
1113 nearest->
index = -1;
1127 if (nearest->
index != -1) {
1147 const float hit_co[3],
1148 const float hit_no[3],
1154 const int face_i =
tree->mesh->corner_tri_faces()[corner_tri_idx];
1157 if (
tree->sharp_faces.is_empty() ||
tree->sharp_faces[face_i]) {
1158 const int vert_indices[3] = {treeData->
corner_verts[tri[0]],
1161 float w[3], no[3][3], tmp_co[3];
1164 if (!
tree->corner_normals.is_empty()) {
1200 else if (!
tree->face_normals.is_empty()) {
1214 const float point_co[3],
1215 const float hit_co[3],
1216 const float hit_no[3],
1224 float dist =
len_v3(delta);
1227 if (dist < FLT_EPSILON) {
1228 if (forcesnap || goal_dist > 0) {
1229 madd_v3_v3v3fl(r_point_co, hit_co, hit_no, goal_dist * forcesign);
1239 if (forcesign == 0.0f) {
1244 if (forcesnap || dsign * dist * forcesign < goal_dist) {
1250 if (dist < dist_epsilon) {
1251#ifdef TRACE_TARGET_PROJECT
1252 printf(
"zero_factor %g = %g / %g\n", dist / dist_epsilon, dist, dist_epsilon);
1258 madd_v3_v3v3fl(r_point_co, hit_co, delta, goal_dist * forcesign);
1270 const float hit_co[3],
1271 const float hit_no[3],
1273 const float point_co[3],
1274 float r_point_co[3])
1281 if (goal_dist != 0) {
1298 if (goal_dist != 0) {
1308 if (goal_dist != 0) {
1318 printf(
"Unknown Shrinkwrap surface snap mode: %d\n", mode);
1345 Mesh *
mesh,
const int subdivision_level)
1355 settings.
level = subdivision_level;
1380 const int defgrp_index,
1381 float (*vertexCos)[3],
1401 calc.
vgroup = defgrp_index;
1404 if (smd->
target !=
nullptr) {
1425 subdivided_positions = shrinkwrap_calc_subdivided_positions(mesh, smd->subsurfLevels);
1426 calc.vert_positions = reinterpret_cast<float (*)[3]>(subdivided_positions.data());
1459 const int defgrp_index,
1480 calc.
vertexCos =
reinterpret_cast<float (*)[3]
>(positions.
data());
1482 calc.
vgroup = defgrp_index;
1490 case MOD_SHRINKWRAP_NEAREST_SURFACE:
1491 case MOD_SHRINKWRAP_TARGET_PROJECT:
1492 TIMEIT_BENCH(shrinkwrap_calc_nearest_surface_point(&calc), gpdeform_surface);
1495 case MOD_SHRINKWRAP_PROJECT:
1496 TIMEIT_BENCH(shrinkwrap_calc_normal_projection(&calc), gpdeform_project);
1499 case MOD_SHRINKWRAP_NEAREST_VERTEX:
1500 TIMEIT_BENCH(shrinkwrap_calc_nearest_vertex(&calc), gpdeform_vertex);
1528 reinterpret_cast<float (*)[3]
>(src_me->vert_positions_for_write().data()),
1530 src_me->tag_positions_changed();
1545 const float projLimitTolerance = 5.0f;
1552 calc.
vertexCos =
reinterpret_cast<float (*)[3]
>(src_me->vert_positions_for_write().
data());
1557 calc.
vert_positions =
reinterpret_cast<float (*)[3]
>(src_me->vert_positions_for_write().
data());
1567 src_me->tag_positions_changed();
void BKE_mesh_wrapper_ensure_mdata(Mesh *mesh)
Mesh * BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval)
#define NULL_BVHTreeNearest
#define NULL_ShrinkwrapCalcData
#define BVH_RAYCAST_DIST_MAX
int BLI_bvhtree_find_nearest(const BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
int BLI_bvhtree_ray_cast(const BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata)
@ BVH_NEAREST_OPTIMAL_ORDER
int BLI_bvhtree_find_nearest_ex(const BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata, int flag)
MINLINE float signf(float f)
void interp_weights_tri_v3(float w[3], const float v1[3], const float v2[3], const float v3[3], const float co[3])
void closest_on_tri_to_point_v3(float r[3], const float p[3], const float v1[3], const float v2[3], const float v3[3])
float mat4_to_scale(const float mat[4][4])
void BLI_space_transform_apply_normal(const struct SpaceTransform *data, float no[3])
void BLI_space_transform_apply(const struct SpaceTransform *data, float co[3])
void BLI_space_transform_invert_normal(const struct SpaceTransform *data, float no[3])
void BLI_space_transform_invert(const struct SpaceTransform *data, float co[3])
#define BLI_SPACE_TRANSFORM_SETUP(data, local, target)
bool BLI_newton3d_solve(Newton3D_DeltaFunc func_delta, Newton3D_JacobianFunc func_jacobian, Newton3D_CorrectionFunc func_correction, void *userdata, float epsilon, int max_iterations, bool trace, const float x_init[3], float result[3])
Solve a generic f(x) = 0 equation using Newton's method.
MINLINE float len_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void sub_v3_v3(float r[3], const float a[3])
void interp_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float w[3])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
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 void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void add_v2_fl(float r[2], float f)
MINLINE void negate_v3(float r[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE float len_manhattan_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Utility defines for timing/benchmarks.
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
#define MOD_SHRINKWRAP_CULL_TARGET_MASK
@ MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS
@ MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS
@ MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS
@ MOD_SHRINKWRAP_PROJECT_OVER_NORMAL
@ MOD_SHRINKWRAP_TARGET_PROJECT
@ MOD_SHRINKWRAP_NEAREST_VERTEX
@ MOD_SHRINKWRAP_NEAREST_SURFACE
@ MOD_SHRINKWRAP_ON_SURFACE
@ MOD_SHRINKWRAP_ABOVE_SURFACE
@ MOD_SHRINKWRAP_OUTSIDE_SURFACE
@ MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR
@ MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE
@ MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR
@ MOD_SHRINKWRAP_CULL_TARGET_BACKFACE
@ MOD_SHRINKWRAP_INVERT_VGROUP
@ MOD_SHRINKWRAP_INVERT_CULL_TARGET
Object is a sort of wrapper for general info.
switch((BMIterType) itype)
BMesh const char void * data
BPy_StructRNA * depsgraph
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
static T sum(const btAlignedObjectArray< T > &items)
constexpr int64_t size() const
constexpr T * data() const
constexpr const T * data() const
constexpr int64_t size() const
constexpr IndexRange index_range() const
constexpr bool is_empty() const
GAttributeReader lookup(const StringRef attribute_id) const
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
CCL_NAMESPACE_BEGIN struct Options options
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
int3 corner_tri_get_real_edges(Span< int2 > edges, Span< int > corner_verts, Span< int > corner_edges, const int3 &corner_tri)
static void merge_vert_dir(ShrinkwrapBoundaryVertData *vdata, MutableSpan< int8_t > status, int index, const float edge_dir[3], signed char side)
const ShrinkwrapBoundaryData & boundary_cache_ensure(const Mesh &mesh)
static ShrinkwrapBoundaryData shrinkwrap_build_boundary_data(const Mesh &mesh)
void free(Subdiv *subdiv)
@ SUBDIV_VTX_BOUNDARY_EDGE_ONLY
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_AND_JUNCTIONS
void deform_coarse_vertices(Subdiv *subdiv, const Mesh *coarse_mesh, MutableSpan< float3 > vert_positions)
Subdiv * update_from_mesh(Subdiv *subdiv, const Settings *settings, const Mesh *mesh)
VecBase< int32_t, 2 > int2
VecBase< int32_t, 3 > int3
static void target_project_edge(const ShrinkwrapTreeData *tree, int index, const float co[3], BVHTreeNearest *nearest, int eidx)
static void target_project_tri_clamp(float x[3])
static bool target_project_solve_point_tri(const float *vtri_co[3], const float vtri_no[3][3], const float point_co[3], const float hit_co[3], float hit_dist_sq, float r_hit_co[3], float r_hit_no[3])
void BKE_shrinkwrap_snap_point_to_surface(const ShrinkwrapTreeData *tree, const SpaceTransform *transform, int mode, int hit_idx, const float hit_co[3], const float hit_no[3], float goal_dist, const float point_co[3], float r_point_co[3])
static void mesh_corner_tris_target_project(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc)
void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, const ModifierEvalContext *ctx, Scene *, Object *ob, Mesh *mesh, const MDeformVert *dvert, const int defgrp_index, float(*vertexCos)[3], int numVerts)
void BKE_shrinkwrap_free_tree(ShrinkwrapTreeData *)
static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
static bool update_hit(BVHTreeNearest *nearest, int index, const float co[3], const float hit_co[3], const float hit_no[3])
static void shrinkwrap_snap_with_side(float r_point_co[3], const float point_co[3], const float hit_co[3], const float hit_no[3], float goal_dist, float forcesign, bool forcesnap)
bool BKE_shrinkwrap_project_normal(char options, const float vert[3], const float dir[3], const float ray_radius, const SpaceTransform *transf, ShrinkwrapTreeData *tree, BVHTreeRayHit *hit)
static void target_project_tri_deviation(void *userdata, const float x[3], float r_delta[3])
static void shrinkwrap_calc_nearest_vertex_cb_ex(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict tls)
void BKE_shrinkwrap_mesh_nearest_surface_deform(Depsgraph *depsgraph, Scene *scene, Object *ob_source, Object *ob_target)
static void shrinkwrap_calc_normal_projection_cb_ex(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict tls)
void BKE_shrinkwrap_remesh_target_project(Mesh *src_me, Mesh *target_me, Object *ob_target)
#define TIMEIT_BENCH(expr, id)
bool BKE_shrinkwrap_needs_normals(int shrinkType, int shrinkMode)
static void target_project_tri_jacobian(void *userdata, const float x[3], float r_jacobian[3][3])
void BKE_shrinkwrap_compute_smooth_normal(const ShrinkwrapTreeData *tree, const SpaceTransform *transform, int corner_tri_idx, const float hit_co[3], const float hit_no[3], float r_no[3])
static blender::Array< blender::float3 > shrinkwrap_calc_subdivided_positions(Mesh *mesh, const int subdivision_level)
bool BKE_shrinkwrap_init_tree(ShrinkwrapTreeData *data, Mesh *mesh, int shrinkType, int shrinkMode, bool force_normals)
void shrinkwrapParams_deform(const ShrinkwrapParams ¶ms, Object &object, ShrinkwrapTreeData &tree, const blender::Span< MDeformVert > dvert, const int defgrp_index, const blender::MutableSpan< blender::float3 > positions)
static bool target_project_tri_correct(void *, const float x[3], float step[3], float x_next[3])
void BKE_shrinkwrap_find_nearest_surface(ShrinkwrapTreeData *tree, BVHTreeNearest *nearest, float co[3], int type)
static void shrinkwrap_calc_nearest_surface_point_cb_ex(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict tls)
static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
SpaceTransform * local2aux
ShrinkwrapTreeData * tree
ShrinkwrapCalcData * calc
ShrinkwrapTreeData * aux_tree
SpaceTransform local2target
float(* vert_positions)[3]
blender::Span< blender::float3 > vert_normals
const MDeformVert * dvert
ShrinkwrapTreeData * tree
ShrinkwrapModifierData * smd
struct Object * auxTarget
const float(* vtri_no)[3]
size_t userdata_chunk_size
BVHTree_NearestPointCallback nearest_callback
Span< float3 > vert_positions
VtxBoundaryInterpolation vtx_boundary_interpolation
FVarLinearInterpolation fvar_linear_interpolation