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:
authorCampbell Barton <ideasman42@gmail.com>2015-08-04 14:30:10 +0300
committerCampbell Barton <ideasman42@gmail.com>2015-08-04 14:58:35 +0300
commitf1a9a8cbfddd0fe62e8a72b4d2c8c13852d216b6 (patch)
tree57c2579c1733f2ae05f143c3e0e68379c2671c21 /source/blender/modifiers/intern/MOD_laplaciansmooth.c
parentc1938eb127d02aba4b6251d6f13ea5c8b30fa673 (diff)
Remove MFace use w/ laplacian smooth
Use polygons for calculation
Diffstat (limited to 'source/blender/modifiers/intern/MOD_laplaciansmooth.c')
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciansmooth.c283
1 files changed, 103 insertions, 180 deletions
diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
index a142d18a6d3..6a72c92c559 100644
--- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c
+++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c
@@ -59,7 +59,8 @@ struct BLaplacianSystem {
float *vlengths; /* Total sum of lengths(edges) per vertice*/
float *vweights; /* Total sum of weights per vertice*/
int numEdges; /* Number of edges*/
- int numFaces; /* Number of faces*/
+ int numLoops; /* Number of edges*/
+ int numPolys; /* Number of faces*/
int numVerts; /* Number of verts*/
short *numNeFa; /* Number of neighboors faces around vertice*/
short *numNeEd; /* Number of neighboors Edges around vertice*/
@@ -67,8 +68,9 @@ struct BLaplacianSystem {
/* Pointers to data*/
float (*vertexCos)[3];
- MFace *mfaces;
- MEdge *medges;
+ const MPoly *mpoly;
+ const MLoop *mloop;
+ const MEdge *medges;
NLContext *context;
/*Data*/
@@ -79,9 +81,8 @@ typedef struct BLaplacianSystem LaplacianSystem;
static CustomDataMask required_data_mask(Object *ob, ModifierData *md);
static bool is_disabled(ModifierData *md, int useRenderParams);
-static float average_area_quad_v3(float *v1, float *v2, float *v3, float *v4);
-static float compute_volume(float (*vertexCos)[3], MFace *mfaces, int numFaces);
-static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts);
+static float compute_volume(const float center[3], float (*vertexCos)[3], const MPoly *mpoly, int numPolys, const MLoop *mloop);
+static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numPolys, int a_numLoops, int a_numVerts);
static void copy_data(ModifierData *md, ModifierData *target);
static void delete_laplacian_system(LaplacianSystem *sys);
static void delete_void_pointer(void *data);
@@ -113,7 +114,8 @@ static void delete_laplacian_system(LaplacianSystem *sys)
nlDeleteContext(sys->context);
}
sys->vertexCos = NULL;
- sys->mfaces = NULL;
+ sys->mpoly = NULL;
+ sys->mloop = NULL;
sys->medges = NULL;
MEM_freeN(sys);
}
@@ -121,7 +123,7 @@ static void delete_laplacian_system(LaplacianSystem *sys)
static void memset_laplacian_system(LaplacianSystem *sys, int val)
{
memset(sys->eweights, val, sizeof(float) * sys->numEdges);
- memset(sys->fweights, val, sizeof(float) * sys->numFaces * 3);
+ memset(sys->fweights, val, sizeof(float[3]) * sys->numLoops);
memset(sys->numNeEd, val, sizeof(short) * sys->numVerts);
memset(sys->numNeFa, val, sizeof(short) * sys->numVerts);
memset(sys->ring_areas, val, sizeof(float) * sys->numVerts);
@@ -130,12 +132,13 @@ static void memset_laplacian_system(LaplacianSystem *sys, int val)
memset(sys->zerola, val, sizeof(short) * sys->numVerts);
}
-static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts)
+static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numPolys, int a_numLoops, int a_numVerts)
{
LaplacianSystem *sys;
sys = MEM_callocN(sizeof(LaplacianSystem), "ModLaplSmoothSystem");
sys->numEdges = a_numEdges;
- sys->numFaces = a_numFaces;
+ sys->numPolys = a_numPolys;
+ sys->numLoops = a_numLoops;
sys->numVerts = a_numVerts;
sys->eweights = MEM_callocN(sizeof(float) * sys->numEdges, "ModLaplSmoothEWeight");
@@ -144,7 +147,7 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, in
return NULL;
}
- sys->fweights = MEM_callocN(sizeof(float) * 3 * sys->numFaces, "ModLaplSmoothFWeight");
+ sys->fweights = MEM_callocN(sizeof(float[3]) * sys->numLoops, "ModLaplSmoothFWeight");
if (!sys->fweights) {
delete_laplacian_system(sys);
return NULL;
@@ -189,46 +192,33 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, in
return sys;
}
-static float average_area_quad_v3(float *v1, float *v2, float *v3, float *v4)
+static float compute_volume(
+ const float center[3], float (*vertexCos)[3],
+ const MPoly *mpoly, int numPolys, const MLoop *mloop)
{
- float areaq;
- areaq = area_tri_v3(v1, v2, v3) + area_tri_v3(v1, v2, v4) + area_tri_v3(v1, v3, v4);
- return areaq / 2.0f;
-}
-
-static float compute_volume(float (*vertexCos)[3], MFace *mfaces, int numFaces)
-{
- float vol = 0.0f;
- float x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4;
int i;
- float *vf[4];
- for (i = 0; i < numFaces; i++) {
- vf[0] = vertexCos[mfaces[i].v1];
- vf[1] = vertexCos[mfaces[i].v2];
- vf[2] = vertexCos[mfaces[i].v3];
-
- x1 = vf[0][0];
- y1 = vf[0][1];
- z1 = vf[0][2];
-
- x2 = vf[1][0];
- y2 = vf[1][1];
- z2 = vf[1][2];
-
- x3 = vf[2][0];
- y3 = vf[2][1];
- z3 = vf[2][2];
-
-
- vol += (1.0f / 6.0f) * (x2 * y3 * z1 + x3 * y1 * z2 - x1 * y3 * z2 - x2 * y1 * z3 + x1 * y2 * z3 - x3 * y2 * z1);
- if ((&mfaces[i])->v4) {
- vf[3] = vertexCos[mfaces[i].v4];
- x4 = vf[3][0];
- y4 = vf[3][1];
- z4 = vf[3][2];
- vol += (1.0f / 6.0f) * (x1 * y3 * z4 - x1 * y4 * z3 - x3 * y1 * z4 + x3 * z1 * y4 + y1 * x4 * z3 - x4 * y3 * z1);
+ float vol = 0.0f;
+
+ for (i = 0; i < numPolys; i++) {
+ const MPoly *mp = &mpoly[i];
+ const MLoop *l_first = &mloop[mp->loopstart];
+ const MLoop *l_prev = l_first + 1;
+ const MLoop *l_curr = l_first + 2;
+ const MLoop *l_term = l_first + mp->totloop;
+
+
+ for (;
+ l_curr != l_term;
+ l_prev = l_curr, l_curr++)
+ {
+ vol += volume_tetrahedron_signed_v3(
+ center,
+ vertexCos[l_first->v],
+ vertexCos[l_prev->v],
+ vertexCos[l_curr->v]);
}
}
+
return fabsf(vol);
}
@@ -256,12 +246,12 @@ static void volume_preservation(LaplacianSystem *sys, float vini, float vend, sh
static void init_laplacian_matrix(LaplacianSystem *sys)
{
- float *v1, *v2, *v3, *v4;
- float w1, w2, w3, w4;
+ float *v1, *v2;
+ float w1, w2, w3;
float areaf;
- int i, j;
- unsigned int idv1, idv2, idv3, idv4, idv[4];
- bool has_4_vert;
+ int i;
+ unsigned int idv1, idv2;
+
for (i = 0; i < sys->numEdges; i++) {
idv1 = sys->medges[i].v1;
idv2 = sys->medges[i].v2;
@@ -282,86 +272,46 @@ static void init_laplacian_matrix(LaplacianSystem *sys)
sys->eweights[i] = w1;
}
- for (i = 0; i < sys->numFaces; i++) {
- has_4_vert = ((&sys->mfaces[i])->v4) ? 1 : 0;
-
- idv1 = sys->mfaces[i].v1;
- idv2 = sys->mfaces[i].v2;
- idv3 = sys->mfaces[i].v3;
- idv4 = has_4_vert ? sys->mfaces[i].v4 : 0;
- sys->numNeFa[idv1] += 1;
- sys->numNeFa[idv2] += 1;
- sys->numNeFa[idv3] += 1;
- if (has_4_vert) sys->numNeFa[idv4] += 1;
-
- v1 = sys->vertexCos[idv1];
- v2 = sys->vertexCos[idv2];
- v3 = sys->vertexCos[idv3];
- v4 = has_4_vert ? sys->vertexCos[idv4] : NULL;
+ for (i = 0; i < sys->numPolys; i++) {
+ const MPoly *mp = &sys->mpoly[i];
+ const MLoop *l_next = &sys->mloop[mp->loopstart];
+ const MLoop *l_term = l_next + mp->totloop;
+ const MLoop *l_prev = l_term - 2;
+ const MLoop *l_curr = l_term - 1;
- if (has_4_vert) {
- areaf = area_quad_v3(v1, v2, v3, sys->vertexCos[sys->mfaces[i].v4]);
- }
- else {
- areaf = area_tri_v3(v1, v2, v3);
- }
- if (fabsf(areaf) < sys->min_area) {
- sys->zerola[idv1] = 1;
- sys->zerola[idv2] = 1;
- sys->zerola[idv3] = 1;
- if (has_4_vert) sys->zerola[idv4] = 1;
- }
+ for (;
+ l_next != l_term;
+ l_prev = l_curr, l_curr = l_next, l_next++)
+ {
+ const float *v_prev = sys->vertexCos[l_prev->v];
+ const float *v_curr = sys->vertexCos[l_curr->v];
+ const float *v_next = sys->vertexCos[l_next->v];
+ const unsigned int l_curr_index = l_curr - sys->mloop;
- if (has_4_vert) {
- sys->ring_areas[idv1] += average_area_quad_v3(v1, v2, v3, v4);
- sys->ring_areas[idv2] += average_area_quad_v3(v2, v3, v4, v1);
- sys->ring_areas[idv3] += average_area_quad_v3(v3, v4, v1, v2);
- sys->ring_areas[idv4] += average_area_quad_v3(v4, v1, v2, v3);
- }
- else {
- sys->ring_areas[idv1] += areaf;
- sys->ring_areas[idv2] += areaf;
- sys->ring_areas[idv3] += areaf;
- }
+ sys->numNeFa[l_curr->v] += 1;
- if (has_4_vert) {
+ areaf = area_tri_v3(v_prev, v_curr, v_next);
- idv[0] = idv1;
- idv[1] = idv2;
- idv[2] = idv3;
- idv[3] = idv4;
+ if (areaf < sys->min_area) {
+ sys->zerola[l_curr->v] = 1;
+ }
- for (j = 0; j < 4; j++) {
- idv1 = idv[j];
- idv2 = idv[(j + 1) % 4];
- idv3 = idv[(j + 2) % 4];
- idv4 = idv[(j + 3) % 4];
+ sys->ring_areas[l_prev->v] += areaf;
+ sys->ring_areas[l_curr->v] += areaf;
+ sys->ring_areas[l_next->v] += areaf;
- v1 = sys->vertexCos[idv1];
- v2 = sys->vertexCos[idv2];
- v3 = sys->vertexCos[idv3];
- v4 = sys->vertexCos[idv4];
+ w1 = cotangent_tri_weight_v3(v_curr, v_next, v_prev) / 2.0f;
+ w2 = cotangent_tri_weight_v3(v_next, v_prev, v_curr) / 2.0f;
+ w3 = cotangent_tri_weight_v3(v_prev, v_curr, v_next) / 2.0f;
- w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2);
- w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3);
- w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1);
+ sys->fweights[l_curr_index][0] += w1;
+ sys->fweights[l_curr_index][1] += w2;
+ sys->fweights[l_curr_index][2] += w3;
- sys->vweights[idv1] += (w2 + w3 + w4) / 4.0f;
- }
- }
- else {
- w1 = cotangent_tri_weight_v3(v1, v2, v3) / 2.0f;
- w2 = cotangent_tri_weight_v3(v2, v3, v1) / 2.0f;
- w3 = cotangent_tri_weight_v3(v3, v1, v2) / 2.0f;
-
- sys->fweights[i][0] = sys->fweights[i][0] + w1;
- sys->fweights[i][1] = sys->fweights[i][1] + w2;
- sys->fweights[i][2] = sys->fweights[i][2] + w3;
-
- sys->vweights[idv1] = sys->vweights[idv1] + w2 + w3;
- sys->vweights[idv2] = sys->vweights[idv2] + w1 + w3;
- sys->vweights[idv3] = sys->vweights[idv3] + w1 + w2;
+ sys->vweights[l_curr->v] += w2 + w3;
+ sys->vweights[l_next->v] += w1 + w3;
+ sys->vweights[l_prev->v] += w1 + w2;
}
}
for (i = 0; i < sys->numEdges; i++) {
@@ -378,62 +328,34 @@ static void init_laplacian_matrix(LaplacianSystem *sys)
static void fill_laplacian_matrix(LaplacianSystem *sys)
{
- float *v1, *v2, *v3, *v4;
- float w2, w3, w4;
- int i, j;
- bool has_4_vert;
- unsigned int idv1, idv2, idv3, idv4, idv[4];
-
- for (i = 0; i < sys->numFaces; i++) {
- idv1 = sys->mfaces[i].v1;
- idv2 = sys->mfaces[i].v2;
- idv3 = sys->mfaces[i].v3;
- has_4_vert = ((&sys->mfaces[i])->v4) ? 1 : 0;
-
- if (has_4_vert) {
- idv[0] = sys->mfaces[i].v1;
- idv[1] = sys->mfaces[i].v2;
- idv[2] = sys->mfaces[i].v3;
- idv[3] = sys->mfaces[i].v4;
- for (j = 0; j < 4; j++) {
- idv1 = idv[j];
- idv2 = idv[(j + 1) % 4];
- idv3 = idv[(j + 2) % 4];
- idv4 = idv[(j + 3) % 4];
-
- v1 = sys->vertexCos[idv1];
- v2 = sys->vertexCos[idv2];
- v3 = sys->vertexCos[idv3];
- v4 = sys->vertexCos[idv4];
-
- w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2);
- w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3);
- w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1);
-
- w2 = w2 / 4.0f;
- w3 = w3 / 4.0f;
- w4 = w4 / 4.0f;
-
- if (sys->numNeEd[idv1] == sys->numNeFa[idv1] && sys->zerola[idv1] == 0) {
- nlMatrixAdd(idv1, idv2, w2 * sys->vweights[idv1]);
- nlMatrixAdd(idv1, idv3, w3 * sys->vweights[idv1]);
- nlMatrixAdd(idv1, idv4, w4 * sys->vweights[idv1]);
- }
- }
- }
- else {
+ int i;
+ unsigned int idv1, idv2;
+
+ for (i = 0; i < sys->numPolys; i++) {
+ const MPoly *mp = &sys->mpoly[i];
+ const MLoop *l_next = &sys->mloop[mp->loopstart];
+ const MLoop *l_term = l_next + mp->totloop;
+ const MLoop *l_prev = l_term - 2;
+ const MLoop *l_curr = l_term - 1;
+
+ for (;
+ l_next != l_term;
+ l_prev = l_curr, l_curr = l_next, l_next++)
+ {
+ const unsigned int l_curr_index = l_curr - sys->mloop;
+
/* Is ring if number of faces == number of edges around vertice*/
- if (sys->numNeEd[idv1] == sys->numNeFa[idv1] && sys->zerola[idv1] == 0) {
- nlMatrixAdd(idv1, idv2, sys->fweights[i][2] * sys->vweights[idv1]);
- nlMatrixAdd(idv1, idv3, sys->fweights[i][1] * sys->vweights[idv1]);
+ if (sys->numNeEd[l_curr->v] == sys->numNeFa[l_curr->v] && sys->zerola[l_curr->v] == 0) {
+ nlMatrixAdd(l_curr->v, l_next->v, sys->fweights[l_curr_index][2] * sys->vweights[l_curr->v]);
+ nlMatrixAdd(l_curr->v, l_prev->v, sys->fweights[l_curr_index][1] * sys->vweights[l_curr->v]);
}
- if (sys->numNeEd[idv2] == sys->numNeFa[idv2] && sys->zerola[idv2] == 0) {
- nlMatrixAdd(idv2, idv1, sys->fweights[i][2] * sys->vweights[idv2]);
- nlMatrixAdd(idv2, idv3, sys->fweights[i][0] * sys->vweights[idv2]);
+ if (sys->numNeEd[l_next->v] == sys->numNeFa[l_next->v] && sys->zerola[l_next->v] == 0) {
+ nlMatrixAdd(l_next->v, l_curr->v, sys->fweights[l_curr_index][2] * sys->vweights[l_next->v]);
+ nlMatrixAdd(l_next->v, l_prev->v, sys->fweights[l_curr_index][0] * sys->vweights[l_next->v]);
}
- if (sys->numNeEd[idv3] == sys->numNeFa[idv3] && sys->zerola[idv3] == 0) {
- nlMatrixAdd(idv3, idv1, sys->fweights[i][1] * sys->vweights[idv3]);
- nlMatrixAdd(idv3, idv2, sys->fweights[i][0] * sys->vweights[idv3]);
+ if (sys->numNeEd[l_prev->v] == sys->numNeFa[l_prev->v] && sys->zerola[l_prev->v] == 0) {
+ nlMatrixAdd(l_prev->v, l_curr->v, sys->fweights[l_curr_index][1] * sys->vweights[l_prev->v]);
+ nlMatrixAdd(l_prev->v, l_next->v, sys->fweights[l_curr_index][0] * sys->vweights[l_prev->v]);
}
}
}
@@ -460,7 +382,7 @@ static void validate_solution(LaplacianSystem *sys, short flag, float lambda, fl
float vini, vend;
if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) {
- vini = compute_volume(sys->vertexCos, sys->mfaces, sys->numFaces);
+ vini = compute_volume(sys->vert_centroid, sys->vertexCos, sys->mpoly, sys->numPolys, sys->mloop);
}
for (i = 0; i < sys->numVerts; i++) {
if (sys->zerola[i] == 0) {
@@ -477,7 +399,7 @@ static void validate_solution(LaplacianSystem *sys, short flag, float lambda, fl
}
}
if (flag & MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME) {
- vend = compute_volume(sys->vertexCos, sys->mfaces, sys->numFaces);
+ vend = compute_volume(sys->vert_centroid, sys->vertexCos, sys->mpoly, sys->numPolys, sys->mloop);
volume_preservation(sys, vini, vend, flag);
}
}
@@ -495,12 +417,13 @@ static void laplaciansmoothModifier_do(
DM_ensure_tessface(dm);
- sys = init_laplacian_system(dm->getNumEdges(dm), dm->getNumTessFaces(dm), numVerts);
+ sys = init_laplacian_system(dm->getNumEdges(dm), dm->getNumPolys(dm), dm->getNumLoops(dm), numVerts);
if (!sys) {
return;
}
- sys->mfaces = dm->getTessFaceArray(dm);
+ sys->mpoly = dm->getPolyArray(dm);
+ sys->mloop = dm->getLoopArray(dm);
sys->medges = dm->getEdgeArray(dm);
sys->vertexCos = vertexCos;
sys->min_area = 0.00001f;