Fix #34625: duplivert/face rendering with modifier could crash accessing UV and
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 3 Apr 2013 20:10:08 +0000 (20:10 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 3 Apr 2013 20:10:08 +0000 (20:10 +0000)
generated coordinates on the original mesh, after the change that made duplis
take modifiers into account.

source/blender/blenkernel/BKE_DerivedMesh.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/anim.c

index 0c988ac45fc4e1b15b75ff4603ec00666b937791..2cb9d42b479a27c5ed3bdf69fe4e310b387693bc 100644 (file)
@@ -247,6 +247,7 @@ struct DerivedMesh {
        void *(*getVertDataArray)(DerivedMesh *dm, int type);
        void *(*getEdgeDataArray)(DerivedMesh *dm, int type);
        void *(*getTessFaceDataArray)(DerivedMesh *dm, int type);
        void *(*getVertDataArray)(DerivedMesh *dm, int type);
        void *(*getEdgeDataArray)(DerivedMesh *dm, int type);
        void *(*getTessFaceDataArray)(DerivedMesh *dm, int type);
+       void *(*getLoopDataArray)(DerivedMesh *dm, int type);
        void *(*getPolyDataArray)(DerivedMesh *dm, int type);
 
        /** Retrieves the base CustomData structures for
        void *(*getPolyDataArray)(DerivedMesh *dm, int type);
 
        /** Retrieves the base CustomData structures for
index cc0770cd18614b2a180ec79beca790d1bee301b7..48b2a54c128f5a236add5a7b80272a8cf635acc4 100644 (file)
@@ -270,6 +270,7 @@ void DM_init_funcs(DerivedMesh *dm)
        dm->getEdgeDataArray = DM_get_edge_data_layer;
        dm->getTessFaceDataArray = DM_get_tessface_data_layer;
        dm->getPolyDataArray = DM_get_poly_data_layer;
        dm->getEdgeDataArray = DM_get_edge_data_layer;
        dm->getTessFaceDataArray = DM_get_tessface_data_layer;
        dm->getPolyDataArray = DM_get_poly_data_layer;
+       dm->getLoopDataArray = DM_get_loop_data_layer;
 
        bvhcache_init(&dm->bvhCache);
 }
 
        bvhcache_init(&dm->bvhCache);
 }
index 1855090375727f5be9248fdfa195b995c837c999..9c472ed64c61377ff462c62d3818e402fba18e5b 100644 (file)
@@ -953,6 +953,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
        float vec[3], no[3], pmat[4][4];
        int totvert, a, oblay;
        unsigned int lay;
        float vec[3], no[3], pmat[4][4];
        int totvert, a, oblay;
        unsigned int lay;
+       CustomDataMask dm_mask;
        
        copy_m4_m4(pmat, par->obmat);
        
        
        copy_m4_m4(pmat, par->obmat);
        
@@ -961,16 +962,18 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
        
        em = BMEdit_FromObject(par);
        
        
        em = BMEdit_FromObject(par);
        
-       if (em) {
-               dm = editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH);
-       }
+       /* get derived mesh */
+       dm_mask = CD_MASK_BAREMESH;
+       if (flag & DUPLILIST_FOR_RENDER)
+               dm_mask |= CD_MASK_ORCO;
+       
+       if (em)
+               dm = editbmesh_get_derived_cage(scene, par, em, dm_mask);
        else
        else
-               dm = mesh_get_derived_final(scene, par, CD_MASK_BAREMESH);
+               dm = mesh_get_derived_final(scene, par, dm_mask);
        
        
-       if (flag & DUPLILIST_FOR_RENDER) {
-               vdd.orco = (float(*)[3])BKE_mesh_orco_verts_get(par);
-               BKE_mesh_orco_verts_transform(me, vdd.orco, me->totvert, 0);
-       }
+       if (flag & DUPLILIST_FOR_RENDER)
+               vdd.orco = dm->getVertDataArray(dm, CD_ORCO);
        else
                vdd.orco = NULL;
        
        else
                vdd.orco = NULL;
        
@@ -1057,8 +1060,6 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
                else go = go->next;             /* group loop */
        }
 
                else go = go->next;             /* group loop */
        }
 
