106 {v1,
v2}, [](
int *value) { *value = 1; }, [](
int *value) { (*value)++; });
118 float t1, t2, t3, len1, len2, len3, area;
119 float *varea = sys->
varea, *v1, *
v2, *v3;
143 varea[i1] += (obtuse == 1) ? area : area * 0.5f;
144 varea[i2] += (obtuse == 2) ? area : area * 0.5f;
145 varea[i3] += (obtuse == 3) ? area : area * 0.5f;
156 varea[i1] += (t2 + t3) * 0.25f;
157 varea[i2] += (t1 + t3) * 0.25f;
158 varea[i3] += (t1 + t2) * 0.25f;
165 float *varea = sys->
varea, *v1, *
v2, *v3;
191 sys->
fweights[f][0] = t1 * varea[i1];
192 sys->
fweights[f][1] = t2 * varea[i2];
193 sys->
fweights[f][2] = t3 * varea[i3];
201 sys = MEM_new<LaplacianSystem>(__func__);
203 sys->
verts =
static_cast<float **
>(
204 MEM_callocN(
sizeof(
float *) * verts_num,
"LaplacianSystemVerts"));
205 sys->
vpinned =
static_cast<char *
>(
206 MEM_callocN(
sizeof(
char) * verts_num,
"LaplacianSystemVpinned"));
207 sys->
faces =
static_cast<int(*)[3]
>(
208 MEM_callocN(
sizeof(
int[3]) * faces_num,
"LaplacianSystemFaces"));
249 sys->
varea =
static_cast<float *
>(
250 MEM_callocN(
sizeof(
float) * verts_num,
"LaplacianSystemVarea"));
265 for (a = 0; a < verts_num; a++) {
267 if (sys->
varea[a] != 0.0f) {
272 sys->
varea[a] = 1.0f;
282 sys->
fweights =
static_cast<float(*)[3]
>(
283 MEM_callocN(
sizeof(
float[3]) * faces_num,
"LaplacianFWeight"));
286 for (a = 0, face = sys->
faces; a < faces_num; a++, face++) {
291 sys->
faces =
nullptr;
360#define WEIGHT_LIMIT_START 0.05f
361#define WEIGHT_LIMIT_END 0.025f
362#define DISTANCE_EPSILON 1e-4f
373 const blender::int3 &tri = data->sys->heat.corner_tris[index];
376 const float *vtri_co[3];
379 vtri_co[0] =
verts[corner_verts[tri[0]]];
380 vtri_co[1] =
verts[corner_verts[tri[1]]];
381 vtri_co[2] =
verts[corner_verts[tri[2]]];
383#ifdef USE_KDOPBVH_WATERTIGHT
385 data->start, ray->isect_precalc,
UNPACK3(vtri_co), &dist_test,
nullptr))
391 if (dist_test < hit->dist) {
394 if (
dot_v3v3(n, data->vec) < -1e-5f) {
396 hit->dist = dist_test;
416 for (a = 0; a < tris_num; a++) {
421 vtri[0] = corner_verts[tri[0]];
422 vtri[1] = corner_verts[tri[1]];
423 vtri[2] = corner_verts[tri[2]];
476 float closest[3], d[3], dist, cosine;
488 return dist / (0.5f * (cosine + 1.001f));
508 float dist, mindist, h;
509 int j, numclosest = 0;
517 if (dist < mindist) {
531 sys->
heat.
p[vertex] = (numclosest > 0) ? 1.0f / numclosest : 0.0f;
534 if (numclosest > 0) {
535 mindist =
max_ff(mindist, 1e-4f);
536 h = numclosest *
C_WEIGHT / (mindist * mindist);
542 sys->
heat.
H[vertex] = h;
548 int a, v1,
v2, v3, (*face)[3];
580 sys->
heat.
H =
static_cast<float *
>(
MEM_callocN(
sizeof(
float) * verts_num,
"HeatH"));
581 sys->
heat.
p =
static_cast<float *
>(
MEM_callocN(
sizeof(
float) * verts_num,
"HeatP"));
584 for (a = 0; a < verts_num; a++) {
588 for (a = 0; a < tris_num; a++) {
590 vtri[0] = corner_verts[corner_tris[a][0]];
591 vtri[1] = corner_verts[corner_tris[a][1]];
592 vtri[2] = corner_verts[corner_tris[a][2]];
599 for (a = 0; a < verts_num; a++) {
638 const bool *selected,
639 const char **r_error_str)
644 float solution, weight;
645 int *vertsflipped =
nullptr, *mask =
nullptr;
646 int a, tris_num, j, bbone, firstsegment, lastsegment;
656 *r_error_str =
nullptr;
663 mask =
static_cast<int *
>(
664 MEM_callocN(
sizeof(
int) * mesh->verts_num,
"heat_bone_weighting mask"));
668 const VArray select_vert = *attributes.lookup_or_default<
bool>(
669 ".select_vert", bke::AttrDomain::Point,
false);
671 for (
const int i : faces.index_range()) {
672 for (
const int vert : corner_verts.
slice(faces[i])) {
673 mask[vert] = select_vert[vert];
678 else if (use_face_sel) {
679 const VArray select_poly = *attributes.lookup_or_default<
bool>(
680 ".select_poly", bke::AttrDomain::Face,
false);
682 for (
const int i : faces.index_range()) {
683 if (select_poly[i]) {
684 for (
const int vert : corner_verts.
slice(faces[i])) {
701 vert_positions, faces, corner_verts, {corner_tris, sys->
heat.
tris_num});
717 vertsflipped =
static_cast<int *
>(
MEM_callocN(
sizeof(
int) * mesh->verts_num,
"vertsflipped"));
718 for (a = 0; a < mesh->verts_num; a++) {
724 for (j = 0; j < numbones; j++) {
725 if (selected[j] ==
false) {
729 firstsegment = (j == 0 || dgrouplist[j - 1] != dgrouplist[j]);
730 lastsegment = (j == numbones - 1 || dgrouplist[j] != dgrouplist[j + 1]);
731 bbone = !(firstsegment && lastsegment);
734 if (bbone && firstsegment) {
735 for (a = 0; a < mesh->verts_num; a++) {
736 if (mask && !mask[a]) {
741 if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
750 for (a = 0; a < mesh->verts_num; a++) {
759 for (a = 0; a < mesh->verts_num; a++) {
760 if (mask && !mask[a]) {
767 if (solution > 0.0f) {
782 if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
784 if (solution > 0.0f) {
786 ob, dgroupflip[j], vertsflipped[a], solution,
WEIGHT_ADD);
802 else if (*r_error_str ==
nullptr) {
803 *r_error_str =
N_(
"Bone Heat Weighting: failed to find solution for one or more bones");
808 if (bbone && lastsegment) {
809 for (a = 0; a < mesh->verts_num; a++) {
810 if (mask && !mask[a]) {
816 if (weight <= 0.0f) {
820 if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
823 if (weight <= 0.0f) {
849#define EPSILON 0.0001f
851#define MESHDEFORM_TAG_UNTYPED 0
852#define MESHDEFORM_TAG_BOUNDARY 1
853#define MESHDEFORM_TAG_INTERIOR 2
854#define MESHDEFORM_TAG_EXTERIOR 3
857#define MESHDEFORM_LEN_THRESHOLD 1e-6f
859#define MESHDEFORM_MIN_INFLUENCE 0.0005f
959 float no[3], co[3], dist;
964 face[0] = mdb->
cagecos[corner_verts[tri[0]]];
965 face[1] = mdb->
cagecos[corner_verts[tri[1]]];
966 face[2] = mdb->
cagecos[corner_verts[tri[2]]];
969 ray->origin, ray->isect_precalc,
UNPACK3(face), &dist,
nullptr);
971 if (!isect_ray_tri || dist > isec->
vec_length) {
976 copy_v3_v3(no, face_normals[tri_faces[index]]);
984 if (dist < hit->dist) {
1004 float end[3], vec_normal[3];
1012 memset(&isect_mdef, 0,
sizeof(isect_mdef));
1013 isect_mdef.
lambda = 1e10f;
1054 for (
int i = 0; i < face.size(); i++) {
1055 copy_v3_v3(mp_cagecos[i], cagecos[corner_verts[face[i]]]);
1059 reinterpret_cast<float(*)[3]
>(mp_cagecos.
data()),
1072 float outside[3], start[3], dir[3];
1075 for (i = 1; i <= 6; i++) {
1085 if (isect && !isect->
facing) {
1097 int size = mdb->
size;
1113 return x + y * size +
z * size *
size;
1131 float center[3], ncenter[3];
1138 for (i = 1; i <= 6; i++) {
1155 int *stack, *tag = mdb->
tag;
1156 int a,
b, i, xyz[3], stacksize, size = mdb->
size;
1158 stack =
static_cast<int *
>(
MEM_callocN(
sizeof(
int) * mdb->
size3, __func__));
1166 while (stacksize > 0) {
1167 a = stack[--stacksize];
1169 xyz[2] = a / (size *
size);
1170 xyz[1] = (a - xyz[2] * size *
size) / size;
1171 xyz[0] = a - xyz[1] * size - xyz[2] * size *
size;
1173 for (i = 1; i <= 6; i++) {
1181 stack[stacksize++] =
b;
1188 for (a = 0; a < size * size *
size; a++) {
1197 tb = ti = te = ts = 0;
1198 for (a = 0; a < size * size *
size; a++) {
1214 printf(
"interior %d exterior %d boundary %d semi-boundary %d\n", ti, te, tb, ts);
1228 for (
int i = 0; i < face.size(); i++) {
1229 if (corner_verts[face[i]] == cagevert) {
1238 const float *gridvec,
1242 float dvec[3], ivec[3], result = 0.0f;
1243 float totweight = 0.0f;
1245 for (
int i = 0; i < 3; i++) {
1246 ivec[i] =
int(gridvec[i]);
1247 dvec[i] = gridvec[i] - ivec[i];
1250 for (
int i = 0; i < 8; i++) {
1260 wx = 1.0f - dvec[0];
1269 wy = 1.0f - dvec[1];
1278 wz = 1.0f - dvec[2];
1286 float weight = wx * wy * wz;
1287 result += weight * mdb->
phi[a];
1288 totweight += weight;
1291 if (totweight > 0.0f) {
1292 result /= totweight;
1307 for (i = 1; i <= 6; i++) {
1316 float weight, totweight = 0.0f;
1322 for (i = 1; i <= 6; i++) {
1331 weight = 1.0f / mdb->
width[0];
1337 totweight += weight;
1347 float weight, totweight;
1358 for (i = 1; i <= 6; i++) {
1366 weight = (1.0f / mdb->
width[0]) / totweight;
1376 float rhs, weight, totweight;
1385 for (i = 1; i <= 6; i++) {
1394 weight = (1.0f / isect->
len) / totweight;
1405 float rhs, weight, totweight;
1416 for (i = 1; i <= 6; i++) {
1420 weight = (1.0f / isect->
len) / totweight;
1430 float phi, totweight;
1440 for (i = 1; i <= 6; i++) {
1449 if (totweight != 0.0f) {
1450 mdb->
phi[acenter] = phi / totweight;
1457 float vec[3], gridvec[3];
1458 int a,
b,
x,
y,
z, totvar;
1463 for (a = 0, totvar = 0; a < mdb->
size3; a++) {
1478 for (
z = 0;
z < mdb->
size;
z++) {
1479 for (y = 0; y < mdb->
size; y++) {
1480 for (x = 0; x < mdb->
size; x++) {
1489 for (
z = 0;
z < mdb->
size;
z++) {
1490 for (y = 0; y < mdb->
size; y++) {
1491 for (x = 0; x < mdb->
size; x++) {
1498 for (
z = 0;
z < mdb->
size;
z++) {
1499 for (y = 0; y < mdb->
size; y++) {
1500 for (x = 0; x < mdb->
size; x++) {
1506 for (
z = 0;
z < mdb->
size;
z++) {
1507 for (y = 0; y < mdb->
size; y++) {
1508 for (x = 0; x < mdb->
size; x++) {
1552 mmd->
object, &mmd->
modifier,
"Failed to find bind solution (increase precision?)");
1553 error(
"Mesh Deform: failed to find bind solution.");
1566 printf(
"totalphi deficiency [%s|%d] %d: %.10f\n",
1587 float center[3], vec[3], maxwidth, totweight;
1588 int a,
b,
x,
y,
z, totinside, offset;
1600 mdb->
tag =
static_cast<int *
>(
MEM_callocN(
sizeof(
int) * mdb->
size3,
"MeshDeformBindTag"));
1601 mdb->
phi =
static_cast<float *
>(
MEM_callocN(
sizeof(
float) * mdb->
size3,
"MeshDeformBindPhi"));
1602 mdb->
totalphi =
static_cast<float *
>(
1616 mdb->
weights =
static_cast<float *
>(
1636 for (a = 0; a < 3; a++) {
1637 if (mdb->
max[a] - mdb->
min[a] > maxwidth) {
1638 maxwidth = mdb->
max[a] - mdb->
min[a];
1642 for (a = 0; a < 3; a++) {
1643 center[a] = (mdb->
min[a] + mdb->
max[a]) * 0.5f;
1644 mdb->
min[a] = center[a] - maxwidth * 0.5f;
1645 mdb->
max[a] = center[a] + maxwidth * 0.5f;
1648 mdb->
min[a] -= 2.1f * mdb->
width[a];
1649 mdb->
max[a] += 2.1f * mdb->
width[a];
1672 for (a = 0; a < mdb->
size3; a++) {
1677 for (
z = 0;
z < mdb->
size;
z++) {
1678 for (y = 0; y < mdb->
size; y++) {
1679 for (x = 0; x < mdb->
size; x++) {
1688 for (
z = 0;
z < mdb->
size;
z++) {
1689 for (y = 0; y < mdb->
size; y++) {
1690 for (x = 0; x < mdb->
size; x++) {
1702 for (a = 0; a < mdb->
size3; a++) {
1703 for (inf = mdb->
dyngrid[a]; inf; inf = inf->
next) {
1714 for (a = 0; a < mdb->
size3; a++) {
1720 for (inf = mdb->
dyngrid[a]; inf; inf = inf->
next, mdinf++) {
1723 totweight += mdinf->
weight;
1727 if (totweight > 0.0f) {
1730 mdinf->
weight /= totweight;
1762 float cagemat[4][4])
1776 mdb.vertexcos =
static_cast<float(*)[3]
>(
1777 MEM_callocN(
sizeof(
float[3]) * verts_num,
"MeshDeformCos"));
1778 mdb.verts_num = verts_num;
1780 mdb.cagemesh = cagemesh;
1781 mdb.cage_verts_num = mdb.cagemesh->
verts_num;
1782 mdb.cagecos =
static_cast<float(*)[3]
>(
1783 MEM_callocN(
sizeof(*mdb.cagecos) * mdb.cage_verts_num,
"MeshDeformBindCos"));
1787 for (a = 0; a < mdb.cage_verts_num; a++) {
1790 for (a = 0; a < mdb.verts_num; a++) {
1791 mul_v3_m4v3(mdb.vertexcos[a], mdb.cagemat, vertexcos + a * 3);
1804 for (a = 0; a < mdb.cage_verts_num; a++) {
void free_bvhtree_from_mesh(BVHTreeFromMesh *data)
BVHTree * BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data, const Mesh *mesh, BVHCacheType bvh_cache_type, int tree_type)
@ BVHTREE_FROM_CORNER_TRIS
void BKE_mesh_wrapper_ensure_mdata(Mesh *mesh)
ModifierData * BKE_modifier_get_original(const Object *object, ModifierData *md)
void BKE_modifier_set_error(const Object *ob, ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_modifier_mdef_compact_influences(ModifierData *md)
BVHTree * BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
#define BVH_RAYCAST_DIST_MAX
void BLI_bvhtree_balance(BVHTree *tree)
void BLI_bvhtree_free(BVHTree *tree)
void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
int BLI_bvhtree_ray_cast_ex(const BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata, int flag)
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)
MINLINE float max_ff(float a, float b)
bool isect_ray_tri_v3(const float ray_origin[3], const float ray_direction[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2])
float closest_to_line_segment_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3])
float area_tri_v3(const float v1[3], const float v2[3], const float v3[3])
bool isect_ray_tri_watertight_v3(const float ray_origin[3], const struct IsectRayPrecalc *isect_precalc, const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2])
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float v3[3])
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
void interp_weights_poly_v3(float w[], float v[][3], int n, const float co[3])
void mul_m4_v3(const float M[4][4], float r[3])
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])
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
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 float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
float angle_v3v3v3(const float a[3], const float b[3], const float c[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
struct MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
#define BLI_MEMARENA_STD_BUFSIZE
void BLI_memarena_use_calloc(struct MemArena *ma) ATTR_NONNULL(1)
#define SNPRINTF(dst, format,...)
#define INIT_MINMAX(min, max)
Object is a sort of wrapper for general info.
int mesh_get_x_mirror_vert(Object *ob, Mesh *mesh_eval, int index, bool use_topology)
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
const Value & lookup(const Key &key) const
auto add_or_modify(const Key &key, const CreateValueF &create_value, const ModifyValueF &modify_value) -> decltype(create_value(nullptr))
constexpr Span slice(int64_t start, int64_t size) const
constexpr bool is_empty() const
local_group_size(16, 16) .push_constant(Type b
local_group_size(16, 16) .push_constant(Type rhs
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
LinearSolver * EIG_linear_solver_new(int num_rows, int num_columns, int num_rhs)
LinearSolver * EIG_linear_least_squares_solver_new(int num_rows, int num_columns, int num_rhs)
void EIG_linear_solver_variable_set(LinearSolver *solver, int rhs, int index, double value)
void EIG_linear_solver_right_hand_side_add(LinearSolver *solver, int rhs, int index, double value)
void EIG_linear_solver_delete(LinearSolver *solver)
double EIG_linear_solver_variable_get(LinearSolver *solver, int rhs, int index)
void EIG_linear_solver_matrix_add(LinearSolver *solver, int row, int col, double value)
bool EIG_linear_solver_solve(LinearSolver *solver)
void EIG_linear_solver_variable_lock(LinearSolver *solver, int index)
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
static void meshdeform_bind_floodfill(MeshDeformBind *mdb)
void heat_bone_weighting(Object *ob, Mesh *mesh, float(*verts)[3], int numbones, bDeformGroup **dgrouplist, bDeformGroup **dgroupflip, float(*root)[3], float(*tip)[3], const bool *selected, const char **r_error_str)
static float meshdeform_boundary_phi(const MeshDeformBind *mdb, const MDefBoundIsect *isect, int cagevert)
static void laplacian_system_delete(LaplacianSystem *sys)
BLI_INLINE void meshdeform_cell_center(MeshDeformBind *mdb, int x, int y, int z, int n, float *center)
static void laplacian_triangle_area(LaplacianSystem *sys, int i1, int i2, int i3)
static void start_progress_bar()
float laplacian_system_get_solution(LaplacianSystem *sys, int v)
static void laplacian_system_construct_end(LaplacianSystem *sys)
static int meshdeform_inside_cage(MeshDeformBind *mdb, float *co)
static void heat_set_H(LaplacianSystem *sys, int vertex)
void laplacian_add_right_hand_side(LaplacianSystem *sys, int v, float value)
static float heat_limit_weight(float weight)
int laplacian_system_solve(LaplacianSystem *sys)
static void heat_ray_tree_create(LaplacianSystem *sys)
static void meshdeform_matrix_add_semibound_phi(MeshDeformBind *mdb, int x, int y, int z, int cagevert)
#define WEIGHT_LIMIT_START
static float heat_source_distance(LaplacianSystem *sys, int vertex, int source)
static void meshdeform_matrix_add_cell(MeshDeformBind *mdb, LinearSolver *context, int x, int y, int z)
void ED_mesh_deform_bind_callback(Object *object, MeshDeformModifierData *mmd, Mesh *cagemesh, float *vertexcos, int verts_num, float cagemat[4][4])
#define MESHDEFORM_MIN_INFLUENCE
static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind *mdb)
static int laplacian_edge_count(const blender::Map< blender::OrderedEdge, int > &edgehash, int v1, int v2)
static void end_progress_bar()
static void progress_bar(int, const char *)
static void meshdeform_add_intersections(MeshDeformBind *mdb, int x, int y, int z)
static void harmonic_coordinates_bind(MeshDeformModifierData *mmd, MeshDeformBind *mdb)
void laplacian_add_triangle(LaplacianSystem *sys, int v1, int v2, int v3)
static void waitcursor(int)
static void error(const char *str)
static LaplacianSystem * laplacian_system_construct_begin(int verts_num, int faces_num, int lsq)
static MDefBoundIsect * meshdeform_ray_tree_intersect(MeshDeformBind *mdb, const float co1[3], const float co2[3])
static int heat_source_closest(LaplacianSystem *sys, int vertex, int source)
BLI_INLINE int meshdeform_index(MeshDeformBind *mdb, int x, int y, int z, int n)
static void meshdeform_matrix_add_exterior_phi(MeshDeformBind *mdb, int x, int y, int z, int)
static float meshdeform_boundary_total_weight(MeshDeformBind *mdb, int x, int y, int z)
static void heat_calc_vnormals(LaplacianSystem *sys)
static void harmonic_ray_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
static void heat_laplacian_create(LaplacianSystem *sys)
static const int MESHDEFORM_OFFSET[7][3]
#define MESHDEFORM_TAG_UNTYPED
#define MESHDEFORM_TAG_BOUNDARY
static void meshdeform_check_semibound(MeshDeformBind *mdb, int x, int y, int z)
#define MESHDEFORM_TAG_INTERIOR
static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int i2, int i3)
#define MESHDEFORM_LEN_THRESHOLD
static void heat_system_free(LaplacianSystem *sys)
static int heat_ray_source_visible(LaplacianSystem *sys, int vertex, int source)
static void meshdeform_matrix_add_rhs(MeshDeformBind *mdb, LinearSolver *context, int x, int y, int z, int cagevert)
void laplacian_add_vertex(LaplacianSystem *sys, float *co, int pinned)
static void laplacian_increase_edge_count(blender::Map< blender::OrderedEdge, int > &edgehash, int v1, int v2)
#define MESHDEFORM_TAG_EXTERIOR
static float meshdeform_interp_w(MeshDeformBind *mdb, const float *gridvec, float *, int)
void laplacian_begin_solve(LaplacianSystem *sys, int index)
void corner_tris_calc(Span< float3 > vert_positions, OffsetIndices< int > faces, Span< int > corner_verts, MutableSpan< int3 > corner_tris)
float vgroup_vert_weight(Object *ob, bDeformGroup *dg, int vertnum)
void vgroup_vert_add(Object *ob, bDeformGroup *dg, int vertnum, float weight, int assignmode)
void vgroup_vert_remove(Object *ob, bDeformGroup *dg, int vertnum)
const blender::int3 * corner_tris
blender::Span< int > corner_verts
const blender::int3 ** vltree
blender::Map< blender::OrderedEdge, int > edgehash
struct LaplacianSystem::HeatWeighting heat