Refactor to Dyntopo node customdata commit.
authorAntony Riakiotakis <kalast@gmail.com>
Thu, 17 Apr 2014 16:02:55 +0000 (19:02 +0300)
committerAntony Riakiotakis <kalast@gmail.com>
Thu, 17 Apr 2014 16:03:08 +0000 (19:03 +0300)
Don't use a dedicated node layer but use temporary int layer instead.
Works like a charm as long as we are careful resetting the layer when
needed (after pbvh clearing and always after bmesh has been filled in
undo)

Tip by Campbell, thanks!

source/blender/blenkernel/BKE_paint.h
source/blender/blenkernel/BKE_pbvh.h
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/customdata.c
source/blender/blenkernel/intern/pbvh_bmesh.c
source/blender/blenkernel/intern/pbvh_intern.h
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/sculpt_paint/sculpt_intern.h
source/blender/editors/sculpt_paint/sculpt_undo.c
source/blender/makesdna/DNA_customdata_types.h

index 60c448608d7c120ced1b0bff34bdac86af372bfb..df72cb988b138fc75992aa11d3643b82e681ed48 100644 (file)
@@ -135,6 +135,8 @@ typedef struct SculptSession {
 
        /* BMesh for dynamic topology sculpting */
        struct BMesh *bm;
+       int cd_vert_node_offset;
+       int cd_face_node_offset;
        bool bm_smooth_shading;
        /* Undo/redo log for dynamic topology sculpting */
        struct BMLog *bm_log;
index d29ded6771726b2cb3eaed1831019598fe7b61d0..c5f82babb6d4a66a021d4411ca07f5dea4a07885 100644 (file)
@@ -67,7 +67,7 @@ void BKE_pbvh_build_grids(PBVH *bvh, struct CCGElem **grid_elems,
                           struct DMGridAdjacency *gridadj, int totgrid,
                           struct CCGKey *key, void **gridfaces, struct DMFlagMat *flagmats,
                           unsigned int **grid_hidden);
-void BKE_pbvh_build_bmesh(PBVH *bvh, struct BMesh *bm, bool smooth_shading, struct BMLog *log);
+void BKE_pbvh_build_bmesh(PBVH *bvh, struct BMesh *bm, bool smooth_shading, struct BMLog *log, const int cd_vert_node_offset, const int cd_face_node_offset);
 
 void BKE_pbvh_free(PBVH *bvh);
 void BKE_pbvh_free_layer_disp(PBVH *bvh);
index 7faeecb87cdf5f5ef5748f84710d1aa8b2f5994e..5f38eb610fc468d31d3c827f22ceeff49ab403e2 100644 (file)
@@ -269,7 +269,8 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
 
                BKE_pbvh_build_bmesh(cddm->pbvh, ob->sculpt->bm,
                                     ob->sculpt->bm_smooth_shading,
-                                    ob->sculpt->bm_log);
+                                    ob->sculpt->bm_log, ob->sculpt->cd_vert_node_offset,
+                                    ob->sculpt->cd_face_node_offset);
 
                pbvh_show_diffuse_color_set(cddm->pbvh, ob->sculpt->show_diffuse_color);
        }
index 4a76abc01544494bd6c4294d4ec907e434ae639a..78c88cdfd0fb1cb2fb68de555ccc042483f248a7 100644 (file)
@@ -1037,17 +1037,6 @@ static void layerDefault_mvert_skin(void *data, int count)
        }
 }
 
-static void layerDefault_dyntopo_node(void *data, int count)
-{
-       int *indices = data;
-       int i;
-
-       for (i = 0; i < count; i++) {
-               indices[i] = DYNTOPO_NODE_NONE;
-       }
-}
-
-
 static void layerInterp_mvert_skin(void **sources, const float *weights,
                                    const float *UNUSED(sub_weights),
                                    int count, void *dest)
@@ -1196,8 +1185,6 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
        {sizeof(float[4]), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
        /* 40: CD_TESSLOOPNORMAL */
        {sizeof(short[4][3]), "", 0, NULL, NULL, NULL, NULL, layerSwap_flnor, NULL},
-    /* 41: CD_DYNTOPO_NODE */
-       {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, layerDefault_dyntopo_node},
 };
 
 /* note, numbers are from trunk and need updating for bmesh */
@@ -1214,7 +1201,6 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
        /* 30-34 */ "CDSubSurfCrease", "CDOrigSpaceLoop", "CDPreviewLoopCol", "CDBMElemPyPtr", "CDPaintMask",
        /* 35-36 */ "CDGridPaintMask", "CDMVertSkin",
        /* 37-40 */ "CDFreestyleEdge", "CDFreestyleFace", "CDMLoopTangent", "CDTessLoopNormal",
-    /* 41 */ "CDDyntopoNode"
 };
 
 
