Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Bishop <nicholasbishop@gmail.com>2007-01-09 08:22:48 +0300
committerNicholas Bishop <nicholasbishop@gmail.com>2007-01-09 08:22:48 +0300
commitfae8716c54fee52f413d9dc89d6d03729d296ee8 (patch)
tree80ff2e2aa7044bd49dce0bb0b726fa6524a39c2c /source/blender/src/multires.c
parentcc359a6fd5049a995b2b3145c3ed6580f4dc02a0 (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.c135
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 */