-       if (vdd.orco)
-               MEM_freeN(vdd.orco);
        dm->release(dm);
 }
 
        dm->release(dm);
 }
 
@@ -1069,7 +1070,6 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
        Base *base = NULL;
        DupliObject *dob;
        DerivedMesh *dm;
        Base *base = NULL;
        DupliObject *dob;
        DerivedMesh *dm;
-       Mesh *me = par->data;
        MLoopUV *mloopuv;
        MPoly *mpoly, *mp;
        MLoop *mloop;
        MLoopUV *mloopuv;
        MPoly *mpoly, *mp;
        MLoop *mloop;
@@ -1081,6 +1081,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
        GroupObject *go = NULL;
        BMEditMesh *em;
        float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */
        GroupObject *go = NULL;
        BMEditMesh *em;
        float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */
+       CustomDataMask dm_mask;
        
        /* simple preventing of too deep nested groups */
        if (level > MAX_DUPLI_RECUR) return;
        
        /* simple preventing of too deep nested groups */
        if (level > MAX_DUPLI_RECUR) return;
@@ -1088,11 +1089,16 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
        copy_m4_m4(pmat, par->obmat);
        em = BMEdit_FromObject(par);
 
        copy_m4_m4(pmat, par->obmat);
        em = BMEdit_FromObject(par);
 
+       /* get derived mesh */
+       dm_mask = CD_MASK_BAREMESH;
+       if (flag & DUPLILIST_FOR_RENDER)
+               dm_mask |= CD_MASK_ORCO|CD_MASK_MLOOPUV;
+
        if (em) {
        if (em) {
-               dm = editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH);
+               dm = editbmesh_get_derived_cage(scene, par, em, dm_mask);
        }
        else {
        }
        else {
-               dm = mesh_get_derived_final(scene, par, CD_MASK_BAREMESH);
+               dm = mesh_get_derived_final(scene, par, dm_mask);
        }
 
        totface = dm->getNumPolys(dm);
        }
 
        totface = dm->getNumPolys(dm);
@@ -1101,9 +1107,8 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
        mvert = dm->getVertArray(dm);
 
        if (flag & DUPLILIST_FOR_RENDER) {
        mvert = dm->getVertArray(dm);
 
        if (flag & DUPLILIST_FOR_RENDER) {
-               orco = (float(*)[3])BKE_mesh_orco_verts_get(par);
-               BKE_mesh_orco_verts_transform(me, orco, me->totvert, 0);
-               mloopuv = me->mloopuv;
+               orco = dm->getVertDataArray(dm, CD_ORCO);
+               mloopuv = dm->getLoopDataArray(dm, CD_MLOOPUV);
        }
        else {
                orco = NULL;
        }
        else {
                orco = NULL;
@@ -1215,7 +1220,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
                                                        if (mloopuv) {
                                                                int j;
                                                                for (j = 0; j < mpoly->totloop; j++) {
                                                        if (mloopuv) {
                                                                int j;
                                                                for (j = 0; j < mpoly->totloop; j++) {
-                                                                       madd_v2_v2fl(dob->orco, mloopuv[loopstart[j].v].uv, w);
+                                                                       madd_v2_v2fl(dob->uv, mloopuv[mp->loopstart + j].uv, w);
                                                                }
                                                        }
                                                }
                                                                }
                                                        }
                                                }
@@ -1238,9 +1243,6 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
                else go = go->next;             /* group loop */
        }
 
                else go = go->next;             /* group loop */
        }
 
-       if (orco)
-               MEM_freeN(orco);
-       
        dm->release(dm);
 }
 
        dm->release(dm);
 }