index cca24682f952e9b6157219fa7b90051a7c81dde8..d316cbba86b30a36b58e7f3be1b066c8fa2cd600 100644 (file)
@@ -96,8 +96,7 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index, const int cd_ver
 }
 
 /* Recursively split the node if it exceeds the leaf_limit */
-static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index,
-                                  const int cd_vert_node_offset, const int cd_face_node_offset)
+static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index)
 {
        GSet *empty, *other;
        GSetIterator gs_iter;
@@ -105,7 +104,8 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index,
        BB cb;
        float mid;
        int axis, children;
-
+       const int cd_vert_node_offset = bvh->cd_vert_node_offset;
+       const int cd_face_node_offset = bvh->cd_face_node_offset;
        n = &bvh->nodes[node_index];
 
        if (BLI_gset_size(n->bm_faces) <= bvh->leaf_limit) {
@@ -210,8 +210,8 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index,
        
        /* Recurse */
        c1 = c2 = NULL;
-       pbvh_bmesh_node_split(bvh, prim_bbc, children, cd_vert_node_offset, cd_face_node_offset);
-       pbvh_bmesh_node_split(bvh, prim_bbc, children + 1, cd_vert_node_offset, cd_face_node_offset);
+       pbvh_bmesh_node_split(bvh, prim_bbc, children);
+       pbvh_bmesh_node_split(bvh, prim_bbc, children + 1);
 
        /* Array maybe reallocated, update current node pointer */
        n = &bvh->nodes[node_index];
@@ -224,7 +224,7 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index,
 }
 
 /* Recursively split the node if it exceeds the leaf_limit */
-static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index, const int cd_vert_node_offset, const int cd_face_node_offset)
+static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
 {
        GHash *prim_bbc;
        GSet *bm_faces;
@@ -260,7 +260,7 @@ static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index, const int cd
                BLI_ghash_insert(prim_bbc, f, bbc);
        }
 
-       pbvh_bmesh_node_split(bvh, prim_bbc, node_index, cd_vert_node_offset, cd_face_node_offset);
+       pbvh_bmesh_node_split(bvh, prim_bbc, node_index);
 
        BLI_ghash_free(prim_bbc, NULL, NULL);
        MEM_freeN(bbc_array);
@@ -1144,16 +1144,16 @@ void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode)
 /***************************** Public API *****************************/
 
 /* Build a PBVH from a BMesh */
-void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, bool smooth_shading, BMLog *log)
+void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, bool smooth_shading, BMLog *log,
+                          const int cd_vert_node_offset, const int cd_face_node_offset)
 {
        BMIter iter;
        BMFace *f;
        PBVHNode *n;
        int node_index = 0;
 
-       const int cd_vert_node_offset = CustomData_get_offset(&bm->vdata, CD_DYNTOPO_NODE);
-       const int cd_face_node_offset = CustomData_get_offset(&bm->pdata, CD_DYNTOPO_NODE);
-
+       bvh->cd_vert_node_offset = cd_vert_node_offset;
+       bvh->cd_face_node_offset = cd_face_node_offset;
        bvh->bm = bm;
 
        BKE_pbvh_bmesh_detail_size_set(bvh, 0.75);
@@ -1178,7 +1178,7 @@ void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, bool smooth_shading, BMLog *log)
 
        /* Recursively split the node until it is under the limit; if no
         * splitting occurs then finalize the existing leaf node */
-       if (!pbvh_bmesh_node_limit_ensure(bvh, node_index, cd_vert_node_offset, cd_face_node_offset))
+       if (!pbvh_bmesh_node_limit_ensure(bvh, node_index))
                pbvh_bmesh_node_finalize(bvh, 0, cd_vert_node_offset, cd_face_node_offset);
 }
 
@@ -1190,8 +1190,8 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode,
        BLI_buffer_declare_static(BMFace *, edge_loops, BLI_BUFFER_NOP, 2);
        BLI_buffer_declare_static(BMFace *, deleted_faces, BLI_BUFFER_NOP, 32);
        const int cd_vert_mask_offset = CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK);
-       const int cd_vert_node_offset = CustomData_get_offset(&bvh->bm->vdata, CD_DYNTOPO_NODE);
-       const int cd_face_node_offset = CustomData_get_offset(&bvh->bm->pdata, CD_DYNTOPO_NODE);
+       const int cd_vert_node_offset = bvh->cd_vert_node_offset;
+       const int cd_face_node_offset = bvh->cd_face_node_offset;
 
        bool modified = false;
        int n;
