diff options
author | Nicholas Bishop <nicholasbishop@gmail.com> | 2007-01-09 08:22:48 +0300 |
---|---|---|
committer | Nicholas Bishop <nicholasbishop@gmail.com> | 2007-01-09 08:22:48 +0300 |
commit | fae8716c54fee52f413d9dc89d6d03729d296ee8 (patch) | |
tree | 80ff2e2aa7044bd49dce0bb0b726fa6524a39c2c /source/blender/src/multires.c | |
parent | cc359a6fd5049a995b2b3145c3ed6580f4dc02a0 (diff) |
Bugfix for multires: when deleting lower levels, special first-level data must be subdivided up to the level of the new lowest level. This wasn't being done for dverts. In fixing this, I also reorganized the code for subdividing multires dverts, much cleaner now.
Diffstat (limited to 'source/blender/src/multires.c')
-rw-r--r-- | source/blender/src/multires.c | 135 |
1 files changed, 79 insertions, 56 deletions
diff --git a/source/blender/src/multires.c b/source/blender/src/multires.c index 06057912014..f9ff3c7065c 100644 --- a/source/blender/src/multires.c +++ b/source/blender/src/multires.c @@ -454,6 +454,57 @@ void multires_add_dvert(MDeformVert *out, const MDeformVert *in, const float w) } } +/* Takes an input array of dverts and subdivides them (linear) using the topology of lvl */ +MDeformVert *subdivide_dverts(MDeformVert *src, MultiresLevel *lvl) +{ + if(lvl && lvl->prev) { + MDeformVert *out = MEM_callocN(sizeof(MDeformVert)*lvl->totvert, "dvert prop array"); + int i, j; + + /* Copy lower level */ + for(i=0; i<lvl->prev->totvert; ++i) + multires_add_dvert(&out[i], &src[i], 1); + /* Edge verts */ + for(i=0; i<lvl->prev->totedge; ++i) { + for(j=0; j<2; ++j) + multires_add_dvert(&out[lvl->prev->totvert+i], &src[lvl->prev->edges[i].v[j]],0.5); + } + + /* Face verts */ + for(i=0; i<lvl->prev->totface; ++i) { + for(j=0; j<(lvl->prev->faces[i].v[3]?4:3); ++j) + multires_add_dvert(&out[lvl->prev->totvert + lvl->prev->totedge + i], + &src[lvl->prev->faces[i].v[j]], + lvl->prev->faces[i].v[3]?0.25:(1.0f/3.0f)); + } + + return out; + } + + return NULL; +} + +/* Uses subdivide_dverts to subdivide src to match lvl_end. Does not free src. */ +MDeformVert *subdivide_dverts_to_level(MDeformVert *src, MultiresLevel *lvl_start, MultiresLevel *lvl_end) +{ + MultiresLevel *lvl; + MDeformVert *cr_dverts= NULL, *pr_dverts= NULL; + + pr_dverts= src; + for(lvl= lvl_start->next; lvl && lvl != lvl_end->next; lvl= lvl->next) { + cr_dverts= subdivide_dverts(pr_dverts, lvl); + + /* Free previous dvert subdivision level */ + if(lvl->prev != lvl_start) + free_dverts(pr_dverts, lvl->prev->totvert); + + pr_dverts= cr_dverts; + cr_dverts= NULL; + } + + return pr_dverts; +} + void multires_load_cols(Mesh *me) { MultiresLevel *lvl= BLI_findlink(&me->mr->levels,me->mr->current-1), *cur; @@ -787,25 +838,38 @@ void multires_free_level(MultiresLevel *lvl) } } +/* Delete all multires levels beneath current level. Subdivide special + first-level data up to the new lowest level. */ void multires_del_lower(void *ob, void *me) { Multires *mr= ((Mesh*)me)->mr; - MultiresLevel *lvl= mr->levels.first; - MultiresLevel *lvlprev; + MultiresLevel *lvl1= mr->levels.first, *cr_lvl= current_level(mr); + MultiresLevel *lvl= NULL, *lvlprev= NULL; short *edgeflags= NULL; + MDeformVert *dverts= NULL; int i, last; + if(cr_lvl == lvl1) return; + multires_check_state(); /* Subdivide the edge flags to the current level */ edgeflags= MEM_callocN(sizeof(short)*current_level(mr)->totedge, "Multires Edge Flags"); - last= lvl->totedge * pow(2, mr->current-1); + last= lvl1->totedge * pow(2, mr->current-1); for(i=0; i<last; ++i) edgeflags[i] = mr->edge_flags[(int)(i / pow(2, mr->current-1))]; MEM_freeN(mr->edge_flags); mr->edge_flags= edgeflags; - lvl= current_level(mr)->prev; + /* Subdivide the dverts to the current level */ + dverts= subdivide_dverts_to_level(CustomData_get(&mr->vdata, 0, CD_MDEFORMVERT), + mr->levels.first, cr_lvl); + if(dverts) { + CustomData_free_layers(&mr->vdata, CD_MDEFORMVERT, lvl1->totvert); + CustomData_add_layer(&mr->vdata, CD_MDEFORMVERT, CD_ASSIGN, dverts, cr_lvl->totvert); + } + + lvl= cr_lvl->prev; while(lvl) { lvlprev= lvl->prev; @@ -1206,63 +1270,22 @@ void multires_level_to_mesh(Object *ob, Mesh *me) CustomData_get(&me->mr->vdata, i, CD_MDEFORMVERT)); } else { CustomData_merge(&me->mr->vdata, &me->vdata, vdata_mask, CD_DUPLICATE, lvl->totvert); - CustomData_get(&me->mr->vdata, 0, CD_MDEFORMVERT); } } else if(CustomData_has_layer(&me->mr->vdata, CD_MDEFORMVERT)) { - MultiresLevel *dlvl, *lvl1= me->mr->levels.first; - MDeformVert **lvl_dverts; - MDeformVert *source; - int dlvl_ndx= 0; - int j; - - lvl_dverts= MEM_callocN(sizeof(MDeformVert*) * (me->mr->current-1), "dvert prop array"); + MDeformVert *dverts= subdivide_dverts_to_level(CustomData_get(&me->mr->vdata, 0, CD_MDEFORMVERT), + me->mr->levels.first, lvl); - /* dverts are not (yet?) propagated with catmull-clark */ - for(dlvl= lvl1->next; dlvl && dlvl != lvl->next; dlvl= dlvl->next) { - lvl_dverts[dlvl_ndx]= MEM_callocN(sizeof(MDeformVert)*dlvl->totvert, "dvert prop data"); - - if(dlvl->prev==lvl1) - source= CustomData_get(&me->mr->vdata, 0, CD_MDEFORMVERT); - else - source= lvl_dverts[dlvl_ndx-1]; - - /* Copy lower level */ - for(i=0; i<dlvl->prev->totvert; ++i) - multires_add_dvert(&lvl_dverts[dlvl_ndx][i], - &source[i], 1); - /* Edge verts */ - for(i=0; i<dlvl->prev->totedge; ++i) { - multires_add_dvert(&lvl_dverts[dlvl_ndx][dlvl->prev->totvert+i], - &source[dlvl->prev->edges[i].v[0]],0.5); - multires_add_dvert(&lvl_dverts[dlvl_ndx][dlvl->prev->totvert+i], - &source[dlvl->prev->edges[i].v[1]],0.5); - } - /* Face verts */ - for(i=0; i<dlvl->prev->totface; ++i) { - for(j=0; j<(dlvl->prev->faces[i].v[3]?4:3); ++j) - multires_add_dvert(&lvl_dverts[dlvl_ndx][dlvl->prev->totvert+dlvl->prev->totedge+i], - &source[dlvl->prev->faces[i].v[j]], - dlvl->prev->faces[i].v[3]?0.25:(1.0f/3.0f)); - } - - ++dlvl_ndx; + if(dverts) { + if(em) { + EM_add_data_layer(&em->vdata, CD_MDEFORMVERT); + for(i=0, eve= em->verts.first; eve; ++i, eve= eve->next) + CustomData_em_set(&em->vdata, eve->data, CD_MDEFORMVERT, &dverts[i]); + free_dverts(dverts, lvl->totvert); + } else + CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, + CD_ASSIGN, dverts, me->totvert); } - - dlvl= lvl1->next; - for(i=0; i<(dlvl_ndx-1); ++i, dlvl= dlvl->next) - free_dverts(lvl_dverts[i], dlvl->totvert); - - if(em) { - EM_add_data_layer(&em->vdata, CD_MDEFORMVERT); - for(i=0, eve= em->verts.first; eve; ++i, eve= eve->next) - CustomData_em_set(&em->vdata, eve->data, CD_MDEFORMVERT, &lvl_dverts[dlvl_ndx-1][i]); - free_dverts(lvl_dverts[dlvl_ndx-1], dlvl->totvert); - } else - me->dvert= CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, 0, - lvl_dverts[dlvl_ndx-1], me->totvert); - - MEM_freeN(lvl_dverts); } /* Colors and UVs */ |