108 {v1,
v2}, [](
int *value) { *value = 1; }, [](
int *value) { (*value)++; });
120 float t1, t2, t3, len1, len2, len3, area;
121 float *varea = sys->
varea, *v1, *
v2, *v3;
145 varea[i1] += (obtuse == 1) ? area : area * 0.5f;
146 varea[i2] += (obtuse == 2) ? area : area * 0.5f;
147 varea[i3] += (obtuse == 3) ? area : area * 0.5f;
158 varea[i1] += (t2 + t3) * 0.25f;
159 varea[i2] += (t1 + t3) * 0.25f;
160 varea[i3] += (t1 + t2) * 0.25f;
167 float *varea = sys->
varea, *v1, *
v2, *v3;
193 sys->
fweights[f][0] = t1 * varea[i1];
194 sys->
fweights[f][1] = t2 * varea[i2];
195 sys->
fweights[f][2] = t3 * varea[i3];
203 sys = MEM_new<LaplacianSystem>(__func__);
207 sys->
faces =
static_cast<int(*)[3]
>(
208 MEM_callocN(
sizeof(
int[3]) * faces_num,
"LaplacianSystemFaces"));
252 for (a = 0, face = sys->
faces; a < sys->faces_num; a++, face++) {
259 for (a = 0, face = sys->
faces; a < sys->faces_num; a++, face++) {
264 for (a = 0; a < verts_num; a++) {
266 if (sys->
varea[a] != 0.0f) {
271 sys->
varea[a] = 1.0f;
281 sys->
fweights =
static_cast<float(*)[3]
>(
282 MEM_callocN(
sizeof(
float[3]) * faces_num,
"LaplacianFWeight"));
285 for (a = 0, face = sys->
faces; a < faces_num; a++, face++) {
290 sys->
faces =
nullptr;
359#define WEIGHT_LIMIT_START 0.05f
360#define WEIGHT_LIMIT_END 0.025f
361#define DISTANCE_EPSILON 1e-4f
374 float(*
verts)[3] =
data->sys->heat.verts;
375 const float *vtri_co[3];
378 vtri_co[0] =
verts[corner_verts[tri[0]]];
379 vtri_co[1] =
verts[corner_verts[tri[1]]];
380 vtri_co[2] =
verts[corner_verts[tri[2]]];
382#ifdef USE_KDOPBVH_WATERTIGHT
390 if (dist_test < hit->dist) {
395 hit->
dist = dist_test;
415 for (a = 0; a < tris_num; a++) {
420 vtri[0] = corner_verts[tri[0]];
421 vtri[1] = corner_verts[tri[1]];
422 vtri[2] = corner_verts[tri[2]];
475 float closest[3], d[3], dist, cosine;
487 return dist / (0.5f * (cosine + 1.001f));
507 float dist, mindist, h;
508 int j, numclosest = 0;
516 mindist = std::min(dist, mindist);
528 sys->
heat.
p[vertex] = (numclosest > 0) ? 1.0f / numclosest : 0.0f;
531 if (numclosest > 0) {
532 mindist =
max_ff(mindist, 1e-4f);
533 h = numclosest *
C_WEIGHT / (mindist * mindist);
539 sys->
heat.
H[vertex] = h;
545 int a, v1,
v2, v3, (*face)[3];
550 for (a = 0, face = sys->
faces; a < sys->faces_num; a++, face++) {
555 normal_tri_v3(fnor, sys->verts[v1], sys->verts[v2], sys->verts[v3]);
557 add_v3_v3(sys->heat.vert_normals[v1], fnor);
558 add_v3_v3(sys->heat.vert_normals[v2], fnor);
559 add_v3_v3(sys->heat.vert_normals[v3], fnor);
581 for (a = 0; a < verts_num; a++) {
585 for (a = 0; a < tris_num; a++) {
587 vtri[0] = corner_verts[corner_tris[a][0]];
588 vtri[1] = corner_verts[corner_tris[a][1]];
589 vtri[2] = corner_verts[corner_tris[a][2]];
596 for (a = 0; a < verts_num; a++) {
635 const bool *selected,
636 const char **r_error_str)
641 float solution, weight;
642 int *vertsflipped =
nullptr, *
mask =
nullptr;
643 int a, tris_num, j, bbone, firstsegment, lastsegment;
653 *r_error_str =
nullptr;
667 for (
const int i :
faces.index_range()) {
668 for (
const int vert : corner_verts.
slice(
faces[
i])) {
669 mask[vert] = select_vert[vert];
674 else if (use_face_sel) {
678 for (
const int i :
faces.index_range()) {
679 if (select_poly[
i]) {
680 for (
const int vert : corner_verts.
slice(
faces[
i])) {
720 for (j = 0; j < numbones; j++) {
721 if (selected[j] ==
false) {
725 firstsegment = (j == 0 || dgrouplist[j - 1] != dgrouplist[j]);
726 lastsegment = (j == numbones - 1 || dgrouplist[j] != dgrouplist[j + 1]);
727 bbone = !(firstsegment && lastsegment);
730 if (bbone && firstsegment) {
737 if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
763 if (solution > 0.0f) {
778 if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
780 if (solution > 0.0f) {
782 ob, dgroupflip[j], vertsflipped[a], solution,
WEIGHT_ADD);
798 else if (*r_error_str ==
nullptr) {
799 *r_error_str =
N_(
"Bone Heat Weighting: failed to find solution for one or more bones");
804 if (bbone && lastsegment) {
812 if (weight <= 0.0f) {
816 if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
819 if (weight <= 0.0f) {
845#define EPSILON 0.0001f
847#define MESHDEFORM_TAG_UNTYPED 0
848#define MESHDEFORM_TAG_BOUNDARY 1
849#define MESHDEFORM_TAG_INTERIOR 2
850#define MESHDEFORM_TAG_EXTERIOR 3
853#define MESHDEFORM_LEN_THRESHOLD 1e-6f
855#define MESHDEFORM_MIN_INFLUENCE 0.0005f
955 float no[3], co[3], dist;
960 face[0] = mdb->
cagecos[corner_verts[tri[0]]];
961 face[1] = mdb->
cagecos[corner_verts[tri[1]]];
962 face[2] = mdb->
cagecos[corner_verts[tri[2]]];
967 if (!isect_ray_tri || dist > isec->
vec_length) {
972 copy_v3_v3(no, face_normals[tri_faces[index]]);
980 if (dist < hit->dist) {
1000 float end[3], vec_normal[3];
1008 memset(&isect_mdef, 0,
sizeof(isect_mdef));
1009 isect_mdef.
lambda = 1e10f;
1030 const float(*cagecos)[3] = mdb->
cagecos;
1050 for (
int i = 0;
i < face.
size();
i++) {
1051 copy_v3_v3(mp_cagecos[
i], cagecos[corner_verts[face[
i]]]);
1055 reinterpret_cast<float(*)[3]
>(mp_cagecos.
data()),
1068 float outside[3], start[3], dir[3];
1071 for (
i = 1;
i <= 6;
i++) {
1081 if (isect && !isect->
facing) {
1127 float center[3], ncenter[3];
1134 for (
i = 1;
i <= 6;
i++) {
1151 int *stack, *tag = mdb->
tag;
1152 int a,
b,
i, xyz[3], stacksize,
size = mdb->
size;
1162 while (stacksize > 0) {
1163 a = stack[--stacksize];
1169 for (
i = 1;
i <= 6;
i++) {
1177 stack[stacksize++] =
b;
1193 tb = ti = te = ts = 0;
1210 printf(
"interior %d exterior %d boundary %d semi-boundary %d\n", ti, te, tb, ts);
1224 for (
int i = 0;
i < face.
size();
i++) {
1225 if (corner_verts[face[
i]] == cagevert) {
1234 const float *gridvec,
1238 float dvec[3], ivec[3],
result = 0.0f;
1239 float totweight = 0.0f;
1241 for (
int i = 0;
i < 3;
i++) {
1242 ivec[
i] = int(gridvec[
i]);
1243 dvec[
i] = gridvec[
i] - ivec[
i];
1246 for (
int i = 0;
i < 8;
i++) {
1256 wx = 1.0f - dvec[0];
1265 wy = 1.0f - dvec[1];
1274 wz = 1.0f - dvec[2];
1282 float weight = wx * wy * wz;
1284 totweight += weight;
1287 if (totweight > 0.0f) {
1303 for (
i = 1;
i <= 6;
i++) {
1312 float weight, totweight = 0.0f;
1318 for (
i = 1;
i <= 6;
i++) {
1327 weight = 1.0f / mdb->
width[0];
1333 totweight += weight;
1343 float weight, totweight;
1354 for (
i = 1;
i <= 6;
i++) {
1362 weight = (1.0f / mdb->
width[0]) / totweight;
1372 float rhs, weight, totweight;
1381 for (
i = 1;
i <= 6;
i++) {
1390 weight = (1.0f / isect->
len) / totweight;
1401 float rhs, weight, totweight;
1412 for (
i = 1;
i <= 6;
i++) {
1416 weight = (1.0f / isect->
len) / totweight;
1426 float phi, totweight;
1436 for (
i = 1;
i <= 6;
i++) {
1445 if (totweight != 0.0f) {
1446 mdb->
phi[acenter] = phi / totweight;
1453 float vec[3], gridvec[3];
1454 int a,
b,
x,
y,
z, totvar;
1459 for (a = 0, totvar = 0; a < mdb->
size3; a++) {
1474 for (
z = 0;
z < mdb->
size;
z++) {
1475 for (
y = 0;
y < mdb->
size;
y++) {
1476 for (
x = 0;
x < mdb->
size;
x++) {
1485 for (
z = 0;
z < mdb->
size;
z++) {
1486 for (
y = 0;
y < mdb->
size;
y++) {
1487 for (
x = 0;
x < mdb->
size;
x++) {
1494 for (
z = 0;
z < mdb->
size;
z++) {
1495 for (
y = 0;
y < mdb->
size;
y++) {
1496 for (
x = 0;
x < mdb->
size;
x++) {
1502 for (
z = 0;
z < mdb->
size;
z++) {
1503 for (
y = 0;
y < mdb->
size;
y++) {
1504 for (
x = 0;
x < mdb->
size;
x++) {
1548 mmd->
object, &mmd->
modifier,
"Failed to find bind solution (increase precision?)");
1549 error(
"Mesh Deform: failed to find bind solution.");
1562 printf(
"totalphi deficiency [%s|%d] %d: %.10f\n",
1583 float center[3], vec[3], maxwidth, totweight;
1584 int a,
b,
x,
y,
z, totinside, offset;
1629 for (a = 0; a < 3; a++) {
1630 maxwidth = std::max(mdb->
max[a] - mdb->
min[a], maxwidth);
1633 for (a = 0; a < 3; a++) {
1634 center[a] = (mdb->
min[a] + mdb->
max[a]) * 0.5f;
1635 mdb->
min[a] = center[a] - maxwidth * 0.5f;
1636 mdb->
max[a] = center[a] + maxwidth * 0.5f;
1639 mdb->
min[a] -= 2.1f * mdb->
width[a];
1640 mdb->
max[a] += 2.1f * mdb->
width[a];
1663 for (a = 0; a < mdb->
size3; a++) {
1668 for (
z = 0;
z < mdb->
size;
z++) {
1669 for (
y = 0;
y < mdb->
size;
y++) {
1670 for (
x = 0;
x < mdb->
size;
x++) {
1679 for (
z = 0;
z < mdb->
size;
z++) {
1680 for (
y = 0;
y < mdb->
size;
y++) {
1681 for (
x = 0;
x < mdb->
size;
x++) {
1693 for (a = 0; a < mdb->
size3; a++) {
1694 for (inf = mdb->
dyngrid[a]; inf; inf = inf->
next) {
1703 for (a = 0; a < mdb->
size3; a++) {
1709 for (inf = mdb->
dyngrid[a]; inf; inf = inf->
next, mdinf++) {
1712 totweight += mdinf->
weight;
1716 if (totweight > 0.0f) {
1719 mdinf->
weight /= totweight;
1750 float cagemat[4][4])
1764 mdb.
vertexcos =
static_cast<float(*)[3]
>(
1765 MEM_callocN(
sizeof(
float[3]) * verts_num,
"MeshDeformCos"));
1770 mdb.
cagecos =
static_cast<float(*)[3]
>(
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 float normalize_v3(float n[3])
#define BLI_MEMARENA_STD_BUFSIZE
MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
void BLI_memarena_free(MemArena *ma) ATTR_NONNULL(1)
void * BLI_memarena_alloc(MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void BLI_memarena_use_calloc(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.
for(;discarded_id_iter !=nullptr;discarded_id_iter=static_cast< ID * >(discarded_id_iter->next))
BMesh const char void * data
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.
bool closest(btVector3 &v)
constexpr int64_t size() const
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
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
LinearSolver * EIG_linear_solver_new(int num_rows, int num_columns, int num_right_hand_sides)
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)
LinearSolver * EIG_linear_least_squares_solver_new(int num_rows, int num_columns, int num_right_hand_sides)
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_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_callocN(size_t len, const char *str)
void MEM_freeN(void *vmemh)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
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)
VecBase< int32_t, 3 > int3
struct IsectRayPrecalc * isect_precalc
const blender::int3 * corner_tris
blender::Span< int > corner_verts
const blender::int3 ** vltree
blender::Map< blender::OrderedEdge, int > edgehash
struct LaplacianSystem::HeatWeighting heat