svn merge ^/trunk/blender -r42564:42586
[blender.git] / source / blender / blenkernel / intern / DerivedMesh.c
index 1e09dc43f61058c3108b64797259b96d144153e7..8405a3922e6b285113db76321a7f265516ab67dc 100644 (file)
@@ -64,6 +64,7 @@
 #include "BKE_particle.h"
 #include "BKE_tessmesh.h"
 #include "BKE_bvhutils.h"
+#include "BKE_deform.h"
 
 #ifdef WITH_GAMEENGINE
 #include "BKE_navmesh_conversion.h"
@@ -115,7 +116,7 @@ static MEdge *dm_getEdgeArray(DerivedMesh *dm)
        return medge;
 }
 
-static MFace *dm_getFaceArray(DerivedMesh *dm)
+static MFace *dm_getTessFaceArray(DerivedMesh *dm)
 {
        MFace *mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
 
@@ -135,7 +136,7 @@ static MLoop *dm_getLoopArray(DerivedMesh *dm)
 
        if (!mloop) {
                mloop = CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL,
-                       dm->numLoopData);
+                       dm->getNumLoops(dm));
                CustomData_set_layer_flag(&dm->loopData, CD_MLOOP, CD_FLAG_TEMPORARY);
                dm->copyLoopArray(dm, mloop);
        }
@@ -149,7 +150,7 @@ static MPoly *dm_getPolyArray(DerivedMesh *dm)
 
        if (!mpoly) {
                mpoly = CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL,
-                       dm->getNumFaces(dm));
+                       dm->getNumPolys(dm));
                CustomData_set_layer_flag(&dm->polyData, CD_MPOLY, CD_FLAG_TEMPORARY);
                dm->copyPolyArray(dm, mpoly);
        }
@@ -189,7 +190,7 @@ static MFace *dm_dupFaceArray(DerivedMesh *dm)
 
 static MLoop *dm_dupLoopArray(DerivedMesh *dm)
 {
-       MLoop *tmp = MEM_callocN(sizeof(*tmp) * dm->numLoopData,
+       MLoop *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumLoops(dm),
                                                         "dm_dupLoopArray tmp");
 
        if(tmp) dm->copyLoopArray(dm, tmp);
@@ -199,7 +200,7 @@ static MLoop *dm_dupLoopArray(DerivedMesh *dm)
 
 static MPoly *dm_dupPolyArray(DerivedMesh *dm)
 {
-       MPoly *tmp = MEM_callocN(sizeof(*tmp) * dm->numFaceData,
+       MPoly *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumPolys(dm),
                                                         "dm_dupPolyArray tmp");
 
        if(tmp) dm->copyPolyArray(dm, tmp);
@@ -217,7 +218,7 @@ static CustomData *dm_getEdgeCData(DerivedMesh *dm)
        return &dm->edgeData;
 }
 
-static CustomData *dm_getFaceCData(DerivedMesh *dm)
+static CustomData *dm_getTessFaceCData(DerivedMesh *dm)
 {
        return &dm->faceData;
 }
@@ -237,7 +238,7 @@ void DM_init_funcs(DerivedMesh *dm)
        /* default function implementations */
        dm->getVertArray = dm_getVertArray;
        dm->getEdgeArray = dm_getEdgeArray;
-       dm->getTessFaceArray = dm_getFaceArray;
+       dm->getTessFaceArray = dm_getTessFaceArray;
        dm->getLoopArray = dm_getLoopArray;
        dm->getPolyArray = dm_getPolyArray;
        dm->dupVertArray = dm_dupVertArray;
@@ -248,13 +249,13 @@ void DM_init_funcs(DerivedMesh *dm)
 
        dm->getVertDataLayout = dm_getVertCData;
        dm->getEdgeDataLayout = dm_getEdgeCData;
-       dm->getTessFaceDataLayout = dm_getFaceCData;
+       dm->getTessFaceDataLayout = dm_getTessFaceCData;
        dm->getLoopDataLayout = dm_getLoopCData;
-       dm->getFaceDataLayout = dm_getPolyCData;
+       dm->getPolyDataLayout = dm_getPolyCData;
 
        dm->getVertData = DM_get_vert_data;
        dm->getEdgeData = DM_get_edge_data;
-       dm->getTessFaceData = DM_get_face_data;
+       dm->getTessFaceData = DM_get_tessface_data;
        dm->getVertDataArray = DM_get_vert_data_layer;
        dm->getEdgeDataArray = DM_get_edge_data_layer;
        dm->getTessFaceDataArray = DM_get_tessface_data_layer;
@@ -263,30 +264,31 @@ void DM_init_funcs(DerivedMesh *dm)
 }
 
 void DM_init(DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges,
-            int numFaces, int numLoops, int numPoly)
+            int numTessFaces, int numLoops, int numPolys)
 {
        dm->type = type;
        dm->numVertData = numVerts;
        dm->numEdgeData = numEdges;
-       dm->numFaceData = numFaces;
+       dm->numTessFaceData = numTessFaces;
        dm->numLoopData = numLoops;
-       dm->numPolyData = numPoly;
+       dm->numPolyData = numPolys;
 
        DM_init_funcs(dm);
        
        dm->needsFree = 1;
+       dm->auto_bump_scale = -1.0f;
 }
 
 void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type,
