Support logging of modified faces in dyntopo.
authorAntony Riakiotakis <kalast@gmail.com>
Thu, 10 Apr 2014 23:29:37 +0000 (02:29 +0300)
committerAntony Riakiotakis <kalast@gmail.com>
Thu, 10 Apr 2014 23:29:59 +0000 (02:29 +0300)
This is meant to support undo when hiding parts of the mesh.
Also avoid rebuilding the PBVH in that case as well (no nodes split)

source/blender/bmesh/intern/bmesh_log.c
source/blender/bmesh/intern/bmesh_log.h
source/blender/editors/sculpt_paint/sculpt_undo.c

index f7c2b7d..d9bbb5c 100644 (file)
@@ -67,6 +67,7 @@ struct BMLogEntry {
 
        /* Vertices whose coordinates, mask value, or hflag have changed */
        GHash *modified_verts;
+       GHash *modified_faces;
 
        BLI_mempool *pool_verts;
        BLI_mempool *pool_faces;
@@ -120,6 +121,7 @@ typedef struct {
 
 typedef struct {
        unsigned int v_ids[3];
+       char hflag;
 } BMLogFace;
 
 /************************* Get/set element IDs ************************/
@@ -234,6 +236,7 @@ static BMLogFace *bm_log_face_alloc(BMLog *log, BMFace *f)
        lf->v_ids[1] = bm_log_vert_id_get(log, v[1]);
        lf->v_ids[2] = bm_log_vert_id_get(log, v[2]);
 
+       lf->hflag = f->head.hflag;
        return lf;
 }
 
@@ -341,6 +344,19 @@ static void bm_log_vert_values_swap(BMesh *bm, BMLog *log, GHash *verts)
        }
 }
 
+static void bm_log_face_values_swap(BMLog *log, GHash *faces)
+{
+       GHashIterator gh_iter;
+       GHASH_ITER (gh_iter, faces) {
+               void *key = BLI_ghashIterator_getKey(&gh_iter);
+               BMLogFace *lf = BLI_ghashIterator_getValue(&gh_iter);
+               unsigned int id = GET_UINT_FROM_POINTER(key);
+               BMFace *f = bm_log_face_from_id(log, id);
+
+               SWAP(char, f->head.hflag, lf->hflag);
+       }
+}
+
 
 /**********************************************************************/
 
@@ -374,6 +390,7 @@ static BMLogEntry *bm_log_entry_create(void)
        entry->added_verts = BLI_ghash_ptr_new(__func__);
        entry->added_faces = BLI_ghash_ptr_new(__func__);
        entry->modified_verts = BLI_ghash_ptr_new(__func__);
+       entry->modified_faces = BLI_ghash_ptr_new(__func__);
 
        entry->pool_verts = BLI_mempool_create(sizeof(BMLogVert), 0, 64, BLI_MEMPOOL_NOP);
        entry->pool_faces = BLI_mempool_create(sizeof(BMLogFace), 0, 64, BLI_MEMPOOL_NOP);
@@ -391,6 +408,7 @@ static void bm_log_entry_free(BMLogEntry *entry)
        BLI_ghash_free(entry->added_verts, NULL, NULL);
        BLI_ghash_free(entry->added_faces, NULL, NULL);
        BLI_ghash_free(entry->modified_verts, NULL, NULL);
+       BLI_ghash_free(entry->modified_faces, NULL, NULL);
 
        BLI_mempool_destroy(entry->pool_verts);
        BLI_mempool_destroy(entry->pool_faces);
@@ -706,6 +724,7 @@ void BM_log_undo(BMesh *bm, BMLog *log)
 
                /* Restore vertex coordinates, mask, and hflag */
                bm_log_vert_values_swap(bm, log, entry->modified_verts);
+               bm_log_face_values_swap(log, entry->modified_faces);
        }
 }
 
@@ -742,6 +761,7 @@ void BM_log_redo(BMesh *bm, BMLog *log)
 
                /* Restore vertex coordinates, mask, and hflag */
                bm_log_vert_values_swap(bm, log, entry->modified_verts);
+               bm_log_face_values_swap(log, entry->modified_faces);
        }
 }
 
@@ -785,6 +805,7 @@ void BM_log_vert_before_modified(BMLog *log, BMVert *v, const int cd_vert_mask_o
        }
 }
 
+
 /* Log a new vertex as added to the BMesh
  *
  * The new vertex gets a unique ID assigned. It is then added to a map
@@ -802,6 +823,22 @@ void BM_log_vert_added(BMLog *log, BMVert *v, const int cd_vert_mask_offset)
        BLI_ghash_insert(log->current_entry->added_verts, key, lv);
 }
 
+
+/* Log a face before it is modified
+ *
+ * This is intended to handle only header flags and we always
+ * assume face has been added before
+ */
+void BM_log_face_modified(BMLog *log, BMFace *f)
+{
+       BMLogFace *lf;
+       unsigned int f_id = bm_log_face_id_get(log, f);
+       void *key = SET_UINT_IN_POINTER(f_id);
+
+       lf = bm_log_face_alloc(log, f);
+       BLI_ghash_insert(log->current_entry->modified_faces, key, lf);
+}
+
 /* Log a new face as added to the BMesh
  *
  * The new face gets a unique ID assigned. It is then added to a map
index dab1726..7a26506 100644 (file)
@@ -66,6 +66,9 @@ void BM_log_vert_before_modified(BMLog *log, struct BMVert *v, const int cd_vert
 /* Log a new vertex as added to the BMesh */
 void BM_log_vert_added(BMLog *log, struct BMVert *v, const int cd_vert_mask_offset);
 
+/* Log a face before it is modified */
+void BM_log_face_modified(BMLog *log, struct BMFace *f);
+
 /* Log a new face as added to the BMesh */
 void BM_log_face_added(BMLog *log, struct BMFace *f);
 
index 90e26f0..673e4d9 100644 (file)
@@ -280,7 +280,7 @@ static void sculpt_undo_bmesh_restore_generic(bContext *C,
                unode->applied = true;
        }
 
-       if (unode->type == SCULPT_UNDO_MASK) {
+       if (ELEM(unode->type, SCULPT_UNDO_MASK, SCULPT_UNDO_MASK)) {
                int i, totnode;
                PBVHNode **nodes;
 
@@ -756,7 +756,6 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
        if (node) {
                switch (type) {
                        case SCULPT_UNDO_COORDS:
-                       case SCULPT_UNDO_HIDDEN:
                        case SCULPT_UNDO_MASK:
                                /* Before any vertex values get modified, ensure their
                                 * original positions are logged */
@@ -766,6 +765,22 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob,
                                BKE_pbvh_vertex_iter_end;
                                break;
 
+                       case SCULPT_UNDO_HIDDEN:
+                       {
+                               GSetIterator gs_iter;
+                               GSet *faces = BKE_pbvh_bmesh_node_faces(node);
+                               BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL) {
+                                       BM_log_vert_before_modified(ss->bm_log, vd.bm_vert, vd.cd_vert_mask_offset);
+                               }
+                               BKE_pbvh_vertex_iter_end;
+
+                               GSET_ITER (gs_iter, faces) {
+                                       BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
+                                       BM_log_face_modified(ss->bm_log, f);
+                               }
+                               break;
+                       }
+
                        case SCULPT_UNDO_DYNTOPO_BEGIN:
                        case SCULPT_UNDO_DYNTOPO_END:
                        case SCULPT_UNDO_DYNTOPO_SYMMETRIZE: