From 1a9f0e692acc3d5b2b9111e781d5e4a018c811d5 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Fri, 1 Jun 2007 02:21:11 +0000 Subject: == Multires == * 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 | 2 +- source/blender/blenkernel/intern/DerivedMesh.c | 2 +- source/blender/blenkernel/intern/mesh.c | 2 +- source/blender/blenloader/intern/readfile.c | 21 ++ source/blender/blenloader/intern/writefile.c | 6 +- source/blender/include/multires.h | 2 + source/blender/makesdna/DNA_meshdata_types.h | 6 +- source/blender/src/multires-firstlevel.c | 37 +++ source/blender/src/multires.c | 368 ++++++++++++------------- 9 files changed, 257 insertions(+), 189 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index bf3e25b1c5a..4b9e10651cf 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -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 diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index dc54fc7c1f0..5f8e9c7b207 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -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; itotvert; ++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; diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 278d49e2198..4c6bfda1517 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -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 { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 118c2779ac0..4bbcfab74ae 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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! */ diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 0d4d9d82ee1..226561ab97b 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -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 */ diff --git a/source/blender/include/multires.h b/source/blender/include/multires.h index 6c33af2d5e3..069dbee802f 100644 --- a/source/blender/include/multires.h +++ b/source/blender/include/multires.h @@ -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, diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 4d78f577137..af9c1ae629d 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -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; diff --git a/source/blender/src/multires-firstlevel.c b/source/blender/src/multires-firstlevel.c index db39a429c22..2be867b5db0 100644 --- a/source/blender/src/multires-firstlevel.c +++ b/source/blender/src/multires-firstlevel.c @@ -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; itotedge; ++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 */ diff --git a/source/blender/src/multires.c b/source/blender/src/multires.c index a249b6b408b..33b85bd27b6 100644 --- a/source/blender/src/multires.c +++ b/source/blender/src/multires.c @@ -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; itotvert; ++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; iprev->totvert; ++i) - lvl->verts[i]= lvl->prev->verts[i]; + me->mr->verts[i]= oldverts[i]; /* Create new edge verts */ for(i=0; iprev->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; iprev->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; iprev->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; iprev->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; itotvert; ++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; itotedge; ++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; itotedge; ++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; itotedge; ++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; itotvert; ++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; itotface; ++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; itotvert; ++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; itotface; ++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; itotvert; ++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; itotface; ++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; itotedge; ++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; itotedge; ++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; itotvert; ++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; itotvert; ++i) { - VecAddf(cr_lvl->verts[i].co, - cr_lvl->verts[i].co, - &cr_deltas[i].x); } - /* Update faces */ - curf= 0; - for(i=0; itotface; ++i) { - const int sides= cr_lvl->prev->faces[i].v[3] ? 4 : 3; - for(j=0; jfaces[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; itotface; ++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; itotvert; ++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; itotface; ++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; itotface; ++i) { + const int sides= cr_lvl->prev->faces[i].v[3] ? 4 : 3; + for(j=0; jfaces[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) -- cgit v1.2.3