[Bf-blender-cvs] [68586d2c183] master: Complex Solidify: improve constraints solver

Henrik Dick noreply at git.blender.org
Mon Feb 21 14:14:05 CET 2022


Commit: 68586d2c183bb36464d8de4c50b1c23c47631a83
Author: Henrik Dick
Date:   Mon Feb 21 14:05:00 2022 +0100
Branches: master
https://developer.blender.org/rB68586d2c183bb36464d8de4c50b1c23c47631a83

Complex Solidify: improve constraints solver

The constraints solver is now able to handle more cases correctly.
Also the behavior of the boundary fixes is slightly changed if
the constraints thickness mode is used.

Differential Revision: https://developer.blender.org/D14143

===================================================================

M	source/blender/modifiers/intern/MOD_solidify_nonmanifold.c

===================================================================

diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
index ed7acef4cdc..e4f7a7b5473 100644
--- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
+++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
@@ -1405,21 +1405,26 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
         for (uint j = 0; g->valid; j++, g++) {
           if (!g->is_singularity) {
             float *nor = g->no;
+            /* During vertex position calculation, the algorithm decides if it wants to disable the
+             * boundary fix to maintain correct thickness. If the used algorithm does not produce a
+             * free move direction (move_nor), it can use approximate_free_direction to decide on
+             * a movement direction based on the connected edges. */
             float move_nor[3] = {0, 0, 0};
             bool disable_boundary_fix = (smd->nonmanifold_boundary_mode ==
                                              MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_NONE ||
                                          (g->is_orig_closed || g->split));
+            bool approximate_free_direction = false;
             /* Constraints Method. */
             if (smd->nonmanifold_offset_mode == MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_CONSTRAINTS) {
               NewEdgeRef *first_edge = NULL;
               NewEdgeRef **edge_ptr = g->edges;
               /* Contains normal and offset [nx, ny, nz, ofs]. */
-              float(*normals_queue)[4] = MEM_malloc_arrayN(
-                  g->edges_len + 1, sizeof(*normals_queue), "normals_queue in solidify");
+              float(*planes_queue)[4] = MEM_malloc_arrayN(
+                  g->edges_len + 1, sizeof(*planes_queue), "planes_queue in solidify");
               uint queue_index = 0;
 
-              float face_nors[3][3];
-              float nor_ofs[3];
+              float fallback_nor[3];
+              float fallback_ofs = 0.0f;
 
               const bool cycle = (g->is_orig_closed && !g->split) || g->is_even_split;
               for (uint k = 0; k < g->edges_len; k++, edge_ptr++) {
@@ -1436,17 +1441,17 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
                       }
 
                       if (!null_faces[face->index]) {
-                        /* And normal to the queue. */
-                        mul_v3_v3fl(normals_queue[queue_index],
+                        /* And plane to the queue. */
+                        mul_v3_v3fl(planes_queue[queue_index],
                                     poly_nors[face->index],
                                     face->reversed ? -1 : 1);
-                        normals_queue[queue_index++][3] = ofs;
+                        planes_queue[queue_index++][3] = ofs;
                       }
                       else {
                         /* Just use this approximate normal of the null face if there is no other
                          * normal to use. */
-                        mul_v3_v3fl(face_nors[0], poly_nors[face->index], face->reversed ? -1 : 1);
-                        nor_ofs[0] = ofs;
+                        mul_v3_v3fl(fallback_nor, poly_nors[face->index], face->reversed ? -1 : 1);
+                        fallback_ofs = ofs;
                       }
                     }
                   }
@@ -1455,131 +1460,170 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
                   }
                 }
               }
