= Multires =
authorNicholas Bishop <nicholasbishop@gmail.com>
Sun, 21 Jan 2007 23:46:00 +0000 (23:46 +0000)
committerNicholas Bishop <nicholasbishop@gmail.com>
Sun, 21 Jan 2007 23:46:00 +0000 (23:46 +0000)
Fixed bug #5756, Rendering artifacts when MRM is not set to maximum

Several changes were made:
* Added function multires_level_n to get the nth level from a multires mesh
* Removed the changes I made some time ago to init_render_mesh for multires meshes. Previously it was making a full copy of the mesh object in order to be able to apply deformations to the Pin level and propagate them to the Render level.
* Added two functions to DerivedMesh.c, multires_render_pin and multires_render_final. These two functions work together in the mesh_create_derived_*_render functions to apply all modifiers to the Pin level, then create the DerivedMesh from the Render level, and lastly restore the mesh to its original (undeformed) state.
* Added a check in multires_del_lower and multires_del_higher to ensure that level indices are properly clipped to the actual range of available levels.

source/blender/blenkernel/BKE_bad_level_calls.h
source/blender/blenkernel/bad_level_call_stubs/stubs.c
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/mesh.c
source/blender/include/multires.h
source/blender/render/intern/source/convertblender.c
source/blender/src/multires.c

index 90ae0c107663cbbc26de5e28387bb3ffc977fd14..5c71fb6cf312cbabb12a1dcf1bead4323f460ca9 100644 (file)
@@ -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);
index 63b904c57cc1fc33c7c9ab9dd2f0cbfd66f5dff9..fc01086a48cce1a822ed2941918bb0dfb6d77080 100644 (file)
@@ -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) {}
index b6ba816698b284ec1fb6eb71ef9f50c6906eb59b..62c1a5f613f849115f0ca0d7f578329d637320cf 100644 (file)
@@ -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;
 }
index cfdb79c2257fd08d271a091599fbaf1a716ce777..9f9e39cbd8a8b7279446e5d222912fd1b4b3d95d 100644 (file)
@@ -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];
index cf96ea588693a5843bfd66e05da9cffd0353a343..48a5b4554a93ad483f1d2e3c2762b487489c26aa 100644 (file)
@@ -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*);
 
index 21cada785a797c188ba35ed412e073ea1eddca70..d98d570803dd4dc74b854fea2f1cf0e2437d289e 100644 (file)
@@ -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);
-       }
 }
 
 /* ------------------------------------------------------------------------- */
index acf53e08ccdf6189fe05cd4d645b9b4680980aac..554cdf3e9e82bf19b556af5eea528ab9db74bb5a 100644 (file)
@@ -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);