Fix a bug in CustomData_duplicate_referenced_layer(_named) functions: MEM_dupallocN...
authorBastien Montagne <montagne29@wanadoo.fr>
Mon, 19 Dec 2011 08:26:53 +0000 (08:26 +0000)
committerBastien Montagne <montagne29@wanadoo.fr>
Mon, 19 Dec 2011 08:26:53 +0000 (08:26 +0000)
source/blender/blenkernel/BKE_customdata.h
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/customdata.c
source/blender/modifiers/intern/MOD_solidify.c
source/blender/modifiers/intern/MOD_uvproject.c

index f6b4240a026a2972936794773c32a3f0eefd9ff6..1d344c6e81091e7a2daa88d63c26ce7a2bcfd24d 100644 (file)
@@ -121,9 +121,9 @@ int CustomData_number_of_layers(const struct CustomData *data, int type);
 
 /* duplicate data of a layer with flag NOFREE, and remove that flag.
  * returns the layer data */
-void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type);
+void *CustomData_duplicate_referenced_layer(struct CustomData *data, const int type, const int totelem);
 void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
-                                                                                                 int type, const char *name);
+                                                                                                 const int type, const char *name, const int totelem);
 
 /* set the CD_FLAG_NOCOPY flag in custom data layers where the mask is
  * zero for the layer type, so only layer types specified by the mask
index 2cf2225607ecceb512590d58879cbfe4fdc328bc..6f088b8abf75aaa93f3c5df08e85043792640319 100644 (file)
@@ -1870,7 +1870,7 @@ void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
        int i;
 
        /* this will just return the pointer if it wasn't a referenced layer */
-       vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
+       vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData);
        cddm->mvert = vert;
 
        for(i = 0; i < dm->numVertData; ++i, ++vert)
@@ -1884,7 +1884,7 @@ void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
        int i;
 
        /* this will just return the pointer if it wasn't a referenced layer */
-       vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
+       vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData);
        cddm->mvert = vert;
 
        for(i = 0; i < dm->numVertData; ++i, ++vert)
@@ -1899,7 +1899,7 @@ void CDDM_calc_normals(DerivedMesh *dm)
        if(dm->numVertData == 0) return;
 
        /* we don't want to overwrite any referenced layers */
-       cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
+       cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData);
 
        /* make a face normal layer if not present */
        face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
index c88b21e2813ebd4cff3785c3e92d307335f82323..5305372402b18b012b7a60f7ccd531ca1fb67b26 100644 (file)
@@ -1404,7 +1404,7 @@ int CustomData_number_of_layers(const CustomData *data, int type)
        return number;
 }
 
-void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type)
+void *CustomData_duplicate_referenced_layer(struct CustomData *data, const int type, const int totelem)
 {
        CustomDataLayer *layer;
        int layer_index;
@@ -1416,7 +1416,20 @@ void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type)
        layer = &data->layers[layer_index];
 
        if (layer->flag & CD_FLAG_NOFREE) {
-               layer->data = MEM_dupallocN(layer->data);
+               /* MEM_dupallocN won’t work in case of complex layers, like e.g.
+                * CD_MDEFORMVERT, which has pointers to allocated data...
+                * So in case a custom copy function is defined, use it!
+                */
+               const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
+
+               if(typeInfo->copy) {
+                       char *dest_data = MEM_mallocN(typeInfo->size * totelem, "CD duplicate ref layer");
+                       typeInfo->copy(layer->data, dest_data, totelem);
+                       layer->data = dest_data;
+               }
+               else
+                       layer->data = MEM_dupallocN(layer->data);
+
                layer->flag &= ~CD_FLAG_NOFREE;
        }
 
@@ -1424,7 +1437,7 @@ void *CustomData_duplicate_referenced_layer(struct CustomData *data, int type)
 }
 
 void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
-                                                                                                 int type, const char *name)
+                                                                                                 const int type, const char *name, const int totelem)
 {
        CustomDataLayer *layer;
        int layer_index;
@@ -1436,7 +1449,20 @@ void *CustomData_duplicate_referenced_layer_named(struct CustomData *data,
        layer = &data->layers[layer_index];
 
        if (layer->flag & CD_FLAG_NOFREE) {
-               layer->data = MEM_dupallocN(layer->data);
+               /* MEM_dupallocN won’t work in case of complex layers, like e.g.
+                * CD_MDEFORMVERT, which has pointers to allocated data...
+                * So in case a custom copy function is defined, use it!
+                */
+               const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
+
+               if(typeInfo->copy) {
+                       char *dest_data = MEM_mallocN(typeInfo->size * totelem, "CD duplicate ref layer");
+                       typeInfo->copy(layer->data, dest_data, totelem);
+                       layer->data = dest_data;
+               }
+               else
+                       layer->data = MEM_dupallocN(layer->data);
+
                layer->flag &= ~CD_FLAG_NOFREE;
        }
 
index 347af0066c6fdfdcda1fc90ebc0aea16a084325f..067d66fc82c1abb96a9c49c030b80d87f6e89eac 100644 (file)
@@ -75,8 +75,8 @@ static void dm_calc_normal(DerivedMesh *dm, float (*temp_nors)[3])
        /* we don't want to overwrite any referenced layers */
 
        /*
-       Dosnt work here!
-       mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT);
+       Doesn't work here!
+       mv = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, numVerts);
        cddm->mvert = mv;
        */
 
index acf65a565610c9c37bb791e080cbee772d4a219f..3146d1c9d5dd83e5a9ba53abd80932dc8cd464bb 100644 (file)
@@ -259,11 +259,12 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
                mul_mat3_m4_v3(projectors[i].ob->obmat, projectors[i].normal);
        }
 
+       numFaces = dm->getNumFaces(dm);
+
        /* make sure we are not modifying the original UV map */
        tface = CustomData_duplicate_referenced_layer_named(&dm->faceData,
-                       CD_MTFACE, uvname);
+                       CD_MTFACE, uvname, numFaces);
 
-       
        numVerts = dm->getNumVerts(dm);
 
        coords = MEM_callocN(sizeof(*coords) * numVerts,
@@ -280,7 +281,6 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
                        mul_project_m4_v3(projectors[0].projmat, *co);
 
        mface = dm->getFaceArray(dm);
-       numFaces = dm->getNumFaces(dm);
 
        /* apply coords as UVs, and apply image if tfaces are new */
        for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tface) {