-              uint face_nors_len = 0;
-              const float stop_explosion = 0.999f - fabsf(smd->offset_fac) * 0.05f;
-              while (queue_index > 0) {
-                if (face_nors_len == 0) {
-                  if (queue_index <= 2) {
-                    for (uint k = 0; k < queue_index; k++) {
-                      copy_v3_v3(face_nors[k], normals_queue[k]);
-                      nor_ofs[k] = normals_queue[k][3];
+              if (queue_index > 2) {
+                /* Find the two most different normals. */
+                float min_p = 2.0f;
+                uint min_n0 = 0;
+                uint min_n1 = 0;
+                for (uint k = 0; k < queue_index; k++) {
+                  for (uint m = k + 1; m < queue_index; m++) {
+                    float p = dot_v3v3(planes_queue[k], planes_queue[m]);
+                    if (p <= min_p + FLT_EPSILON) {
+                      min_p = p;
+                      min_n0 = m;
+                      min_n1 = k;
                     }
-                    face_nors_len = queue_index;
-                    queue_index = 0;
                   }
-                  else {
-                    /* Find most different two normals. */
-                    float min_p = 2;
-                    uint min_n0 = 0;
-                    uint min_n1 = 0;
-                    for (uint k = 0; k < queue_index; k++) {
-                      for (uint m = k + 1; m < queue_index; m++) {
-                        float p = dot_v3v3(normals_queue[k], normals_queue[m]);
-                        if (p <= min_p + FLT_EPSILON) {
-                          min_p = p;
-                          min_n0 = m;
-                          min_n1 = k;
-                        }
-                      }
-                    }
-                    copy_v3_v3(face_nors[0], normals_queue[min_n0]);
-                    copy_v3_v3(face_nors[1], normals_queue[min_n1]);
-                    nor_ofs[0] = normals_queue[min_n0][3];
-                    nor_ofs[1] = normals_queue[min_n1][3];
-                    face_nors_len = 2;
-                    queue_index--;
-                    memmove(normals_queue + min_n0,
-                            normals_queue + min_n0 + 1,
-                            (queue_index - min_n0) * sizeof(*normals_queue));
-                    queue_index--;
-                    memmove(normals_queue + min_n1,
-                            normals_queue + min_n1 + 1,
-                            (queue_index - min_n1) * sizeof(*normals_queue));
-                    min_p = 1;
-                    min_n1 = 0;
-                    float max_p = -1;
-                    for (uint k = 0; k < queue_index; k++) {
-                      max_p = -1;
-                      for (uint m = 0; m < face_nors_len; m++) {
-                        float p = dot_v3v3(face_nors[m], normals_queue[k]);
-                        if (p > max_p + FLT_EPSILON) {
-                          max_p = p;
-                        }
-                      }
-                      if (max_p <= min_p + FLT_EPSILON) {
-                        min_p = max_p;
-                        min_n1 = k;
-                      }
+                }
+                /* Put the two found normals, first in the array queue. */
+                if (min_n1 != 0) {
+                  swap_v4_v4(planes_queue[min_n0], planes_queue[0]);
+                  swap_v4_v4(planes_queue[min_n1], planes_queue[1]);
+                }
+                else {
+                  swap_v4_v4(planes_queue[min_n0], planes_queue[1]);
+                }
+                /* Find the third most important/different normal. */
+                min_p = 1;
+                min_n1 = 0;
+                float max_p = -1;
+                for (uint k = 2; k < queue_index; k++) {
+                  max_p = -1;
+                  for (uint m = 0; m < 2; m++) {
+                    float p = dot_v3v3(planes_queue[m], planes_queue[k]);
+                    if (p > max_p + FLT_EPSILON) {
+                      max_p = p;
                     }
-                    if (min_p < 0.8) {
-                      copy_v3_v3(face_nors[2], normals_queue[min_n1]);
-                      nor_ofs[2] = normals_queue[min_n1][3];
-                      face_nors_len++;
-                      queue_index--;
-                      memmove(normals_queue + min_n1,
-                              normals_queue + min_n1 + 1,
-                              (queue_index - min_n1) * sizeof(*normals_queue));
+                  }
+                  if (max_p <= min_p + FLT_EPSILON) {
+                    min_p = max_p;
+                    min_n1 = k;
+                  }
+                }
+                swap_v4_v4(planes_queue[min_n1], planes_queue[2]);
+              }
+              /* Remove/average duplicate normals in planes_queue. */
+              while (queue_index > 0) {
+                uint best_n0 = 0;
+                uint best_n1 = 0;
+                float best_p = -1.0f;
+                float best_ofs_diff = 0.0f;
+                for (uint k = 0; k < queue_index; k++) {
+                  for (uint m = k + 1; m < queue_index; m++) {
+                    float p = dot_v3v3(planes_queue[m], planes_queue[k]);
+                    float ofs_diff = fabsf(planes_queue[m][3] - planes_queue[k][3]);
+                    if (p > best_p + FLT_EPSILON || (p >= best_p && ofs_diff < best_ofs_diff)) {
+                      best_p = p;
+                      best_ofs_diff = ofs_diff;
+                      best_n0 = m;
+                      best_n1 = k;
                     }
                   }
                 }
-                else {
-                  uint best = 0;
-                  uint best_group = 0;
-                  float best_p = -1.0f;
-                  for (uint k = 0; k < queue_index; k++) {
-                    for (uint m = 0; m < face_nors_len; m++) {
-                      float p = dot_v3v3(face_nors[m], normals_queue[k]);
-                      if (p > best_p + FLT_EPSILON) {
-                        best_p = p;
-                        best = m;
-                        best_group = k;
+                if (best_p < 0.999f) {
+                  break;
+                }
+                add_v3_v3(planes_queue[best_n0], planes_queue[best_n1]);
+                normalize_v3(planes_queue[best_n0]);
+                planes_queue[best_n0][3] = (planes_queue[best_n0][3] + planes_queue[best_n1][3]) *
+                                           0.5f;
+                queue_index--;
+                memmove(planes_queue + best_n1,
+                        planes_queue + best_n1 + 1,
+                        (queue_index - best_n1) * 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list