[Bf-blender-cvs] [c1f5ac7cfec] sculpt-dev: Array Brush: Support array editing with the voxel remesher

Pablo Dobarro noreply at git.blender.org
Sun Jul 25 20:38:05 CEST 2021


Commit: c1f5ac7cfecb0fc8d2cdecb866a1d25fd0712267
Author: Pablo Dobarro
Date:   Sun Jul 25 20:36:56 2021 +0200
Branches: sculpt-dev
https://developer.blender.org/rBc1f5ac7cfecb0fc8d2cdecb866a1d25fd0712267

Array Brush: Support array editing with the voxel remesher

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

M	source/blender/blenkernel/BKE_mesh_remesh_voxel.h
M	source/blender/blenkernel/BKE_paint.h
M	source/blender/blenkernel/intern/mesh_remesh_voxel.c
M	source/blender/editors/object/object_remesh.c
M	source/blender/editors/sculpt_paint/sculpt_array.c

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

diff --git a/source/blender/blenkernel/BKE_mesh_remesh_voxel.h b/source/blender/blenkernel/BKE_mesh_remesh_voxel.h
index 01ff7143109..b7feb402c73 100644
--- a/source/blender/blenkernel/BKE_mesh_remesh_voxel.h
+++ b/source/blender/blenkernel/BKE_mesh_remesh_voxel.h
@@ -62,6 +62,7 @@ void BKE_mesh_remesh_reproject_paint_mask(struct Mesh *target, struct Mesh *sour
 void BKE_remesh_reproject_vertex_paint(struct Mesh *target, struct Mesh *source);
 void BKE_remesh_reproject_sculpt_face_sets(struct Mesh *target, struct Mesh *source);
 void BKE_remesh_reproject_materials(struct Mesh *target, struct Mesh *source);
+void BKE_mesh_remesh_sculpt_array_update(struct Object *ob, struct Mesh *target, struct Mesh *source);
 
 #ifdef __cplusplus
 }
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 066faa6f959..11bf40dfa55 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -492,6 +492,8 @@ typedef struct SculptArray {
   int *copy_index;
   int *symmetry_pass;
 
+  float *smooth_strength;
+
 } SculptArray;
 
 typedef struct SculptFakeNeighbors {
diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.c b/source/blender/blenkernel/intern/mesh_remesh_voxel.c
index eec20e190a5..a713c47aa25 100644
--- a/source/blender/blenkernel/intern/mesh_remesh_voxel.c
+++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.c
@@ -45,6 +45,7 @@
 #include "BKE_mesh.h"
 #include "BKE_mesh_remesh_voxel.h" /* own include */
 #include "BKE_mesh_runtime.h"
+#include "BKE_paint.h"
 
 #include "bmesh_tools.h"
 
@@ -352,6 +353,79 @@ void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, Mesh *source)
   free_bvhtree_from_mesh(&bvhtree);
 }
 
