[Bf-blender-cvs] [4745f299716] sculpt-dev: Sculpt Symmetrize: Add base symmetrize map code
Pablo Dobarro
noreply at git.blender.org
Sun Apr 18 18:15:06 CEST 2021
Commit: 4745f299716dc980e5a2c5ed745490eeecbdd503
Author: Pablo Dobarro
Date: Fri Apr 16 00:56:39 2021 +0200
Branches: sculpt-dev
https://developer.blender.org/rB4745f299716dc980e5a2c5ed745490eeecbdd503
Sculpt Symmetrize: Add base symmetrize map code
===================================================================
M source/blender/blenkernel/BKE_paint.h
M source/blender/editors/sculpt_paint/sculpt_symmetrize.c
===================================================================
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 27ecf6824f0..c7753cf7a3f 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -362,6 +362,9 @@ typedef struct SculptVertexInfo {
/* Indexed by base mesh vertex index, stores if that vertex is a boundary. */
BLI_bitmap *boundary;
+
+ /* Indexed by vertex, stores the symmetrical topology vertex index found by symmetrize. */
+ int *symmetrize_map;
} SculptVertexInfo;
typedef struct SculptBoundaryEditInfo {
diff --git a/source/blender/editors/sculpt_paint/sculpt_symmetrize.c b/source/blender/editors/sculpt_paint/sculpt_symmetrize.c
index e860657ee7c..ff774ff3cc2 100644
--- a/source/blender/editors/sculpt_paint/sculpt_symmetrize.c
+++ b/source/blender/editors/sculpt_paint/sculpt_symmetrize.c
@@ -57,6 +57,160 @@
#include <math.h>
#include <stdlib.h>
+typedef uint MirrTopoHash_t;
+
+typedef struct MirrTopoVert_t {
+ MirrTopoHash_t hash;
+ int v_index;
+} MirrTopoVert_t;
+
+static int mirrtopo_hash_sort(const void *l1, const void *l2)
+{
+ if ((MirrTopoHash_t)(intptr_t)l1 > (MirrTopoHash_t)(intptr_t)l2) {
+ return 1;
+ }
+ if ((MirrTopoHash_t)(intptr_t)l1 < (MirrTopoHash_t)(intptr_t)l2) {
+ return -1;
+ }
+ return 0;
+}
+
+static int mirrtopo_vert_sort(const void *v1, const void *v2)
+{
+ if (((MirrTopoVert_t *)v1)->hash > ((MirrTopoVert_t *)v2)->hash) {
+ return 1;
+ }
+ if (((MirrTopoVert_t *)v1)->hash < ((MirrTopoVert_t *)v2)->hash) {
+ return -1;
+ }
+ return 0;
+}
+
+void SCULPT_symmetrize_map_ensure(Object *ob)
+{
+ SculptSession *ss = ob->sculpt;
+ Mesh *me = BKE_mesh_from_object(ob);
+
+ if (ss->vertex_info.symmetrize_map) {
+ /* Nothing to do. */
+ return;
+ }
+
+ MEdge *medge = NULL, *med;
+
+ int a, last;
+ int totvert, totedge;
+ int tot_unique = -1, tot_unique_prev = -1;
+ int tot_unique_edges = 0, tot_unique_edges_prev;
+
+ MirrTopoHash_t *topo_hash = NULL;
+ MirrTopoHash_t *topo_hash_prev = NULL;
+ MirrTopoVert_t *topo_pairs;
+ MirrTopoHash_t topo_pass = 1;
+
+ intptr_t *index_lookup; /* direct access to mesh_topo_store->index_lookup */
+
+ totvert = me->totvert;
+ topo_hash = MEM_callocN(totvert * sizeof(MirrTopoHash_t), "TopoMirr");
+
+ /* Initialize the vert-edge-user counts used to detect unique topology */
+ totedge = me->totedge;
+ medge = me->medge;
+
+ for (a = 0, med = medge; a < totedge; a++, med++) {
+ const uint i1 = med->v1, i2 = med->v2;
+ topo_hash[i1]++;
+ topo_hash[i2]++;
+ }
+
+ topo_hash_prev = MEM_dupallocN(topo_hash);
+
+ tot_unique_prev = -1;
+ tot_unique_edges_prev = -1;
+ while (true) {
+ /* use the number of edges per vert to give verts unique topology IDs */
+
+ tot_unique_edges = 0;
+
+ /* This can make really big numbers, wrapping around here is fine */
+ for (a = 0, med = medge; a < totedge; a++, med++) {
+ const uint i1 = med->v1, i2 = med->v2;
+ topo_hash[i1] += topo_hash_prev[i2] * topo_pass;
+ topo_hash[i2] += topo_hash_prev[i1] * topo_pass;
+ tot_unique_edges += (topo_hash[i1] != topo_hash[i2]);
+ }
+ memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert);
+
+ /* sort so we can count unique values */
+ qsort(topo_hash_prev, totvert, sizeof(MirrTopoHash_t), mirrtopo_hash_sort);
+
+ tot_unique = 1; /* account for skipping the first value */
+ for (a = 1; a < totvert; a++) {
+ if (topo_hash_prev[a - 1] != topo_hash_prev[a]) {
+ tot_unique++;
+ }
+ }
+
+ if ((tot_unique <= tot_unique_prev) && (tot_unique_edges <= tot_unique_edges_prev)) {
+ /* Finish searching for unique values when 1 loop doesn't give a
+ * higher number of unique values compared to the previous loop. */
+ break;
+ }
+ tot_unique_prev = tot_unique;
+ tot_unique_edges_prev = tot_unique_edges;
+ /* Copy the hash calculated this iteration, so we can use them next time */
+ memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert);
+
+ topo_pass++;
+ }
+
+ /* Hash/Index pairs are needed for sorting to find index pairs */
+ topo_pairs = MEM_callocN(sizeof(MirrTopoVert_t) * totvert, "MirrTopoPairs");
+
+ /* since we are looping through verts, initialize these values here too */
+ index_lookup = MEM_mallocN(totvert * sizeof(*index_lookup), "mesh_topo_lookup");
+
+ for (a = 0; a < totvert; a++) {
+ topo_pairs[a].hash = topo_hash[a];
+ topo_pairs[a].v_index = a;
+
+ /* initialize lookup */
+ index_lookup[a] = -1;
+ }
+
+ qsort(topo_pairs, totvert, sizeof(MirrTopoVert_t), mirrtopo_vert_sort);
+
+ last = 0;
+
+ /* Get the pairs out of the sorted hashes, note, totvert+1 means we can use the previous 2,
+ * but you cant ever access the last 'a' index of MirrTopoPairs */
+ for (a = 1; a <= totvert; a++) {
+ if ((a == totvert) || (topo_pairs[a - 1].hash != topo_pairs[a].hash)) {
+ const int match_count = a - last;
+ if (match_count == 2) {
+ const int j = topo_pairs[a - 1].v_index, k = topo_pairs[a - 2].v_index;
+ index_lookup[j] = k;
+ index_lookup[k] = j;
+ }
+ else if (match_count == 1) {
+ /* Center vertex. */
+ const int j = topo_pairs[a - 1].v_index;
+ index_lookup[j] = j;
+ }
+ last = a;
+ }
+ }
+
+ MEM_freeN(topo_pairs);
+ topo_pairs = NULL;
+
+ MEM_freeN(topo_hash);
+ MEM_freeN(topo_hash_prev);
+
+ ss->vertex_info.symmetrize_map = index_lookup;
+}
+
+
static void do_shape_symmetrize_brush_task_cb(void *__restrict userdata,
const int n,
More information about the Bf-blender-cvs
mailing list