-                      int numVerts, int numEdges, int numFaces,
-                     int numLoops, int numPolys)
+                      int numVerts, int numEdges, int numTessFaces,
+                      int numLoops, int numPolys)
 {
        CustomData_copy(&source->vertData, &dm->vertData, CD_MASK_DERIVEDMESH,
                                        CD_CALLOC, numVerts);
        CustomData_copy(&source->edgeData, &dm->edgeData, CD_MASK_DERIVEDMESH,
                                        CD_CALLOC, numEdges);
        CustomData_copy(&source->faceData, &dm->faceData, CD_MASK_DERIVEDMESH,
-                                       CD_CALLOC, numFaces);
+                                       CD_CALLOC, numTessFaces);
        CustomData_copy(&source->loopData, &dm->loopData, CD_MASK_DERIVEDMESH,
                        CD_CALLOC, numLoops);
        CustomData_copy(&source->polyData, &dm->polyData, CD_MASK_DERIVEDMESH,
@@ -295,7 +297,7 @@ void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type
        dm->type = type;
        dm->numVertData = numVerts;
        dm->numEdgeData = numEdges;
-       dm->numFaceData = numFaces;
+       dm->numTessFaceData = numTessFaces;
        dm->numLoopData = numLoops;
        dm->numPolyData = numPolys;
 
@@ -311,7 +313,7 @@ int DM_release(DerivedMesh *dm)
                GPU_drawobject_free( dm );
                CustomData_free(&dm->vertData, dm->numVertData);
                CustomData_free(&dm->edgeData, dm->numEdgeData);
-               CustomData_free(&dm->faceData, dm->numFaceData);
+               CustomData_free(&dm->faceData, dm->numTessFaceData);
                CustomData_free(&dm->loopData, dm->numLoopData);
                CustomData_free(&dm->polyData, dm->numPolyData);
 
@@ -320,7 +322,7 @@ int DM_release(DerivedMesh *dm)
        else {
                CustomData_free_temporary(&dm->vertData, dm->numVertData);
                CustomData_free_temporary(&dm->edgeData, dm->numEdgeData);
-               CustomData_free_temporary(&dm->faceData, dm->numFaceData);
+               CustomData_free_temporary(&dm->faceData, dm->numTessFaceData);
                CustomData_free_temporary(&dm->loopData, dm->numLoopData);
                CustomData_free_temporary(&dm->polyData, dm->numPolyData);
 
@@ -365,8 +367,8 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob)
 
        totvert = tmp.totvert = dm->getNumVerts(dm);
        totedge = tmp.totedge = dm->getNumEdges(dm);
-       totpoly = tmp.totpoly = dm->getNumFaces(dm);
-       totloop = tmp.totloop = dm->numLoopData;
+       totloop = tmp.totloop = dm->getNumLoops(dm);
+       totpoly = tmp.totpoly = dm->getNumPolys(dm);
 
        CustomData_copy(&dm->vertData, &tmp.vdata, CD_MASK_MESH, CD_DUPLICATE, totvert);
        CustomData_copy(&dm->edgeData, &tmp.edata, CD_MASK_MESH, CD_DUPLICATE, totedge);
@@ -386,7 +388,9 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob)
                        }
                        
                        if (!kb) {
-                               printf("error in DM_to_mesh: could not find active shapekey! eek!!\n");
+                               printf("%s: error - could not find active shapekey %d!\n",
+                                      __func__, ob->shapenr-1);
+
                                i = INT_MAX;
                        }
                } else {
@@ -421,8 +425,13 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me, Object *ob)
                }
        }
 
+       /* yes, must be before _and_ after tesselate */
+       mesh_update_customdata_pointers(&tmp, TRUE);
+
        tmp.totface = mesh_recalcTesselation(&tmp.fdata, &tmp.ldata, &tmp.pdata, tmp.mvert, tmp.totface, tmp.totloop, tmp.totpoly);