+void BKE_mesh_remesh_sculpt_array_update(Object *ob, Mesh *target, Mesh *source)
+{
+
+  SculptSession *ss = ob->sculpt;
+
+  if (!ss) {
+    return;
+  }
+
+  SculptArray *array = ss->array;
+  if (!array) {
+    return;
+  }
+
+  BVHTreeFromMesh bvhtree = {
+      .nearest_callback = NULL,
+  };
+  BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2);
+  MVert *target_verts = CustomData_get_layer(&target->vdata, CD_MVERT);
+
+  const int target_totvert = target->totvert;
+
+  int *target_copy_index = MEM_malloc_arrayN(sizeof(int), target_totvert, "target_copy_index");
+  int *target_symmertry = MEM_malloc_arrayN(sizeof(int), target_totvert, "target_copy_index");
+  float (*target_orco)[3] = MEM_malloc_arrayN(target->totvert, sizeof(float) * 3, "array orco");
+
+  for (int i = 0; i < target_totvert; i++) {
+    target_copy_index[i] = -1;
+    target_symmertry[i] = 0;
+    copy_v3_v3(target_orco, target->mvert[i].co);
+  }
+  
+  for (int i = 0; i < target->totvert; i++) {
+    float from_co[3];
+    BVHTreeNearest nearest;
+    nearest.index = -1;
+    nearest.dist_sq = FLT_MAX;
+    copy_v3_v3(from_co, target_verts[i].co);
+    BLI_bvhtree_find_nearest(bvhtree.tree, from_co, &nearest, bvhtree.nearest_callback, &bvhtree);
+    if (nearest.index != -1) {
+      target_copy_index[i] = array->copy_index[nearest.index];
+      target_symmertry[i] = array->symmetry_pass[nearest.index];
+    }
+  }
+  free_bvhtree_from_mesh(&bvhtree);
+
+  MEM_freeN(array->copy_index);
+  MEM_freeN(array->symmetry_pass);
+  MEM_freeN(array->orco);
+
+  array->copy_index = target_copy_index;
+  array->symmetry_pass = target_symmertry;
+  array->orco = target_orco;
+
+    for (int i = 0; i < target->totvert; i++) {
+        int array_index = target_copy_index[i];
+        int array_symm_pass = target_symmertry[i];
+        if (array_index == -1) {
+          continue;
+        }
+       SculptArrayCopy *copy = &array->copies[array_symm_pass][array_index];
+       float co[3];
+       float source_origin_symm[3];
+       copy_v3_v3(co, target->mvert[i].co);
+       /* TODO: MAke symmetry work here. */
+       //flip_v3_v3(source_origin_symm, array->source_origin, array_symm_pass);
+       mul_v3_m4v3(co, array->source_imat, co); 
+       mul_v3_m4v3(co, copy->imat, co);
+       sub_v3_v3v3(co, co, source_origin_symm);
+       copy_v3_v3(array->orco[i], co);
+      }
+}
+
 void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, Mesh *source)
 {
   BVHTreeFromMesh bvhtree = {
diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c
index 5d0f7a7934f..b874d597cf0 100644
--- a/source/blender/editors/object/object_remesh.c
+++ b/source/blender/editors/object/object_remesh.c
@@ -195,6 +195,10 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op)
     BKE_remesh_reproject_vertex_paint(new_mesh, mesh);
   }
 
+  if (ob->mode == OB_MODE_SCULPT) {
+    BKE_mesh_remesh_sculpt_array_update(ob, new_mesh, mesh);
+  }
+
   BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob, &CD_MASK_MESH, true);
 
   if (smooth_normals) {
diff --git a/source/blender/editors/sculpt_paint/sculpt_array.c b/source/blender/editors/sculpt_paint/sculpt_array.c
index cb316b40d47..8793162f1c2 100644
--- a/source/blender/editors/sculpt_paint/sculpt_array.c
+++ b/source/blender/editors/sculpt_paint/sculpt_array.c
@@ -513,7 +513,6 @@ static void sculpt_array_update(Object *ob, Brush *brush, SculptArray *array) {
       }
       for (int copy_index = 0; copy_index < array->num_copies; copy_index++) {
           SculptArrayCopy *copy = &array->copies[symm_pass][copy_index];
-          print_m4("cosa", copy->mat);
           invert_m4_m4(copy->imat, copy->mat);
       }
   }
@@ -581,6 +580,104 @@ static void sculpt_array_deform(Sculpt *sd, Object *ob, PBVHNode **nodes, int to
       0, totnode, &data, do_array_deform_task_cb_ex, &settings);
 }
 
