== Multires ==
authorNicholas Bishop <nicholasbishop@gmail.com>
Fri, 1 Jun 2007 02:21:11 +0000 (02:21 +0000)
committerNicholas Bishop <nicholasbishop@gmail.com>
Fri, 1 Jun 2007 02:21:11 +0000 (02:21 +0000)
* Moved the multires vertex data from struct MultiresLevel to struct Multires. There's no longer any reason to store data seperately for each level; it was just taking up extra memory.

* Incremented the subversion to 2 and adjusted do_versions to correctly load older files.

* Refactored the multires update process (which handles propagating changes to other levels)

source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/include/multires.h
source/blender/makesdna/DNA_meshdata_types.h
source/blender/src/multires-firstlevel.c
source/blender/src/multires.c

index bf3e25b1c5a3575244c03c04826c749215831052..4b9e10651cf065a4ff0bb63480dfec93d51f48fd 100644 (file)
@@ -44,7 +44,7 @@ struct ListBase;
 struct MemFile;
 
 #define BLENDER_VERSION                        244
-#define BLENDER_SUBVERSION             1
+#define BLENDER_SUBVERSION             2
 
 #define BLENDER_MINVERSION             240
 #define BLENDER_MINSUBVERSION  0
index dc54fc7c1f07654873f917c176a1326c32dd252f..5f8e9c7b207bcdcdbcf776bb7bf36de7d23a0374 100644 (file)
@@ -2272,7 +2272,7 @@ float *multires_render_pin(Object *ob, Mesh *me, int *orig_lvl)
                lvl= multires_level_n(me->mr, BLI_countlist(&me->mr->levels));
                vert_copy= MEM_callocN(sizeof(float)*3*lvl->totvert, "multires vert_copy");
                for(i=0; i<lvl->totvert; ++i)
-                       VecCopyf(&vert_copy[i*3], lvl->verts[i].co);
+                       VecCopyf(&vert_copy[i*3], me->mr->verts[i].co);
        
                /* Goto the pin level for multires */
                me->mr->newlvl= me->mr->pinlvl;
index 278d49e219854f48714107286d8829fb8f8184bd..4c6bfda151730ddec7d7f43922e86f68895ec7ac 100644 (file)
@@ -504,7 +504,7 @@ static float *make_orco_mesh_internal(Object *ob, int render)
                if(me->mr) {
                        lvl = multires_level_n(me->mr, me->mr->pinlvl);
                        vcos = MEM_callocN(sizeof(*vcos)*lvl->totvert, "orco mr mesh");
-                       mvert = lvl->verts;
+                       mvert = me->mr->verts;
                        totvert = lvl->totvert;
                }
                else {
index 118c2779ac0da54e377c081463c0025aa9175304..4bbcfab74aefa805f49c788df116a2926b44142f 100644 (file)
@@ -2554,6 +2554,8 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
                        mesh->mr->edge_flags= MEM_callocN(sizeof(short)*lvl->totedge, "Multires Edge Flags");
                if(!mesh->mr->edge_creases)
                        mesh->mr->edge_creases= MEM_callocN(sizeof(char)*lvl->totedge, "Multires Edge Creases");
+
+               mesh->mr->verts = newdataadr(fd, mesh->mr->verts);
                        
                for(; lvl; lvl= lvl->next) {
                        lvl->verts= newdataadr(fd, lvl->verts);
@@ -6469,6 +6471,25 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        for(sce= main->scene.first; sce; sce= sce->id.next)
                                sce->r.mode |= R_SSS;
                }
+               if(main->versionfile != 244 || main->subversionfile < 2) {
+                       /* Copy over old per-level multires vertex data
+                          into a single vertex array in struct Multires */
+                       Mesh *me;
+                       for(me = main->mesh.first; me; me=me->id.next) {
+                               if(me->mr) {
+                                       MultiresLevel *lvl = me->mr->levels.last;
+                                       if(lvl) {
+                                               me->mr->verts = lvl->verts;
+                                               lvl->verts = NULL;
+                                               /* Don't need the other vert arrays */
+                                               for(lvl = lvl->prev; lvl; lvl = lvl->prev) {
+                                                       MEM_freeN(lvl->verts);
+                                                       lvl->verts = NULL;
+                                               }
+                                       }
+                               }
+                       }
+               }
        }
 
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
index 0d4d9d82ee1f75ed9c52b011bfc471154032a2fd..226561ab97be53175bf1e567f84bdc9b9b34f4c1 100644 (file)
@@ -1156,13 +1156,17 @@ static void write_meshs(WriteData *wd, ListBase *idbase)
                                        writedata(wd, DATA, sizeof(short)*lvl->totedge, mesh->mr->edge_flags);
                                        writedata(wd, DATA, sizeof(char)*lvl->totedge, mesh->mr->edge_creases);
                                }