-       mesh_update_customdata_pointers(&tmp);
+
+       mesh_update_customdata_pointers(&tmp, TRUE);
+
 
        CustomData_free(&me->vdata, me->totvert);
        CustomData_free(&me->edata, me->totedge);
@@ -481,7 +490,7 @@ void DM_add_edge_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
 
 void DM_add_tessface_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
 {
-       CustomData_add_layer(&dm->faceData, type, alloctype, layer, dm->numFaceData);
+       CustomData_add_layer(&dm->faceData, type, alloctype, layer, dm->numTessFaceData);
 }
 
 void DM_add_loop_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
@@ -489,7 +498,7 @@ void DM_add_loop_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
        CustomData_add_layer(&dm->loopData, type, alloctype, layer, dm->numLoopData);
 }
 
-void DM_add_face_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
+void DM_add_poly_layer(DerivedMesh *dm, int type, int alloctype, void *layer)
 {
        CustomData_add_layer(&dm->polyData, type, alloctype, layer, dm->numPolyData);
 }
@@ -504,7 +513,7 @@ void *DM_get_edge_data(DerivedMesh *dm, int index, int type)
        return CustomData_get(&dm->edgeData, index, type);
 }
 
-void *DM_get_face_data(DerivedMesh *dm, int index, int type)
+void *DM_get_tessface_data(DerivedMesh *dm, int index, int type)
 {
        return CustomData_get(&dm->faceData, index, type);
 }
@@ -533,7 +542,7 @@ void *DM_get_tessface_data_layer(DerivedMesh *dm, int type)
        return CustomData_get_layer(&dm->faceData, type);
 }
 
-void *DM_get_face_data_layer(DerivedMesh *dm, int type)
+void *DM_get_poly_data_layer(DerivedMesh *dm, int type)
 {
        return CustomData_get_layer(&dm->polyData, type);
 }
@@ -548,7 +557,7 @@ void DM_set_edge_data(DerivedMesh *dm, int index, int type, void *data)
        CustomData_set(&dm->edgeData, index, type, data);
 }
 
-void DM_set_face_data(DerivedMesh *dm, int index, int type, void *data)
+void DM_set_tessface_data(DerivedMesh *dm, int index, int type, void *data)
 {
        CustomData_set(&dm->faceData, index, type, data);
 }
@@ -581,7 +590,7 @@ void DM_copy_loop_data(DerivedMesh *source, DerivedMesh *dest,
                             source_index, dest_index, count);
 }
 
