[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