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_laplaciandeform.c')
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciandeform.c218
1 files changed, 119 insertions, 99 deletions
diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c
index 0471539dc14..df64bf63ff7 100644
--- a/source/blender/modifiers/intern/MOD_laplaciandeform.c
+++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c
@@ -15,7 +15,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * The Original Code is Copyright (C) 2005 by the Blender Foundation.
+ * The Original Code is Copyright (C) 2013 by the Blender Foundation.
* All rights reserved.
*
* Contributor(s): Alexander Pinzon Fernandez
@@ -23,7 +23,7 @@
* ***** END GPL LICENSE BLOCK *****
*
*/
-
+
/** \file blender/modifiers/intern/MOD_laplaciandeform.c
* \ingroup modifiers
*/
@@ -41,16 +41,21 @@
#include "MOD_util.h"
-#include "ONL_opennl.h"
-#define LAPDEFORM_SYSTEM_NOT_CHANGE 0
-#define LAPDEFORM_SYSTEM_IS_DIFFERENT 1
-#define LAPDEFORM_SYSTEM_ONLY_CHANGE_ANCHORS 2
-#define LAPDEFORM_SYSTEM_ONLY_CHANGE_GROUP 3
-#define LAPDEFORM_SYSTEM_ONLY_CHANGE_MESH 4
-#define LAPDEFORM_SYSTEM_CHANGE_VERTEXES 5
-#define LAPDEFORM_SYSTEM_CHANGE_EDGES 6
-#define LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP 7
+enum {
+ LAPDEFORM_SYSTEM_NOT_CHANGE = 0,
+ LAPDEFORM_SYSTEM_IS_DIFFERENT,
+ LAPDEFORM_SYSTEM_ONLY_CHANGE_ANCHORS,
+ LAPDEFORM_SYSTEM_ONLY_CHANGE_GROUP,
+ LAPDEFORM_SYSTEM_ONLY_CHANGE_MESH,
+ LAPDEFORM_SYSTEM_CHANGE_VERTEXES,
+ LAPDEFORM_SYSTEM_CHANGE_EDGES,
+ LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP,
+};
+
+#ifdef WITH_OPENNL
+
+#include "ONL_opennl.h"
typedef struct LaplacianSystem {
bool is_matrix_computed;
@@ -60,18 +65,18 @@ typedef struct LaplacianSystem {
int total_faces;
int total_anchors;
int repeat;
- char anchor_grp_name[64]; /* Vertex Group name*/
- float (*co)[3]; /* Original vertex coordinates*/
- float (*no)[3]; /* Original vertex normal*/
- float (*delta)[3]; /* Differential Coordinates*/
+ char anchor_grp_name[64]; /* Vertex Group name */
+ float (*co)[3]; /* Original vertex coordinates */
+ float (*no)[3]; /* Original vertex normal */
+ float (*delta)[3]; /* Differential Coordinates */
unsigned int (*faces)[4]; /* Copy of MFace (tessface) v1-v4 */
- int *index_anchors; /* Static vertex index list*/
- int *unit_verts; /* Unit vectors of projected edges onto the plane orthogonal to n*/
- int *ringf_indices; /* Indices of faces per vertex*/
- int *ringv_indices; /* Indices of neighbors(vertex) per vertex*/
- NLContext *context; /* System for solve general implicit rotations*/
- MeshElemMap *ringf_map; /* Map of faces per vertex*/
- MeshElemMap *ringv_map; /* Map of vertex per vertex*/
+ int *index_anchors; /* Static vertex index list */
+ int *unit_verts; /* Unit vectors of projected edges onto the plane orthogonal to n */
+ int *ringf_indices; /* Indices of faces per vertex */
+ int *ringv_indices; /* Indices of neighbors(vertex) per vertex */
+ NLContext *context; /* System for solve general implicit rotations */
+ MeshElemMap *ringf_map; /* Map of faces per vertex */
+ MeshElemMap *ringv_map; /* Map of vertex per vertex */
} LaplacianSystem;
static LaplacianSystem *newLaplacianSystem(void)
@@ -125,6 +130,7 @@ static void deleteLaplacianSystem(LaplacianSystem *sys)
MEM_SAFE_FREE(sys->ringv_indices);
MEM_SAFE_FREE(sys->ringf_map);
MEM_SAFE_FREE(sys->ringv_map);
+
if (sys->context) {
nlDeleteContext(sys->context);
}
@@ -140,11 +146,13 @@ static float cotan_weight(const float v1[3], const float v2[3], const float v3[3
cross_v3_v3v3(c, a, b);
clen = len_v3(c);
- if (clen < FLT_EPSILON) {
+
+ if (clen > FLT_EPSILON) {
+ return dot_v3v3(a, b) / clen;
+ }
+ else {
return 0.0f;
}
-
- return dot_v3v3(a, b) / clen;
}
static void createFaceRingMap(
@@ -225,33 +233,33 @@ static void createVertRingMap(
}
/**
-* This method computes the Laplacian Matrix and Differential Coordinates for all vertex in the mesh.
-* The Linear system is LV = d
-* Where L is Laplacian Matrix, V as the vertexes in Mesh, d is the differential coordinates
-* The Laplacian Matrix is computes as a
-* Lij = sum(Wij) (if i == j)
-* Lij = Wij (if i != j)
-* Wij is weight between vertex Vi and vertex Vj, we use cotangent weight
-*
-* The Differential Coordinate is computes as a
-* di = Vi * sum(Wij) - sum(Wij * Vj)
-* Where :
-* di is the Differential Coordinate i
-* sum (Wij) is the sum of all weights between vertex Vi and its vertexes neighbors (Vj)
-* sum (Wij * Vj) is the sum of the product between vertex neighbor Vj and weight Wij for all neighborhood.
-*
-* This Laplacian Matrix is described in the paper:
-* Desbrun M. et.al, Implicit fairing of irregular meshes using diffusion and curvature flow, SIGGRAPH '99, pag 317-324,
-* New York, USA
-*
-* The computation of Laplace Beltrami operator on Hybrid Triangle/Quad Meshes is described in the paper:
-* Pinzon A., Romero E., Shape Inflation With an Adapted Laplacian Operator For Hybrid Quad/Triangle Meshes,
-* Conference on Graphics Patterns and Images, SIBGRAPI, 2013
-*
-* The computation of Differential Coordinates is described in the paper:
-* Sorkine, O. Laplacian Surface Editing. Proceedings of the EUROGRAPHICS/ACM SIGGRAPH Symposium on Geometry Processing,
-* 2004. p. 179-188.
-*/
+ * This method computes the Laplacian Matrix and Differential Coordinates for all vertex in the mesh.
+ * The Linear system is LV = d
+ * Where L is Laplacian Matrix, V as the vertexes in Mesh, d is the differential coordinates
+ * The Laplacian Matrix is computes as a
+ * Lij = sum(Wij) (if i == j)
+ * Lij = Wij (if i != j)
+ * Wij is weight between vertex Vi and vertex Vj, we use cotangent weight
+ *
+ * The Differential Coordinate is computes as a
+ * di = Vi * sum(Wij) - sum(Wij * Vj)
+ * Where :
+ * di is the Differential Coordinate i
+ * sum (Wij) is the sum of all weights between vertex Vi and its vertexes neighbors (Vj)
+ * sum (Wij * Vj) is the sum of the product between vertex neighbor Vj and weight Wij for all neighborhood.
+ *
+ * This Laplacian Matrix is described in the paper:
+ * Desbrun M. et.al, Implicit fairing of irregular meshes using diffusion and curvature flow, SIGGRAPH '99, pag 317-324,
+ * New York, USA
+ *
+ * The computation of Laplace Beltrami operator on Hybrid Triangle/Quad Meshes is described in the paper:
+ * Pinzon A., Romero E., Shape Inflation With an Adapted Laplacian Operator For Hybrid Quad/Triangle Meshes,
+ * Conference on Graphics Patterns and Images, SIBGRAPI, 2013
+ *
+ * The computation of Differential Coordinates is described in the paper:
+ * Sorkine, O. Laplacian Surface Editing. Proceedings of the EUROGRAPHICS/ACM SIGGRAPH Symposium on Geometry Processing,
+ * 2004. p. 179-188.
+ */
static void initLaplacianMatrix(LaplacianSystem *sys)
{
float v1[3], v2[3], v3[3], v4[3], no[3];
@@ -270,12 +278,12 @@ static void initLaplacianMatrix(LaplacianSystem *sys)
has_4_vert = vidf[3] ? 1 : 0;
if (has_4_vert) {
- normal_quad_v3(no, sys->co[idv1], sys->co[idv2], sys->co[idv3], sys->co[idv4]);
+ normal_quad_v3(no, sys->co[idv1], sys->co[idv2], sys->co[idv3], sys->co[idv4]);
add_v3_v3(sys->no[idv4], no);
i = 4;
- }
+ }
else {
- normal_tri_v3(no, sys->co[idv1], sys->co[idv2], sys->co[idv3]);
+ normal_tri_v3(no, sys->co[idv1], sys->co[idv2], sys->co[idv3]);
i = 3;
}
add_v3_v3(sys->no[idv1], no);
@@ -332,14 +340,14 @@ static void initLaplacianMatrix(LaplacianSystem *sys)
nlMatrixAdd(idv1, idv2, -w2);
nlMatrixAdd(idv1, idv3, -w3);
nlMatrixAdd(idv1, idv1, w2 + w3 + w4);
-
+
}
}
}
static void computeImplictRotations(LaplacianSystem *sys)
{
- int vid, * vidn = NULL;
+ int vid, *vidn = NULL;
float minj, mjt, qj[3], vj[3];
int i, j, ln;
@@ -371,10 +379,10 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys)
int *fidn;
for (i = 0; i < sys->total_verts; i++) {
- copy_v3_v3(pi, sys->co[i]);
- copy_v3_v3(ni, sys->no[i]);
+ copy_v3_v3(pi, sys->co[i]);
+ copy_v3_v3(ni, sys->no[i]);
k = sys->unit_verts[i];
- copy_v3_v3(pj, sys->co[k]);
+ copy_v3_v3(pj, sys->co[k]);
sub_v3_v3v3(uij, pj, pi);
mul_v3_v3fl(dun, ni, dot_v3v3(uij, ni));
sub_v3_v3(uij, dun);
@@ -388,7 +396,7 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys)
pi[0] = nlGetVariable(0, i);
pi[1] = nlGetVariable(1, i);
pi[2] = nlGetVariable(2, i);
- ni[0] = 0.0f; ni[1] = 0.0f; ni[2] = 0.0f;
+ zero_v3(ni);
num_fni = 0;
num_fni = sys->ringf_map[i].count;
for (fi = 0; fi < num_fni; fi++) {
@@ -407,10 +415,10 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys)
if (lvin == 3) {
normal_tri_v3(fni, vn[0], vn[1], vn[2]);
- }
+ }
else if (lvin == 4) {
normal_quad_v3(fni, vn[0], vn[1], vn[2], vn[3]);
- }
+ }
add_v3_v3(ni, fni);
}
@@ -428,7 +436,7 @@ static void rotateDifferentialCoordinates(LaplacianSystem *sys)
nlRightHandSideSet(0, i, fni[0]);
nlRightHandSideSet(1, i, fni[1]);
nlRightHandSideSet(2, i, fni[2]);
- }
+ }
else {
nlRightHandSideSet(0, i, sys->delta[i][0]);
nlRightHandSideSet(1, i, sys->delta[i][1]);
@@ -485,7 +493,7 @@ static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3])
nlEnd(NL_SYSTEM);
if (nlSolveAdvanced(NULL, NL_TRUE)) {
sys->has_solution = true;
-
+
for (j = 1; j <= sys->repeat; j++) {
nlBegin(NL_SYSTEM);
nlBegin(NL_MATRIX);
@@ -510,18 +518,18 @@ static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3])
vertexCos[vid][0] = nlGetVariable(0, vid);
vertexCos[vid][1] = nlGetVariable(1, vid);
vertexCos[vid][2] = nlGetVariable(2, vid);
- }
- }
+ }
+ }
else {
sys->has_solution = false;
}
-
- }
+
+ }
else {
sys->has_solution = false;
}
sys->is_matrix_computed = true;
- }
+ }
else {
if (!sys->has_solution) {
return;
@@ -570,12 +578,12 @@ static void laplacianDeformPreview(LaplacianSystem *sys, float (*vertexCos)[3])
vertexCos[vid][0] = nlGetVariable(0, vid);
vertexCos[vid][1] = nlGetVariable(1, vid);
vertexCos[vid][2] = nlGetVariable(2, vid);
- }
- }
+ }
+ }
else {
sys->has_solution = false;
}
- }
+ }
else {
sys->has_solution = false;
}
@@ -620,9 +628,9 @@ static void initSystem(LaplacianDeformModifierData *lmd, Object *ob, DerivedMesh
}
DM_ensure_tessface(dm);
total_anchors = STACK_SIZE(index_anchors);
- lmd->cacheSystem = initLaplacianSystem(numVerts, dm->getNumEdges(dm), dm->getNumTessFaces(dm),
+ lmd->cache_system = initLaplacianSystem(numVerts, dm->getNumEdges(dm), dm->getNumTessFaces(dm),
total_anchors, lmd->anchor_grp_name, lmd->repeat);
- sys = (LaplacianSystem *)lmd->cacheSystem;
+ sys = (LaplacianSystem *)lmd->cache_system;
memcpy(sys->index_anchors, index_anchors, sizeof(int) * total_anchors);
memcpy(sys->co, vertexCos, sizeof(float[3]) * numVerts);
MEM_freeN(index_anchors);
@@ -655,7 +663,7 @@ static int isSystemDifferent(LaplacianDeformModifierData *lmd, Object *ob, Deriv
float wpaint;
MDeformVert *dvert = NULL;
MDeformVert *dv = NULL;
- LaplacianSystem *sys = (LaplacianSystem *)lmd->cacheSystem;
+ LaplacianSystem *sys = (LaplacianSystem *)lmd->cache_system;
if (sys->total_verts != numVerts) {
return LAPDEFORM_SYSTEM_CHANGE_VERTEXES;
@@ -664,7 +672,7 @@ static int isSystemDifferent(LaplacianDeformModifierData *lmd, Object *ob, Deriv
return LAPDEFORM_SYSTEM_CHANGE_EDGES;
}
if (!STREQ(lmd->anchor_grp_name, sys->anchor_grp_name)) {
- return LAPDEFORM_SYSTEM_ONLY_CHANGE_GROUP;
+ return LAPDEFORM_SYSTEM_ONLY_CHANGE_GROUP;
}
modifier_get_vgroup(ob, dm, lmd->anchor_grp_name, &dvert, &defgrp_index);
if (!dvert) {
@@ -694,18 +702,18 @@ static void LaplacianDeformModifier_do(
LaplacianSystem *sys = NULL;
filevertexCos = NULL;
if (!(lmd->flag & MOD_LAPLACIANDEFORM_BIND)) {
- if (lmd->cacheSystem) {
- sys = lmd->cacheSystem;
+ if (lmd->cache_system) {
+ sys = lmd->cache_system;
deleteLaplacianSystem(sys);
- lmd->cacheSystem = NULL;
+ lmd->cache_system = NULL;
}
lmd->total_verts = 0;
MEM_SAFE_FREE(lmd->vertexco);
return;
}
- if (lmd->cacheSystem) {
+ if (lmd->cache_system) {
sysdif = isSystemDifferent(lmd, ob, dm, numVerts);
- sys = lmd->cacheSystem;
+ sys = lmd->cache_system;
if (sysdif) {
if (sysdif == LAPDEFORM_SYSTEM_ONLY_CHANGE_ANCHORS || sysdif == LAPDEFORM_SYSTEM_ONLY_CHANGE_GROUP) {
filevertexCos = MEM_mallocN(sizeof(float[3]) * numVerts, "TempModDeformCoordinates");
@@ -713,23 +721,26 @@ static void LaplacianDeformModifier_do(
MEM_SAFE_FREE(lmd->vertexco);
lmd->total_verts = 0;
deleteLaplacianSystem(sys);
+ lmd->cache_system = NULL;
initSystem(lmd, ob, dm, filevertexCos, numVerts);
- sys = lmd->cacheSystem; /* may have been reallocated */
+ sys = lmd->cache_system; /* may have been reallocated */
MEM_SAFE_FREE(filevertexCos);
- laplacianDeformPreview(sys, vertexCos);
+ if (sys) {
+ laplacianDeformPreview(sys, vertexCos);
+ }
}
else {
if (sysdif == LAPDEFORM_SYSTEM_CHANGE_VERTEXES) {
- modifier_setError(&lmd->modifier, "Verts changed from %d to %d", lmd->total_verts, numVerts);
- }
+ modifier_setError(&lmd->modifier, "Vertices changed from %d to %d", lmd->total_verts, numVerts);
+ }
else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_EDGES) {
modifier_setError(&lmd->modifier, "Edges changed from %d to %d", sys->total_edges, dm->getNumEdges(dm));
- }
+ }
else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP) {
- modifier_setError(&lmd->modifier, "Vertex group %s is not valid", sys->anchor_grp_name);
+ modifier_setError(&lmd->modifier, "Vertex group '%s' is not valid", sys->anchor_grp_name);
}
}
- }
+ }
else {
sys->repeat = lmd->repeat;
laplacianDeformPreview(sys, vertexCos);
@@ -743,24 +754,32 @@ static void LaplacianDeformModifier_do(
MEM_SAFE_FREE(lmd->vertexco);
lmd->total_verts = 0;
initSystem(lmd, ob, dm, filevertexCos, numVerts);
- sys = lmd->cacheSystem;
+ sys = lmd->cache_system;
MEM_SAFE_FREE(filevertexCos);
laplacianDeformPreview(sys, vertexCos);
}
- }
+ }
else {
if (isValidVertexGroup(lmd, ob, dm)) {
initSystem(lmd, ob, dm, vertexCos, numVerts);
- sys = lmd->cacheSystem;
+ sys = lmd->cache_system;
laplacianDeformPreview(sys, vertexCos);
}
}
}
if (sys->is_matrix_computed && !sys->has_solution) {
- modifier_setError(&lmd->modifier, "The system not found a solution.");
+ modifier_setError(&lmd->modifier, "The system did not find a solution");
}
}
+#else /* WITH_OPENNL */
+static void LaplacianDeformModifier_do(
+ LaplacianDeformModifierData *lmd, Object *ob, DerivedMesh *dm,
+ float (*vertexCos)[3], int numVerts)
+{
+ (void)lmd, (void)ob, (void)dm, (void)vertexCos, (void)numVerts;
+}
+#endif /* WITH_OPENNL */
static void initData(ModifierData *md)
{
@@ -769,7 +788,7 @@ static void initData(ModifierData *md)
lmd->total_verts = 0;
lmd->repeat = 1;
lmd->vertexco = NULL;
- lmd->cacheSystem = NULL;
+ lmd->cache_system = NULL;
lmd->flag = 0;
}
@@ -781,7 +800,7 @@ static void copyData(ModifierData *md, ModifierData *target)
tlmd->repeat = lmd->repeat;
BLI_strncpy(tlmd->anchor_grp_name, lmd->anchor_grp_name, sizeof(tlmd->anchor_grp_name));
tlmd->vertexco = MEM_dupallocN(lmd->vertexco);
- tlmd->cacheSystem = MEM_dupallocN(lmd->cacheSystem);
+ tlmd->cache_system = MEM_dupallocN(lmd->cache_system);
tlmd->flag = lmd->flag;
}
@@ -810,14 +829,14 @@ static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData,
dm->release(dm);
}
}
-
+
static void deformVertsEM(
ModifierData *md, Object *ob, struct BMEditMesh *editData,
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
DerivedMesh *dm = get_dm(ob, editData, derivedData, NULL, false, false);
LaplacianDeformModifier_do((LaplacianDeformModifierData *)md, ob, dm,
- vertexCos, numVerts);
+ vertexCos, numVerts);
if (dm != derivedData) {
dm->release(dm);
}
@@ -826,11 +845,12 @@ static void deformVertsEM(
static void freeData(ModifierData *md)
{
LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)md;
- LaplacianSystem *sys = (LaplacianSystem *)(lmd->cacheSystem);
-
+#ifdef WITH_OPENNL
+ LaplacianSystem *sys = (LaplacianSystem *)lmd->cache_system;
if (sys) {
deleteLaplacianSystem(sys);
}
+#endif
MEM_SAFE_FREE(lmd->vertexco);
lmd->total_verts = 0;
}