[Bf-blender-cvs] [b535223b291] soc-2019-npr: LANPR: Smooth contour modifier file.

YimingWu noreply at git.blender.org
Sun Aug 11 05:07:42 CEST 2019


Commit: b535223b2913aea15d1c1fe7024d6bc8f295a8a2
Author: YimingWu
Date:   Sun Aug 11 11:07:11 2019 +0800
Branches: soc-2019-npr
https://developer.blender.org/rBb535223b2913aea15d1c1fe7024d6bc8f295a8a2

LANPR: Smooth contour modifier file.

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

A	source/blender/modifiers/intern/MOD_smoothcontour.c

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

diff --git a/source/blender/modifiers/intern/MOD_smoothcontour.c b/source/blender/modifiers/intern/MOD_smoothcontour.c
new file mode 100644
index 00000000000..40d08043a29
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_smoothcontour.c
@@ -0,0 +1,4799 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software  Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+/** \file blender/modifiers/intern/MOD_mybmesh.c
+ *  \ingroup modifiers
+ */
+
+/* This code is based of the tessellation part of the paper
+ * "Computing Smooth Surface Contours with Accurate Topology"
+ * (Pierre Bénard, Aaron Hertzmann, Michael Kass).
+ * Currently available at:
+ * http://www.labri.fr/perso/pbenard/publications/contours.html
+ *
+ * The numbers in the comments refers to the chapters in the paper.
+ */
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+#include "BLI_buffer.h"
+#include "BLI_alloca.h"
+#include "BLI_ghash.h"
+#include "BLI_gsqueue.h"
+#include "BLI_memarena.h"
+#include "BLI_rand.h"
+#include "BLI_listbase.h"
+#include "BLI_threads.h"
+
+#include "BKE_library_query.h"
+#include "BKE_modifier.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_deform.h"
+
+#include "bmesh.h"
+#include "bmesh_tools.h"
+
+#include "MOD_util.h"
+#include "MOD_modifiertypes.h"
+
+#include "DEG_depsgraph_build.h"
+
+// BMesh intern
+#include "../../bmesh/intern/bmesh_private.h"
+
+// TODO this modifier depends on OpenSubDiv. So if it's not compiled in, remove this modifier
+
+#include "../../../../intern/opensubdiv/opensubdiv_capi.h"
+#include "../../../../intern/opensubdiv/opensubdiv_converter_capi.h"
+#include "../../../../intern/opensubdiv/opensubdiv_evaluator_capi.h"
+#include "../../../../intern/opensubdiv/opensubdiv_topology_refiner_capi.h"
+
+#include "../../blenkernel/intern/subdiv_converter.h"
+
+#include "PIL_time.h"
+#include "PIL_time_utildefines.h"
+
+struct OpenSubdiv_Evaluator;
+
+typedef struct {
+  BMVert *vert;  // Only used for shifted verts
+  BMEdge *orig_edge;
+  BMFace *orig_face;
+  float u, v;
+} Vert_buf;
+
+typedef struct {
+  BMEdge *cusp_e;
+  BMFace *orig_face;
+  float cusp_co[3];
+  float cusp_no[3];
+
+  float u, v;
+} Cusp;
+
+typedef struct {
+  bool b_arr[3];
+  bool kr_arr[3];
+  float co_arr[3][3];
+  float u_arr[3];
+  float v_arr[3];
+} Cusp_triang;
+
+typedef struct {
+  BMVert *vert;
+  BMVert *C_vert;
+  // Can we extend this radial vert?
+  bool extendable;
+  bool is_B;
+  float radi_plane_no[3];
+} Radi_vert;
+
+typedef struct {
+  BMFace *face;
+  // Should be front or back facing?
+  bool back_f;
+} IncoFace;
+
+typedef struct {
+  BMesh *bm;
+  BMesh *bm_orig;
+
+  float cam_loc[3];
+
+  GHash *vert_hash;
+
+  BLI_Buffer *new_vert_buffer;
+  BLI_Buffer *shifted_verts;
+  BLI_Buffer *cusp_edges;
+  BLI_Buffer *C_verts;
+  BLI_Buffer *cusp_verts;
+  BLI_Buffer *radi_vert_buffer;
+  // Idx of next inserted vert
+  int new_vert_idx;
+  // Radial edge vert start idx
+  int radi_start_idx;
+
+  struct OpenSubdiv_Evaluator *eval;
+} MeshData;
+
+// TODO for Kr look in subdiv.cpp in coutours source code (II)
+
+// TODO dynamic arrays, use BLI_stack, BLI_buffer, BLI_mempool, BLI_memarena.
+
+static void verts_to_limit(BMesh *bm, struct OpenSubdiv_Evaluator *eval)
+{
+
+  int i, j;
+
+  BMIter iter_v, iter_f;
+  BMVert *vert;
+  BMFace *f;
+
+  // TODO is it possible to only get non adjusted verts?
+  // IE not moving a vert more than once.
+
+  BM_ITER_MESH_INDEX (f, &iter_f, bm, BM_FACES_OF_MESH, i) {
+    BM_ITER_ELEM_INDEX (vert, &iter_v, f, BM_VERTS_OF_FACE, j) {
+      float u, v, du[3], dv[3];
+      switch (j) {
+        case 1:
+          u = 1, v = 0;
+          break;
+        case 2:
+          u = v = 1;
+          break;
+        case 3:
+          u = 0, v = 1;
+          break;
+        default:
+          u = v = 0;
+          break;
+      }
+      eval->evaluateLimit(eval, i, u, v, vert->co, du, dv);
+      // Adjust vert normal to the limit normal
+      cross_v3_v3v3(vert->no, du, dv);
+      normalize_v3(vert->no);
+      // printf("j: %d\n",j);
+    }
+    // printf("i: %d\n",i);
+    // printf("face i: %d\n", BM_elem_index_get(f));
+  }
+}
+
+static Vert_buf *get_shift_vert(BMVert *vert, MeshData *m_d)
+{
+  int vert_i;
+
+  // check if vert is in the buffer
+  for (vert_i = 0; vert_i < m_d->shifted_verts->count; vert_i++) {
+    Vert_buf *buf = &BLI_buffer_at(m_d->shifted_verts, Vert_buf, vert_i);
+    if (vert == buf->vert) {
+      return buf;
+    }
+  }
+  return NULL;
+}
+
+static void add_shifted_vert(BMVert *vert, BMFace *orig_face, float uv[2], MeshData *m_d)
+{
+  Vert_buf *buf = get_shift_vert(vert, m_d);
+
+  if (buf != NULL) {
+    buf->orig_face = orig_face;
+    buf->u = uv[0];
+    buf->v = uv[1];
+    return;
+  }
+
+  int orig_verts = BM_mesh_elem_count(m_d->bm_orig, BM_VERT);
+  int v_idx = BM_elem_index_get(vert);
+  if ((v_idx + 1) > orig_verts) {
+    // If this is a non original vert, just update the data instead
+    Vert_buf *v_buf = &BLI_buffer_at(m_d->new_vert_buffer, Vert_buf, v_idx - orig_verts);
+    v_buf->orig_face = orig_face;
+    v_buf->orig_edge = NULL;
+    v_buf->u = uv[0];
+    v_buf->v = uv[1];
+  }
+  else {
+    Vert_buf new_buf;
+    new_buf.orig_face = orig_face;
+    new_buf.vert = vert;
+    new_buf.u = uv[0];
+    new_buf.v = uv[1];
+    BLI_buffer_append(m_d->shifted_verts, Vert_buf, new_buf);
+  }
+}
+
+static bool calc_if_B(const float cam_loc[3],
+                      const float P[3],
+                      const float du[3],
+                      const float dv[3])
+{
+  // Is the point back facing?
+  float nor[3], view_vec[3];
+
+  cross_v3_v3v3(nor, du, dv);
+  // TODO normalization is probably not needed
+  normalize_v3(nor);
+  sub_v3_v3v3(view_vec, cam_loc, P);
+
+  return (dot_v3v3(nor, view_vec) < 0);
+}
+
+static bool calc_if_B_nor(const float cam_loc[3], const float P[3], const float nor[3])
+{
+  // Is the point back facing?
+  float view_vec[3];
+
+  sub_v3_v3v3(view_vec, cam_loc, P);
+
+  return (dot_v3v3(nor, view_vec) < 0);
+}
+
+static float get_facing_dir(const float cam_loc[3],
+                            const float P[3],
+                            const float du[3],
+                            const float dv[3])
+{
+  // Get if point is back facing (-) or front facing (+). Zero if it's directly on the contour
+  float nor[3], view_vec[3];
+
+  cross_v3_v3v3(nor, du, dv);
+  normalize_v3(nor);
+  sub_v3_v3v3(view_vec, cam_loc, P);
+  normalize_v3(view_vec);
+
+  return dot_v3v3(nor, view_vec);
+}
+
+static float get_facing_dir_nor(const float cam_loc[3], const float P[3], const float nor[3])
+{
+  // Get if point is back facing (-) or front facing (+). Zero if it's directly on the contour
+  float view_vec[3];
+
+  sub_v3_v3v3(view_vec, cam_loc, P);
+  normalize_v3(view_vec);
+
+  return dot_v3v3(nor, view_vec);
+}
+
+static BMVert *split_edge_and_move_nor(
+    MeshData *m_d, BMesh *bm, BMEdge *edge, const float new_pos[3], const float new_no[3])
+{
+  // Split edge one time and move the created vert to new_pos
+  BMVert *vert;
+  int face_count = BM_edge_face_count(edge);
+  BMFace **face_arr = BLI_array_alloca(face_arr, face_count);
+
+  BMIter iter;
+  BMFace *face;
+  int i;
+
+  // Save the connected faces for triangulation later
+  BM_ITER_ELEM_INDEX (face, &iter, edge, BM_FACES_OF_EDGE, i) {
+    face_arr[i] = face;
+  }
+
+  if (i > 2) {
+    print_v3("deg coord", edge->v1->co);
+    printf("Deg face!\n");
+  }
+
+  // printf("Split edge!\n");
+
+  // TODO perhaps use BM_edge_split instead?
+  vert = bmesh_kernel_split_edge_make_vert(bm, edge->v1, edge, NULL);
+  if (m_d != NULL) {
+    BM_elem_index_set(vert, m_d->new_vert_idx++);
+  }
+
+  /*{
+    MemArena *pf_arena;
+    pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
+    LinkNode *faces_double = NULL;
+    BM_face_triangulate(
+        bm, face_arr[0],
+        NULL, NULL,
+        NULL, NULL,
+        &faces_double,
+        MOD_TRIANGULATE_QUAD_FIXED,
+        0,false,
+        pf_arena,
+        NULL, NULL);
+
+    BM_face_triangulate(
+        bm, face_arr[1],
+        NULL, NULL,
+        NULL, NULL,
+        &faces_double,
+        MOD_TRIANGULATE_QUAD_FIXED,
+        0,false,
+        pf_arena,
+        NULL, NULL);
+
+    while (faces_double) {
+      LinkNode *next = faces_double->next;
+      BM_face_kill(bm, faces_double->link);
+      MEM_freeN(faces_double);
+      faces_double = next;
+    }
+    BLI_memarena_free(pf_arena);
+  }*/
+
+  // Triangulate the faces connected to the new vert
+  {
+    BMLoop *start;
+    BMLoop *end;
+
+    BMFace *new_f;
+
+    for (int j = 0; j < i; j++) {
+      start = BM_face_vert_share_loop(face_arr[j], vert);
+      end = (start->next)->next;
+
+      // TODO maybe use bmesh_sfme instead?
+      new_f = BM_face_split(bm, face_arr[j], start, end, NULL, NULL, false);
+
+      BM_face_normal_update(face_arr[j]);
+      BM_face_normal_update(new_f);
+    }
+  }
+
+  copy_v3_v3(vert->co, new_pos);
+  // Adjust vert normal to the limit normal
+  copy_v3_v3(vert->no, new_no);
+  normalize_v3(vert->no);
+
+  return vert;
+}
+
+static BMVert *split_edge_and_move_vert(MeshData *m_d,
+                                        BMesh *bm,
+                                        BMEdge *edge,
+                                  

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list