@@ -1312,9 +1312,6 @@ void BKE_pbvh_bmesh_after_stroke(PBVH *bvh)
 {
        int i;
 
-       const int cd_vert_node_offset = CustomData_get_offset(&bvh->bm->vdata, CD_DYNTOPO_NODE);
-       const int cd_face_node_offset = CustomData_get_offset(&bvh->bm->pdata, CD_DYNTOPO_NODE);
-
        for (i = 0; i < bvh->totnode; i++) {
                PBVHNode *n = &bvh->nodes[i];
                if (n->flag & PBVH_Leaf) {
@@ -1323,7 +1320,7 @@ void BKE_pbvh_bmesh_after_stroke(PBVH *bvh)
 
                        /* Recursively split nodes that have gotten too many
                         * elements */
-                       pbvh_bmesh_node_limit_ensure(bvh, i, cd_vert_node_offset, cd_face_node_offset);
+                       pbvh_bmesh_node_limit_ensure(bvh, i);
                }
        }
 }
index ef5828e8097572e4eb74fa1aaa0ca34a521e3979..6b3ef8eb5da409913dc1a198d7349af30f8cf3da 100644 (file)
@@ -162,6 +162,8 @@ struct PBVH {
        BMesh *bm;
        float bm_max_edge_len;
        float bm_min_edge_len;
+       int cd_vert_node_offset;
+       int cd_face_node_offset;
 
        struct BMLog *bm_log;
 };
index 4873587e9f5092e4c5c1a1f55065c223c6d0778e..dbf99e960532f965c26e1556f6fe29f58e931e2d 100644 (file)
@@ -4793,15 +4793,14 @@ void sculpt_pbvh_clear(Object *ob)
        BKE_object_free_derived_caches(ob);
 }
 
-void sculpt_dyntopo_node_layers_reset(BMesh *bm)
+void sculpt_dyntopo_node_layers_reset(SculptSession *ss)
 {
-       /* A bit lame, but for now just recreate the PBVH. The alternative
-        * is to store changes to the PBVH in the undo stack. */
        BMFace *f;
        BMVert *v;
        BMIter iter;
-       const int cd_vert_node_offset = CustomData_get_offset(&bm->vdata, CD_DYNTOPO_NODE);
-       const int cd_face_node_offset = CustomData_get_offset(&bm->pdata, CD_DYNTOPO_NODE);
+       BMesh *bm = ss->bm;
+       int cd_vert_node_offset = ss->cd_vert_node_offset;
+       int cd_face_node_offset = ss->cd_face_node_offset;
 
        /* clear the elements of the node information */
        BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
@@ -4813,6 +4812,34 @@ void sculpt_dyntopo_node_layers_reset(BMesh *bm)
        }
 }
 
+void sculpt_dyntopo_node_layers_add(SculptSession *ss)
+{
+       int cd_node_layer_index;
+
+       char layer_id[] = "_dyntopo_node_id";
+
+       cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->vdata, CD_PROP_INT, layer_id);
+       if (cd_node_layer_index == -1) {
+               BM_data_layer_add_named(ss->bm, &ss->bm->vdata, CD_PROP_INT, layer_id);
+               cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->vdata, CD_PROP_INT, layer_id);
+       }
+
+       ss->cd_vert_node_offset = CustomData_get_n_offset(&ss->bm->vdata, CD_PROP_INT, cd_node_layer_index);
+
+       ss->bm->vdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY;
+
+       cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->pdata, CD_PROP_INT, layer_id);
+       if (cd_node_layer_index == -1) {
+               BM_data_layer_add_named(ss->bm, &ss->bm->pdata, CD_PROP_INT, layer_id);
+               cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->pdata, CD_PROP_INT, layer_id);
+       }
+
+       ss->cd_face_node_offset = CustomData_get_n_offset(&ss->bm->pdata, CD_PROP_INT, cd_node_layer_index);
+
+       ss->bm->pdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY;
+}
+
+
 void sculpt_update_after_dynamic_topology_toggle(bContext *C)
 {
        Scene *scene = CTX_data_scene(C);
@@ -4845,8 +4872,9 @@ void sculpt_dynamic_topology_enable(bContext *C)
        BM_mesh_bm_from_me(ss->bm, me, true, true, ob->shapenr);
        sculpt_dynamic_topology_triangulate(ss->bm);
        BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK);
-       BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_DYNTOPO_NODE);
-       BM_data_layer_add(ss->bm, &ss->bm->pdata, CD_DYNTOPO_NODE);
+       sculpt_dyntopo_node_layers_add(ss);
+       /* make sure the data for existing faces are initialized */
+       sculpt_dyntopo_node_layers_reset(ss);
        BM_mesh_normals_update(ss->bm);
 
        /* Enable dynamic topology */
@@ -5303,7 +5331,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op))
 
        /* force rebuild of pbvh for better BB placement */
        sculpt_pbvh_clear(ob);
-       sculpt_dyntopo_node_layers_reset(ss->bm);
+       sculpt_dyntopo_node_layers_reset(ss);
        /* Redraw */
        WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
 