+
+static void do_array_smooth_task_cb_ex(void *__restrict userdata,
+                                     const int n,
+                                     const TaskParallelTLS *__restrict tls)
+{
+  SculptThreadedTaskData *data = userdata;
+  SculptSession *ss = data->ob->sculpt;
+  SculptArray *array = ss->array;
+
+    Mesh *mesh = BKE_object_get_original_mesh(data->ob);
+
+    bool any_modified = false;
+
+  PBVHVertexIter vd;
+  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
+    int array_index = ARRAY_INSTANCE_ORIGINAL;
+    int array_symm_pass = 0;
+    sculpt_vertex_array_data_get(array, vd.index, &array_index, &array_symm_pass);
+
+    const float fade = array->smooth_strength[vd.index];
+
+    if (fade == 0.0f) {
+      continue;
+    }
+
+    float smooth_co[3];
+    SCULPT_neighbor_coords_average(ss, smooth_co, vd.index);
+    float disp[3];
+    sub_v3_v3v3(disp, smooth_co, vd.co);
+    mul_v3_fl(disp, fade);
+    add_v3_v3(vd.co, disp);
+
+
+/*
+    if (array_index == ARRAY_INSTANCE_ORIGINAL) {
+      continue;
+    }
+
+    bool do_smooth = false;
+    SculptVertexNeighborIter ni;
+    SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
+      int neighbor_array_index = ARRAY_INSTANCE_ORIGINAL;
+      int neighbor_symm_pass = 0;
+      sculpt_vertex_array_data_get(array, ni.index, &neighbor_array_index,&neighbor_symm_pass);
+      if (neighbor_array_index != array_index) {
+        do_smooth = true;
+      }
+    }
+    SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+
+    if (!do_smooth) {
+      continue;
+    }
+    */
+
+
+
+    any_modified = true;
+
+
+    if (vd.mvert) {
+      vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+    }
+  }
+  BKE_pbvh_vertex_iter_end;
+
+  if (any_modified) {
+    BKE_pbvh_node_mark_update(data->nodes[n]);
+  }
+}
+
+static void sculpt_array_smooth(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) {
+
+
+
+  /* Threaded loop over nodes. */
+  SculptSession *ss = ob->sculpt;
+  SculptArray *array = ss->array;
+
+  if (!array) {
+    return;
+  }
+
+  if (!array->smooth_strength) {
+    return;
+  }
+  SculptThreadedTaskData data = {
+      .sd = sd,
+      .ob = ob,
+      .nodes = nodes,
+  };
+
+  TaskParallelSettings settings;
+  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
+  BLI_task_parallel_range(
+      0, totnode, &data, do_array_smooth_task_cb_ex, &settings);
+}
+
 static void sculpt_array_ensure_original_coordinates(Object *ob, SculptArray *array){
   SculptSession *ss = ob->sculpt;
   Mesh *sculpt_mesh = BKE_object_get_original_mesh(ob);
@@ -690,9 +787,56 @@ void SCULPT_do_array_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
     }
 
     if (SCULPT_stroke_is_first_brush_step(ss->cache)) {
+    SculptArray *array = ss->array;
+    const int totvert = SCULPT_vertex_count_get(ss);
+
+
+    /* Rebuild smooth strength cache. */
+    MEM_SAFE_FREE(array->smooth_strength);
+    array->smooth_strength = MEM_calloc_arrayN(sizeof(float), totvert, "smooth_strength");
+
+
+    for (int i = 0; i < totvert; i++) {
+    int array_index = ARRAY_INSTANCE_ORIGINAL;
+    int array_symm_pass = 0;
+    sculpt_vertex_array_data_get(array, i, &array_index, &array_symm_pass);
+
+    if (array_index == ARRAY_INSTANCE_ORIGINAL) {
+      continue;
+    }
+
+    /* TODO: this can be cached. */
+    SculptVertexNeighborIter ni;
+    SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) {
+      int neighbor_array_index = ARRAY_INSTANCE_ORIGINAL;
+      int neighbor_symm_pass = 0;
+      sculpt_vertex_array_data_get(array, ni.index, &neighbor_array_index,&neighbor_symm_pass);
+      if (neighbor_array_index != array_index) {
+        array->smooth_strength[i] = 1.0f;
+        break;
+      }
+    }
+    SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+    }
+
+    for(int smooth_iterations = 0; smooth_iterations < 4; smooth_iterations++) {
+      for (int i = 0; i < totvert; i++) {
+      float avg = array->smooth_strength[i];
+      int count = 1;
+       SculptVertexNeighborIter ni;
+        SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) {
+          avg += array->smooth_strength[ni.index];
+          count++;
+       }
+       SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+       array->smooth_strength[i] = avg / count;
+      }
+    }
+
+
+
 
     /* Update Array Path Orco. */
-    SculptArray *array = ss->array;
     for (int i = 0; i < array->path.tot_points; i++) {
       ScultpArrayPathPoint *point = &array->path.points[i];
       copy_v3_v3(point->orco, point->co);
@@ -700,7 +844,6 @@ void SCULPT_do_array_brush(Sculpt *sd, Object *ob, PBVHNode

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list