diff options
-rw-r--r-- | source/blender/blenkernel/BKE_bad_level_calls.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/bad_level_call_stubs/stubs.c | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 92 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh.c | 22 | ||||
-rw-r--r-- | source/blender/include/multires.h | 2 | ||||
-rw-r--r-- | source/blender/render/intern/source/convertblender.c | 20 | ||||
-rw-r--r-- | source/blender/src/multires.c | 30 |
7 files changed, 126 insertions, 42 deletions
diff --git a/source/blender/blenkernel/BKE_bad_level_calls.h b/source/blender/blenkernel/BKE_bad_level_calls.h index 90ae0c10766..5c71fb6cf31 100644 --- a/source/blender/blenkernel/BKE_bad_level_calls.h +++ b/source/blender/blenkernel/BKE_bad_level_calls.h @@ -199,6 +199,7 @@ void post_server_add(void); /* multires.c */ struct Multires; struct MultiresLevel; +struct MultiresLevel *multires_level_n(struct Multires *mr, int n); void multires_free(struct Multires *mr); void multires_set_level(void *ob, void *me_v); void multires_calc_level_maps(struct MultiresLevel *lvl); diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c index 63b904c57cc..fc01086a48c 100644 --- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c +++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c @@ -292,6 +292,7 @@ void post_layer_create(struct VLayer *vlayer) {} void post_layer_destroy(struct VLayer *vlayer) {} void post_server_add(void) {} /* Multires/sculpt stubs */ +struct MultiresLevel *multires_level_n(struct Multires *mr, int n) {return NULL;} void multires_free(struct Multires *mr) {} void multires_set_level(void *ob, void *me_v) {} void multires_calc_level_maps(struct MultiresLevel *lvl) {} diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index b6ba816698b..62c1a5f613f 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2213,31 +2213,80 @@ DerivedMesh *mesh_get_derived_deform(Object *ob, CustomDataMask dataMask) return ob->derivedDeform; } -DerivedMesh *mesh_create_derived_render(Object *ob, CustomDataMask dataMask) +/* Move to multires Pin level, returns a copy of the original vertex coords. */ +float *multires_render_pin(Object *ob, Mesh *me, int *orig_lvl) { - DerivedMesh *final; - Mesh *m= get_mesh(ob); + float *vert_copy= NULL; - /* Goto the pin level for multires */ - if(m->mr) { - m->mr->newlvl= m->mr->pinlvl; - multires_set_level(ob,m); + if(me->mr) { + MultiresLevel *lvl= NULL; + int i; + + /* Copy the highest level of multires verts */ + *orig_lvl= me->mr->current; + 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); + + /* Goto the pin level for multires */ + me->mr->newlvl= me->mr->pinlvl; + multires_set_level(ob, me); } + + return vert_copy; +} - mesh_calc_modifiers(ob, NULL, NULL, &final, 1, 1, 0, dataMask); +/* Propagate the changes to render level - fails if mesh topology changed */ +void multires_render_final(Object *ob, Mesh *me, DerivedMesh **dm, float *vert_copy, const int orig_lvl) +{ + if(me->mr) { + if((*dm)->getNumVerts(*dm) == me->totvert && + (*dm)->getNumFaces(*dm) == me->totface) { + MultiresLevel *lvl= multires_level_n(me->mr, BLI_countlist(&me->mr->levels)); + DerivedMesh *old= NULL; + int i; - /* Propagate the changes to render level - fails if mesh topology changed */ - if(m->mr) { - if(final->getNumVerts(final) == m->totvert && - final->getNumFaces(final) == m->totface) { - final->copyVertArray(final, m->mvert); - final->release(final); - - m->mr->newlvl= m->mr->renderlvl; - multires_set_level(ob,m); - final= getMeshDerivedMesh(m,ob,NULL); + (*dm)->copyVertArray(*dm, me->mvert); + (*dm)->release(*dm); + + me->mr->newlvl= me->mr->renderlvl; + multires_set_level(ob, me); + (*dm)= getMeshDerivedMesh(me, ob, NULL); + + /* Some of the data in dm is referenced externally, so make a copy */ + old= *dm; + (*dm)= CDDM_copy(old); + old->release(old); + + /* Restore the original verts */ + me->mr->newlvl= BLI_countlist(&me->mr->levels); + multires_set_level(ob, me); + for(i=0; i<lvl->totvert; ++i) + VecCopyf(me->mvert[i].co, &vert_copy[i*3]); } + + if(vert_copy) + MEM_freeN(vert_copy); + + me->mr->newlvl= orig_lvl; + multires_set_level(ob, me); } +} + +/* Multires note - if mesh has multires enabled, mesh is first set to the Pin level, + where all modifiers are applied, then if the topology hasn't changed, the changes + from modifiers are propagated up to the Render level. */ +DerivedMesh *mesh_create_derived_render(Object *ob, CustomDataMask dataMask) +{ + DerivedMesh *final; + Mesh *me= get_mesh(ob); + float *vert_copy= NULL; + int orig_lvl= 0; + + vert_copy= multires_render_pin(ob, me, &orig_lvl); + mesh_calc_modifiers(ob, NULL, NULL, &final, 1, 1, 0, dataMask); + multires_render_final(ob, me, &final, vert_copy, orig_lvl); return final; } @@ -2255,7 +2304,7 @@ DerivedMesh *mesh_create_derived_no_deform(Object *ob, float (*vertCos)[3], CustomDataMask dataMask) { DerivedMesh *final; - + mesh_calc_modifiers(ob, vertCos, NULL, &final, 0, 0, 0, dataMask); return final; @@ -2266,8 +2315,13 @@ DerivedMesh *mesh_create_derived_no_deform_render(Object *ob, CustomDataMask dataMask) { DerivedMesh *final; + Mesh *me= get_mesh(ob); + float *vert_copy= NULL; + int orig_lvl= 0; + vert_copy= multires_render_pin(ob, me, &orig_lvl); mesh_calc_modifiers(ob, vertCos, NULL, &final, 1, 0, 0, dataMask); + multires_render_final(ob, me, &final, vert_copy, orig_lvl); return final; } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index cfdb79c2257..9f9e39cbd8a 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -481,11 +481,13 @@ static float *make_orco_mesh_internal(Object *ob, int render) int a, totvert; float loc[3], size[3]; DerivedMesh *dm; - float (*vcos)[3] = MEM_callocN(sizeof(*vcos)*me->totvert, "orco mesh"); + float (*vcos)[3] = NULL; /* Get appropriate vertex coordinates */ if(me->key && me->texcomesh==0 && me->key->refkey) { + vcos = MEM_callocN(sizeof(*vcos)*me->totvert, "orco mesh"); + KeyBlock *kb= me->key->refkey; float *fp= kb->data; totvert= MIN2(kb->totelem, me->totvert); @@ -497,9 +499,21 @@ static float *make_orco_mesh_internal(Object *ob, int render) } } else { - Mesh *tme = me->texcomesh?me->texcomesh:me; - MVert *mvert = tme->mvert; - totvert = MIN2(tme->totvert, me->totvert); + MultiresLevel *lvl = NULL; + MVert *mvert = NULL; + + 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; + totvert = lvl->totvert; + } + else { + vcos = MEM_callocN(sizeof(*vcos)*me->totvert, "orco mesh"); + Mesh *tme = me->texcomesh?me->texcomesh:me; + mvert = tme->mvert; + totvert = MIN2(tme->totvert, me->totvert); + } for(a=0; a<totvert; a++, mvert++) { vcos[a][0]= mvert->co[0]; diff --git a/source/blender/include/multires.h b/source/blender/include/multires.h index cf96ea58869..48a5b4554a9 100644 --- a/source/blender/include/multires.h +++ b/source/blender/include/multires.h @@ -42,6 +42,8 @@ struct uiBlock; int multires_test(); int multires_level1_test(); +struct MultiresLevel *multires_level_n(struct Multires *mr, int n); + void multires_draw_interface(struct uiBlock *block, unsigned short cx, unsigned short cy); void multires_disp_map(void *, void*); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 21cada785a7..d98d570803d 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -1766,7 +1766,7 @@ static void use_mesh_edge_lookup(Render *re, DerivedMesh *dm, MEdge *medge, Vlak static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts) { - Mesh *me, *me_store= NULL; + Mesh *me; MVert *mvert = NULL; MFace *mface; VlakRen *vlr; //, *vlr1; @@ -1834,23 +1834,8 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts if(!only_verts) if(need_orco) orco = get_object_orco(re, ob); - /* If multires is enabled, a copy is made of the mesh - to allow multires to be applied with modifiers. */ - if(me->mr) { - me_store= me; - me= copy_mesh(me); - ob->data= me; - } - dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL); - - /* (Multires) Now switch the meshes back around */ - if(me->mr) { - ob->data= me_store; - me_store= me; - me= ob->data; - } if(dm==NULL) return; /* in case duplicated object fails? */ @@ -2087,9 +2072,6 @@ static void init_render_mesh(Render *re, Object *ob, Object *par, int only_verts } dm->release(dm); - if(me_store) { - free_libblock(&G.main->mesh, &me_store->id); - } } /* ------------------------------------------------------------------------- */ diff --git a/source/blender/src/multires.c b/source/blender/src/multires.c index acf53e08ccd..554cdf3e9e8 100644 --- a/source/blender/src/multires.c +++ b/source/blender/src/multires.c @@ -124,6 +124,14 @@ MultiresLevel *current_level(Multires *mr) return BLI_findlink(&mr->levels, mr->current - 1); } +MultiresLevel *multires_level_n(Multires *mr, int n) +{ + if(mr) + return BLI_findlink(&mr->levels, n - 1); + else + return NULL; +} + void Vec3fAvg3(float *out, float *v1, float *v2, float *v3) { out[0]= (v1[0]+v2[0]+v3[0])/3; @@ -693,6 +701,24 @@ void multires_free_level(MultiresLevel *lvl) } } +/* Make sure that all level indices are clipped to [1, mr->level_count] */ +void multires_clip_levels(Multires *mr) +{ + if(mr) { + const int cnt = mr->level_count; + + if(mr->current < 1) mr->current = 1; + if(mr->edgelvl < 1) mr->edgelvl = 1; + if(mr->pinlvl < 1) mr->pinlvl = 1; + if(mr->renderlvl < 1) mr->renderlvl = 1; + + if(mr->current > cnt) mr->current = cnt; + if(mr->edgelvl > cnt) mr->edgelvl = cnt; + if(mr->pinlvl > cnt) mr->pinlvl = cnt; + if(mr->renderlvl > cnt) mr->renderlvl = cnt; + } +} + /* 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) @@ -730,6 +756,8 @@ void multires_del_lower(void *ob, void *me) lvl= lvlprev; } mr->newlvl= mr->current; + + multires_clip_levels(mr); allqueue(REDRAWBUTSEDIT, 0); @@ -755,6 +783,8 @@ void multires_del_higher(void *ob, void *me) lvl= lvlnext; } + + multires_clip_levels(mr); allqueue(REDRAWBUTSEDIT, 0); |