index 79fd388e3323090c4d61af801f629cca3b802727..8cf5bf88bcca4494b71315597ef93973ce981307 100644 (file)
 
 struct bContext;
 struct Brush;
-struct BMesh;
 struct KeyBlock;
 struct Mesh;
 struct MultiresModifierData;
 struct Object;
 struct Scene;
 struct Sculpt;
+struct SculptSession;
 struct SculptStroke;
 struct SculptUndoNode;
 
@@ -68,7 +68,8 @@ bool sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
 
 /* Dynamic topology */
 void sculpt_pbvh_clear(Object *ob);
-void sculpt_dyntopo_node_layers_reset(struct BMesh *bm);
+void sculpt_dyntopo_node_layers_reset(struct SculptSession *ss);
+void sculpt_dyntopo_node_layers_add(struct SculptSession *ss);
 void sculpt_update_after_dynamic_topology_toggle(bContext *C);
 void sculpt_dynamic_topology_enable(struct bContext *C);
 void sculpt_dynamic_topology_disable(struct bContext *C,
index b0fd7faa70d4be5ce7898d3386f30274c6926706..39df15bd985d279c0401a3d4817a9cdbfef48f2c 100644 (file)
@@ -301,7 +301,7 @@ static void sculpt_undo_bmesh_restore_generic(bContext *C,
                        MEM_freeN(nodes);
        }
        else {
-               sculpt_dyntopo_node_layers_reset(ss->bm);
+               sculpt_dyntopo_node_layers_reset(ss);
                sculpt_pbvh_clear(ob);
        }
 }
@@ -318,8 +318,7 @@ static void sculpt_undo_bmesh_enable(Object *ob,
        /* Create empty BMesh and enable logging */
        ss->bm = BM_mesh_create(&bm_mesh_allocsize_default);
        BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_PAINT_MASK);
-       BM_data_layer_add(ss->bm, &ss->bm->vdata, CD_DYNTOPO_NODE);
-       BM_data_layer_add(ss->bm, &ss->bm->pdata, CD_DYNTOPO_NODE);
+       sculpt_dyntopo_node_layers_add(ss);
        me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY;
 
        /* Restore the BMLog using saved entries */
@@ -342,6 +341,9 @@ static void sculpt_undo_bmesh_restore_begin(bContext *C,
                /* Restore the mesh from the first log entry */
                BM_log_redo(ss->bm, ss->bm_log);
 
+               /* reset layers for all bmesh data */
+               sculpt_dyntopo_node_layers_reset(ss);
+
                unode->applied = true;
        }
 }
@@ -357,6 +359,9 @@ static void sculpt_undo_bmesh_restore_end(bContext *C,
                /* Restore the mesh from the last log entry */
                BM_log_undo(ss->bm, ss->bm_log);
 
+               /* reset layers for all bmesh data */
+               sculpt_dyntopo_node_layers_reset(ss);
+
                unode->applied = false;
        }
        else {
index 4869c9a74f1901246a699e39f66a9ef4f0114e99..70dc43676ac41fb82c2ccf3a55925a93956e48c1 100644 (file)
@@ -63,10 +63,9 @@ typedef struct CustomDataExternal {
  * layers, each with a data type (e.g. MTFace, MDeformVert, etc.). */
 typedef struct CustomData {
        CustomDataLayer *layers;      /* CustomDataLayers, ordered by type */
-       int typemap[42];              /* runtime only! - maps types to indices of first layer of that type,
+       int typemap[41];              /* runtime only! - maps types to indices of first layer of that type,
                                       * MUST be >= CD_NUMTYPES, but we cant use a define here.
                                       * Correct size is ensured in CustomData_update_typemap assert() */
-       int pad;
        int totlayer, maxlayer;       /* number of layers, size of layers array */
        int totsize;                  /* in editmode, total size of all data layers */
        struct BLI_mempool *pool;     /* (BMesh Only): Memory pool for allocation of blocks */
@@ -121,8 +120,7 @@ enum {
        CD_MLOOPTANGENT     = 39,
        CD_TESSLOOPNORMAL   = 40,
 
-       CD_DYNTOPO_NODE     = 41,
-       CD_NUMTYPES         = 42
+       CD_NUMTYPES         = 41
 };
 
 /* Bits for CustomDataMask */
@@ -170,8 +168,6 @@ enum {
 #define CD_MASK_MLOOPTANGENT    (1LL << CD_MLOOPTANGENT)
 #define CD_MASK_TESSLOOPNORMAL  (1LL << CD_TESSLOOPNORMAL)
 
-#define CD_MASK_DYNTOPO_NODE    (1LL << CD_DYNTOPO_NODE)
-
 /* CustomData.flag */
 enum {
        /* Indicates layer should not be copied by CustomData_from_template or CustomData_copy_data */