+
                                for(; lvl; lvl= lvl->next) {
                                        writestruct(wd, DATA, "MultiresLevel", 1, lvl);
-                                       writestruct(wd, DATA, "MVert", lvl->totvert, lvl->verts);
                                        writestruct(wd, DATA, "MultiresFace", lvl->totface, lvl->faces);
                                        writestruct(wd, DATA, "MultiresEdge", lvl->totedge, lvl->edges);
                                        writestruct(wd, DATA, "MultiresColFace", lvl->totface, lvl->colfaces);
                                }
+
+                               lvl= mesh->mr->levels.last;
+                               if(lvl)
+                                       writestruct(wd, DATA, "MVert", lvl->totvert, mesh->mr->verts);
                        }
 
                        /* PMV data */
index 6c33af2d5e393d3b01e261c5c81a5efc5147c06b..069dbee802f3b4a84b341bec29dcd5530c13b66b 100644 (file)
@@ -31,6 +31,7 @@
 #define MULTIRES_H
 
 struct CustomData;
+struct EditMesh;
 struct Object;
 struct MDeformVert;
 struct Mesh;
@@ -65,6 +66,7 @@ int multires_modifier_warning();
 
 /* multires-firstlevel.c */
 /* Generic */
+void multires_update_first_level(struct Mesh *me, struct EditMesh *em);
 void multires_update_customdata(struct MultiresLevel *lvl1, struct CustomData *src,
                                 struct CustomData *dst, const int type);
 void multires_customdata_to_mesh(struct Mesh *me, struct EditMesh *em, struct MultiresLevel *lvl,
index 4d78f57713729833b7ef1f7f46650619d3fed74a..af9c1ae629df6973942715973dd82281be14677f 100644 (file)
@@ -109,7 +109,6 @@ struct MultiresMapNode;
 typedef struct MultiresLevel {
        struct MultiresLevel *next, *prev;
 
-       MVert *verts;
        MultiresFace *faces;
        MultiresColFace *colfaces;
        MultiresEdge *edges;
@@ -118,10 +117,15 @@ typedef struct MultiresLevel {
        struct MultiresMapNode *map_mem;
 
        unsigned int totvert, totface, totedge, pad;
+
+       /* Kept for compatibility with older files */
+       MVert *verts;
 } MultiresLevel;
 
 typedef struct Multires {
        ListBase levels;
+       MVert *verts;
+
        unsigned char level_count, current, newlvl, edgelvl, pinlvl, renderlvl;
        unsigned char use_col, pad;
 
index db39a429c22e4a41778c03479365e95d19a29e06..2be867b5db017e79815b17e92d7b4a673ea8a620 100644 (file)
@@ -55,6 +55,8 @@
 
 MDeformVert *subdivide_dverts(MDeformVert *src, MultiresLevel *lvl);
 MTFace *subdivide_mtfaces(MTFace *src, MultiresLevel *lvl);
+void multires_update_edge_flags(Mesh *me, EditMesh *em);
+void eed_to_medge_flag(EditEdge *eed, short *flag, char *crease);
 
 /***********    Generic     ***********/
 
@@ -221,6 +223,41 @@ void multires_del_lower_customdata(Multires *mr, MultiresLevel *cr_lvl)
        mr->fdata= cdf;
 }
 
+/* Update all special first-level data, if the first-level is active */
+void multires_update_first_level(Mesh *me, EditMesh *em)
+{
+       if(me && me->mr && me->mr->current == 1) {
+               multires_update_customdata(me->mr->levels.first, em ? &em->vdata : &me->vdata,
+                                          &me->mr->vdata, CD_MDEFORMVERT);
+               multires_update_customdata(me->mr->levels.first, em ? &em->fdata : &me->fdata,
+                                          &me->mr->fdata, CD_MTFACE);
+               multires_update_edge_flags(me, em);
+       }
+}
+
+/*********** Multires.edge_flags ***********/
+void multires_update_edge_flags(Mesh *me, EditMesh *em)
+{
+       MultiresLevel *lvl= me->mr->levels.first;
+       EditEdge *eed= NULL;
+       int i;
+       
+       if(em) eed= em->edges.first;
+       for(i=0; i<lvl->totedge; ++i) {
+               if(em) {
+                       me->mr->edge_flags[i]= 0;
+                       eed_to_medge_flag(eed, &me->mr->edge_flags[i], &me->mr->edge_creases[i]);
+                       eed= eed->next;
+               }
+               else {
+                       me->mr->edge_flags[i]= me->medge[i].flag;
+                       me->mr->edge_creases[i]= me->medge[i].crease;
+               }
+       }
+}
+
+
+
 /*********** Multires.vdata ***********/
 
 /* MDeformVert */
index a249b6b408b3ed1a84bb9c6cac785030fd74d089..33b85bd27b6de33b277184efb320eefb59b0c88f 100644 (file)
@@ -484,13 +484,14 @@ void multires_get_face(MultiresFace *f, EditFace *efa, MFace *m)
                tmp.v3= efa->v3->tmp.l;
                tmp.v4= 0;
                if(efa->v4) tmp.v4= efa->v4->tmp.l;
-               tmp.flag= efa->flag;
-               if(efa->f & 1) tmp.flag |= ME_FACE_SEL;
-               else f->flag &= ~ME_FACE_SEL;
-               if(efa->h) tmp.flag |= ME_HIDE;
                test_index_face(&tmp, NULL, 0, efa->v4?4:3);
                for(j=0; j<4; ++j) f->v[j]= (&tmp.v1)[j];
-               f->flag= tmp.flag;
+
+               /* Flags */
+               f->flag= efa->flag;
+               if(efa->f & 1) f->flag |= ME_FACE_SEL;
+               else f->flag &= ~ME_FACE_SEL;
+               if(efa->h) f->flag |= ME_HIDE;
                f->mat_nr= efa->mat_nr;
        } else {                
                f->v[0]= m->v1;
@@ -575,12 +576,12 @@ void multires_make(void *ob, void *me_v)
 
        /* Load vertices and vdata (MDeformVerts) */
        lvl->totvert= em ? BLI_countlist(&em->verts) : me->totvert;
-       lvl->verts= MEM_callocN(sizeof(MVert)*lvl->totvert,"multires verts");
+       me->mr->verts= MEM_callocN(sizeof(MVert)*lvl->totvert,"multires verts");
        multires_update_customdata(me->mr->levels.first, em ? &em->vdata : &me->vdata,
                                   &me->mr->vdata, CD_MDEFORMVERT);
        if(em) eve= em->verts.first;
        for(i=0; i<lvl->totvert; ++i) {
-               multires_get_vert(&lvl->verts[i], eve, &me->mvert[i], i);
+               multires_get_vert(&me->mr->verts[i], eve, &me->mvert[i], i);
                if(em) eve= eve->next;
        }
 
@@ -636,7 +637,6 @@ MultiresLevel *multires_level_copy(MultiresLevel *orig)
                MultiresLevel *lvl= MEM_dupallocN(orig);
                
                lvl->next= lvl->prev= NULL;
-               lvl->verts= MEM_dupallocN(orig->verts);
                lvl->faces= MEM_dupallocN(orig->faces);
                lvl->colfaces= MEM_dupallocN(orig->colfaces);
                lvl->edges= MEM_dupallocN(orig->edges);
@@ -658,6 +658,8 @@ Multires *multires_copy(Multires *orig)
                
                for(lvl= orig->levels.first; lvl; lvl= lvl->next)
                        BLI_addtail(&mr->levels, multires_level_copy(lvl));
+
+               mr->verts= MEM_dupallocN(orig->verts);
                
                lvl= mr->levels.first;
                if(lvl) {
@@ -690,6 +692,8 @@ void multires_free(Multires *mr)
                        lvl= lvl->next;
                }
 
+               MEM_freeN(mr->verts);
+
                BLI_freelistN(&mr->levels);
 
                MEM_freeN(mr);
@@ -700,7 +704,6 @@ void multires_free(Multires *mr)
 void multires_free_level(MultiresLevel *lvl)
 {
        if(lvl) {
-               if(lvl->verts) MEM_freeN(lvl->verts);
                if(lvl->faces) MEM_freeN(lvl->faces);
                if(lvl->edges) MEM_freeN(lvl->edges);
                if(lvl->colfaces) MEM_freeN(lvl->colfaces);
@@ -844,6 +847,7 @@ void multires_add_level(void *ob, void *me_v)
        Mesh *me= me_v;
        MultiresLevel *lvl= MEM_callocN(sizeof(MultiresLevel), "multireslevel");
        MultiApplyData data;
+       MVert *oldverts= NULL;
        
        multires_check_state();
 
@@ -859,15 +863,16 @@ void multires_add_level(void *ob, void *me_v)
        /* Create vertices
           =============== */
        lvl->totvert= lvl->prev->totvert + lvl->prev->totedge + lvl->prev->totface;
-       lvl->verts= MEM_callocN(sizeof(MVert)*lvl->totvert,"multires verts");
-       /* Copy previous level's verts */
+       oldverts= me->mr->verts;
+       me->mr->verts= MEM_callocN(sizeof(MVert)*lvl->totvert, "multitres verts");
+       /* Copy old verts */
        for(i=0; i<lvl->prev->totvert; ++i)
-               lvl->verts[i]= lvl->prev->verts[i];
+               me->mr->verts[i]= oldverts[i];
        /* Create new edge verts */
        for(i=0; i<lvl->prev->totedge; ++i) {
-               VecMidf(lvl->verts[lvl->prev->totvert + i].co,
-                       lvl->prev->verts[lvl->prev->edges[i].v[0]].co,
-                       lvl->prev->verts[lvl->prev->edges[i].v[1]].co);
+               VecMidf(me->mr->verts[lvl->prev->totvert + i].co,
+                       oldverts[lvl->prev->edges[i].v[0]].co,
+                       oldverts[lvl->prev->edges[i].v[1]].co);
                lvl->prev->edges[i].mid= lvl->prev->totvert + i;
        }
        /* Create new face verts */
@@ -937,38 +942,42 @@ void multires_add_level(void *ob, void *me_v)
           =============== */
        for(i=0; i<lvl->prev->totface; ++i) {
                const MultiresFace *f= &lvl->prev->faces[i];
-               data.corner1= lvl->prev->verts[f->v[0]].co;
-               data.corner2= lvl->prev->verts[f->v[1]].co;
-               data.corner3= lvl->prev->verts[f->v[2]].co;
-               data.corner4= lvl->prev->verts[f->v[3]].co;
+               data.corner1= oldverts[f->v[0]].co;
+               data.corner2= oldverts[f->v[1]].co;
+               data.corner3= oldverts[f->v[2]].co;
+               data.corner4= oldverts[f->v[3]].co;
                data.quad= f->v[3] ? 1 : 0;
-               multi_apply(lvl->verts[f->mid].co, &data, 3, catmullclark_smooth_face);
+               multi_apply(me->mr->verts[f->mid].co, &data, 3, catmullclark_smooth_face);
        }
 
        if(G.scene->toolsettings->multires_subdiv_type == 0) {
                for(i=0; i<lvl->prev->totedge; ++i) {
                        const MultiresEdge *e= &lvl->prev->edges[i];
                        data.boundary= multires_edge_is_boundary(lvl->prev,i);
-                       edge_face_neighbor_midpoints_accum(&data,lvl->prev,lvl->verts,sizeof(MVert),e);
-                       data.endpoint1= lvl->prev->verts[e->v[0]].co;
-                       data.endpoint2= lvl->prev->verts[e->v[1]].co;
-                       multi_apply(lvl->verts[e->mid].co, &data, 3, catmullclark_smooth_edge);
+                       edge_face_neighbor_midpoints_accum(&data,lvl->prev, me->mr->verts, sizeof(MVert),e);
+                       data.endpoint1= oldverts[e->v[0]].co;
+                       data.endpoint2= oldverts[e->v[1]].co;
+                       multi_apply(me->mr->verts[e->mid].co, &data, 3, catmullclark_smooth_edge);
                }
                
                for(i=0; i<lvl->prev->totvert; ++i) {
                        data.boundary= multires_vert_is_boundary(lvl->prev,i);
-                       data.original= lvl->verts[i].co;
+                       data.original= oldverts[i].co;
                        data.edge_count= BLI_countlist(&lvl->prev->vert_edge_map[i]);
                        if(data.boundary)
-                               boundary_edges_average(&data,lvl->prev,lvl->prev->verts,sizeof(MVert),i);
+                               boundary_edges_average(&data,lvl->prev, oldverts, sizeof(MVert),i);
                        else {
-                               vert_face_neighbor_midpoints_average(&data,lvl->prev,lvl->verts,sizeof(MVert),i);
-                               vert_edge_neighbor_midpoints_average(&data,lvl->prev,lvl->prev->verts,sizeof(MVert),i);
+                               vert_face_neighbor_midpoints_average(&data,lvl->prev, me->mr->verts,
+                                                                    sizeof(MVert),i);
+                               vert_edge_neighbor_midpoints_average(&data,lvl->prev, oldverts,
+                                                                    sizeof(MVert),i);
                        }
-                       multi_apply(lvl->verts[i].co, &data, 3, catmullclark_smooth_vert);
+                       multi_apply(me->mr->verts[i].co, &data, 3, catmullclark_smooth_vert);
                }
        }
 
+       MEM_freeN(oldverts);
+
        /* Vertex Colors
           ============= */
        curf= 0;
@@ -1094,13 +1103,13 @@ void multires_level_to_mesh(Object *ob, Mesh *me, const int render)
        
        for(i=0; i<lvl->totvert; ++i) {
                if(em) {
-                       eves[i]= addvertlist(lvl->verts[i].co, NULL); /* TODO */
-                       if(lvl->verts[i].flag & 1) eves[i]->f |= SELECT;
-                       if(lvl->verts[i].flag & ME_HIDE) eves[i]->h= 1;
+                       eves[i]= addvertlist(me->mr->verts[i].co, NULL);
+                       if(me->mr->verts[i].flag & 1) eves[i]->f |= SELECT;
+                       if(me->mr->verts[i].flag & ME_HIDE) eves[i]->h= 1;
                        eves[i]->data= NULL;
                }
                else
-                       me->mvert[i]= lvl->verts[i];
+                       me->mvert[i]= me->mr->verts[i];
        }
        for(i=0; i<lvl->totedge; ++i) {
                if(em) {
@@ -1115,9 +1124,12 @@ void multires_level_to_mesh(Object *ob, Mesh *me, const int render)
                if(em) {
                        EditVert *eve4= lvl->faces[i].v[3] ? eves[lvl->faces[i].v[3]] : NULL;
                        EditFace *efa= addfacelist(eves[lvl->faces[i].v[0]], eves[lvl->faces[i].v[1]],
-                                      eves[lvl->faces[i].v[2]], eve4, NULL, NULL); /* TODO */
-                       efa->flag= lvl->faces[i].flag;
+                                      eves[lvl->faces[i].v[2]], eve4, NULL, NULL);
+                       efa->flag= lvl->faces[i].flag & ~ME_HIDE;
                        efa->mat_nr= lvl->faces[i].mat_nr;
+                       if(lvl->faces[i].flag & ME_FACE_SEL)
+                               efa->f |= SELECT;
+                       if(lvl->faces[i].flag & ME_HIDE) efa->h= 1;
                        efa->data= NULL;
                }
                else {
@@ -1160,6 +1172,14 @@ void multires_level_to_mesh(Object *ob, Mesh *me, const int render)
                        }
                }
        }
+
+       if(em) {
+               eed= em->edges.first;
+               for(i=0, eed= em->edges.first; i<lvl->totedge; ++i, eed= eed->next) {
+                       eed->h= me->mr->verts[lvl->edges[i].v[0]].flag & ME_HIDE ||
+                               me->mr->verts[lvl->edges[i].v[1]].flag & ME_HIDE;
+               }
+       }
        
        EM_select_flush();
 
@@ -1313,108 +1333,65 @@ void multires_update_colors(Mesh *me)
        }
 }
 
-void multires_update_edge_flags(Multires *mr, Mesh *me, EditMesh *em)
-{
-       MultiresLevel *lvl= current_level(mr);
-       EditEdge *eed= NULL;
-       int i;
-       
-       if(em) eed= em->edges.first;
-       for(i=0; i<lvl->totedge; ++i) {
-               if(em) {
-                       mr->edge_flags[i]= 0;
-                       eed_to_medge_flag(eed, &mr->edge_flags[i], &mr->edge_creases[i]);
-                       eed= eed->next;
-               }
-               else {
-                       mr->edge_flags[i]= me->medge[i].flag;
-                       mr->edge_creases[i]= me->medge[i].crease;
-               }
-       }
-}
-
-void multires_update_levels(Mesh *me, const int render)
+/* Update vertex locations and vertex flags */
+void multires_update_vertices(Mesh *me, EditMesh *em)
 {
-       /* cr=current, pr=previous, or=original */
-       MultiresLevel *cr_lvl= current_level(me->mr), *pr_lvl;
-       MultiresLevel *or_lvl= cr_lvl;
-       vec3f *pr_deltas= NULL, *cr_deltas= NULL;
-       char *pr_flag_damaged= NULL, *cr_flag_damaged= NULL, *pr_mat_damaged= NULL, *cr_mat_damaged= NULL;
-       char *or_flag_damaged= NULL, *or_mat_damaged= NULL;
-       EditMesh *em= (!render && G.obedit) ? G.editMesh : NULL;
+       MultiresLevel *cr_lvl= current_level(me->mr), *pr_lvl= NULL,
+                     *last_lvl= me->mr->levels.last;
+       vec3f *pr_deltas= NULL, *cr_deltas= NULL, *swap_deltas= NULL;
        EditVert *eve= NULL;
-       EditFace *efa= NULL;
        MultiApplyData data;
-       unsigned i,j,curf;
-
-       /* Update special first-level data */
-       if(cr_lvl==me->mr->levels.first) {
-               multires_update_customdata(me->mr->levels.first, em ? &em->vdata : &me->vdata,
-                                          &me->mr->vdata, CD_MDEFORMVERT);
-               multires_update_customdata(me->mr->levels.first, em ? &em->fdata : &me->fdata,
-                                          &me->mr->fdata, CD_MTFACE);
-               multires_update_edge_flags(me->mr, me, em);
-       }
+       int i, j;
 
        /* Prepare deltas */
-       cr_deltas= MEM_callocN(sizeof(vec3f)*cr_lvl->totvert,"initial deltas");
+       pr_deltas= MEM_callocN(sizeof(vec3f)*last_lvl->totvert, "multires deltas 1");
+       cr_deltas= MEM_callocN(sizeof(vec3f)*last_lvl->totvert, "multires deltas 2");
 
        /* Calculate initial deltas -- current mesh subtracted from current level*/
        if(em) eve= em->verts.first;
        for(i=0; i<cr_lvl->totvert; ++i) {
                if(em) {
-                       VecSubf(&cr_deltas[i].x, eve->co, cr_lvl->verts[i].co);
+                       VecSubf(&cr_deltas[i].x, eve->co, me->mr->verts[i].co);
                        eve= eve->next;
                } else
-                       VecSubf(&cr_deltas[i].x, me->mvert[i].co, cr_lvl->verts[i].co);
-       }
-       
-       /* Faces -- find whether flag/mat has changed */
-       cr_flag_damaged= MEM_callocN(sizeof(char)*cr_lvl->totface, "flag_damaged 1");
-       cr_mat_damaged= MEM_callocN(sizeof(char)*cr_lvl->totface, "mat_damaged 1");
-       if(em) efa= em->faces.first;
-       for(i=0; i<cr_lvl->totface; ++i) {
-               if(cr_lvl->faces[i].flag != (em ? efa->flag : me->mface[i].flag))
-                       cr_flag_damaged[i]= 1;
-               if(cr_lvl->faces[i].mat_nr != (em ? efa->mat_nr : me->mface[i].mat_nr))
-                       cr_mat_damaged[i]= 1;
-               if(em) efa= efa->next;
+                       VecSubf(&cr_deltas[i].x, me->mvert[i].co, me->mr->verts[i].co);
        }
-       or_flag_damaged= MEM_dupallocN(cr_flag_damaged);
-       or_mat_damaged= MEM_dupallocN(cr_mat_damaged);
 
-       /* Update current level -- copy current mesh into current level */
-       if(em) {
-               eve= em->verts.first;
-               efa= em->faces.first;
-       }
-       for(i=0; i<cr_lvl->totvert; ++i) {
-               multires_get_vert(&cr_lvl->verts[i], eve, &me->mvert[i], i);
-               if(em) eve= eve->next;
+
+       /* Copy current level's vertex flags and clear the rest */
+       if(em) eve= em->verts.first;    
+       for(i=0; i < last_lvl->totvert; ++i) {
+               if(i < cr_lvl->totvert) {
+                       MVert mvflag;
+                       multires_get_vert(&mvflag, eve, &me->mvert[i], i);
+                       if(em) eve= eve->next;
+                       me->mr->verts[i].flag= mvflag.flag;
+               }
+               else
+                       me->mr->verts[i].flag= 0;
        }
-       for(i=0; i<cr_lvl->totface; ++i) {
-               cr_lvl->faces[i].flag= em ? efa->flag : me->mface[i].flag;
-               cr_lvl->faces[i].mat_nr= em ? efa->mat_nr : me->mface[i].mat_nr;
-               if(em) efa= efa->next;
+
+       /* If already on the highest level, copy current verts (including flags) into current level */
+       if(cr_lvl == last_lvl) {
+               if(em)
+                       eve= em->verts.first;
+               for(i=0; i<cr_lvl->totvert; ++i) {
+                       multires_get_vert(&me->mr->verts[i], eve, &me->mvert[i], i);
+                       if(em) eve= eve->next;
+               }
        }
 
        /* Update higher levels */
        pr_lvl= BLI_findlink(&me->mr->levels,me->mr->current-1);
        cr_lvl= pr_lvl->next;
        while(cr_lvl) {
-               /* Set up new deltas, but keep the ones from the previous level */
-               if(pr_deltas) MEM_freeN(pr_deltas);
+               /* Swap the old/new deltas */
+               swap_deltas= pr_deltas;
                pr_deltas= cr_deltas;
-               cr_deltas= MEM_callocN(sizeof(vec3f)*cr_lvl->totvert,"deltas");
-               if(pr_flag_damaged) MEM_freeN(pr_flag_damaged);
-               pr_flag_damaged= cr_flag_damaged;
-               cr_flag_damaged= MEM_callocN(sizeof(char)*cr_lvl->totface,"flag_damaged 2");
-               if(pr_mat_damaged) MEM_freeN(pr_mat_damaged);
-               pr_mat_damaged= cr_mat_damaged;
-               cr_mat_damaged= MEM_callocN(sizeof(char)*cr_lvl->totface,"mat_damaged 2");
+               cr_deltas= swap_deltas;
 
                /* Calculate and add new deltas
-                  ============================*/
+                  ============================ */
                for(i=0; i<pr_lvl->totface; ++i) {
                        const MultiresFace *f= &pr_lvl->faces[i];
                        data.corner1= &pr_deltas[f->v[0]].x;
@@ -1423,18 +1400,9 @@ void multires_update_levels(Mesh *me, const int render)
                        data.corner4= &pr_deltas[f->v[3]].x;
                        data.quad= f->v[3] ? 1 : 0;
                        multi_apply(&cr_deltas[f->mid].x, &data, 3, catmullclark_smooth_face);
-
-                       VecAddf(cr_lvl->verts[f->mid].co,
-                               cr_lvl->verts[f->mid].co,
-                               &cr_deltas[f->mid].x);
                        
-                       cr_lvl->verts[f->mid].flag= 0;
-                       for(j=0; j<(data.quad?4:3); ++j) {
-                               if(pr_lvl->verts[f->v[j]].flag & 1)
-                                       cr_lvl->verts[f->mid].flag |= 1;
-                               if(pr_lvl->verts[f->v[j]].flag & ME_HIDE)
-                                       cr_lvl->verts[f->mid].flag |= ME_HIDE;
-                       }
+                       for(j=0; j<(data.quad?4:3); ++j)
+                               me->mr->verts[f->mid].flag |= me->mr->verts[f->v[j]].flag;
                }
 
                for(i=0; i<pr_lvl->totedge; ++i) {
@@ -1444,20 +1412,9 @@ void multires_update_levels(Mesh *me, const int render)
                        data.endpoint1= &pr_deltas[e->v[0]].x;
                        data.endpoint2= &pr_deltas[e->v[1]].x;
                        multi_apply(&cr_deltas[e->mid].x, &data, 3, catmullclark_smooth_edge);
-                       
-                       cr_lvl->verts[e->mid].flag= 0;
-                       for(j=0; j<2; ++j) {
-                               if(pr_lvl->verts[e->v[j]].flag & 1)
-                                       cr_lvl->verts[e->mid].flag |= 1;
-                               if(pr_lvl->verts[e->v[j]].flag & ME_HIDE)
-                                       cr_lvl->verts[e->mid].flag |= ME_HIDE;
-                       }
-               }
-               for(i=0; i<pr_lvl->totedge; ++i) {
-                       const unsigned ndx= pr_lvl->edges[i].mid;
-                       VecAddf(cr_lvl->verts[ndx].co,
-                               cr_lvl->verts[ndx].co,
-                               &cr_deltas[ndx].x);
+                               
+                       for(j=0; j<2; ++j)
+                               me->mr->verts[e->mid].flag |= me->mr->verts[e->v[j]].flag;
                }
 
                for(i=0; i<pr_lvl->totvert; ++i) {
@@ -1471,31 +1428,13 @@ void multires_update_levels(Mesh *me, const int render)
                                vert_edge_neighbor_midpoints_average(&data,pr_lvl,pr_deltas,sizeof(vec3f),i);
                        }
                        multi_apply(&cr_deltas[i].x, &data, 3, catmullclark_smooth_vert);
-                       cr_lvl->verts[i].flag= 0;
-                       if(pr_lvl->verts[i].flag & 1) cr_lvl->verts[i].flag |= 1;
-                       if(pr_lvl->verts[i].flag & ME_HIDE) cr_lvl->verts[i].flag |= ME_HIDE;
-               }
-               for(i=0; i<pr_lvl->totvert; ++i) {
-                       VecAddf(cr_lvl->verts[i].co,
-                               cr_lvl->verts[i].co,
-                               &cr_deltas[i].x);
                }
 
-               /* Update faces */
-               curf= 0;
-               for(i=0; i<pr_lvl->totface; ++i) {
-                       const int sides= cr_lvl->prev->faces[i].v[3] ? 4 : 3;
-                       for(j=0; j<sides; ++j) {
-                               if(pr_flag_damaged[i]) {
-                                       cr_lvl->faces[curf].flag= pr_lvl->faces[i].flag;
-                                       cr_flag_damaged[curf]= 1;
-                               }
-                               if(pr_mat_damaged[i]) {
-                                       cr_lvl->faces[curf].mat_nr= pr_lvl->faces[i].mat_nr;
-                                       cr_mat_damaged[curf]= 1;
-                               }
-                               ++curf;
-                       }
+               /* Apply deltas to vertex locations */
+               for(i=0; (cr_lvl == last_lvl) && (i < cr_lvl->totvert); ++i) {
+                       VecAddf(me->mr->verts[i].co,
+                               me->mr->verts[i].co,
+                               &cr_deltas[i].x);                       
                }
 
                pr_lvl= pr_lvl->next;
@@ -1504,34 +1443,51 @@ void multires_update_levels(Mesh *me, const int render)
        if(pr_deltas) MEM_freeN(pr_deltas);
        if(cr_deltas) MEM_freeN(cr_deltas);
 
+}
+
+void multires_update_faces(Mesh *me, EditMesh *em)
+{
+       MultiresLevel *cr_lvl= current_level(me->mr), *pr_lvl= NULL,
+                     *last_lvl= me->mr->levels.last;
+       char *pr_flag_damaged= NULL, *cr_flag_damaged= NULL, *or_flag_damaged= NULL,
+            *pr_mat_damaged= NULL, *cr_mat_damaged= NULL, *or_mat_damaged= NULL, *swap= NULL;
+       EditFace *efa= NULL;
+       unsigned i,j,curf;
+
+       /* Find for each face whether flag/mat has changed */
+       pr_flag_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "flag_damaged 1");
+       cr_flag_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "flag_damaged 1");
+       pr_mat_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "mat_damaged 1");
+       cr_mat_damaged= MEM_callocN(sizeof(char) * last_lvl->totface, "mat_damaged 1");
+       if(em) efa= em->faces.first;
+       for(i=0; i<cr_lvl->totface; ++i) {
+               MultiresFace mftmp;
+               multires_get_face(&mftmp, efa, &me->mface[i]);
+               if(cr_lvl->faces[i].flag != mftmp.flag)
+                       cr_flag_damaged[i]= 1;
+               if(cr_lvl->faces[i].mat_nr != mftmp.mat_nr)
+                       cr_mat_damaged[i]= 1;
+
+               /* Update current level */
+               cr_lvl->faces[i].flag= mftmp.flag;
+               cr_lvl->faces[i].mat_nr= mftmp.mat_nr;
+
+               if(em) efa= efa->next;
+       }
+       or_flag_damaged= MEM_dupallocN(cr_flag_damaged);
+       or_mat_damaged= MEM_dupallocN(cr_mat_damaged);
+
        /* Update lower levels */
-       cr_lvl= me->mr->levels.last;
        cr_lvl= cr_lvl->prev;
-       /* Update Verts */
-       while(cr_lvl) {
-               for(i=0; i<cr_lvl->totvert; ++i)
-                       cr_lvl->verts[i]= cr_lvl->next->verts[i];
-               cr_lvl= cr_lvl->prev;
-       }
-       
-       /* Update Faces */
-       
-       /* Clear to original damages */
-       if(cr_flag_damaged) MEM_freeN(cr_flag_damaged);
-       if(cr_mat_damaged) MEM_freeN(cr_mat_damaged);
-       cr_flag_damaged= or_flag_damaged;
-       cr_mat_damaged= or_mat_damaged;
-       
-       cr_lvl= or_lvl->prev;
        while(cr_lvl) {
-               if(pr_flag_damaged) MEM_freeN(pr_flag_damaged);
+               swap= pr_flag_damaged;
                pr_flag_damaged= cr_flag_damaged;
-               cr_flag_damaged= MEM_callocN(sizeof(char)*cr_lvl->totface,"flag_damaged 3");
-               if(pr_mat_damaged) MEM_freeN(pr_mat_damaged);
+               cr_flag_damaged= swap;
+
+               swap= pr_mat_damaged;
                pr_mat_damaged= cr_mat_damaged;
-               cr_mat_damaged= MEM_callocN(sizeof(char)*cr_lvl->totface,"mat_damaged 3");
+               cr_mat_damaged= swap;
 
-               /* Update faces */
                curf= 0;
                for(i=0; i<cr_lvl->totface; ++i) {
                        const int sides= cr_lvl->faces[i].v[3] ? 4 : 3;
@@ -1551,14 +1507,58 @@ void multires_update_levels(Mesh *me, const int render)
 
                cr_lvl= cr_lvl->prev;
        }
+       
+       /* Clear to original damages */
+       if(cr_flag_damaged) MEM_freeN(cr_flag_damaged);
+       if(cr_mat_damaged) MEM_freeN(cr_mat_damaged);
+       cr_flag_damaged= or_flag_damaged;
+       cr_mat_damaged= or_mat_damaged;
+       
+       /* Update higher levels */
+       pr_lvl= current_level(me->mr);
+       cr_lvl= pr_lvl->next;
+       while(cr_lvl) {
+               swap= pr_flag_damaged;
+               pr_flag_damaged= cr_flag_damaged;
+               cr_flag_damaged= swap;
+
+               swap= pr_mat_damaged;
+               pr_mat_damaged= cr_mat_damaged;
+               cr_mat_damaged= swap;
+
+               /* Update faces */
+               for(i=0, curf= 0; i<pr_lvl->totface; ++i) {
+                       const int sides= cr_lvl->prev->faces[i].v[3] ? 4 : 3;
+                       for(j=0; j<sides; ++j, ++curf) {
+                               if(pr_flag_damaged[i]) {
+                                       cr_lvl->faces[curf].flag= pr_lvl->faces[i].flag;
+                                       cr_flag_damaged[curf]= 1;
+                               }
+                               if(pr_mat_damaged[i]) {
+                                       cr_lvl->faces[curf].mat_nr= pr_lvl->faces[i].mat_nr;
+                                       cr_mat_damaged[curf]= 1;
+                               }
+                       }
+               }
+
+               pr_lvl= pr_lvl->next;
+               cr_lvl= cr_lvl->next;
+       }
 
        if(pr_flag_damaged) MEM_freeN(pr_flag_damaged);
        if(cr_flag_damaged) MEM_freeN(cr_flag_damaged);
        if(pr_mat_damaged) MEM_freeN(pr_mat_damaged);
        if(cr_mat_damaged) MEM_freeN(cr_mat_damaged);
+}
 
-       multires_update_colors(me);
+void multires_update_levels(Mesh *me, const int render)
+{
+       EditMesh *em= (!render && G.obedit) ? G.editMesh : NULL;
 
+       multires_update_first_level(me, em);
+       multires_update_vertices(me, em);
+       multires_update_faces(me, em);
+       multires_update_colors(me);
 }
 
 void multires_calc_level_maps(MultiresLevel *lvl)