-void DM_copy_face_data(DerivedMesh *source, DerivedMesh *dest,
+void DM_copy_poly_data(DerivedMesh *source, DerivedMesh *dest,
                        int source_index, int dest_index, int count)
 {
        CustomData_copy_data(&source->polyData, &dest->polyData,
@@ -608,7 +617,7 @@ void DM_free_loop_data(struct DerivedMesh *dm, int index, int count)
        CustomData_free_elem(&dm->loopData, index, count);
 }
 
-void DM_free_face_data(struct DerivedMesh *dm, int index, int count)
+void DM_free_poly_data(struct DerivedMesh *dm, int index, int count)
 {
        CustomData_free_elem(&dm->polyData, index, count);
 }
@@ -652,7 +661,7 @@ void DM_interp_loop_data(DerivedMesh *source, DerivedMesh *dest,
                          weights, NULL, count, dest_index);
 }
 
-void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest,
+void DM_interp_poly_data(DerivedMesh *source, DerivedMesh *dest,
                          int *src_indices,
                          float *weights, int count, int dest_index)
 {
@@ -760,12 +769,10 @@ static void *get_orco_coords_dm(Object *ob, BMEditMesh *em, int layer, int *free
                   by a more flexible customdata system, but not simple */
                if(!em) {
                        ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
-                       if (clmd) {
-                               KeyBlock *kb= key_get_keyblock(ob_get_key(ob), clmd->sim_parms->shapekey_rest);
-       
-                               if(kb->data)
-                                       return kb->data;
-                       }
+                       KeyBlock *kb= key_get_keyblock(ob_get_key(ob), clmd->sim_parms->shapekey_rest);
+
+                       if(kb->data)
+                               return kb->data;
                }
 
                return NULL;
@@ -837,66 +844,77 @@ static void add_orco_dm(Object *ob, BMEditMesh *em, DerivedMesh *dm,
  * happens on enter/exit wpaint.
  */
 
-void weight_to_rgb(float input, float *fr, float *fg, float *fb)
+void weight_to_rgb(float r_rgb[3], const float weight)
 {
-       float blend;
-       
-       blend= ((input/2.0f)+0.5f);
-       
-       if (input<=0.25f){      // blue->cyan
-               *fr= 0.0f;
-               *fg= blend*input*4.0f;
-               *fb= blend;
+       const float blend= ((weight/2.0f)+0.5f);
+
+       if (weight<=0.25f){     // blue->cyan
+               r_rgb[0]= 0.0f;
+               r_rgb[1]= blend*weight*4.0f;
+               r_rgb[2]= blend;
+       }
+       else if (weight<=0.50f){        // cyan->green
+               r_rgb[0]= 0.0f;
+               r_rgb[1]= blend;
+               r_rgb[2]= blend*(1.0f-((weight-0.25f)*4.0f));
        }
-       else if (input<=0.50f){ // cyan->green
-               *fr= 0.0f;
-               *fg= blend;
-               *fb= blend*(1.0f-((input-0.25f)*4.0f)); 
+       else if (weight <= 0.75f){      // green->yellow
+               r_rgb[0]= blend * ((weight-0.50f)*4.0f);
+               r_rgb[1]= blend;
+               r_rgb[2]= 0.0f;
        }
-       else if (input <= 0.75f){       // green->yellow
-               *fr= blend * ((input-0.50f)*4.0f);
-               *fg= blend;
-               *fb= 0.0f;
+       else if (weight <= 1.0f){ // yellow->red
+               r_rgb[0]= blend;
+               r_rgb[1]= blend * (1.0f-((weight-0.75f)*4.0f));
+               r_rgb[2]= 0.0f;
        }
-       else if (input <= 1.0f){ // yellow->red
-               *fr= blend;
-               *fg= blend * (1.0f-((input-0.75f)*4.0f)); 
-               *fb= 0.0f;
+       else {
+               /* exceptional value, unclamped or nan,
+                * avoid uninitialized memory use */
+               r_rgb[0]= 1.0f;
+               r_rgb[1]= 0.0f;
+               r_rgb[2]= 1.0f;
        }
 }
 
 /* draw_flag's for calc_weightpaint_vert_color */
 enum {
        CALC_WP_MULTIPAINT= (1<<0),
-       CALC_WP_AUTO_NORMALIZE= (1<<1),
+       CALC_WP_AUTO_NORMALIZE= (1<<1)
 };
 
-static void calc_weightpaint_vert_color(Object *ob, ColorBand *coba, int vert, unsigned char *col, char *dg_flags, int selected, int UNUSED(unselected), const int draw_flag)
+static void calc_weightpaint_vert_color(
+        Object *ob, const int defbase_tot, ColorBand *coba, int vert, unsigned char *col,
+        const char *dg_flags, int selected, int UNUSED(unselected), const int draw_flag)
 {
        Mesh *me = ob->data;
-       float colf[4], input = 0.0f;
-       int i;
-
+       float input = 0.0f;
        
        int make_black= FALSE;
 
        if (me->dvert) {
+               MDeformVert *dvert= &me->dvert[vert];
+
                if ((selected > 1) && (draw_flag & CALC_WP_MULTIPAINT)) {
-                       
                        int was_a_nonzero= FALSE;
-                       for (i=0; i<me->dvert[vert].totweight; i++) {
+                       int i;
+
+                       MDeformWeight *dw= dvert->dw;
+                       for (i = dvert->totweight; i > 0; i--, dw++) {
                                /* in multipaint, get the average if auto normalize is inactive
                                 * get the sum if it is active */
-                               if(dg_flags[me->dvert[vert].dw[i].def_nr]) {
-                                       if(me->dvert[vert].dw[i].weight) {
-                                               input+= me->dvert[vert].dw[i].weight;
-                                               was_a_nonzero= TRUE;
+                               if (dw->def_nr < defbase_tot) {
+                                       if (dg_flags[dw->def_nr]) {
+                                               if (dw->weight) {
+                                                       input += dw->weight;
+                                                       was_a_nonzero= TRUE;
+                                               }
                                        }
                                }
                        }
 
                        /* make it black if the selected groups have no weight on a vertex */
-                       if(was_a_nonzero == FALSE) {
+                       if (was_a_nonzero == FALSE) {
                                make_black = TRUE;
                        }
                        else if ((draw_flag & CALC_WP_AUTO_NORMALIZE) == FALSE) {
@@ -905,11 +923,7 @@ static void calc_weightpaint_vert_color(Object *ob, ColorBand *coba, int vert, u
                }
                else {
                        /* default, non tricky behavior */
-                       for (i=0; i<me->dvert[vert].totweight; i++) {
-                               if (me->dvert[vert].dw[i].def_nr==ob->actdef-1) {
-                                       input+=me->dvert[vert].dw[i].weight;
-                               }
-                       }
+                       input= defvert_find_weight(dvert, ob->actdef-1);
                }
        }
        
@@ -918,20 +932,19 @@ static void calc_weightpaint_vert_color(Object *ob, ColorBand *coba, int vert, u
                col[2] = 0;
                col[1] = 0;
                col[0] = 255;
-               return;
        }
+       else {
+               float colf[4];
+               CLAMP(input, 0.0f, 1.0f);
 
-       CLAMP(input, 0.0f, 1.0f);       
+               if(coba) do_colorband(coba, input, colf);
+               else     weight_to_rgb(colf, input);
 
-       if(coba)
-               do_colorband(coba, input, colf);
-       else
-               weight_to_rgb(input, colf, colf+1, colf+2);
-       
-       col[3] = (unsigned char)(colf[0] * 255.0f);
-       col[2] = (unsigned char)(colf[1] * 255.0f);
-       col[1] = (unsigned char)(colf[2] * 255.0f);
-       col[0] = 255;
+               col[3] = (unsigned char)(colf[0] * 255.0f);
+               col[2] = (unsigned char)(colf[1] * 255.0f);
+               col[1] = (unsigned char)(colf[2] * 255.0f);
+               col[0] = 255;
+       }
 }
 
 static ColorBand *stored_cb= NULL;
@@ -954,10 +967,10 @@ static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag)
        int i, j, totface=dm->getNumTessFaces(dm), totloop;
        int *origIndex = dm->getVertDataArray(dm, CD_ORIGINDEX);
 
-       int defbase_len = BLI_countlist(&ob->defbase);
-       char *defbase_sel = MEM_mallocN(defbase_len * sizeof(char), __func__);
-       int selected = get_selected_defgroups(ob, defbase_sel, defbase_len);
-       int unselected = defbase_len - selected;
+       int defbase_tot = BLI_countlist(&ob->defbase);
+       char *defbase_sel = MEM_mallocN(defbase_tot * sizeof(char), __func__);
+       int selected = get_selected_defgroups(ob, defbase_sel, defbase_tot);
+       int unselected = defbase_tot - selected;
 
        wtcol = MEM_callocN (sizeof (unsigned char) * totface*4*4, "weightmap");
        
@@ -965,11 +978,11 @@ static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag)
        memset(wtcol, 0x55, sizeof (unsigned char) * totface*4*4);
        for (i=0; i<totface; i++, mf++) {
                /*origindex being NULL means we're operating on original mesh data*/
-               calc_weightpaint_vert_color(ob, coba, mf->v1, &wtcol[(i*4 + 0)*4], defbase_sel, selected, unselected, draw_flag);
-               calc_weightpaint_vert_color(ob, coba, mf->v2, &wtcol[(i*4 + 1)*4], defbase_sel, selected, unselected, draw_flag);
-               calc_weightpaint_vert_color(ob, coba, mf->v3, &wtcol[(i*4 + 2)*4], defbase_sel, selected, unselected, draw_flag);
+               calc_weightpaint_vert_color(ob, defbase_tot, coba, mf->v1, &wtcol[(i*4 + 0)*4], defbase_sel, selected, unselected, draw_flag);
+               calc_weightpaint_vert_color(ob, defbase_tot, coba, mf->v2, &wtcol[(i*4 + 1)*4], defbase_sel, selected, unselected, draw_flag);
+               calc_weightpaint_vert_color(ob, defbase_tot, coba, mf->v3, &wtcol[(i*4 + 2)*4], defbase_sel, selected, unselected, draw_flag);
                if (mf->v4)
-                       calc_weightpaint_vert_color(ob, coba, mf->v4, &wtcol[(i*4 + 3)*4], defbase_sel, selected, unselected, draw_flag);
+                       calc_weightpaint_vert_color(ob, defbase_tot, coba, mf->v4, &wtcol[(i*4 + 3)*4], defbase_sel, selected, unselected, draw_flag);
        }
        
        CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol, totface);
@@ -982,7 +995,7 @@ static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag)
                for (j=0; j<mp->totloop; j++, ml++, totloop++) {
                        BLI_array_growone(wlcol);
 
-                       calc_weightpaint_vert_color(ob, coba, origIndex ? origIndex[ml->v] : ml->v,
+                       calc_weightpaint_vert_color(ob, defbase_tot, coba, origIndex ? origIndex[ml->v] : ml->v,
                                                                                (unsigned char *)&wlcol[totloop], defbase_sel, selected, unselected, draw_flag);
                }
        }
@@ -1165,7 +1178,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                 */
                if (deform_r) {
                        *deform_r = CDDM_from_mesh(me, ob);
-                       
+                        
                        if (build_shapekey_layers)
                                add_shapekey_layers(dm, me, ob);
                        
@@ -1301,11 +1314,11 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                                        /* calc */
                                        DM_add_vert_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
                                        DM_add_edge_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
-                                       DM_add_face_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
+                                       DM_add_poly_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
 
-                                       range_vni(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0);
-                                       range_vni(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0);
-                                       range_vni(DM_get_face_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0);
+                                       range_vn_i(DM_get_vert_data_layer(dm, CD_ORIGINDEX), dm->numVertData, 0);
+                                       range_vn_i(DM_get_edge_data_layer(dm, CD_ORIGINDEX), dm->numEdgeData, 0);
+                                       range_vn_i(DM_get_poly_data_layer(dm, CD_ORIGINDEX), dm->numPolyData, 0);
                                }
 
                                if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))
@@ -1406,10 +1419,12 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                dm->release(dm);
 
                CDDM_apply_vert_coords(finaldm, deformedVerts);
+
                CDDM_calc_normals(finaldm);
 
                if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT))
                        add_weight_mcol_dm(ob, finaldm, draw_flag);
+
        } else if(dm) {
                finaldm = dm;
        } else {
@@ -1454,7 +1469,22 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
        }
 #endif /* WITH_GAMEENGINE */
 
+
+       /* --------------------------------------------------------------------- */
+       /* Re-tesselation is necessary to push render data (uvs, textures, colors)
+        * from loops and polys onto the tessfaces. This may be currently be
+        * redundantin cases where the render mode doesn't use these inputs, but
+        * ideally eventually tesselation would happen on-demand, and this is one
+        * of the primary places it would be needed. */
+       finaldm->recalcTesselation(finaldm);
+       /* if we have no modifiers applied we'lll still want the tessface normals
+        * to be calculated from the polygon noramals,
+        * 'CDDM_calc_normals' checks for this case - campbell */
        finaldm->calcNormals(finaldm);
+       /* Need to watch this, it can cause issues, see bug [#29338]             */
+       /* take care with this block, we really need testing frameworks          */
+       /* --------------------------------------------------------------------- */
+
 
        *final_r = finaldm;
 
@@ -1968,7 +1998,7 @@ typedef struct
        MVert * mvert;          // vertices & normals
        float (*orco)[3];
        float (*tangent)[4];    // destination
-       int numFaces;
+       int numTessFaces;
 
 } SGLSLMeshToTangent;
 
@@ -1978,7 +2008,7 @@ typedef struct
 static int GetNumFaces(const SMikkTSpaceContext * pContext)
 {
        SGLSLMeshToTangent * pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
-       return pMesh->numFaces;
+       return pMesh->numTessFaces;
 }
 
 static int GetNumVertsOfFace(const SMikkTSpaceContext * pContext, const int face_num)
@@ -2105,7 +2135,7 @@ void DM_add_tangent_layer(DerivedMesh *dm)
                mesh2tangent.mvert = mvert;
                mesh2tangent.orco = orco;
                mesh2tangent.tangent = tangent;
-               mesh2tangent.numFaces = totface;
+               mesh2tangent.numTessFaces = totface;
 
                sContext.m_pUserData = &mesh2tangent;
                sContext.m_pInterface = &sInterface;
@@ -2195,6 +2225,159 @@ void DM_add_tangent_layer(DerivedMesh *dm)
        MEM_freeN(vtangents);
 }
 
+void DM_calc_auto_bump_scale(DerivedMesh *dm)
+{
+       /* int totvert= dm->getNumVerts(dm); */ /* UNUSED */
+       int totface= dm->getNumTessFaces(dm);
+
+       MVert * mvert = dm->getVertArray(dm);
+       MFace * mface = dm->getTessFaceArray(dm);
+       MTFace * mtface = dm->getTessFaceDataArray(dm, CD_MTFACE);
+
+       if(mtface)
+       {
+               double dsum = 0.0;
+               int nr_accumulated = 0;
+               int f;
+
+               for ( f=0; f<totface; f++ )
+               {
+                       {
+                               float * verts[4], * tex_coords[4];
+                               const int nr_verts = mface[f].v4!=0 ? 4 : 3;
+                               int i, is_degenerate;
+
+                               verts[0]=mvert[mface[f].v1].co; verts[1]=mvert[mface[f].v2].co; verts[2]=mvert[mface[f].v3].co;
+                               tex_coords[0]=mtface[f].uv[0]; tex_coords[1]=mtface[f].uv[1]; tex_coords[2]=mtface[f].uv[2];
+                               if(nr_verts==4)
+                               {
+                                       verts[3]=mvert[mface[f].v4].co;
+                                       tex_coords[3]=mtface[f].uv[3];
+                               }
+
+                               // discard degenerate faces
+                               is_degenerate = 0;
+                               if(     equals_v3v3(verts[0], verts[1]) || equals_v3v3(verts[0], verts[2]) || equals_v3v3(verts[1], verts[2]) ||
+                                       equals_v2v2(tex_coords[0], tex_coords[1]) || equals_v2v2(tex_coords[0], tex_coords[2]) || equals_v2v2(tex_coords[1], tex_coords[2]) )
+                               {
+                                       is_degenerate = 1;
+                               }
+
+                               // verify last vertex as well if this is a quad
+                               if ( is_degenerate==0 && nr_verts==4 )
+                               {
+                                       if(     equals_v3v3(verts[3], verts[0]) || equals_v3v3(verts[3], verts[1]) || equals_v3v3(verts[3], verts[2]) ||
+                                               equals_v2v2(tex_coords[3], tex_coords[0]) || equals_v2v2(tex_coords[3], tex_coords[1]) || equals_v2v2(tex_coords[3], tex_coords[2]) )
+                                       {
+                                               is_degenerate = 1;
+                                       }
+
+                                       // verify the winding is consistent
+                                       if ( is_degenerate==0 )
+                                       {
+                                               float prev_edge[2];
+                                               int is_signed = 0;
+                                               sub_v2_v2v2(prev_edge, tex_coords[0], tex_coords[3]);
+
+                                               i = 0;
+                                               while ( is_degenerate==0 && i<4 )
+                                               {
+                                                       float cur_edge[2], signed_area;
+                                                       sub_v2_v2v2(cur_edge, tex_coords[(i+1)&0x3], tex_coords[i]);
+                                                       signed_area = prev_edge[0]*cur_edge[1] - prev_edge[1]*cur_edge[0];
+                                                       if ( i==0 ) is_signed = signed_area<0.0f ? 1 : 0;
+                                                       else if((is_signed!=0)!=(signed_area<0.0f)) is_degenerate=1;
+
+                                                       if ( is_degenerate==0 )
+                                                       {
+                                                               copy_v2_v2(prev_edge, cur_edge);
+                                                               ++i;
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               // proceed if not a degenerate face
+                               if ( is_degenerate==0 )
+                               {
+                                       int nr_tris_to_pile=0;
+                                       // quads split at shortest diagonal
+                                       int offs = 0;           // initial triangulation is 0,1,2 and 0, 2, 3
+                                       if ( nr_verts==4 )
+                                       {
+                                               float pos_len_diag0, pos_len_diag1;
+                                               float vtmp[3];
+                                               sub_v3_v3v3(vtmp, verts[2], verts[0]);
+                                               pos_len_diag0 = dot_v3v3(vtmp, vtmp);
+                                               sub_v3_v3v3(vtmp, verts[3], verts[1]);
+                                               pos_len_diag1 = dot_v3v3(vtmp, vtmp);
+
+                                               if(pos_len_diag1<pos_len_diag0)
+                                                       offs=1;         // alter split
+                                               else if(pos_len_diag0==pos_len_diag1)           // do UV check instead
+                                               {
+                                                       float tex_len_diag0, tex_len_diag1;
+
+                                                       sub_v2_v2v2(vtmp, tex_coords[2], tex_coords[0]);
+                                                       tex_len_diag0 = dot_v2v2(vtmp, vtmp);
+                                                       sub_v2_v2v2(vtmp, tex_coords[3], tex_coords[1]);
+                                                       tex_len_diag1 = dot_v2v2(vtmp, vtmp);
+
+                                                       if(tex_len_diag1<tex_len_diag0)
+                                                       {
+                                                               offs=1;         // alter split
+                                                       }
+                                               }
+                                       }
+                                       nr_tris_to_pile = nr_verts-2 ;
+                                       if ( nr_tris_to_pile==1 || nr_tris_to_pile==2 )
+                                       {
+                                               const int indices[] = {offs+0, offs+1, offs+2, offs+0, offs+2, (offs+3)&0x3 };
+                                               int t;
+                                               for ( t=0; t<nr_tris_to_pile; t++ )
+                                               {
+                                                       float f2x_area_uv;
+                                                       float * p0 = verts[indices[t*3+0]];
+                                                       float * p1 = verts[indices[t*3+1]];
+                                                       float * p2 = verts[indices[t*3+2]];
+
+                                                       float edge_t0[2], edge_t1[2];
+                                                       sub_v2_v2v2(edge_t0, tex_coords[indices[t*3+1]], tex_coords[indices[t*3+0]]);
+                                                       sub_v2_v2v2(edge_t1, tex_coords[indices[t*3+2]], tex_coords[indices[t*3+0]]);
+
+                                                       f2x_area_uv = fabsf(edge_t0[0]*edge_t1[1] - edge_t0[1]*edge_t1[0]);
+                                                       if ( f2x_area_uv>FLT_EPSILON )
+                                                       {
+                                                               float norm[3], v0[3], v1[3], f2x_surf_area, fsurf_ratio;
+                                                               sub_v3_v3v3(v0, p1, p0);
+                                                               sub_v3_v3v3(v1, p2, p0);
+                                                               cross_v3_v3v3(norm, v0, v1);
+
+                                                               f2x_surf_area = len_v3(norm);
+                                                               fsurf_ratio = f2x_surf_area/f2x_area_uv;        // tri area divided by texture area
+
+                                                               ++nr_accumulated;
+                                                               dsum += (double)(fsurf_ratio);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               // finalize
+               {
+                       const float avg_area_ratio = (nr_accumulated>0) ? ((float)(dsum / nr_accumulated)) : 1.0f;
+                       const float use_as_render_bump_scale = sqrtf(avg_area_ratio);           // use width of average surface ratio as your bump scale
+                       dm->auto_bump_scale = use_as_render_bump_scale;
+               }
+       }
+       else
+       {
+               dm->auto_bump_scale = 1.0f;
+       }
+}
+
 void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, DMVertexAttribs *attribs)
 {
        CustomData *vdata, *fdata, *tfdata = NULL;
@@ -2208,6 +2391,15 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
        vdata = &dm->vertData;
        fdata = tfdata = dm->getTessFaceDataLayout(dm);
        
+       /* calc auto bump scale if necessary */
+#if 0
+       if(dm->auto_bump_scale<=0.0f)
+               DM_calc_auto_bump_scale(dm);
+#else
+       dm->auto_bump_scale = 1.0f; // will revert this after release
+#endif
+
+
        /* add a tangent layer if necessary */
        for(b = 0; b < gattribs->totlayer; b++)
                if(gattribs->layer[b].type == CD_TANGENT)
@@ -2229,9 +2421,12 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
                                attribs->tface[a].array = tfdata->layers[layer].data;
                                attribs->tface[a].emOffset = tfdata->layers[layer].offset;
                                attribs->tface[a].glIndex = gattribs->layer[b].glindex;
-                       } /*else {
+                               /* attribs->tface[a].glTexco = gattribs->layer[b].gltexco; */ /* BMESH_TODO, trunk has this but not bmesh, need to investigate whats going on here - campbell */
+                       }
+                       /* BMESH ONLY, may need to get this working?, otherwise remove */
+                       /* else {
                                int player;
-                               CustomData *pdata = dm->getFaceDataLayout(dm);
+                               CustomData *pdata = dm->getPolyDataLayout(dm);
                                
                                if(gattribs->layer[b].name[0])
                                        player = CustomData_get_named_layer_index(pdata, CD_MTEXPOLY,
@@ -2248,7 +2443,8 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs,
                                        attribs->tface[a].glTexco = gattribs->layer[b].gltexco;
                                        
                                }
-                       }*/
+                       }
+                       */
                }
                else if(gattribs->layer[b].type == CD_MCOL) {
                        /* vertex colors */
@@ -2351,7 +2547,7 @@ static void navmesh_drawColored(DerivedMesh *dm)
                DEBUG_VBO( "Using legacy code. drawNavMeshColored\n" );
                //glShadeModel(GL_SMOOTH);
                glBegin(glmode = GL_QUADS);
-               for(a = 0; a < dm->numFaceData; a++, mface++) {
+               for(a = 0; a < dm->numTessFaceData; a++, mface++) {
                        int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
                        int pi = polygonIdx[a];
                        if (pi <= 0) {
@@ -2378,9 +2574,14 @@ static void navmesh_drawColored(DerivedMesh *dm)
        glEnable(GL_LIGHTING);
 }
 
-static void navmesh_DM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tface, int has_mcol, int matnr))
+static void navmesh_DM_drawFacesTex(DerivedMesh *dm,
+                       int (*setDrawOptions)(MTFace *tface, int has_mcol, int matnr),
+                       int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
+                       void *userData)
 {
        (void) setDrawOptions;
+       (void) compareDrawOptions;
+       (void) userData;
 
        navmesh_drawColored(dm);
 }
@@ -2399,7 +2600,7 @@ static void navmesh_DM_drawFacesSolid(DerivedMesh *dm,
 static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm)
 {
        DerivedMesh *result;
-       int maxFaces = dm->getNumFaces(dm);
+       int maxFaces = dm->getNumPolys(dm);
        int *recastData;
        int vertsPerPoly=0, nverts=0, ndtris=0, npolys=0;
        float* verts=NULL;