diff options
author | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2012-03-25 12:20:19 +0400 |
---|---|---|
committer | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2012-03-25 12:20:19 +0400 |
commit | 3b711a6ed009b35bb69cd0ca878eeb8d55fa0e77 (patch) | |
tree | b3fdb366cb49bdea5b57dfa6ba4a82635c68d0ee /source/blender/editors/sculpt_paint/sculpt_undo.c | |
parent | a2ebfc82dbe954acc432ae017ac62a30a11b6a16 (diff) | |
parent | e99a23fc6b33b5097eab44aac19c2a089ddebce6 (diff) |
Merged changes in the trunk up to revision 45133.
Conflicts resolved:
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/bmesh/intern/bmesh_construct.c
source/blender/bmesh/intern/bmesh_mesh_conv.c
source/blender/bmesh/intern/bmesh_mesh_conv.h
source/blender/editors/interface/interface_templates.c
source/blender/editors/interface/resources.c
source/blender/editors/mesh/bmesh_select.c
source/blender/editors/mesh/bmesh_tools.c
source/blender/editors/space_view3d/drawobject.c
source/blender/render/intern/source/shadeoutput.c
Diffstat (limited to 'source/blender/editors/sculpt_paint/sculpt_undo.c')
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_undo.c | 284 |
1 files changed, 216 insertions, 68 deletions
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index 84b8b5a8bce..73fa546b357 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -55,6 +55,7 @@ #include "BKE_paint.h" #include "BKE_key.h" #include "BKE_mesh.h" +#include "BKE_subsurf.h" #include "WM_api.h" #include "WM_types.h" @@ -67,17 +68,23 @@ /************************** Undo *************************/ -static void update_cb(PBVHNode *node, void *UNUSED(unused)) +static void update_cb(PBVHNode *node, void *rebuild) { BLI_pbvh_node_mark_update(node); + if (*((int*)rebuild)) + BLI_pbvh_node_mark_rebuild_draw(node); + BLI_pbvh_node_fully_hidden_set(node, 0); } static void sculpt_undo_restore_deformed(SculptSession *ss, SculptUndoNode *unode, int uindex, int oindex, float coord[3]) { - if(unode->orig_co) { + if (unode->orig_co) { swap_v3_v3(coord, unode->orig_co[uindex]); copy_v3_v3(unode->co[uindex], ss->deform_cos[oindex]); - } else swap_v3_v3(coord, unode->co[uindex]); + } + else { + swap_v3_v3(coord, unode->co[uindex]); + } } static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNode *unode) @@ -89,7 +96,7 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo MVert *mvert; int *index, i, j; - if(unode->maxvert) { + if (unode->maxvert) { /* regular mesh restore */ if (ss->kb && strcmp(ss->kb->name, unode->shapeName)) { @@ -103,7 +110,8 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo sculpt_update_mesh_elements(scene, sd, ob, 0); WM_event_add_notifier(C, NC_OBJECT|ND_DATA, ob); - } else { + } + else { /* key has been removed -- skip this undo node */ return 0; } @@ -116,10 +124,10 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo float (*vertCos)[3]; vertCos= key_to_vertcos(ob, ss->kb); - for(i=0; i<unode->totvert; i++) { - if(ss->modifiers_active) sculpt_undo_restore_deformed(ss, unode, i, index[i], vertCos[index[i]]); + for (i=0; i<unode->totvert; i++) { + if (ss->modifiers_active) sculpt_undo_restore_deformed(ss, unode, i, index[i], vertCos[index[i]]); else { - if(unode->orig_co) swap_v3_v3(vertCos[index[i]], unode->orig_co[i]); + if (unode->orig_co) swap_v3_v3(vertCos[index[i]], unode->orig_co[i]); else swap_v3_v3(vertCos[index[i]], unode->co[i]); } } @@ -132,18 +140,19 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo BLI_pbvh_apply_vertCos(ss->pbvh, vertCos); MEM_freeN(vertCos); - } else { - for(i=0; i<unode->totvert; i++) { - if(ss->modifiers_active) sculpt_undo_restore_deformed(ss, unode, i, index[i], mvert[index[i]].co); + } + else { + for (i=0; i<unode->totvert; i++) { + if (ss->modifiers_active) sculpt_undo_restore_deformed(ss, unode, i, index[i], mvert[index[i]].co); else { - if(unode->orig_co) swap_v3_v3(mvert[index[i]].co, unode->orig_co[i]); + if (unode->orig_co) swap_v3_v3(mvert[index[i]].co, unode->orig_co[i]); else swap_v3_v3(mvert[index[i]].co, unode->co[i]); } mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE; } } } - else if(unode->maxgrid && dm->getGridData) { + else if (unode->maxgrid && dm->getGridData) { /* multires restore */ DMGridData **grids, *grid; float (*co)[3]; @@ -153,10 +162,10 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo gridsize= dm->getGridSize(dm); co = unode->co; - for(j=0; j<unode->totgrid; j++) { + for (j=0; j<unode->totgrid; j++) { grid= grids[unode->grids[j]]; - for(i=0; i<gridsize*gridsize; i++, co++) + for (i=0; i<gridsize*gridsize; i++, co++) swap_v3_v3(grid[i].co, co[0]); } } @@ -164,6 +173,44 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo return 1; } +static int sculpt_undo_restore_hidden(bContext *C, DerivedMesh *dm, + SculptUndoNode *unode) +{ + Object *ob = CTX_data_active_object(C); + SculptSession *ss = ob->sculpt; + int i; + + if (unode->maxvert) { + MVert *mvert= ss->mvert; + + for (i=0; i<unode->totvert; i++) { + MVert *v = &mvert[unode->index[i]]; + int uval= BLI_BITMAP_GET(unode->vert_hidden, i); + + BLI_BITMAP_MODIFY(unode->vert_hidden, i, + v->flag & ME_HIDE); + if (uval) + v->flag |= ME_HIDE; + else + v->flag &= ~ME_HIDE; + + v->flag |= ME_VERT_PBVH_UPDATE; + } + } + else if (unode->maxgrid && dm->getGridData) { + BLI_bitmap *grid_hidden = dm->getGridHidden(dm); + + for (i=0; i<unode->totgrid; i++) { + SWAP(BLI_bitmap, + unode->grid_hidden[i], + grid_hidden[unode->grids[i]]); + + } + } + + return 1; +} + static void sculpt_undo_restore(bContext *C, ListBase *lb) { Scene *scene = CTX_data_scene(C); @@ -173,22 +220,22 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb) SculptSession *ss = ob->sculpt; SculptUndoNode *unode; MultiresModifierData *mmd; - int update= 0; + int update= 0, rebuild= 1; sculpt_update_mesh_elements(scene, sd, ob, 0); - for(unode=lb->first; unode; unode=unode->next) { - if(!(strcmp(unode->idname, ob->id.name)==0)) + for (unode=lb->first; unode; unode=unode->next) { + if (!(strcmp(unode->idname, ob->id.name)==0)) continue; /* check if undo data matches current data well enough to * continue */ - if(unode->maxvert) { - if(ss->totvert != unode->maxvert) + if (unode->maxvert) { + if (ss->totvert != unode->maxvert) continue; } - else if(unode->maxgrid && dm->getGridData) { - if((dm->getNumGrids(dm) != unode->maxgrid) || + else if (unode->maxgrid && dm->getGridData) { + if ((dm->getNumGrids(dm) != unode->maxgrid) || (dm->getGridSize(dm) != unode->gridsize)) continue; } @@ -196,24 +243,36 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb) continue; } - if(sculpt_undo_restore_coords(C, dm, unode)) - update= 1; + switch(unode->type) { + case SCULPT_UNDO_COORDS: + if (sculpt_undo_restore_coords(C, dm, unode)) + update= 1; + break; + case SCULPT_UNDO_HIDDEN: + if (sculpt_undo_restore_hidden(C, dm, unode)) + rebuild= 1; + break; + } } - if(update) { + if (update || rebuild) { int tag_update= 0; /* we update all nodes still, should be more clever, but also * needs to work correct when exiting/entering sculpt mode and * the nodes get recreated, though in that case it could do all */ - BLI_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, NULL); + BLI_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, &rebuild); BLI_pbvh_update(ss->pbvh, PBVH_UpdateBB|PBVH_UpdateOriginalBB|PBVH_UpdateRedraw, NULL); - if((mmd=sculpt_multires_active(scene, ob))) - multires_mark_as_modified(ob); + if ((mmd=sculpt_multires_active(scene, ob))) { + if (rebuild) + multires_mark_as_modified(ob, MULTIRES_HIDDEN_MODIFIED); + else + multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED); + } tag_update= ((Mesh*)ob->data)->id.us > 1; - if(ss->modifiers_active) { + if (ss->modifiers_active) { Mesh *mesh= ob->data; mesh_calc_normals_mapping(mesh->mvert, mesh->totvert, mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly, NULL, NULL, 0, NULL, NULL); @@ -221,7 +280,7 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb) tag_update|= 1; } - if(tag_update) + if (tag_update) DAG_id_tag_update(&ob->id, OB_RECALC_DATA); /* for non-PBVH drawing, need to recreate VBOs */ @@ -232,20 +291,30 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb) static void sculpt_undo_free(ListBase *lb) { SculptUndoNode *unode; + int i; - for(unode=lb->first; unode; unode=unode->next) { - if(unode->co) + for (unode=lb->first; unode; unode=unode->next) { + if (unode->co) MEM_freeN(unode->co); - if(unode->no) + if (unode->no) MEM_freeN(unode->no); - if(unode->index) + if (unode->index) MEM_freeN(unode->index); - if(unode->grids) + if (unode->grids) MEM_freeN(unode->grids); - if(unode->layer_disp) + if (unode->layer_disp) MEM_freeN(unode->layer_disp); - if(unode->orig_co) + if (unode->orig_co) MEM_freeN(unode->orig_co); + if (unode->vert_hidden) + MEM_freeN(unode->vert_hidden); + if (unode->grid_hidden) { + for (i=0; i<unode->totgrid; i++) { + if (unode->grid_hidden[i]) + MEM_freeN(unode->grid_hidden[i]); + } + MEM_freeN(unode->grid_hidden); + } } } @@ -254,17 +323,41 @@ SculptUndoNode *sculpt_undo_get_node(PBVHNode *node) ListBase *lb= undo_paint_push_get_list(UNDO_PAINT_MESH); SculptUndoNode *unode; - if(!lb) + if (!lb) return NULL; - for(unode=lb->first; unode; unode=unode->next) - if(unode->node == node) + for (unode=lb->first; unode; unode=unode->next) + if (unode->node == node) return unode; return NULL; } -SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node) +static void sculpt_undo_alloc_and_store_hidden(PBVH *pbvh, + SculptUndoNode *unode) +{ + PBVHNode *node= unode->node; + BLI_bitmap *grid_hidden; + int i, *grid_indices, totgrid; + + grid_hidden= BLI_pbvh_grid_hidden(pbvh); + + BLI_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, + NULL, NULL, NULL, NULL); + + unode->grid_hidden= MEM_mapallocN(sizeof(BLI_bitmap) * totgrid, + "unode->grid_hidden"); + + for (i = 0; i < totgrid; i++) { + if (grid_hidden[grid_indices[i]]) + unode->grid_hidden[i] = MEM_dupallocN(grid_hidden[grid_indices[i]]); + else + unode->grid_hidden[i] = NULL; + } +} + +static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, + SculptUndoType type) { ListBase *lb= undo_paint_push_get_list(UNDO_PAINT_MESH); SculptUndoNode *unode; @@ -273,6 +366,7 @@ SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node) unode= MEM_callocN(sizeof(SculptUndoNode), "SculptUndoNode"); BLI_strncpy(unode->idname, ob->id.name, sizeof(unode->idname)); + unode->type= type; unode->node= node; BLI_pbvh_node_num_verts(ss->pbvh, node, &totvert, &allvert); @@ -280,13 +374,28 @@ SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node) &maxgrid, &gridsize, NULL, NULL); unode->totvert= totvert; + /* we will use this while sculpting, is mapalloc slow to access then? */ - unode->co= MEM_mapallocN(sizeof(float)*3*allvert, "SculptUndoNode.co"); - unode->no= MEM_mapallocN(sizeof(short)*3*allvert, "SculptUndoNode.no"); - undo_paint_push_count_alloc(UNDO_PAINT_MESH, (sizeof(float)*3 + sizeof(short)*3 + sizeof(int))*allvert); + + /* general TODO, fix count_alloc */ + switch(type) { + case SCULPT_UNDO_COORDS: + unode->co= MEM_mapallocN(sizeof(float)*3*allvert, "SculptUndoNode.co"); + unode->no= MEM_mapallocN(sizeof(short)*3*allvert, "SculptUndoNode.no"); + undo_paint_push_count_alloc(UNDO_PAINT_MESH, (sizeof(float)*3 + sizeof(short)*3 + sizeof(int))*allvert); + break; + case SCULPT_UNDO_HIDDEN: + if (maxgrid) + sculpt_undo_alloc_and_store_hidden(ss->pbvh, unode); + else + unode->vert_hidden= BLI_BITMAP_NEW(allvert, "SculptUndoNode.vert_hidden"); + + break; + } + BLI_addtail(lb, unode); - if(maxgrid) { + if (maxgrid) { /* multires */ unode->maxgrid= maxgrid; unode->totgrid= totgrid; @@ -299,13 +408,52 @@ SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node) unode->index= MEM_mapallocN(sizeof(int)*allvert, "SculptUndoNode.index"); } - if(ss->modifiers_active) + if (ss->modifiers_active) unode->orig_co= MEM_callocN(allvert*sizeof(*unode->orig_co), "undoSculpt orig_cos"); return unode; } -SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node) +static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode) +{ + SculptSession *ss = ob->sculpt; + PBVHVertexIter vd; + + BLI_pbvh_vertex_iter_begin(ss->pbvh, unode->node, vd, PBVH_ITER_ALL) { + copy_v3_v3(unode->co[vd.i], vd.co); + if (vd.no) copy_v3_v3_short(unode->no[vd.i], vd.no); + else normal_float_to_short_v3(unode->no[vd.i], vd.fno); + + if (ss->modifiers_active) + copy_v3_v3(unode->orig_co[vd.i], ss->orig_cos[unode->index[vd.i]]); + } + BLI_pbvh_vertex_iter_end; +} + +static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode) +{ + PBVH *pbvh= ob->sculpt->pbvh; + PBVHNode *node= unode->node; + + if (unode->grids) { + /* already stored during allocation */ + } + else { + MVert *mvert; + int *vert_indices, allvert; + int i; + + BLI_pbvh_node_num_verts(pbvh, node, NULL, &allvert); + BLI_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert); + for (i = 0; i < allvert; i++) { + BLI_BITMAP_MODIFY(unode->vert_hidden, i, + mvert[vert_indices[i]].flag & ME_HIDE); + } + } +} + +SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, + SculptUndoType type) { SculptSession *ss = ob->sculpt; SculptUndoNode *unode; @@ -313,40 +461,40 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node) /* list is manipulated by multiple threads, so we lock */ BLI_lock_thread(LOCK_CUSTOM1); - if((unode= sculpt_undo_get_node(node))) { + if ((unode= sculpt_undo_get_node(node))) { BLI_unlock_thread(LOCK_CUSTOM1); return unode; } - unode= sculpt_undo_alloc_node(ob, node); - + unode= sculpt_undo_alloc_node(ob, node, type); + BLI_unlock_thread(LOCK_CUSTOM1); /* copy threaded, hopefully this is the performance critical part */ - { - PBVHVertexIter vd; - - BLI_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL) { - copy_v3_v3(unode->co[vd.i], vd.co); - if(vd.no) copy_v3_v3_short(unode->no[vd.i], vd.no); - else normal_float_to_short_v3(unode->no[vd.i], vd.fno); - if(vd.vert_indices) unode->index[vd.i]= vd.vert_indices[vd.i]; - - if(ss->modifiers_active) - copy_v3_v3(unode->orig_co[vd.i], ss->orig_cos[unode->index[vd.i]]); - } - BLI_pbvh_vertex_iter_end; + switch(type) { + case SCULPT_UNDO_COORDS: + sculpt_undo_store_coords(ob, unode); + break; + case SCULPT_UNDO_HIDDEN: + sculpt_undo_store_hidden(ob, unode); + break; } - if(unode->grids) { + if (unode->grids) { int totgrid, *grids; BLI_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid, NULL, NULL, NULL, NULL); memcpy(unode->grids, grids, sizeof(int)*totgrid); } + else { + int *vert_indices, allvert; + BLI_pbvh_node_num_verts(ss->pbvh, node, NULL, &allvert); + BLI_pbvh_node_get_verts(ss->pbvh, node, &vert_indices, NULL); + memcpy(unode->index, vert_indices, sizeof(int)*unode->totvert); + } /* store active shape key */ - if(ss->kb) BLI_strncpy(unode->shapeName, ss->kb->name, sizeof(ss->kb->name)); + if (ss->kb) BLI_strncpy(unode->shapeName, ss->kb->name, sizeof(ss->kb->name)); else unode->shapeName[0]= '\0'; return unode; @@ -364,13 +512,13 @@ void sculpt_undo_push_end(void) SculptUndoNode *unode; /* we don't need normals in the undo stack */ - for(unode=lb->first; unode; unode=unode->next) { - if(unode->no) { + for (unode=lb->first; unode; unode=unode->next) { + if (unode->no) { MEM_freeN(unode->no); unode->no= NULL; } - if(unode->layer_disp) { + if (unode->layer_disp) { MEM_freeN(unode->layer_disp); unode->layer_disp= NULL; } |