107 edgehash.
add_or_modify({v1,
v2}, [](
int *value) { *value = 1; }, [](
int *value) { (*value)++; });
119 float t1, t2, t3, len1, len2, len3, area;
120 float *varea = sys->
varea, *v1, *
v2, *v3;
144 varea[i1] += (obtuse == 1) ? area : area * 0.5f;
145 varea[i2] += (obtuse == 2) ? area : area * 0.5f;
146 varea[i3] += (obtuse == 3) ? area : area * 0.5f;
157 varea[i1] += (t2 + t3) * 0.25f;
158 varea[i2] += (t1 + t3) * 0.25f;
159 varea[i3] += (t1 + t2) * 0.25f;
166 float *varea = sys->
varea, *v1, *
v2, *v3;
192 sys->
fweights[f][0] = t1 * varea[i1];
193 sys->
fweights[f][1] = t2 * varea[i2];
194 sys->
fweights[f][2] = t3 * varea[i3];
202 sys = MEM_new<LaplacianSystem>(__func__);
206 sys->
faces =
static_cast<int (*)[3]
>(
207 MEM_callocN(
sizeof(
int[3]) * faces_num,
"LaplacianSystemFaces"));
251 for (a = 0, face = sys->
faces; a < sys->faces_num; a++, face++) {
258 for (a = 0, face = sys->
faces; a < sys->faces_num; a++, face++) {
263 for (a = 0; a < verts_num; a++) {
265 if (sys->
varea[a] != 0.0f) {
270 sys->
varea[a] = 1.0f;
280 sys->
fweights =
static_cast<float (*)[3]
>(
281 MEM_callocN(
sizeof(
float[3]) * faces_num,
"LaplacianFWeight"));
284 for (a = 0, face = sys->
faces; a < faces_num; a++, face++) {
289 sys->
faces =
nullptr;
358#define WEIGHT_LIMIT_START 0.05f
359#define WEIGHT_LIMIT_END 0.025f
360#define DISTANCE_EPSILON 1e-4f
374 const float *vtri_co[3];
377 vtri_co[0] =
verts[corner_verts[tri[0]]];
378 vtri_co[1] =
verts[corner_verts[tri[1]]];
379 vtri_co[2] =
verts[corner_verts[tri[2]]];
381#ifdef USE_KDOPBVH_WATERTIGHT
389 if (dist_test < hit->dist) {
394 hit->
dist = dist_test;
414 for (a = 0; a < tris_num; a++) {
419 vtri[0] = corner_verts[tri[0]];
420 vtri[1] = corner_verts[tri[1]];
421 vtri[2] = corner_verts[tri[2]];
474 float closest[3], d[3], dist, cosine;
486 return dist / (0.5f * (cosine + 1.001f));
506 float dist, mindist, h;
507 int j, numclosest = 0;
515 mindist = std::min(dist, mindist);
527 sys->
heat.
p[vertex] = (numclosest > 0) ? 1.0f / numclosest : 0.0f;
530 if (numclosest > 0) {
531 mindist =
max_ff(mindist, 1e-4f);
532 h = numclosest *
C_WEIGHT / (mindist * mindist);
538 sys->
heat.
H[vertex] = h;
544 int a, v1,
v2, v3, (*face)[3];
549 for (a = 0, face = sys->
faces; a < sys->faces_num; a++, face++) {
554 normal_tri_v3(fnor, sys->verts[v1], sys->verts[v2], sys->verts[v3]);
556 add_v3_v3(sys->heat.vert_normals[v1], fnor);
557 add_v3_v3(sys->heat.vert_normals[v2], fnor);
558 add_v3_v3(sys->heat.vert_normals[v3], fnor);
580 for (a = 0; a < verts_num; a++) {
584 for (a = 0; a < tris_num; a++) {
586 vtri[0] = corner_verts[corner_tris[a][0]];
587 vtri[1] = corner_verts[corner_tris[a][1]];
588 vtri[2] = corner_verts[corner_tris[a][2]];
595 for (a = 0; a < verts_num; a++) {
634 const bool *selected,
635 const char **r_error_str)
640 float solution, weight;
641 int *vertsflipped =
nullptr, *
mask =
nullptr;
642 int a, tris_num, j, bbone, firstsegment, lastsegment;
652 *r_error_str =
nullptr;
666 for (
const int i :
faces.index_range()) {
667 for (
const int vert : corner_verts.
slice(
faces[
i])) {
668 mask[vert] = select_vert[vert];
673 else if (use_face_sel) {
677 for (
const int i :
faces.index_range()) {
678 if (select_poly[
i]) {
679 for (
const int vert : corner_verts.
slice(
faces[
i])) {
719 for (j = 0; j < numbones; j++) {
720 if (selected[j] ==
false) {
724 firstsegment = (j == 0 || dgrouplist[j - 1] != dgrouplist[j]);
725 lastsegment = (j == numbones - 1 || dgrouplist[j] != dgrouplist[j + 1]);
726 bbone = !(firstsegment && lastsegment);
729 if (bbone && firstsegment) {
736 if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
762 if (solution > 0.0f) {
777 if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
779 if (solution > 0.0f) {
781 ob, dgroupflip[j], vertsflipped[a], solution,
WEIGHT_ADD);
797 else if (*r_error_str ==
nullptr) {
798 *r_error_str =
N_(
"Bone Heat Weighting: failed to find solution for one or more bones");
803 if (bbone && lastsegment) {
811 if (weight <= 0.0f) {
815 if (vertsflipped && dgroupflip[j] && vertsflipped[a] >= 0) {
818 if (weight <= 0.0f) {
844#define EPSILON 0.0001f
846#define MESHDEFORM_TAG_UNTYPED 0
847#define MESHDEFORM_TAG_BOUNDARY 1
848#define MESHDEFORM_TAG_INTERIOR 2
849#define MESHDEFORM_TAG_EXTERIOR 3
852#define MESHDEFORM_LEN_THRESHOLD 1e-6f
854#define MESHDEFORM_MIN_INFLUENCE 0.0005f
954 float no[3], co[3], dist;
959 face[0] = mdb->
cagecos[corner_verts[tri[0]]];
960 face[1] = mdb->
cagecos[corner_verts[tri[1]]];
961 face[2] = mdb->
cagecos[corner_verts[tri[2]]];
966 if (!isect_ray_tri || dist > isec->
vec_length) {
971 copy_v3_v3(no, face_normals[tri_faces[index]]);
979 if (dist < hit->dist) {
999 float end[3], vec_normal[3];
1007 memset(&isect_mdef, 0,
sizeof(isect_mdef));
1008 isect_mdef.
lambda = 1e10f;
1049 for (
int i = 0;
i < face.
size();
i++) {
1050 copy_v3_v3(mp_cagecos[
i], cagecos[corner_verts[face[
i]]]);
1054 reinterpret_cast<float (*)[3]
>(mp_cagecos.
data()),
1067 float outside[3], start[3], dir[3];
1070 for (
i = 1;
i <= 6;
i++) {
1080 if (isect && !isect->
facing) {
1126 float center[3], ncenter[3];
1133 for (
i = 1;
i <= 6;
i++) {
1150 int *stack, *tag = mdb->
tag;
1151 int a,
b,
i, xyz[3], stacksize,
size = mdb->
size;
1161 while (stacksize > 0) {
1162 a = stack[--stacksize];
1168 for (
i = 1;
i <= 6;
i++) {
1176 stack[stacksize++] =
b;
1192 tb = ti = te = ts = 0;
1209 printf(
"interior %d exterior %d boundary %d semi-boundary %d\n", ti, te, tb, ts);
1223 for (
int i = 0;
i < face.
size();
i++) {
1224 if (corner_verts[face[
i]] == cagevert) {
1233 const float *gridvec,
1237 float dvec[3], ivec[3],
result = 0.0f;
1238 float totweight = 0.0f;
1240 for (
int i = 0;
i < 3;
i++) {
1241 ivec[
i] = int(gridvec[
i]);
1242 dvec[
i] = gridvec[
i] - ivec[
i];
1245 for (
int i = 0;
i < 8;
i++) {
1255 wx = 1.0f - dvec[0];
1264 wy = 1.0f - dvec[1];
1273 wz = 1.0f - dvec[2];
1281 float weight = wx * wy * wz;
1283 totweight += weight;
1286 if (totweight > 0.0f) {
1302 for (
i = 1;
i <= 6;
i++) {
1311 float weight, totweight = 0.0f;
1317 for (
i = 1;
i <= 6;
i++) {
1326 weight = 1.0f / mdb->
width[0];
1332 totweight += weight;
1342 float weight, totweight;
1353 for (
i = 1;
i <= 6;
i++) {
1361 weight = (1.0f / mdb->
width[0]) / totweight;
1371 float rhs, weight, totweight;
1380 for (
i = 1;
i <= 6;
i++) {
1389 weight = (1.0f / isect->
len) / totweight;
1400 float rhs, weight, totweight;
1411 for (
i = 1;
i <= 6;
i++) {
1415 weight = (1.0f / isect->
len) / totweight;
1425 float phi, totweight;
1435 for (
i = 1;
i <= 6;
i++) {
1444 if (totweight != 0.0f) {
1445 mdb->
phi[acenter] = phi / totweight;
1452 float vec[3], gridvec[3];
1453 int a,
b,
x,
y,
z, totvar;
1458 for (a = 0, totvar = 0; a < mdb->
size3; a++) {
1473 for (
z = 0;
z < mdb->
size;
z++) {
1474 for (
y = 0;
y < mdb->
size;
y++) {
1475 for (
x = 0;
x < mdb->
size;
x++) {
1484 for (
z = 0;
z < mdb->
size;
z++) {
1485 for (
y = 0;
y < mdb->
size;
y++) {
1486 for (
x = 0;
x < mdb->
size;
x++) {
1493 for (
z = 0;
z < mdb->
size;
z++) {
1494 for (
y = 0;
y < mdb->
size;
y++) {
1495 for (
x = 0;
x < mdb->
size;
x++) {
1501 for (
z = 0;
z < mdb->
size;
z++) {
1502 for (
y = 0;
y < mdb->
size;
y++) {
1503 for (
x = 0;
x < mdb->
size;
x++) {
1547 mmd->
object, &mmd->
modifier,
"Failed to find bind solution (increase precision?)");
1548 error(
"Mesh Deform: failed to find bind solution.");
1561 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) {
1705 for (a = 0; a < mdb->
size3; a++) {
1711 for (inf = mdb->
dyngrid[a]; inf; inf = inf->
next, mdinf++) {
1714 totweight += mdinf->
weight;
1718 if (totweight > 0.0f) {
1721 mdinf->
weight /= totweight;
1753 float cagemat[4][4])
1768 mdb.
vertexcos =
static_cast<float (*)[3]
>(
1769 MEM_callocN(
sizeof(
float[3]) * verts_num,
"MeshDeformCos"));
1774 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_UTF8(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.
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, AttrType 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)
const ImplicitSharingInfo * info_for_mem_free(void *data)
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