diff options
author | Antony Riakiotakis <kalast@gmail.com> | 2014-04-17 20:02:55 +0400 |
---|---|---|
committer | Antony Riakiotakis <kalast@gmail.com> | 2014-04-17 20:03:08 +0400 |
commit | 38eef8deee4261f0139d29eb81584131a862bf59 (patch) | |
tree | eabdfc91ed986342d938c1fbcda945e768c5b660 | |
parent | 0ba3f7647071a7bd7fdf48e0d48a9e7e1ee79a7b (diff) |
Refactor to Dyntopo node customdata commit.
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!
-rw-r--r-- | source/blender/blenkernel/BKE_paint.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_pbvh.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/cdderivedmesh.c | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/customdata.c | 14 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pbvh_bmesh.c | 33 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pbvh_intern.h | 2 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt.c | 44 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_intern.h | 5 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_undo.c | 11 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_customdata_types.h | 8 |
10 files changed, 71 insertions, 53 deletions
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 60c448608d7..df72cb988b1 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -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; diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index d29ded67717..c5f82babb6d 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -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); diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 7faeecb87cd..5f38eb610fc 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -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); } diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 4a76abc0154..78c88cdfd0f 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -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" }; diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index cca24682f95..d316cbba86b 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -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); } } } diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h index ef5828e8097..6b3ef8eb5da 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.h +++ b/source/blender/blenkernel/intern/pbvh_intern.h @@ -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; }; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 4873587e9f5..dbf99e96053 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -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); diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 79fd388e332..8cf5bf88bcc 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -42,13 +42,13 @@ 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, diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index b0fd7faa70d..39df15bd985 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -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 { diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 4869c9a74f1..70dc43676ac 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -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 */ |