fix [#36291] Applying subsurf to mesh or setting subdivisions to zero crashes Blender
authorCampbell Barton <ideasman42@gmail.com>
Mon, 16 Sep 2013 06:00:25 +0000 (06:00 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Mon, 16 Sep 2013 06:00:25 +0000 (06:00 +0000)
issue was mesh somehow had a mismatch of UV/texpoly layers. we may want to allow this in the future but for now sync on load just in case.

source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/intern/mesh_validate.c
source/blender/blenloader/intern/readfile.c

index aac91abc449e5f45690011f34acf4f6fb9ff6a3c..8b514c04a1f9c781081ccc19684770e2fad1ec64 100644 (file)
@@ -354,6 +354,7 @@ void BKE_mesh_calc_relative_deform(
 /* *** mesh_validate.c *** */
 
 int BKE_mesh_validate(struct Mesh *me, const int do_verbose);
+void BKE_mesh_cd_validate(struct Mesh *me);
 
 bool BKE_mesh_validate_arrays(
         struct Mesh *me,
index 6ec14add8a9c032ebb0fbfa8ef3c9fc3dc6c3be7..557d201e7fdafd9cc1c1360751236ca4ed903276 100644 (file)
@@ -922,6 +922,7 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata,
 {
        bool is_valid = true;
        bool is_change_v, is_change_e, is_change_l, is_change_p;
+       int tot_texpoly, tot_uvloop;
        CustomDataMask mask = check_meshmask ? CD_MASK_MESH : 0;
 
        is_valid &= mesh_validate_customdata(vdata, mask, do_verbose, do_fixes, &is_change_v);
@@ -929,6 +930,13 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata,
        is_valid &= mesh_validate_customdata(ldata, mask, do_verbose, do_fixes, &is_change_l);
        is_valid &= mesh_validate_customdata(pdata, mask, do_verbose, do_fixes, &is_change_p);
 
+       tot_texpoly = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
+       tot_uvloop = CustomData_number_of_layers(ldata, CD_MLOOPUV);
+       if (tot_texpoly != tot_uvloop) {
+               PRINT_ERR("\tCustomDataLayer mismatch, tot_texpoly(%d), tot_uvloop(%d)\n",
+                         tot_texpoly, tot_uvloop);
+       }
+
        *r_change = (is_change_v || is_change_e || is_change_l || is_change_p);
 
        return is_valid;
@@ -973,6 +981,37 @@ int BKE_mesh_validate(Mesh *me, const int do_verbose)
                return false;
        }
 }
+
+/**
+ * Duplicate of BM_mesh_cd_validate() for Mesh data.
+ */
+void BKE_mesh_cd_validate(Mesh *me)
+{
+       int totlayer_mtex = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
+       int totlayer_uv = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
+
+       if (LIKELY(totlayer_mtex == totlayer_uv)) {
+               /* pass */
+       }
+       else if (totlayer_mtex < totlayer_uv) {
+               const int uv_index_first = CustomData_get_layer_index(&me->ldata, CD_MLOOPUV);
+               do {
+                       const char *from_name =  me->ldata.layers[uv_index_first + totlayer_mtex].name;
+                       CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, from_name);
+                       CustomData_set_layer_unique_name(&me->pdata, totlayer_mtex);
+               } while (totlayer_uv != ++totlayer_mtex);
+       }
+       else if (totlayer_uv < totlayer_mtex) {
+               const int mtex_index_first = CustomData_get_layer_index(&me->pdata, CD_MTEXPOLY);
+               do {
+                       const char *from_name = me->pdata.layers[mtex_index_first + totlayer_uv].name;
+                       CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, from_name);
+                       CustomData_set_layer_unique_name(&me->ldata, totlayer_uv);
+               } while (totlayer_mtex != ++totlayer_uv);
+       }
+
+       BLI_assert(totlayer_mtex == totlayer_uv);
+}
 /** \} */
 
 
index bcbc4c2638b2e2eabc16ebe7af257286fd1ba38e..193177bb33d0081758de2251585902ace11b7c3b 100644 (file)
@@ -4149,6 +4149,12 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
        direct_link_customdata(fd, &mesh->ldata, mesh->totloop);
        direct_link_customdata(fd, &mesh->pdata, mesh->totpoly);
        
+       if (mesh->mloopuv || mesh->mtpoly) {
+               /* for now we have to ensure texpoly and mloopuv layers are aligned
+                * in the future we may allow non-aligned layers */
+               BKE_mesh_cd_validate(mesh);
+       }
+
        mesh->bb = NULL;
        mesh->edit_btmesh = NULL;