Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/modifiers/intern/MOD_surfacedeform.c')
-rw-r--r--source/blender/modifiers/intern/MOD_surfacedeform.c2235
1 files changed, 1140 insertions, 1095 deletions
diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
index 46f4f9c78e9..2a9fff47e5d 100644
--- a/source/blender/modifiers/intern/MOD_surfacedeform.c
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -44,1221 +44,1266 @@
#include "MOD_util.h"
typedef struct SDefAdjacency {
- struct SDefAdjacency *next;
- unsigned int index;
+ struct SDefAdjacency *next;
+ unsigned int index;
} SDefAdjacency;
typedef struct SDefAdjacencyArray {
- SDefAdjacency *first;
- unsigned int num; /* Careful, this is twice the number of polygons (avoids an extra loop) */
+ SDefAdjacency *first;
+ unsigned int num; /* Careful, this is twice the number of polygons (avoids an extra loop) */
} SDefAdjacencyArray;
typedef struct SDefEdgePolys {
- unsigned int polys[2], num;
+ unsigned int polys[2], num;
} SDefEdgePolys;
typedef struct SDefBindCalcData {
- BVHTreeFromMesh * const treeData;
- const SDefAdjacencyArray * const vert_edges;
- const SDefEdgePolys * const edge_polys;
- SDefVert * const bind_verts;
- const MLoopTri * const looptri;
- const MPoly * const mpoly;
- const MEdge * const medge;
- const MLoop * const mloop;
- float (* const targetCos)[3];
- float (* const vertexCos)[3];
- float imat[4][4];
- const float falloff;
- int success;
+ BVHTreeFromMesh *const treeData;
+ const SDefAdjacencyArray *const vert_edges;
+ const SDefEdgePolys *const edge_polys;
+ SDefVert *const bind_verts;
+ const MLoopTri *const looptri;
+ const MPoly *const mpoly;
+ const MEdge *const medge;
+ const MLoop *const mloop;
+ float (*const targetCos)[3];
+ float (*const vertexCos)[3];
+ float imat[4][4];
+ const float falloff;
+ int success;
} SDefBindCalcData;
typedef struct SDefBindPoly {
- float (*coords)[3];
- float (*coords_v2)[2];
- float point_v2[2];
- float weight_angular;
- float weight_dist_proj;
- float weight_dist;
- float weight;
- float scales[2];
- float centroid[3];
- float centroid_v2[2];
- float normal[3];
- float cent_edgemid_vecs_v2[2][2];
- float edgemid_angle;
- float point_edgemid_angles[2];
- float corner_edgemid_angles[2];
- float dominant_angle_weight;
- unsigned int index;
- unsigned int numverts;
- unsigned int loopstart;
- unsigned int edge_inds[2];
- unsigned int edge_vert_inds[2];
- unsigned int corner_ind;
- unsigned int dominant_edge;
- bool inside;
+ float (*coords)[3];
+ float (*coords_v2)[2];
+ float point_v2[2];
+ float weight_angular;
+ float weight_dist_proj;
+ float weight_dist;
+ float weight;
+ float scales[2];
+ float centroid[3];
+ float centroid_v2[2];
+ float normal[3];
+ float cent_edgemid_vecs_v2[2][2];
+ float edgemid_angle;
+ float point_edgemid_angles[2];
+ float corner_edgemid_angles[2];
+ float dominant_angle_weight;
+ unsigned int index;
+ unsigned int numverts;
+ unsigned int loopstart;
+ unsigned int edge_inds[2];
+ unsigned int edge_vert_inds[2];
+ unsigned int corner_ind;
+ unsigned int dominant_edge;
+ bool inside;
} SDefBindPoly;
typedef struct SDefBindWeightData {
- SDefBindPoly *bind_polys;
- unsigned int numpoly;
- unsigned int numbinds;
+ SDefBindPoly *bind_polys;
+ unsigned int numpoly;
+ unsigned int numbinds;
} SDefBindWeightData;
typedef struct SDefDeformData {
- const SDefVert * const bind_verts;
- float (* const targetCos)[3];
- float (* const vertexCos)[3];
+ const SDefVert *const bind_verts;
+ float (*const targetCos)[3];
+ float (*const vertexCos)[3];
} SDefDeformData;
/* Bind result values */
enum {
- MOD_SDEF_BIND_RESULT_SUCCESS = 1,
- MOD_SDEF_BIND_RESULT_GENERIC_ERR = 0,
- MOD_SDEF_BIND_RESULT_MEM_ERR = -1,
- MOD_SDEF_BIND_RESULT_NONMANY_ERR = -2,
- MOD_SDEF_BIND_RESULT_CONCAVE_ERR = -3,
- MOD_SDEF_BIND_RESULT_OVERLAP_ERR = -4,
+ MOD_SDEF_BIND_RESULT_SUCCESS = 1,
+ MOD_SDEF_BIND_RESULT_GENERIC_ERR = 0,
+ MOD_SDEF_BIND_RESULT_MEM_ERR = -1,
+ MOD_SDEF_BIND_RESULT_NONMANY_ERR = -2,
+ MOD_SDEF_BIND_RESULT_CONCAVE_ERR = -3,
+ MOD_SDEF_BIND_RESULT_OVERLAP_ERR = -4,
};
/* Infinite weight flags */
enum {
- MOD_SDEF_INFINITE_WEIGHT_ANGULAR = (1 << 0),
- MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ = (1 << 1),
- MOD_SDEF_INFINITE_WEIGHT_DIST = (1 << 2),
+ MOD_SDEF_INFINITE_WEIGHT_ANGULAR = (1 << 0),
+ MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ = (1 << 1),
+ MOD_SDEF_INFINITE_WEIGHT_DIST = (1 << 2),
};
static void initData(ModifierData *md)
{
- SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
- smd->target = NULL;
- smd->verts = NULL;
- smd->flags = 0;
- smd->falloff = 4.0f;
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+ smd->target = NULL;
+ smd->verts = NULL;
+ smd->flags = 0;
+ smd->falloff = 4.0f;
}
static void freeData(ModifierData *md)
{
- SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
-
- if (smd->verts) {
- for (int i = 0; i < smd->numverts; i++) {
- if (smd->verts[i].binds) {
- for (int j = 0; j < smd->verts[i].numbinds; j++) {
- MEM_SAFE_FREE(smd->verts[i].binds[j].vert_inds);
- MEM_SAFE_FREE(smd->verts[i].binds[j].vert_weights);
- }
-
- MEM_SAFE_FREE(smd->verts[i].binds);
- }
- }
-
- MEM_SAFE_FREE(smd->verts);
- }
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+
+ if (smd->verts) {
+ for (int i = 0; i < smd->numverts; i++) {
+ if (smd->verts[i].binds) {
+ for (int j = 0; j < smd->verts[i].numbinds; j++) {
+ MEM_SAFE_FREE(smd->verts[i].binds[j].vert_inds);
+ MEM_SAFE_FREE(smd->verts[i].binds[j].vert_weights);
+ }
+
+ MEM_SAFE_FREE(smd->verts[i].binds);
+ }
+ }
+
+ MEM_SAFE_FREE(smd->verts);
+ }
}
static void copyData(const ModifierData *md, ModifierData *target, const int flag)
{
- const SurfaceDeformModifierData *smd = (const SurfaceDeformModifierData *)md;
- SurfaceDeformModifierData *tsmd = (SurfaceDeformModifierData *)target;
-
- modifier_copyData_generic(md, target, flag);
-
- if (smd->verts) {
- tsmd->verts = MEM_dupallocN(smd->verts);
-
- for (int i = 0; i < smd->numverts; i++) {
- if (smd->verts[i].binds) {
- tsmd->verts[i].binds = MEM_dupallocN(smd->verts[i].binds);
-
- for (int j = 0; j < smd->verts[i].numbinds; j++) {
- if (smd->verts[i].binds[j].vert_inds) {
- tsmd->verts[i].binds[j].vert_inds = MEM_dupallocN(smd->verts[i].binds[j].vert_inds);
- }
-
- if (smd->verts[i].binds[j].vert_weights) {
- tsmd->verts[i].binds[j].vert_weights = MEM_dupallocN(smd->verts[i].binds[j].vert_weights);
- }
- }
- }
- }
- }
+ const SurfaceDeformModifierData *smd = (const SurfaceDeformModifierData *)md;
+ SurfaceDeformModifierData *tsmd = (SurfaceDeformModifierData *)target;
+
+ modifier_copyData_generic(md, target, flag);
+
+ if (smd->verts) {
+ tsmd->verts = MEM_dupallocN(smd->verts);
+
+ for (int i = 0; i < smd->numverts; i++) {
+ if (smd->verts[i].binds) {
+ tsmd->verts[i].binds = MEM_dupallocN(smd->verts[i].binds);
+
+ for (int j = 0; j < smd->verts[i].numbinds; j++) {
+ if (smd->verts[i].binds[j].vert_inds) {
+ tsmd->verts[i].binds[j].vert_inds = MEM_dupallocN(smd->verts[i].binds[j].vert_inds);
+ }
+
+ if (smd->verts[i].binds[j].vert_weights) {
+ tsmd->verts[i].binds[j].vert_weights = MEM_dupallocN(
+ smd->verts[i].binds[j].vert_weights);
+ }
+ }
+ }
+ }
+ }
}
static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
{
- SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
- walk(userData, ob, &smd->target, IDWALK_NOP);
+ walk(userData, ob, &smd->target, IDWALK_NOP);
}
static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
{
- SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
- if (smd->target != NULL) {
- DEG_add_object_relation(ctx->node, smd->target, DEG_OB_COMP_GEOMETRY, "Surface Deform Modifier");
- }
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+ if (smd->target != NULL) {
+ DEG_add_object_relation(
+ ctx->node, smd->target, DEG_OB_COMP_GEOMETRY, "Surface Deform Modifier");
+ }
}
-static void freeAdjacencyMap(SDefAdjacencyArray * const vert_edges, SDefAdjacency * const adj_ref, SDefEdgePolys * const edge_polys)
+static void freeAdjacencyMap(SDefAdjacencyArray *const vert_edges,
+ SDefAdjacency *const adj_ref,
+ SDefEdgePolys *const edge_polys)
{
- MEM_freeN(edge_polys);
+ MEM_freeN(edge_polys);
- MEM_freeN(adj_ref);
+ MEM_freeN(adj_ref);
- MEM_freeN(vert_edges);
+ MEM_freeN(vert_edges);
}
-static int buildAdjacencyMap(
- const MPoly *poly, const MEdge *edge, const MLoop * const mloop, const unsigned int numpoly, const unsigned int numedges,
- SDefAdjacencyArray * const vert_edges, SDefAdjacency *adj, SDefEdgePolys * const edge_polys)
+static int buildAdjacencyMap(const MPoly *poly,
+ const MEdge *edge,
+ const MLoop *const mloop,
+ const unsigned int numpoly,
+ const unsigned int numedges,
+ SDefAdjacencyArray *const vert_edges,
+ SDefAdjacency *adj,
+ SDefEdgePolys *const edge_polys)
{
- const MLoop *loop;
-
- /* Fing polygons adjacent to edges */
- for (int i = 0; i < numpoly; i++, poly++) {
- loop = &mloop[poly->loopstart];
-
- for (int j = 0; j < poly->totloop; j++, loop++) {
- if (edge_polys[loop->e].num == 0) {
- edge_polys[loop->e].polys[0] = i;
- edge_polys[loop->e].polys[1] = -1;
- edge_polys[loop->e].num++;
- }
- else if (edge_polys[loop->e].num == 1) {
- edge_polys[loop->e].polys[1] = i;
- edge_polys[loop->e].num++;
- }
- else {
- return MOD_SDEF_BIND_RESULT_NONMANY_ERR;
- }
- }
- }
-
- /* Find edges adjacent to vertices */
- for (int i = 0; i < numedges; i++, edge++) {
- adj->next = vert_edges[edge->v1].first;
- adj->index = i;
- vert_edges[edge->v1].first = adj;
- vert_edges[edge->v1].num += edge_polys[i].num;
- adj++;
-
- adj->next = vert_edges[edge->v2].first;
- adj->index = i;
- vert_edges[edge->v2].first = adj;
- vert_edges[edge->v2].num += edge_polys[i].num;
- adj++;
- }
-
- return MOD_SDEF_BIND_RESULT_SUCCESS;
+ const MLoop *loop;
+
+ /* Fing polygons adjacent to edges */
+ for (int i = 0; i < numpoly; i++, poly++) {
+ loop = &mloop[poly->loopstart];
+
+ for (int j = 0; j < poly->totloop; j++, loop++) {
+ if (edge_polys[loop->e].num == 0) {
+ edge_polys[loop->e].polys[0] = i;
+ edge_polys[loop->e].polys[1] = -1;
+ edge_polys[loop->e].num++;
+ }
+ else if (edge_polys[loop->e].num == 1) {
+ edge_polys[loop->e].polys[1] = i;
+ edge_polys[loop->e].num++;
+ }
+ else {
+ return MOD_SDEF_BIND_RESULT_NONMANY_ERR;
+ }
+ }
+ }
+
+ /* Find edges adjacent to vertices */
+ for (int i = 0; i < numedges; i++, edge++) {
+ adj->next = vert_edges[edge->v1].first;
+ adj->index = i;
+ vert_edges[edge->v1].first = adj;
+ vert_edges[edge->v1].num += edge_polys[i].num;
+ adj++;
+
+ adj->next = vert_edges[edge->v2].first;
+ adj->index = i;
+ vert_edges[edge->v2].first = adj;
+ vert_edges[edge->v2].num += edge_polys[i].num;
+ adj++;
+ }
+
+ return MOD_SDEF_BIND_RESULT_SUCCESS;
}
-BLI_INLINE void sortPolyVertsEdge(unsigned int *indices, const MLoop * const mloop, const unsigned int edge, const unsigned int num)
+BLI_INLINE void sortPolyVertsEdge(unsigned int *indices,
+ const MLoop *const mloop,
+ const unsigned int edge,
+ const unsigned int num)
{
- bool found = false;
-
- for (int i = 0; i < num; i++) {
- if (mloop[i].e == edge) {
- found = true;
- }
- if (found) {
- *indices = mloop[i].v;
- indices++;
- }
- }
-
- /* Fill in remaining vertex indices that occur before the edge */
- for (int i = 0; mloop[i].e != edge; i++) {
- *indices = mloop[i].v;
- indices++;
- }
+ bool found = false;
+
+ for (int i = 0; i < num; i++) {
+ if (mloop[i].e == edge) {
+ found = true;
+ }
+ if (found) {
+ *indices = mloop[i].v;
+ indices++;
+ }
+ }
+
+ /* Fill in remaining vertex indices that occur before the edge */
+ for (int i = 0; mloop[i].e != edge; i++) {
+ *indices = mloop[i].v;
+ indices++;
+ }
}
-BLI_INLINE void sortPolyVertsTri(unsigned int *indices, const MLoop * const mloop, const unsigned int loopstart, const unsigned int num)
+BLI_INLINE void sortPolyVertsTri(unsigned int *indices,
+ const MLoop *const mloop,
+ const unsigned int loopstart,
+ const unsigned int num)
{
- for (int i = loopstart; i < num; i++) {
- *indices = mloop[i].v;
- indices++;
- }
-
- for (int i = 0; i < loopstart; i++) {
- *indices = mloop[i].v;
- indices++;
- }
+ for (int i = loopstart; i < num; i++) {
+ *indices = mloop[i].v;
+ indices++;
+ }
+
+ for (int i = 0; i < loopstart; i++) {
+ *indices = mloop[i].v;
+ indices++;
+ }
}
-BLI_INLINE unsigned int nearestVert(SDefBindCalcData * const data, const float point_co[3])
+BLI_INLINE unsigned int nearestVert(SDefBindCalcData *const data, const float point_co[3])
{
- BVHTreeNearest nearest = { .dist_sq = FLT_MAX, .index = -1, };
- const MPoly *poly;
- const MEdge *edge;
- const MLoop *loop;
- float t_point[3];
- float max_dist = FLT_MAX;
- float dist;
- unsigned int index = 0;
-
- mul_v3_m4v3(t_point, data->imat, point_co);
-
- BLI_bvhtree_find_nearest(data->treeData->tree, t_point, &nearest, data->treeData->nearest_callback, data->treeData);
-
- poly = &data->mpoly[data->looptri[nearest.index].poly];
- loop = &data->mloop[poly->loopstart];
-
- for (int i = 0; i < poly->totloop; i++, loop++) {
- edge = &data->medge[loop->e];
- dist = dist_squared_to_line_segment_v3(point_co, data->targetCos[edge->v1], data->targetCos[edge->v2]);
-
- if (dist < max_dist) {
- max_dist = dist;
- index = loop->e;
- }
- }
-
- edge = &data->medge[index];
- if (len_squared_v3v3(point_co, data->targetCos[edge->v1]) < len_squared_v3v3(point_co, data->targetCos[edge->v2])) {
- return edge->v1;
- }
- else {
- return edge->v2;
- }
+ BVHTreeNearest nearest = {
+ .dist_sq = FLT_MAX,
+ .index = -1,
+ };
+ const MPoly *poly;
+ const MEdge *edge;
+ const MLoop *loop;
+ float t_point[3];
+ float max_dist = FLT_MAX;
+ float dist;
+ unsigned int index = 0;
+
+ mul_v3_m4v3(t_point, data->imat, point_co);
+
+ BLI_bvhtree_find_nearest(
+ data->treeData->tree, t_point, &nearest, data->treeData->nearest_callback, data->treeData);
+
+ poly = &data->mpoly[data->looptri[nearest.index].poly];
+ loop = &data->mloop[poly->loopstart];
+
+ for (int i = 0; i < poly->totloop; i++, loop++) {
+ edge = &data->medge[loop->e];
+ dist = dist_squared_to_line_segment_v3(
+ point_co, data->targetCos[edge->v1], data->targetCos[edge->v2]);
+
+ if (dist < max_dist) {
+ max_dist = dist;
+ index = loop->e;
+ }
+ }
+
+ edge = &data->medge[index];
+ if (len_squared_v3v3(point_co, data->targetCos[edge->v1]) <
+ len_squared_v3v3(point_co, data->targetCos[edge->v2])) {
+ return edge->v1;
+ }
+ else {
+ return edge->v2;
+ }
}
BLI_INLINE int isPolyValid(const float coords[][2], const unsigned int nr)
{
- float prev_co[2];
- float curr_vec[2], prev_vec[2];
+ float prev_co[2];
+ float curr_vec[2], prev_vec[2];
- if (!is_poly_convex_v2(coords, nr)) {
- return MOD_SDEF_BIND_RESULT_CONCAVE_ERR;
- }
+ if (!is_poly_convex_v2(coords, nr)) {
+ return MOD_SDEF_BIND_RESULT_CONCAVE_ERR;
+ }
- copy_v2_v2(prev_co, coords[nr - 1]);
- sub_v2_v2v2(prev_vec, prev_co, coords[nr - 2]);
- normalize_v2(prev_vec);
+ copy_v2_v2(prev_co, coords[nr - 1]);
+ sub_v2_v2v2(prev_vec, prev_co, coords[nr - 2]);
+ normalize_v2(prev_vec);
- for (int i = 0; i < nr; i++) {
- sub_v2_v2v2(curr_vec, coords[i], prev_co);
+ for (int i = 0; i < nr; i++) {
+ sub_v2_v2v2(curr_vec, coords[i], prev_co);
- const float curr_len = normalize_v2(curr_vec);
- if (curr_len < FLT_EPSILON) {
- return MOD_SDEF_BIND_RESULT_OVERLAP_ERR;
- }
+ const float curr_len = normalize_v2(curr_vec);
+ if (curr_len < FLT_EPSILON) {
+ return MOD_SDEF_BIND_RESULT_OVERLAP_ERR;
+ }
- if (1.0f - dot_v2v2(prev_vec, curr_vec) < FLT_EPSILON) {
- return MOD_SDEF_BIND_RESULT_CONCAVE_ERR;
- }
+ if (1.0f - dot_v2v2(prev_vec, curr_vec) < FLT_EPSILON) {
+ return MOD_SDEF_BIND_RESULT_CONCAVE_ERR;
+ }
- copy_v2_v2(prev_co, coords[i]);
- copy_v2_v2(prev_vec, curr_vec);
- }
+ copy_v2_v2(prev_co, coords[i]);
+ copy_v2_v2(prev_vec, curr_vec);
+ }
- return MOD_SDEF_BIND_RESULT_SUCCESS;
+ return MOD_SDEF_BIND_RESULT_SUCCESS;
}
-static void freeBindData(SDefBindWeightData * const bwdata)
+static void freeBindData(SDefBindWeightData *const bwdata)
{
- SDefBindPoly *bpoly = bwdata->bind_polys;
+ SDefBindPoly *bpoly = bwdata->bind_polys;
- if (bwdata->bind_polys) {
- for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
- MEM_SAFE_FREE(bpoly->coords);
- MEM_SAFE_FREE(bpoly->coords_v2);
- }
+ if (bwdata->bind_polys) {
+ for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
+ MEM_SAFE_FREE(bpoly->coords);
+ MEM_SAFE_FREE(bpoly->coords_v2);
+ }
- MEM_freeN(bwdata->bind_polys);
- }
+ MEM_freeN(bwdata->bind_polys);
+ }
- MEM_freeN(bwdata);
+ MEM_freeN(bwdata);
}
BLI_INLINE float computeAngularWeight(const float point_angle, const float edgemid_angle)
{
- float weight;
+ float weight;
- weight = point_angle;
- weight /= edgemid_angle;
- weight *= M_PI_2;
+ weight = point_angle;
+ weight /= edgemid_angle;
+ weight *= M_PI_2;
- return sinf(weight);
+ return sinf(weight);
}
-BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData * const data, const float point_co[3])
+BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
+ const float point_co[3])
{
- const unsigned int nearest = nearestVert(data, point_co);
- const SDefAdjacency * const vert_edges = data->vert_edges[nearest].first;
- const SDefEdgePolys * const edge_polys = data->edge_polys;
-
- const SDefAdjacency *vedge;
- const MPoly *poly;
- const MLoop *loop;
-
- SDefBindWeightData *bwdata;
- SDefBindPoly *bpoly;
-
- float world[3] = {0.0f, 0.0f, 1.0f};
- float avg_point_dist = 0.0f;
- float tot_weight = 0.0f;
- int inf_weight_flags = 0;
-
- bwdata = MEM_callocN(sizeof(*bwdata), "SDefBindWeightData");
- if (bwdata == NULL) {
- data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
- return NULL;
- }
-
- bwdata->numpoly = data->vert_edges[nearest].num / 2;
-
- bpoly = MEM_calloc_arrayN(bwdata->numpoly, sizeof(*bpoly), "SDefBindPoly");
- if (bpoly == NULL) {
- freeBindData(bwdata);
- data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
- return NULL;
- }
-
- bwdata->bind_polys = bpoly;
-
- /* Loop over all adjacent edges, and build the SDefBindPoly data for each poly adjacent to those */
- for (vedge = vert_edges; vedge; vedge = vedge->next) {
- unsigned int edge_ind = vedge->index;
-
- for (int i = 0; i < edge_polys[edge_ind].num; i++) {
- {
- bpoly = bwdata->bind_polys;
-
- for (int j = 0; j < bwdata->numpoly; bpoly++, j++) {
- /* If coords isn't allocated, we have reached the first uninitialized bpoly */
- if ((bpoly->index == edge_polys[edge_ind].polys[i]) || (!bpoly->coords)) {
- break;
- }
- }
- }
-
- /* Check if poly was already created by another edge or still has to be initialized */
- if (!bpoly->coords) {
- float angle;
- float axis[3];
- float tmp_vec_v2[2];
- int is_poly_valid;
-
- bpoly->index = edge_polys[edge_ind].polys[i];
- bpoly->coords = NULL;
- bpoly->coords_v2 = NULL;
-
- /* Copy poly data */
- poly = &data->mpoly[bpoly->index];
- loop = &data->mloop[poly->loopstart];
-
- bpoly->numverts = poly->totloop;
- bpoly->loopstart = poly->loopstart;
-
- bpoly->coords = MEM_malloc_arrayN(poly->totloop, sizeof(*bpoly->coords), "SDefBindPolyCoords");
- if (bpoly->coords == NULL) {
- freeBindData(bwdata);
- data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
- return NULL;
- }
-
- bpoly->coords_v2 = MEM_malloc_arrayN(poly->totloop, sizeof(*bpoly->coords_v2), "SDefBindPolyCoords_v2");
- if (bpoly->coords_v2 == NULL) {
- freeBindData(bwdata);
- data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
- return NULL;
- }
-
- for (int j = 0; j < poly->totloop; j++, loop++) {
- copy_v3_v3(bpoly->coords[j], data->targetCos[loop->v]);
-
- /* Find corner and edge indices within poly loop array */
- if (loop->v == nearest) {
- bpoly->corner_ind = j;
- bpoly->edge_vert_inds[0] = (j == 0) ? (poly->totloop - 1) : (j - 1);
- bpoly->edge_vert_inds[1] = (j == poly->totloop - 1) ? (0) : (j + 1);
-
- bpoly->edge_inds[0] = data->mloop[poly->loopstart + bpoly->edge_vert_inds[0]].e;
- bpoly->edge_inds[1] = loop->e;
- }
- }
-
- /* Compute poly's parametric data */
- mid_v3_v3_array(bpoly->centroid, bpoly->coords, poly->totloop);
- normal_poly_v3(bpoly->normal, bpoly->coords, poly->totloop);
-
- /* Compute poly skew angle and axis */
- angle = angle_normalized_v3v3(bpoly->normal, world);
-
- cross_v3_v3v3(axis, bpoly->normal, world);
- normalize_v3(axis);
-
- /* Map coords onto 2d normal plane */
- map_to_plane_axis_angle_v2_v3v3fl(bpoly->point_v2, point_co, axis, angle);
-
- zero_v2(bpoly->centroid_v2);
- for (int j = 0; j < poly->totloop; j++) {
- map_to_plane_axis_angle_v2_v3v3fl(bpoly->coords_v2[j], bpoly->coords[j], axis, angle);
- madd_v2_v2fl(bpoly->centroid_v2, bpoly->coords_v2[j], 1.0f / poly->totloop);
- }
-
- is_poly_valid = isPolyValid(bpoly->coords_v2, poly->totloop);
-
- if (is_poly_valid != MOD_SDEF_BIND_RESULT_SUCCESS) {
- freeBindData(bwdata);
- data->success = is_poly_valid;
- return NULL;
- }
-
- bpoly->inside = isect_point_poly_v2(bpoly->point_v2, bpoly->coords_v2, poly->totloop, false);
-
- /* Initialize weight components */
- bpoly->weight_angular = 1.0f;
- bpoly->weight_dist_proj = len_v2v2(bpoly->centroid_v2, bpoly->point_v2);
- bpoly->weight_dist = len_v3v3(bpoly->centroid, point_co);
-
- avg_point_dist += bpoly->weight_dist;
-
- /* Compute centroid to mid-edge vectors */
- mid_v2_v2v2(bpoly->cent_edgemid_vecs_v2[0],
- bpoly->coords_v2[bpoly->edge_vert_inds[0]],
- bpoly->coords_v2[bpoly->corner_ind]);
-
- mid_v2_v2v2(bpoly->cent_edgemid_vecs_v2[1],
- bpoly->coords_v2[bpoly->edge_vert_inds[1]],
- bpoly->coords_v2[bpoly->corner_ind]);
-
- sub_v2_v2(bpoly->cent_edgemid_vecs_v2[0], bpoly->centroid_v2);
- sub_v2_v2(bpoly->cent_edgemid_vecs_v2[1], bpoly->centroid_v2);
-
- /* Compute poly scales with respect to mid-edges, and normalize the vectors */
- bpoly->scales[0] = normalize_v2(bpoly->cent_edgemid_vecs_v2[0]);
- bpoly->scales[1] = normalize_v2(bpoly->cent_edgemid_vecs_v2[1]);
-
- /* Compute the required polygon angles */
- bpoly->edgemid_angle = angle_normalized_v2v2(bpoly->cent_edgemid_vecs_v2[0], bpoly->cent_edgemid_vecs_v2[1]);
-
- sub_v2_v2v2(tmp_vec_v2, bpoly->coords_v2[bpoly->corner_ind], bpoly->centroid_v2);
- normalize_v2(tmp_vec_v2);
-
- bpoly->corner_edgemid_angles[0] = angle_normalized_v2v2(tmp_vec_v2, bpoly->cent_edgemid_vecs_v2[0]);
- bpoly->corner_edgemid_angles[1] = angle_normalized_v2v2(tmp_vec_v2, bpoly->cent_edgemid_vecs_v2[1]);
-
- /* Check for inifnite weights, and compute angular data otherwise */
- if (bpoly->weight_dist < FLT_EPSILON) {
- inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
- inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST;
- }
- else if (bpoly->weight_dist_proj < FLT_EPSILON) {
- inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
- }
- else {
- float cent_point_vec[2];
-
- sub_v2_v2v2(cent_point_vec, bpoly->point_v2, bpoly->centroid_v2);
- normalize_v2(cent_point_vec);
-
- bpoly->point_edgemid_angles[0] = angle_normalized_v2v2(cent_point_vec, bpoly->cent_edgemid_vecs_v2[0]);
- bpoly->point_edgemid_angles[1] = angle_normalized_v2v2(cent_point_vec, bpoly->cent_edgemid_vecs_v2[1]);
- }
- }
- }
- }
-
- avg_point_dist /= bwdata->numpoly;
-
- /* If weights 1 and 2 are not infinite, loop over all adjacent edges again,
- * and build adjacency dependent angle data (depends on all polygons having been computed) */
- if (!inf_weight_flags) {
- for (vedge = vert_edges; vedge; vedge = vedge->next) {
- SDefBindPoly *bpolys[2];
- const SDefEdgePolys *epolys;
- float ang_weights[2];
- unsigned int edge_ind = vedge->index;
- unsigned int edge_on_poly[2];
-
- epolys = &edge_polys[edge_ind];
-
- /* Find bind polys corresponding to the edge's adjacent polys */
- bpoly = bwdata->bind_polys;
-
- for (int i = 0, j = 0; (i < bwdata->numpoly) && (j < epolys->num); bpoly++, i++) {
- if (ELEM(bpoly->index, epolys->polys[0], epolys->polys[1])) {
- bpolys[j] = bpoly;
-
- if (bpoly->edge_inds[0] == edge_ind) {
- edge_on_poly[j] = 0;
- }
- else {
- edge_on_poly[j] = 1;
- }
-
- j++;
- }
- }
-
- /* Compute angular weight component */
- if (epolys->num == 1) {
- ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]], bpolys[0]->edgemid_angle);
- bpolys[0]->weight_angular *= ang_weights[0] * ang_weights[0];
- }
- else if (epolys->num == 2) {
- ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]], bpolys[0]->edgemid_angle);
- ang_weights[1] = computeAngularWeight(bpolys[1]->point_edgemid_angles[edge_on_poly[1]], bpolys[1]->edgemid_angle);
-
- bpolys[0]->weight_angular *= ang_weights[0] * ang_weights[1];
- bpolys[1]->weight_angular *= ang_weights[0] * ang_weights[1];
- }
- }
- }
-
- /* Compute scalings and falloff.
- * Scale all weights if no infinite weight is found,
- * scale only unprojected weight if projected weight is infinite,
- * scale none if both are infinite. */
- if (!inf_weight_flags) {
- bpoly = bwdata->bind_polys;
-
- for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
- float corner_angle_weights[2];
- float scale_weight, sqr, inv_sqr;
-
- corner_angle_weights[0] = bpoly->point_edgemid_angles[0] / bpoly->corner_edgemid_angles[0];
- corner_angle_weights[1] = bpoly->point_edgemid_angles[1] / bpoly->corner_edgemid_angles[1];
-
- if (isnan(corner_angle_weights[0]) || isnan(corner_angle_weights[1])) {
- freeBindData(bwdata);
- data->success = MOD_SDEF_BIND_RESULT_GENERIC_ERR;
- return NULL;
- }
-
- /* Find which edge the point is closer to */
- if (corner_angle_weights[0] < corner_angle_weights[1]) {
- bpoly->dominant_edge = 0;
- bpoly->dominant_angle_weight = corner_angle_weights[0];
- }
- else {
- bpoly->dominant_edge = 1;
- bpoly->dominant_angle_weight = corner_angle_weights[1];
- }
-
- bpoly->dominant_angle_weight = sinf(bpoly->dominant_angle_weight * M_PI_2);
-
- /* Compute quadratic angular scale interpolation weight */
- scale_weight = bpoly->point_edgemid_angles[bpoly->dominant_edge] / bpoly->edgemid_angle;
- scale_weight /= scale_weight + (bpoly->point_edgemid_angles[!bpoly->dominant_edge] / bpoly->edgemid_angle);
-
- sqr = scale_weight * scale_weight;
- inv_sqr = 1.0f - scale_weight;
- inv_sqr *= inv_sqr;
- scale_weight = sqr / (sqr + inv_sqr);
-
- /* Compute interpolated scale (no longer need the individual scales,
- * so simply storing the result over the scale in index zero) */
- bpoly->scales[0] = bpoly->scales[bpoly->dominant_edge] * (1.0f - scale_weight) +
- bpoly->scales[!bpoly->dominant_edge] * scale_weight;
-
- /* Scale the point distance weights, and introduce falloff */
- bpoly->weight_dist_proj /= bpoly->scales[0];
- bpoly->weight_dist_proj = powf(bpoly->weight_dist_proj, data->falloff);
-
- bpoly->weight_dist /= avg_point_dist;
- bpoly->weight_dist = powf(bpoly->weight_dist, data->falloff);
-
- /* Re-check for infinite weights, now that all scalings and interpolations are computed */
- if (bpoly->weight_dist < FLT_EPSILON) {
- inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
- inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST;
- }
- else if (bpoly->weight_dist_proj < FLT_EPSILON) {
- inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
- }
- else if (bpoly->weight_angular < FLT_EPSILON) {
- inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_ANGULAR;
- }
- }
- }
- else if (!(inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST)) {
- bpoly = bwdata->bind_polys;
-
- for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
- /* Scale the point distance weight by average point distance, and introduce falloff */
- bpoly->weight_dist /= avg_point_dist;
- bpoly->weight_dist = powf(bpoly->weight_dist, data->falloff);
-
- /* Re-check for infinite weights, now that all scalings and interpolations are computed */
- if (bpoly->weight_dist < FLT_EPSILON) {
- inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST;
- }
- }
- }
-
- /* Final loop, to compute actual weights */
- bpoly = bwdata->bind_polys;
-
- for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
- /* Weight computation from components */
- if (inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST) {
- bpoly->weight = bpoly->weight_dist < FLT_EPSILON ? 1.0f : 0.0f;
- }
- else if (inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ) {
- bpoly->weight = bpoly->weight_dist_proj < FLT_EPSILON ?
- 1.0f / bpoly->weight_dist : 0.0f;
- }
- else if (inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_ANGULAR) {
- bpoly->weight = bpoly->weight_angular < FLT_EPSILON ?
- 1.0f / bpoly->weight_dist_proj / bpoly->weight_dist : 0.0f;
- }
- else {
- bpoly->weight = 1.0f / bpoly->weight_angular /
- bpoly->weight_dist_proj /
- bpoly->weight_dist;
- }
-
- tot_weight += bpoly->weight;
- }
-
- bpoly = bwdata->bind_polys;
-
- for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
- bpoly->weight /= tot_weight;
-
- /* Evaluate if this poly is relevant to bind */
- /* Even though the weights should add up to 1.0,
- * the losses of weights smaller than epsilon here
- * should be negligible... */
- if (bpoly->weight >= FLT_EPSILON) {
- if (bpoly->inside) {
- bwdata->numbinds += 1;
- }
- else {
- if (bpoly->dominant_angle_weight < FLT_EPSILON || 1.0f - bpoly->dominant_angle_weight < FLT_EPSILON) {
- bwdata->numbinds += 1;
- }
- else {
- bwdata->numbinds += 2;
- }
- }
- }
- }
-
- return bwdata;
+ const unsigned int nearest = nearestVert(data, point_co);
+ const SDefAdjacency *const vert_edges = data->vert_edges[nearest].first;
+ const SDefEdgePolys *const edge_polys = data->edge_polys;
+
+ const SDefAdjacency *vedge;
+ const MPoly *poly;
+ const MLoop *loop;
+
+ SDefBindWeightData *bwdata;
+ SDefBindPoly *bpoly;
+
+ float world[3] = {0.0f, 0.0f, 1.0f};
+ float avg_point_dist = 0.0f;
+ float tot_weight = 0.0f;
+ int inf_weight_flags = 0;
+
+ bwdata = MEM_callocN(sizeof(*bwdata), "SDefBindWeightData");
+ if (bwdata == NULL) {
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return NULL;
+ }
+
+ bwdata->numpoly = data->vert_edges[nearest].num / 2;
+
+ bpoly = MEM_calloc_arrayN(bwdata->numpoly, sizeof(*bpoly), "SDefBindPoly");
+ if (bpoly == NULL) {
+ freeBindData(bwdata);
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return NULL;
+ }
+
+ bwdata->bind_polys = bpoly;
+
+ /* Loop over all adjacent edges, and build the SDefBindPoly data for each poly adjacent to those */
+ for (vedge = vert_edges; vedge; vedge = vedge->next) {
+ unsigned int edge_ind = vedge->index;
+
+ for (int i = 0; i < edge_polys[edge_ind].num; i++) {
+ {
+ bpoly = bwdata->bind_polys;
+
+ for (int j = 0; j < bwdata->numpoly; bpoly++, j++) {
+ /* If coords isn't allocated, we have reached the first uninitialized bpoly */
+ if ((bpoly->index == edge_polys[edge_ind].polys[i]) || (!bpoly->coords)) {
+ break;
+ }
+ }
+ }
+
+ /* Check if poly was already created by another edge or still has to be initialized */
+ if (!bpoly->coords) {
+ float angle;
+ float axis[3];
+ float tmp_vec_v2[2];
+ int is_poly_valid;
+
+ bpoly->index = edge_polys[edge_ind].polys[i];
+ bpoly->coords = NULL;
+ bpoly->coords_v2 = NULL;
+
+ /* Copy poly data */
+ poly = &data->mpoly[bpoly->index];
+ loop = &data->mloop[poly->loopstart];
+
+ bpoly->numverts = poly->totloop;
+ bpoly->loopstart = poly->loopstart;
+
+ bpoly->coords = MEM_malloc_arrayN(
+ poly->totloop, sizeof(*bpoly->coords), "SDefBindPolyCoords");
+ if (bpoly->coords == NULL) {
+ freeBindData(bwdata);
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return NULL;
+ }
+
+ bpoly->coords_v2 = MEM_malloc_arrayN(
+ poly->totloop, sizeof(*bpoly->coords_v2), "SDefBindPolyCoords_v2");
+ if (bpoly->coords_v2 == NULL) {
+ freeBindData(bwdata);
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return NULL;
+ }
+
+ for (int j = 0; j < poly->totloop; j++, loop++) {
+ copy_v3_v3(bpoly->coords[j], data->targetCos[loop->v]);
+
+ /* Find corner and edge indices within poly loop array */
+ if (loop->v == nearest) {
+ bpoly->corner_ind = j;
+ bpoly->edge_vert_inds[0] = (j == 0) ? (poly->totloop - 1) : (j - 1);
+ bpoly->edge_vert_inds[1] = (j == poly->totloop - 1) ? (0) : (j + 1);
+
+ bpoly->edge_inds[0] = data->mloop[poly->loopstart + bpoly->edge_vert_inds[0]].e;
+ bpoly->edge_inds[1] = loop->e;
+ }
+ }
+
+ /* Compute poly's parametric data */
+ mid_v3_v3_array(bpoly->centroid, bpoly->coords, poly->totloop);
+ normal_poly_v3(bpoly->normal, bpoly->coords, poly->totloop);
+
+ /* Compute poly skew angle and axis */
+ angle = angle_normalized_v3v3(bpoly->normal, world);
+
+ cross_v3_v3v3(axis, bpoly->normal, world);
+ normalize_v3(axis);
+
+ /* Map coords onto 2d normal plane */
+ map_to_plane_axis_angle_v2_v3v3fl(bpoly->point_v2, point_co, axis, angle);
+
+ zero_v2(bpoly->centroid_v2);
+ for (int j = 0; j < poly->totloop; j++) {
+ map_to_plane_axis_angle_v2_v3v3fl(bpoly->coords_v2[j], bpoly->coords[j], axis, angle);
+ madd_v2_v2fl(bpoly->centroid_v2, bpoly->coords_v2[j], 1.0f / poly->totloop);
+ }
+
+ is_poly_valid = isPolyValid(bpoly->coords_v2, poly->totloop);
+
+ if (is_poly_valid != MOD_SDEF_BIND_RESULT_SUCCESS) {
+ freeBindData(bwdata);
+ data->success = is_poly_valid;
+ return NULL;
+ }
+
+ bpoly->inside = isect_point_poly_v2(
+ bpoly->point_v2, bpoly->coords_v2, poly->totloop, false);
+
+ /* Initialize weight components */
+ bpoly->weight_angular = 1.0f;
+ bpoly->weight_dist_proj = len_v2v2(bpoly->centroid_v2, bpoly->point_v2);
+ bpoly->weight_dist = len_v3v3(bpoly->centroid, point_co);
+
+ avg_point_dist += bpoly->weight_dist;
+
+ /* Compute centroid to mid-edge vectors */
+ mid_v2_v2v2(bpoly->cent_edgemid_vecs_v2[0],
+ bpoly->coords_v2[bpoly->edge_vert_inds[0]],
+ bpoly->coords_v2[bpoly->corner_ind]);
+
+ mid_v2_v2v2(bpoly->cent_edgemid_vecs_v2[1],
+ bpoly->coords_v2[bpoly->edge_vert_inds[1]],
+ bpoly->coords_v2[bpoly->corner_ind]);
+
+ sub_v2_v2(bpoly->cent_edgemid_vecs_v2[0], bpoly->centroid_v2);
+ sub_v2_v2(bpoly->cent_edgemid_vecs_v2[1], bpoly->centroid_v2);
+
+ /* Compute poly scales with respect to mid-edges, and normalize the vectors */
+ bpoly->scales[0] = normalize_v2(bpoly->cent_edgemid_vecs_v2[0]);
+ bpoly->scales[1] = normalize_v2(bpoly->cent_edgemid_vecs_v2[1]);
+
+ /* Compute the required polygon angles */
+ bpoly->edgemid_angle = angle_normalized_v2v2(bpoly->cent_edgemid_vecs_v2[0],
+ bpoly->cent_edgemid_vecs_v2[1]);
+
+ sub_v2_v2v2(tmp_vec_v2, bpoly->coords_v2[bpoly->corner_ind], bpoly->centroid_v2);
+ normalize_v2(tmp_vec_v2);
+
+ bpoly->corner_edgemid_angles[0] = angle_normalized_v2v2(tmp_vec_v2,
+ bpoly->cent_edgemid_vecs_v2[0]);
+ bpoly->corner_edgemid_angles[1] = angle_normalized_v2v2(tmp_vec_v2,
+ bpoly->cent_edgemid_vecs_v2[1]);
+
+ /* Check for inifnite weights, and compute angular data otherwise */
+ if (bpoly->weight_dist < FLT_EPSILON) {
+ inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
+ inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST;
+ }
+ else if (bpoly->weight_dist_proj < FLT_EPSILON) {
+ inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
+ }
+ else {
+ float cent_point_vec[2];
+
+ sub_v2_v2v2(cent_point_vec, bpoly->point_v2, bpoly->centroid_v2);
+ normalize_v2(cent_point_vec);
+
+ bpoly->point_edgemid_angles[0] = angle_normalized_v2v2(cent_point_vec,
+ bpoly->cent_edgemid_vecs_v2[0]);
+ bpoly->point_edgemid_angles[1] = angle_normalized_v2v2(cent_point_vec,
+ bpoly->cent_edgemid_vecs_v2[1]);
+ }
+ }
+ }
+ }
+
+ avg_point_dist /= bwdata->numpoly;
+
+ /* If weights 1 and 2 are not infinite, loop over all adjacent edges again,
+ * and build adjacency dependent angle data (depends on all polygons having been computed) */
+ if (!inf_weight_flags) {
+ for (vedge = vert_edges; vedge; vedge = vedge->next) {
+ SDefBindPoly *bpolys[2];
+ const SDefEdgePolys *epolys;
+ float ang_weights[2];
+ unsigned int edge_ind = vedge->index;
+ unsigned int edge_on_poly[2];
+
+ epolys = &edge_polys[edge_ind];
+
+ /* Find bind polys corresponding to the edge's adjacent polys */
+ bpoly = bwdata->bind_polys;
+
+ for (int i = 0, j = 0; (i < bwdata->numpoly) && (j < epolys->num); bpoly++, i++) {
+ if (ELEM(bpoly->index, epolys->polys[0], epolys->polys[1])) {
+ bpolys[j] = bpoly;
+
+ if (bpoly->edge_inds[0] == edge_ind) {
+ edge_on_poly[j] = 0;
+ }
+ else {
+ edge_on_poly[j] = 1;
+ }
+
+ j++;
+ }
+ }
+
+ /* Compute angular weight component */
+ if (epolys->num == 1) {
+ ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]],
+ bpolys[0]->edgemid_angle);
+ bpolys[0]->weight_angular *= ang_weights[0] * ang_weights[0];
+ }
+ else if (epolys->num == 2) {
+ ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]],
+ bpolys[0]->edgemid_angle);
+ ang_weights[1] = computeAngularWeight(bpolys[1]->point_edgemid_angles[edge_on_poly[1]],
+ bpolys[1]->edgemid_angle);
+
+ bpolys[0]->weight_angular *= ang_weights[0] * ang_weights[1];
+ bpolys[1]->weight_angular *= ang_weights[0] * ang_weights[1];
+ }
+ }
+ }
+
+ /* Compute scalings and falloff.
+ * Scale all weights if no infinite weight is found,
+ * scale only unprojected weight if projected weight is infinite,
+ * scale none if both are infinite. */
+ if (!inf_weight_flags) {
+ bpoly = bwdata->bind_polys;
+
+ for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
+ float corner_angle_weights[2];
+ float scale_weight, sqr, inv_sqr;
+
+ corner_angle_weights[0] = bpoly->point_edgemid_angles[0] / bpoly->corner_edgemid_angles[0];
+ corner_angle_weights[1] = bpoly->point_edgemid_angles[1] / bpoly->corner_edgemid_angles[1];
+
+ if (isnan(corner_angle_weights[0]) || isnan(corner_angle_weights[1])) {
+ freeBindData(bwdata);
+ data->success = MOD_SDEF_BIND_RESULT_GENERIC_ERR;
+ return NULL;
+ }
+
+ /* Find which edge the point is closer to */
+ if (corner_angle_weights[0] < corner_angle_weights[1]) {
+ bpoly->dominant_edge = 0;
+ bpoly->dominant_angle_weight = corner_angle_weights[0];
+ }
+ else {
+ bpoly->dominant_edge = 1;
+ bpoly->dominant_angle_weight = corner_angle_weights[1];
+ }
+
+ bpoly->dominant_angle_weight = sinf(bpoly->dominant_angle_weight * M_PI_2);
+
+ /* Compute quadratic angular scale interpolation weight */
+ scale_weight = bpoly->point_edgemid_angles[bpoly->dominant_edge] / bpoly->edgemid_angle;
+ scale_weight /= scale_weight +
+ (bpoly->point_edgemid_angles[!bpoly->dominant_edge] / bpoly->edgemid_angle);
+
+ sqr = scale_weight * scale_weight;
+ inv_sqr = 1.0f - scale_weight;
+ inv_sqr *= inv_sqr;
+ scale_weight = sqr / (sqr + inv_sqr);
+
+ /* Compute interpolated scale (no longer need the individual scales,
+ * so simply storing the result over the scale in index zero) */
+ bpoly->scales[0] = bpoly->scales[bpoly->dominant_edge] * (1.0f - scale_weight) +
+ bpoly->scales[!bpoly->dominant_edge] * scale_weight;
+
+ /* Scale the point distance weights, and introduce falloff */
+ bpoly->weight_dist_proj /= bpoly->scales[0];
+ bpoly->weight_dist_proj = powf(bpoly->weight_dist_proj, data->falloff);
+
+ bpoly->weight_dist /= avg_point_dist;
+ bpoly->weight_dist = powf(bpoly->weight_dist, data->falloff);
+
+ /* Re-check for infinite weights, now that all scalings and interpolations are computed */
+ if (bpoly->weight_dist < FLT_EPSILON) {
+ inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
+ inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST;
+ }
+ else if (bpoly->weight_dist_proj < FLT_EPSILON) {
+ inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
+ }
+ else if (bpoly->weight_angular < FLT_EPSILON) {
+ inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_ANGULAR;
+ }
+ }
+ }
+ else if (!(inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST)) {
+ bpoly = bwdata->bind_polys;
+
+ for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
+ /* Scale the point distance weight by average point distance, and introduce falloff */
+ bpoly->weight_dist /= avg_point_dist;
+ bpoly->weight_dist = powf(bpoly->weight_dist, data->falloff);
+
+ /* Re-check for infinite weights, now that all scalings and interpolations are computed */
+ if (bpoly->weight_dist < FLT_EPSILON) {
+ inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST;
+ }
+ }
+ }
+
+ /* Final loop, to compute actual weights */
+ bpoly = bwdata->bind_polys;
+
+ for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
+ /* Weight computation from components */
+ if (inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST) {
+ bpoly->weight = bpoly->weight_dist < FLT_EPSILON ? 1.0f : 0.0f;
+ }
+ else if (inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ) {
+ bpoly->weight = bpoly->weight_dist_proj < FLT_EPSILON ? 1.0f / bpoly->weight_dist : 0.0f;
+ }
+ else if (inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_ANGULAR) {
+ bpoly->weight = bpoly->weight_angular < FLT_EPSILON ?
+ 1.0f / bpoly->weight_dist_proj / bpoly->weight_dist :
+ 0.0f;
+ }
+ else {
+ bpoly->weight = 1.0f / bpoly->weight_angular / bpoly->weight_dist_proj / bpoly->weight_dist;
+ }
+
+ tot_weight += bpoly->weight;
+ }
+
+ bpoly = bwdata->bind_polys;
+
+ for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
+ bpoly->weight /= tot_weight;
+
+ /* Evaluate if this poly is relevant to bind */
+ /* Even though the weights should add up to 1.0,
+ * the losses of weights smaller than epsilon here
+ * should be negligible... */
+ if (bpoly->weight >= FLT_EPSILON) {
+ if (bpoly->inside) {
+ bwdata->numbinds += 1;
+ }
+ else {
+ if (bpoly->dominant_angle_weight < FLT_EPSILON ||
+ 1.0f - bpoly->dominant_angle_weight < FLT_EPSILON) {
+ bwdata->numbinds += 1;
+ }
+ else {
+ bwdata->numbinds += 2;
+ }
+ }
+ }
+ }
+
+ return bwdata;
}
-BLI_INLINE float computeNormalDisplacement(const float point_co[3], const float point_co_proj[3], const float normal[3])
+BLI_INLINE float computeNormalDisplacement(const float point_co[3],
+ const float point_co_proj[3],
+ const float normal[3])
{
- float disp_vec[3];
- float normal_dist;
+ float disp_vec[3];
+ float normal_dist;
- sub_v3_v3v3(disp_vec, point_co, point_co_proj);
- normal_dist = len_v3(disp_vec);
+ sub_v3_v3v3(disp_vec, point_co, point_co_proj);
+ normal_dist = len_v3(disp_vec);
- if (dot_v3v3(disp_vec, normal) < 0) {
- normal_dist *= -1;
- }
+ if (dot_v3v3(disp_vec, normal) < 0) {
+ normal_dist *= -1;
+ }
- return normal_dist;
+ return normal_dist;
}
-static void bindVert(
- void *__restrict userdata,
- const int index,
- const ParallelRangeTLS *__restrict UNUSED(tls))
+static void bindVert(void *__restrict userdata,
+ const int index,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
{
- SDefBindCalcData * const data = (SDefBindCalcData *)userdata;
- float point_co[3];
- float point_co_proj[3];
-
- SDefBindWeightData *bwdata;
- SDefVert *sdvert = data->bind_verts + index;
- SDefBindPoly *bpoly;
- SDefBind *sdbind;
-
- if (data->success != MOD_SDEF_BIND_RESULT_SUCCESS) {
- sdvert->binds = NULL;
- sdvert->numbinds = 0;
- return;
- }
-
- copy_v3_v3(point_co, data->vertexCos[index]);
- bwdata = computeBindWeights(data, point_co);
-
- if (bwdata == NULL) {
- sdvert->binds = NULL;
- sdvert->numbinds = 0;
- return;
- }
-
- sdvert->binds = MEM_calloc_arrayN(bwdata->numbinds, sizeof(*sdvert->binds), "SDefVertBindData");
- if (sdvert->binds == NULL) {
- data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
- sdvert->numbinds = 0;
- return;
- }
-
- sdvert->numbinds = bwdata->numbinds;
-
- sdbind = sdvert->binds;
-
- bpoly = bwdata->bind_polys;
-
- for (int i = 0; i < bwdata->numbinds; bpoly++) {
- if (bpoly->weight >= FLT_EPSILON) {
- if (bpoly->inside) {
- const MLoop *loop = &data->mloop[bpoly->loopstart];
-
- sdbind->influence = bpoly->weight;
- sdbind->numverts = bpoly->numverts;
-
- sdbind->mode = MOD_SDEF_MODE_NGON;
- sdbind->vert_weights = MEM_malloc_arrayN(bpoly->numverts, sizeof(*sdbind->vert_weights), "SDefNgonVertWeights");
- if (sdbind->vert_weights == NULL) {
- data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
- return;
- }
-
- sdbind->vert_inds = MEM_malloc_arrayN(bpoly->numverts, sizeof(*sdbind->vert_inds), "SDefNgonVertInds");
- if (sdbind->vert_inds == NULL) {
- data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
- return;
- }
-
- interp_weights_poly_v2(sdbind->vert_weights, bpoly->coords_v2, bpoly->numverts, bpoly->point_v2);
-
- /* Reproject vert based on weights and original poly verts, to reintroduce poly non-planarity */
- zero_v3(point_co_proj);
- for (int j = 0; j < bpoly->numverts; j++, loop++) {
- madd_v3_v3fl(point_co_proj, bpoly->coords[j], sdbind->vert_weights[j]);
- sdbind->vert_inds[j] = loop->v;
- }
-
- sdbind->normal_dist = computeNormalDisplacement(point_co, point_co_proj, bpoly->normal);
-
- sdbind++;
- i++;
- }
- else {
- float tmp_vec[3];
- float cent[3], norm[3];
- float v1[3], v2[3], v3[3];
-
- if (1.0f - bpoly->dominant_angle_weight >= FLT_EPSILON) {
- sdbind->influence = bpoly->weight * (1.0f - bpoly->dominant_angle_weight);
- sdbind->numverts = bpoly->numverts;
-
- sdbind->mode = MOD_SDEF_MODE_CENTROID;
- sdbind->vert_weights = MEM_malloc_arrayN(3, sizeof(*sdbind->vert_weights), "SDefCentVertWeights");
- if (sdbind->vert_weights == NULL) {
- data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
- return;
- }
-
- sdbind->vert_inds = MEM_malloc_arrayN(bpoly->numverts, sizeof(*sdbind->vert_inds), "SDefCentVertInds");
- if (sdbind->vert_inds == NULL) {
- data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
- return;
- }
-
- sortPolyVertsEdge(sdbind->vert_inds, &data->mloop[bpoly->loopstart],
- bpoly->edge_inds[bpoly->dominant_edge], bpoly->numverts);
-
- copy_v3_v3(v1, data->targetCos[sdbind->vert_inds[0]]);
- copy_v3_v3(v2, data->targetCos[sdbind->vert_inds[1]]);
- copy_v3_v3(v3, bpoly->centroid);
-
- mid_v3_v3v3v3(cent, v1, v2, v3);
- normal_tri_v3(norm, v1, v2, v3);
-
- add_v3_v3v3(tmp_vec, point_co, bpoly->normal);
-
- /* We are sure the line is not parallel to the plane.
- * Checking return value just to avoid warning... */
- if (!isect_line_plane_v3(point_co_proj, point_co, tmp_vec, cent, norm)) {
- BLI_assert(false);
- }
-
- interp_weights_tri_v3(sdbind->vert_weights, v1, v2, v3, point_co_proj);
-
- sdbind->normal_dist = computeNormalDisplacement(point_co, point_co_proj, bpoly->normal);
-
- sdbind++;
- i++;
- }
-
- if (bpoly->dominant_angle_weight >= FLT_EPSILON) {
- sdbind->influence = bpoly->weight * bpoly->dominant_angle_weight;
- sdbind->numverts = bpoly->numverts;
-
- sdbind->mode = MOD_SDEF_MODE_LOOPTRI;
- sdbind->vert_weights = MEM_malloc_arrayN(3, sizeof(*sdbind->vert_weights), "SDefTriVertWeights");
- if (sdbind->vert_weights == NULL) {
- data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
- return;
- }
-
- sdbind->vert_inds = MEM_malloc_arrayN(bpoly->numverts, sizeof(*sdbind->vert_inds), "SDefTriVertInds");
- if (sdbind->vert_inds == NULL) {
- data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
- return;
- }
-
- sortPolyVertsTri(sdbind->vert_inds, &data->mloop[bpoly->loopstart], bpoly->edge_vert_inds[0], bpoly->numverts);
-
- copy_v3_v3(v1, data->targetCos[sdbind->vert_inds[0]]);
- copy_v3_v3(v2, data->targetCos[sdbind->vert_inds[1]]);
- copy_v3_v3(v3, data->targetCos[sdbind->vert_inds[2]]);
-
- mid_v3_v3v3v3(cent, v1, v2, v3);
- normal_tri_v3(norm, v1, v2, v3);
-
- add_v3_v3v3(tmp_vec, point_co, bpoly->normal);
-
- /* We are sure the line is not parallel to the plane.
- * Checking return value just to avoid warning... */
- if (!isect_line_plane_v3(point_co_proj, point_co, tmp_vec, cent, norm)) {
- BLI_assert(false);
- }
-
- interp_weights_tri_v3(sdbind->vert_weights, v1, v2, v3, point_co_proj);
-
- sdbind->normal_dist = computeNormalDisplacement(point_co, point_co_proj, bpoly->normal);
-
- sdbind++;
- i++;
- }
- }
- }
- }
-
- freeBindData(bwdata);
+ SDefBindCalcData *const data = (SDefBindCalcData *)userdata;
+ float point_co[3];
+ float point_co_proj[3];
+
+ SDefBindWeightData *bwdata;
+ SDefVert *sdvert = data->bind_verts + index;
+ SDefBindPoly *bpoly;
+ SDefBind *sdbind;
+
+ if (data->success != MOD_SDEF_BIND_RESULT_SUCCESS) {
+ sdvert->binds = NULL;
+ sdvert->numbinds = 0;
+ return;
+ }
+
+ copy_v3_v3(point_co, data->vertexCos[index]);
+ bwdata = computeBindWeights(data, point_co);
+
+ if (bwdata == NULL) {
+ sdvert->binds = NULL;
+ sdvert->numbinds = 0;
+ return;
+ }
+
+ sdvert->binds = MEM_calloc_arrayN(bwdata->numbinds, sizeof(*sdvert->binds), "SDefVertBindData");
+ if (sdvert->binds == NULL) {
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ sdvert->numbinds = 0;
+ return;
+ }
+
+ sdvert->numbinds = bwdata->numbinds;
+
+ sdbind = sdvert->binds;
+
+ bpoly = bwdata->bind_polys;
+
+ for (int i = 0; i < bwdata->numbinds; bpoly++) {
+ if (bpoly->weight >= FLT_EPSILON) {
+ if (bpoly->inside) {
+ const MLoop *loop = &data->mloop[bpoly->loopstart];
+
+ sdbind->influence = bpoly->weight;
+ sdbind->numverts = bpoly->numverts;
+
+ sdbind->mode = MOD_SDEF_MODE_NGON;
+ sdbind->vert_weights = MEM_malloc_arrayN(
+ bpoly->numverts, sizeof(*sdbind->vert_weights), "SDefNgonVertWeights");
+ if (sdbind->vert_weights == NULL) {
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return;
+ }
+
+ sdbind->vert_inds = MEM_malloc_arrayN(
+ bpoly->numverts, sizeof(*sdbind->vert_inds), "SDefNgonVertInds");
+ if (sdbind->vert_inds == NULL) {
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return;
+ }
+
+ interp_weights_poly_v2(
+ sdbind->vert_weights, bpoly->coords_v2, bpoly->numverts, bpoly->point_v2);
+
+ /* Reproject vert based on weights and original poly verts, to reintroduce poly non-planarity */
+ zero_v3(point_co_proj);
+ for (int j = 0; j < bpoly->numverts; j++, loop++) {
+ madd_v3_v3fl(point_co_proj, bpoly->coords[j], sdbind->vert_weights[j]);
+ sdbind->vert_inds[j] = loop->v;
+ }
+
+ sdbind->normal_dist = computeNormalDisplacement(point_co, point_co_proj, bpoly->normal);
+
+ sdbind++;
+ i++;
+ }
+ else {
+ float tmp_vec[3];
+ float cent[3], norm[3];
+ float v1[3], v2[3], v3[3];
+
+ if (1.0f - bpoly->dominant_angle_weight >= FLT_EPSILON) {
+ sdbind->influence = bpoly->weight * (1.0f - bpoly->dominant_angle_weight);
+ sdbind->numverts = bpoly->numverts;
+
+ sdbind->mode = MOD_SDEF_MODE_CENTROID;
+ sdbind->vert_weights = MEM_malloc_arrayN(
+ 3, sizeof(*sdbind->vert_weights), "SDefCentVertWeights");
+ if (sdbind->vert_weights == NULL) {
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return;
+ }
+
+ sdbind->vert_inds = MEM_malloc_arrayN(
+ bpoly->numverts, sizeof(*sdbind->vert_inds), "SDefCentVertInds");
+ if (sdbind->vert_inds == NULL) {
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return;
+ }
+
+ sortPolyVertsEdge(sdbind->vert_inds,
+ &data->mloop[bpoly->loopstart],
+ bpoly->edge_inds[bpoly->dominant_edge],
+ bpoly->numverts);
+
+ copy_v3_v3(v1, data->targetCos[sdbind->vert_inds[0]]);
+ copy_v3_v3(v2, data->targetCos[sdbind->vert_inds[1]]);
+ copy_v3_v3(v3, bpoly->centroid);
+
+ mid_v3_v3v3v3(cent, v1, v2, v3);
+ normal_tri_v3(norm, v1, v2, v3);
+
+ add_v3_v3v3(tmp_vec, point_co, bpoly->normal);
+
+ /* We are sure the line is not parallel to the plane.
+ * Checking return value just to avoid warning... */
+ if (!isect_line_plane_v3(point_co_proj, point_co, tmp_vec, cent, norm)) {
+ BLI_assert(false);
+ }
+
+ interp_weights_tri_v3(sdbind->vert_weights, v1, v2, v3, point_co_proj);
+
+ sdbind->normal_dist = computeNormalDisplacement(point_co, point_co_proj, bpoly->normal);
+
+ sdbind++;
+ i++;
+ }
+
+ if (bpoly->dominant_angle_weight >= FLT_EPSILON) {
+ sdbind->influence = bpoly->weight * bpoly->dominant_angle_weight;
+ sdbind->numverts = bpoly->numverts;
+
+ sdbind->mode = MOD_SDEF_MODE_LOOPTRI;
+ sdbind->vert_weights = MEM_malloc_arrayN(
+ 3, sizeof(*sdbind->vert_weights), "SDefTriVertWeights");
+ if (sdbind->vert_weights == NULL) {
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return;
+ }
+
+ sdbind->vert_inds = MEM_malloc_arrayN(
+ bpoly->numverts, sizeof(*sdbind->vert_inds), "SDefTriVertInds");
+ if (sdbind->vert_inds == NULL) {
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return;
+ }
+
+ sortPolyVertsTri(sdbind->vert_inds,
+ &data->mloop[bpoly->loopstart],
+ bpoly->edge_vert_inds[0],
+ bpoly->numverts);
+
+ copy_v3_v3(v1, data->targetCos[sdbind->vert_inds[0]]);
+ copy_v3_v3(v2, data->targetCos[sdbind->vert_inds[1]]);
+ copy_v3_v3(v3, data->targetCos[sdbind->vert_inds[2]]);
+
+ mid_v3_v3v3v3(cent, v1, v2, v3);
+ normal_tri_v3(norm, v1, v2, v3);
+
+ add_v3_v3v3(tmp_vec, point_co, bpoly->normal);
+
+ /* We are sure the line is not parallel to the plane.
+ * Checking return value just to avoid warning... */
+ if (!isect_line_plane_v3(point_co_proj, point_co, tmp_vec, cent, norm)) {
+ BLI_assert(false);
+ }
+
+ interp_weights_tri_v3(sdbind->vert_weights, v1, v2, v3, point_co_proj);
+
+ sdbind->normal_dist = computeNormalDisplacement(point_co, point_co_proj, bpoly->normal);
+
+ sdbind++;
+ i++;
+ }
+ }
+ }
+ }
+
+ freeBindData(bwdata);
}
-static bool surfacedeformBind(
- SurfaceDeformModifierData *smd, float (*vertexCos)[3],
- unsigned int numverts, unsigned int tnumpoly, unsigned int tnumverts, Mesh *target)
+static bool surfacedeformBind(SurfaceDeformModifierData *smd,
+ float (*vertexCos)[3],
+ unsigned int numverts,
+ unsigned int tnumpoly,
+ unsigned int tnumverts,
+ Mesh *target)
{
- BVHTreeFromMesh treeData = {NULL};
- const MVert *mvert = target->mvert;
- const MPoly *mpoly = target->mpoly;
- const MEdge *medge = target->medge;
- const MLoop *mloop = target->mloop;
- unsigned int tnumedges = target->totedge;
- int adj_result;
- SDefAdjacencyArray *vert_edges;
- SDefAdjacency *adj_array;
- SDefEdgePolys *edge_polys;
-
- vert_edges = MEM_calloc_arrayN(tnumverts, sizeof(*vert_edges), "SDefVertEdgeMap");
- if (vert_edges == NULL) {
- modifier_setError((ModifierData *)smd, "Out of memory");
- return false;
- }
-
- adj_array = MEM_malloc_arrayN(tnumedges, 2 * sizeof(*adj_array), "SDefVertEdge");
- if (adj_array == NULL) {
- modifier_setError((ModifierData *)smd, "Out of memory");
- MEM_freeN(vert_edges);
- return false;
- }
-
- edge_polys = MEM_calloc_arrayN(tnumedges, sizeof(*edge_polys), "SDefEdgeFaceMap");
- if (edge_polys == NULL) {
- modifier_setError((ModifierData *)smd, "Out of memory");
- MEM_freeN(vert_edges);
- MEM_freeN(adj_array);
- return false;
- }
-
- smd->verts = MEM_malloc_arrayN(numverts, sizeof(*smd->verts), "SDefBindVerts");
- if (smd->verts == NULL) {
- modifier_setError((ModifierData *)smd, "Out of memory");
- freeAdjacencyMap(vert_edges, adj_array, edge_polys);
- return false;
- }
-
- BKE_bvhtree_from_mesh_get(&treeData, target, BVHTREE_FROM_LOOPTRI, 2);
- if (treeData.tree == NULL) {
- modifier_setError((ModifierData *)smd, "Out of memory");
- freeAdjacencyMap(vert_edges, adj_array, edge_polys);
- MEM_freeN(smd->verts);
- smd->verts = NULL;
- return false;
- }
-
- adj_result = buildAdjacencyMap(mpoly, medge, mloop, tnumpoly, tnumedges, vert_edges, adj_array, edge_polys);
-
- if (adj_result == MOD_SDEF_BIND_RESULT_NONMANY_ERR) {
- modifier_setError((ModifierData *)smd, "Target has edges with more than two polygons");
- freeAdjacencyMap(vert_edges, adj_array, edge_polys);
- free_bvhtree_from_mesh(&treeData);
- MEM_freeN(smd->verts);
- smd->verts = NULL;
- return false;
- }
-
- smd->numverts = numverts;
- smd->numpoly = tnumpoly;
-
- SDefBindCalcData data = {
- .treeData = &treeData,
- .vert_edges = vert_edges,
- .edge_polys = edge_polys,
- .mpoly = mpoly,
- .medge = medge,
- .mloop = mloop,
- .looptri = BKE_mesh_runtime_looptri_ensure(target),
- .targetCos = MEM_malloc_arrayN(tnumverts, sizeof(float[3]), "SDefTargetBindVertArray"),
- .bind_verts = smd->verts,
- .vertexCos = vertexCos,
- .falloff = smd->falloff,
- .success = MOD_SDEF_BIND_RESULT_SUCCESS,
- };
-
- if (data.targetCos == NULL) {
- modifier_setError((ModifierData *)smd, "Out of memory");
- freeData((ModifierData *)smd);
- return false;
- }
-
- invert_m4_m4(data.imat, smd->mat);
-
- for (int i = 0; i < tnumverts; i++) {
- mul_v3_m4v3(data.targetCos[i], smd->mat, mvert[i].co);
- }
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = (numverts > 10000);
- BLI_task_parallel_range(0, numverts,
- &data,
- bindVert,
- &settings);
-
- MEM_freeN(data.targetCos);
-
- if (data.success == MOD_SDEF_BIND_RESULT_MEM_ERR) {
- modifier_setError((ModifierData *)smd, "Out of memory");
- freeData((ModifierData *)smd);
- }
- else if (data.success == MOD_SDEF_BIND_RESULT_NONMANY_ERR) {
- modifier_setError((ModifierData *)smd, "Target has edges with more than two polygons");
- freeData((ModifierData *)smd);
- }
- else if (data.success == MOD_SDEF_BIND_RESULT_CONCAVE_ERR) {
- modifier_setError((ModifierData *)smd, "Target contains concave polygons");
- freeData((ModifierData *)smd);
- }
- else if (data.success == MOD_SDEF_BIND_RESULT_OVERLAP_ERR) {
- modifier_setError((ModifierData *)smd, "Target contains overlapping verts");
- freeData((ModifierData *)smd);
- }
- else if (data.success == MOD_SDEF_BIND_RESULT_GENERIC_ERR) {
- /* I know this message is vague, but I could not think of a way
- * to explain this with a reasonably sized message.
- * Though it shouldn't really matter all that much,
- * because this is very unlikely to occur */
- modifier_setError((ModifierData *)smd, "Target contains invalid polygons");
- freeData((ModifierData *)smd);
- }
-
- freeAdjacencyMap(vert_edges, adj_array, edge_polys);
- free_bvhtree_from_mesh(&treeData);
-
- return data.success == 1;
+ BVHTreeFromMesh treeData = {NULL};
+ const MVert *mvert = target->mvert;
+ const MPoly *mpoly = target->mpoly;
+ const MEdge *medge = target->medge;
+ const MLoop *mloop = target->mloop;
+ unsigned int tnumedges = target->totedge;
+ int adj_result;
+ SDefAdjacencyArray *vert_edges;
+ SDefAdjacency *adj_array;
+ SDefEdgePolys *edge_polys;
+
+ vert_edges = MEM_calloc_arrayN(tnumverts, sizeof(*vert_edges), "SDefVertEdgeMap");
+ if (vert_edges == NULL) {
+ modifier_setError((ModifierData *)smd, "Out of memory");
+ return false;
+ }
+
+ adj_array = MEM_malloc_arrayN(tnumedges, 2 * sizeof(*adj_array), "SDefVertEdge");
+ if (adj_array == NULL) {
+ modifier_setError((ModifierData *)smd, "Out of memory");
+ MEM_freeN(vert_edges);
+ return false;
+ }
+
+ edge_polys = MEM_calloc_arrayN(tnumedges, sizeof(*edge_polys), "SDefEdgeFaceMap");
+ if (edge_polys == NULL) {
+ modifier_setError((ModifierData *)smd, "Out of memory");
+ MEM_freeN(vert_edges);
+ MEM_freeN(adj_array);
+ return false;
+ }
+
+ smd->verts = MEM_malloc_arrayN(numverts, sizeof(*smd->verts), "SDefBindVerts");
+ if (smd->verts == NULL) {
+ modifier_setError((ModifierData *)smd, "Out of memory");
+ freeAdjacencyMap(vert_edges, adj_array, edge_polys);
+ return false;
+ }
+
+ BKE_bvhtree_from_mesh_get(&treeData, target, BVHTREE_FROM_LOOPTRI, 2);
+ if (treeData.tree == NULL) {
+ modifier_setError((ModifierData *)smd, "Out of memory");
+ freeAdjacencyMap(vert_edges, adj_array, edge_polys);
+ MEM_freeN(smd->verts);
+ smd->verts = NULL;
+ return false;
+ }
+
+ adj_result = buildAdjacencyMap(
+ mpoly, medge, mloop, tnumpoly, tnumedges, vert_edges, adj_array, edge_polys);
+
+ if (adj_result == MOD_SDEF_BIND_RESULT_NONMANY_ERR) {
+ modifier_setError((ModifierData *)smd, "Target has edges with more than two polygons");
+ freeAdjacencyMap(vert_edges, adj_array, edge_polys);
+ free_bvhtree_from_mesh(&treeData);
+ MEM_freeN(smd->verts);
+ smd->verts = NULL;
+ return false;
+ }
+
+ smd->numverts = numverts;
+ smd->numpoly = tnumpoly;
+
+ SDefBindCalcData data = {
+ .treeData = &treeData,
+ .vert_edges = vert_edges,
+ .edge_polys = edge_polys,
+ .mpoly = mpoly,
+ .medge = medge,
+ .mloop = mloop,
+ .looptri = BKE_mesh_runtime_looptri_ensure(target),
+ .targetCos = MEM_malloc_arrayN(tnumverts, sizeof(float[3]), "SDefTargetBindVertArray"),
+ .bind_verts = smd->verts,
+ .vertexCos = vertexCos,
+ .falloff = smd->falloff,
+ .success = MOD_SDEF_BIND_RESULT_SUCCESS,
+ };
+
+ if (data.targetCos == NULL) {
+ modifier_setError((ModifierData *)smd, "Out of memory");
+ freeData((ModifierData *)smd);
+ return false;
+ }
+
+ invert_m4_m4(data.imat, smd->mat);
+
+ for (int i = 0; i < tnumverts; i++) {
+ mul_v3_m4v3(data.targetCos[i], smd->mat, mvert[i].co);
+ }
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = (numverts > 10000);
+ BLI_task_parallel_range(0, numverts, &data, bindVert, &settings);
+
+ MEM_freeN(data.targetCos);
+
+ if (data.success == MOD_SDEF_BIND_RESULT_MEM_ERR) {
+ modifier_setError((ModifierData *)smd, "Out of memory");
+ freeData((ModifierData *)smd);
+ }
+ else if (data.success == MOD_SDEF_BIND_RESULT_NONMANY_ERR) {
+ modifier_setError((ModifierData *)smd, "Target has edges with more than two polygons");
+ freeData((ModifierData *)smd);
+ }
+ else if (data.success == MOD_SDEF_BIND_RESULT_CONCAVE_ERR) {
+ modifier_setError((ModifierData *)smd, "Target contains concave polygons");
+ freeData((ModifierData *)smd);
+ }
+ else if (data.success == MOD_SDEF_BIND_RESULT_OVERLAP_ERR) {
+ modifier_setError((ModifierData *)smd, "Target contains overlapping verts");
+ freeData((ModifierData *)smd);
+ }
+ else if (data.success == MOD_SDEF_BIND_RESULT_GENERIC_ERR) {
+ /* I know this message is vague, but I could not think of a way
+ * to explain this with a reasonably sized message.
+ * Though it shouldn't really matter all that much,
+ * because this is very unlikely to occur */
+ modifier_setError((ModifierData *)smd, "Target contains invalid polygons");
+ freeData((ModifierData *)smd);
+ }
+
+ freeAdjacencyMap(vert_edges, adj_array, edge_polys);
+ free_bvhtree_from_mesh(&treeData);
+
+ return data.success == 1;
}
-static void deformVert(
- void *__restrict userdata,
- const int index,
- const ParallelRangeTLS *__restrict UNUSED(tls))
+static void deformVert(void *__restrict userdata,
+ const int index,
+ const ParallelRangeTLS *__restrict UNUSED(tls))
{
- const SDefDeformData * const data = (SDefDeformData *)userdata;
- const SDefBind *sdbind = data->bind_verts[index].binds;
- float * const vertexCos = data->vertexCos[index];
- float norm[3], temp[3];
-
- zero_v3(vertexCos);
-
- for (int j = 0; j < data->bind_verts[index].numbinds; j++, sdbind++) {
- /* Mode-generic operations (allocate poly coordinates) */
- float (*coords)[3] = MEM_malloc_arrayN(sdbind->numverts, sizeof(*coords), "SDefDoPolyCoords");
-
- for (int k = 0; k < sdbind->numverts; k++) {
- copy_v3_v3(coords[k], data->targetCos[sdbind->vert_inds[k]]);
- }
-
- normal_poly_v3(norm, coords, sdbind->numverts);
- zero_v3(temp);
-
- /* ---------- looptri mode ---------- */
- if (sdbind->mode == MOD_SDEF_MODE_LOOPTRI) {
- madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[0]], sdbind->vert_weights[0]);
- madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[1]], sdbind->vert_weights[1]);
- madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[2]], sdbind->vert_weights[2]);
- }
- else {
- /* ---------- ngon mode ---------- */
- if (sdbind->mode == MOD_SDEF_MODE_NGON) {
- for (int k = 0; k < sdbind->numverts; k++) {
- madd_v3_v3fl(temp, coords[k], sdbind->vert_weights[k]);
- }
- }
-
- /* ---------- centroid mode ---------- */
- else if (sdbind->mode == MOD_SDEF_MODE_CENTROID) {
- float cent[3];
- mid_v3_v3_array(cent, coords, sdbind->numverts);
-
- madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[0]], sdbind->vert_weights[0]);
- madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[1]], sdbind->vert_weights[1]);
- madd_v3_v3fl(temp, cent, sdbind->vert_weights[2]);
- }
- }
-
- MEM_freeN(coords);
-
- /* Apply normal offset (generic for all modes) */
- madd_v3_v3fl(temp, norm, sdbind->normal_dist);
-
- madd_v3_v3fl(vertexCos, temp, sdbind->influence);
- }
+ const SDefDeformData *const data = (SDefDeformData *)userdata;
+ const SDefBind *sdbind = data->bind_verts[index].binds;
+ float *const vertexCos = data->vertexCos[index];
+ float norm[3], temp[3];
+
+ zero_v3(vertexCos);
+
+ for (int j = 0; j < data->bind_verts[index].numbinds; j++, sdbind++) {
+ /* Mode-generic operations (allocate poly coordinates) */
+ float(*coords)[3] = MEM_malloc_arrayN(sdbind->numverts, sizeof(*coords), "SDefDoPolyCoords");
+
+ for (int k = 0; k < sdbind->numverts; k++) {
+ copy_v3_v3(coords[k], data->targetCos[sdbind->vert_inds[k]]);
+ }
+
+ normal_poly_v3(norm, coords, sdbind->numverts);
+ zero_v3(temp);
+
+ /* ---------- looptri mode ---------- */
+ if (sdbind->mode == MOD_SDEF_MODE_LOOPTRI) {
+ madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[0]], sdbind->vert_weights[0]);
+ madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[1]], sdbind->vert_weights[1]);
+ madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[2]], sdbind->vert_weights[2]);
+ }
+ else {
+ /* ---------- ngon mode ---------- */
+ if (sdbind->mode == MOD_SDEF_MODE_NGON) {
+ for (int k = 0; k < sdbind->numverts; k++) {
+ madd_v3_v3fl(temp, coords[k], sdbind->vert_weights[k]);
+ }
+ }
+
+ /* ---------- centroid mode ---------- */
+ else if (sdbind->mode == MOD_SDEF_MODE_CENTROID) {
+ float cent[3];
+ mid_v3_v3_array(cent, coords, sdbind->numverts);
+
+ madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[0]], sdbind->vert_weights[0]);
+ madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[1]], sdbind->vert_weights[1]);
+ madd_v3_v3fl(temp, cent, sdbind->vert_weights[2]);
+ }
+ }
+
+ MEM_freeN(coords);
+
+ /* Apply normal offset (generic for all modes) */
+ madd_v3_v3fl(temp, norm, sdbind->normal_dist);
+
+ madd_v3_v3fl(vertexCos, temp, sdbind->influence);
+ }
}
-static void surfacedeformModifier_do(
- ModifierData *md,
- const ModifierEvalContext *ctx,
- float (*vertexCos)[3], unsigned int numverts, Object *ob)
+static void surfacedeformModifier_do(ModifierData *md,
+ const ModifierEvalContext *ctx,
+ float (*vertexCos)[3],
+ unsigned int numverts,
+ Object *ob)
{
- SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
- Mesh *target;
- unsigned int tnumverts, tnumpoly;
-
- /* Exit function if bind flag is not set (free bind data if any). */
- if (!(smd->flags & MOD_SDEF_BIND)) {
- if (smd->verts != NULL) {
- if (!DEG_is_active(ctx->depsgraph)) {
- modifier_setError(md, "Attempt to bind from inactive dependency graph");
- return;
- }
- ModifierData *md_orig = modifier_get_original(md);
- freeData(md_orig);
- }
- return;
- }
-
- Object *ob_target = smd->target;
- target = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false);
- if (!target) {
- modifier_setError(md, "No valid target mesh");
- return;
- }
-
- tnumverts = target->totvert;
- tnumpoly = target->totpoly;
-
- /* If not bound, execute bind. */
- if (smd->verts == NULL) {
- if (!DEG_is_active(ctx->depsgraph)) {
- modifier_setError(md, "Attempt to unbind from inactive dependency graph");
- return;
- }
-
- SurfaceDeformModifierData *smd_orig = (SurfaceDeformModifierData *)modifier_get_original(md);
- float tmp_mat[4][4];
-
- invert_m4_m4(tmp_mat, ob->obmat);
- mul_m4_m4m4(smd_orig->mat, tmp_mat, ob_target->obmat);
-
- if (!surfacedeformBind(smd_orig, vertexCos, numverts, tnumpoly, tnumverts, target)) {
- smd->flags &= ~MOD_SDEF_BIND;
- }
- /* Early abort, this is binding 'call', no need to perform whole evaluation. */
- return;
- }
-
- /* Poly count checks */
- if (smd->numverts != numverts) {
- modifier_setError(md, "Verts changed from %u to %u", smd->numverts, numverts);
- return;
- }
- else if (smd->numpoly != tnumpoly) {
- modifier_setError(md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly);
- return;
- }
-
- /* Actual vertex location update starts here */
- SDefDeformData data = {
- .bind_verts = smd->verts,
- .targetCos = MEM_malloc_arrayN(tnumverts, sizeof(float[3]), "SDefTargetVertArray"),
- .vertexCos = vertexCos,
- };
-
- if (data.targetCos != NULL) {
- const MVert * const mvert = target->mvert;
-
- for (int i = 0; i < tnumverts; i++) {
- mul_v3_m4v3(data.targetCos[i], smd->mat, mvert[i].co);
- }
-
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = (numverts > 10000);
- BLI_task_parallel_range(0, numverts,
- &data,
- deformVert,
- &settings);
-
- MEM_freeN(data.targetCos);
- }
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+ Mesh *target;
+ unsigned int tnumverts, tnumpoly;
+
+ /* Exit function if bind flag is not set (free bind data if any). */
+ if (!(smd->flags & MOD_SDEF_BIND)) {
+ if (smd->verts != NULL) {
+ if (!DEG_is_active(ctx->depsgraph)) {
+ modifier_setError(md, "Attempt to bind from inactive dependency graph");
+ return;
+ }
+ ModifierData *md_orig = modifier_get_original(md);
+ freeData(md_orig);
+ }
+ return;
+ }
+
+ Object *ob_target = smd->target;
+ target = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false);
+ if (!target) {
+ modifier_setError(md, "No valid target mesh");
+ return;
+ }
+
+ tnumverts = target->totvert;
+ tnumpoly = target->totpoly;
+
+ /* If not bound, execute bind. */
+ if (smd->verts == NULL) {
+ if (!DEG_is_active(ctx->depsgraph)) {
+ modifier_setError(md, "Attempt to unbind from inactive dependency graph");
+ return;
+ }
+
+ SurfaceDeformModifierData *smd_orig = (SurfaceDeformModifierData *)modifier_get_original(md);
+ float tmp_mat[4][4];
+
+ invert_m4_m4(tmp_mat, ob->obmat);
+ mul_m4_m4m4(smd_orig->mat, tmp_mat, ob_target->obmat);
+
+ if (!surfacedeformBind(smd_orig, vertexCos, numverts, tnumpoly, tnumverts, target)) {
+ smd->flags &= ~MOD_SDEF_BIND;
+ }
+ /* Early abort, this is binding 'call', no need to perform whole evaluation. */
+ return;
+ }
+
+ /* Poly count checks */
+ if (smd->numverts != numverts) {
+ modifier_setError(md, "Verts changed from %u to %u", smd->numverts, numverts);
+ return;
+ }
+ else if (smd->numpoly != tnumpoly) {
+ modifier_setError(md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly);
+ return;
+ }
+
+ /* Actual vertex location update starts here */
+ SDefDeformData data = {
+ .bind_verts = smd->verts,
+ .targetCos = MEM_malloc_arrayN(tnumverts, sizeof(float[3]), "SDefTargetVertArray"),
+ .vertexCos = vertexCos,
+ };
+
+ if (data.targetCos != NULL) {
+ const MVert *const mvert = target->mvert;
+
+ for (int i = 0; i < tnumverts; i++) {
+ mul_v3_m4v3(data.targetCos[i], smd->mat, mvert[i].co);
+ }
+
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.use_threading = (numverts > 10000);
+ BLI_task_parallel_range(0, numverts, &data, deformVert, &settings);
+
+ MEM_freeN(data.targetCos);
+ }
}
-static void deformVerts(
- ModifierData *md, const ModifierEvalContext *ctx,
- Mesh *UNUSED(mesh),
- float (*vertexCos)[3], int numVerts)
+static void deformVerts(ModifierData *md,
+ const ModifierEvalContext *ctx,
+ Mesh *UNUSED(mesh),
+ float (*vertexCos)[3],
+ int numVerts)
{
- surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object);
+ surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object);
}
-static void deformVertsEM(
- ModifierData *md, const ModifierEvalContext *ctx,
- struct BMEditMesh *UNUSED(editData),
- Mesh *UNUSED(mesh),
- float (*vertexCos)[3], int numVerts)
+static void deformVertsEM(ModifierData *md,
+ const ModifierEvalContext *ctx,
+ struct BMEditMesh *UNUSED(editData),
+ Mesh *UNUSED(mesh),
+ float (*vertexCos)[3],
+ int numVerts)
{
- surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object);
+ surfacedeformModifier_do(md, ctx, vertexCos, numVerts, ctx->object);
}
static bool isDisabled(const Scene *UNUSED(scene), ModifierData *md, bool UNUSED(useRenderParams))
{
- SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
- return smd->target == NULL && !(smd->verts != NULL && !(smd->flags & MOD_SDEF_BIND));
+ return smd->target == NULL && !(smd->verts != NULL && !(smd->flags & MOD_SDEF_BIND));
}
ModifierTypeInfo modifierType_SurfaceDeform = {
- /* name */ "Surface Deform",
- /* structName */ "SurfaceDeformModifierData",
- /* structSize */ sizeof(SurfaceDeformModifierData),
- /* type */ eModifierTypeType_OnlyDeform,
- /* flags */ eModifierTypeFlag_AcceptsMesh |
- eModifierTypeFlag_SupportsEditmode,
-
- /* copyData */ copyData,
-
- /* deformVerts */ deformVerts,
- /* deformMatrices */ NULL,
- /* deformVertsEM */ deformVertsEM,
- /* deformMatricesEM */ NULL,
- /* applyModifier */ NULL,
-
- /* initData */ initData,
- /* requiredDataMask */ NULL,
- /* freeData */ freeData,
- /* isDisabled */ isDisabled,
- /* updateDepsgraph */ updateDepsgraph,
- /* dependsOnTime */ NULL,
- /* dependsOnNormals */ NULL,
- /* foreachObjectLink */ foreachObjectLink,
- /* foreachIDLink */ NULL,
- /* foreachTexLink */ NULL,
- /* freeRuntimeData */ NULL,
+ /* name */ "Surface Deform",
+ /* structName */ "SurfaceDeformModifierData",
+ /* structSize */ sizeof(SurfaceDeformModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+
+ /* deformVerts */ deformVerts,
+ /* deformMatrices */ NULL,
+ /* deformVertsEM */ deformVertsEM,
+ /* deformMatricesEM */ NULL,
+ /* applyModifier */ NULL,
+
+ /* initData */ initData,
+ /* requiredDataMask */ NULL,
+ /* freeData */ freeData,
+ /* isDisabled */ isDisabled,
+ /* updateDepsgraph */ updateDepsgraph,
+ /* dependsOnTime */ NULL,
+ /* dependsOnNormals */ NULL,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+ /* freeRuntimeData */ NULL,
};