NLA SoC: Start of 'Meta' Strips
[blender.git] / source / blender / blenkernel / intern / DerivedMesh.c
index 2ecc8cb175468cd9328ec28a102e19fa5b428b86..090f256ab9fd52802976f777043fca80d8331781 100644 (file)
@@ -76,6 +76,7 @@
 #include "BKE_texture.h"
 #include "BKE_utildefines.h"
 #include "BKE_particle.h"
+#include "BKE_bvhutils.h"
 
 #include "BLO_sys_types.h" // for intptr_t support
 
@@ -177,6 +178,8 @@ void DM_init_funcs(DerivedMesh *dm)
        dm->getVertDataArray = DM_get_vert_data_layer;
        dm->getEdgeDataArray = DM_get_edge_data_layer;
        dm->getFaceDataArray = DM_get_face_data_layer;
+
+       bvhcache_init(&dm->bvhCache);
 }
 
 void DM_init(DerivedMesh *dm,
@@ -213,6 +216,8 @@ void DM_from_template(DerivedMesh *dm, DerivedMesh *source,
 int DM_release(DerivedMesh *dm)
 {
        if (dm->needsFree) {
+               bvhcache_free(&dm->bvhCache);
+
                CustomData_free(&dm->vertData, dm->numVertData);
                CustomData_free(&dm->edgeData, dm->numEdgeData);
                CustomData_free(&dm->faceData, dm->numFaceData);
@@ -899,7 +904,7 @@ static void emDM_drawMappedFacesGLSL(DerivedMesh *dm,
        glShadeModel(GL_SMOOTH);
 
        for (i=0,eve=em->verts.first; eve; eve= eve->next)
-               eve->tmp.l = (long) i++;
+               eve->tmp.l = (intptr_t) i++;
 
 #define PASSATTRIB(efa, eve, vert) {                                                                                   \
        if(attribs.totorco) {                                                                                                           \
@@ -1398,7 +1403,7 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, Modifier
                int numVerts;
                float (*deformedVerts)[3] = mesh_getVertexCos(me, &numVerts);
 
-               mti->deformVerts(md, ob, NULL, deformedVerts, numVerts);
+               mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, 0, 0);
                dm = getMeshDerivedMesh(me, ob, deformedVerts);
 
                MEM_freeN(deformedVerts);
@@ -1433,6 +1438,8 @@ static float *get_editmesh_orco_verts(EditMesh *em)
        return orco;
 }
 
+/* orco custom data layer */
+
 static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, EditMesh *em)
 {
        DerivedMesh *dm;
@@ -1484,6 +1491,101 @@ static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh *
                DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco);
 }
 
+/* weight paint colors */
+
+/* Something of a hack, at the moment deal with weightpaint
+ * by tucking into colors during modifier eval, only in
+ * wpaint mode. Works ok but need to make sure recalc
+ * happens on enter/exit wpaint.
+ */
+
+void weight_to_rgb(float input, float *fr, float *fg, float *fb)
+{
+       float blend;
+       
+       blend= ((input/2.0f)+0.5f);
+       
+       if (input<=0.25f){      // blue->cyan
+               *fr= 0.0f;
+               *fg= blend*input*4.0f;
+               *fb= blend;
+       }
+       else if (input<=0.50f){ // cyan->green
+               *fr= 0.0f;
+               *fg= blend;
+               *fb= blend*(1.0f-((input-0.25f)*4.0f)); 
+       }
+       else if (input<=0.75){  // green->yellow
+               *fr= blend * ((input-0.50f)*4.0f);
+               *fg= blend;
+               *fb= 0.0f;
+       }
+       else if (input<=1.0){ // yellow->red
+               *fr= blend;
+               *fg= blend * (1.0f-((input-0.75f)*4.0f)); 
+               *fb= 0.0f;
+       }
+}
+
+static void calc_weightpaint_vert_color(Object *ob, ColorBand *coba, int vert, unsigned char *col)
+{
+       Mesh *me = ob->data;
+       float colf[4], input = 0.0f;
+       int i;
+
+       if (me->dvert) {
+               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;            
+       }
+
+       CLAMP(input, 0.0f, 1.0f);
+       
+       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;
+}
+
+static ColorBand *stored_cb= NULL;
+
+void vDM_ColorBand_store(ColorBand *coba)
+{
+       stored_cb= coba;
+}
+
+static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm)
+{
+       Mesh *me = ob->data;
+       MFace *mf = me->mface;
+       ColorBand *coba= stored_cb;     /* warning, not a local var */
+       unsigned char *wtcol;
+       int i;
+       
+       wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap");
+       
+       memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4);
+       for (i=0; i<me->totface; i++, mf++) {
+               calc_weightpaint_vert_color(ob, coba, mf->v1, &wtcol[(i*4 + 0)*4]); 
+               calc_weightpaint_vert_color(ob, coba, mf->v2, &wtcol[(i*4 + 1)*4]); 
+               calc_weightpaint_vert_color(ob, coba, mf->v3, &wtcol[(i*4 + 2)*4]); 
+               if (mf->v4)
+                       calc_weightpaint_vert_color(ob, coba, mf->v4, &wtcol[(i*4 + 3)*4]); 
+       }
+       
+       CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol, dm->numFaceData);
+}
+
+/* new value for useDeform -1  (hack for the gameengine):
+ * - apply only the modifier stack of the object, skipping the virtual modifiers,
+ * - don't apply the key
+ * - apply deform modifiers and input vertexco
+ */
 static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos)[3],
                                 DerivedMesh **deform_r, DerivedMesh **final_r,
                                 int useRenderParams, int useDeform,
@@ -1498,25 +1600,27 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
        int numVerts = me->totvert;
        int required_mode;
 
-       md = firstmd = modifiers_getVirtualModifierList(ob);
+       md = firstmd = (useDeform<0) ? ob->modifiers.first : modifiers_getVirtualModifierList(ob);
 
        modifiers_clearErrors(ob);
 
+       if(useRenderParams) required_mode = eModifierMode_Render;
+       else required_mode = eModifierMode_Realtime;
+
        /* we always want to keep original indices */
        dataMask |= CD_MASK_ORIGINDEX;
 
-       datamasks = modifiers_calcDataMasks(md, dataMask);
+       datamasks = modifiers_calcDataMasks(ob, md, dataMask, required_mode);
        curr = datamasks;
 
        if(deform_r) *deform_r = NULL;
        *final_r = NULL;
 
-       if(useRenderParams) required_mode = eModifierMode_Render;
-       else required_mode = eModifierMode_Realtime;
-
        if(useDeform) {
-               if(do_ob_key(scene, ob)) /* shape key makes deform verts */
+               if(useDeform > 0 && do_ob_key(scene, ob)) /* shape key makes deform verts */
                        deformedVerts = mesh_getVertexCos(me, &numVerts);
+               else if(inputVertexCos)
+                       deformedVerts = inputVertexCos;
                
                /* Apply all leading deforming modifiers */
                for(;md; md = md->next, curr = curr->next) {
@@ -1524,14 +1628,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
 
                        md->scene= scene;
                        
-                       if((md->mode & required_mode) != required_mode) continue;
-                       if(mti->isDisabled && mti->isDisabled(md)) continue;
+                       if(!modifier_isEnabled(md, required_mode)) continue;
+                       if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue;
 
                        if(mti->type == eModifierTypeType_OnlyDeform) {
                                if(!deformedVerts)
                                        deformedVerts = mesh_getVertexCos(me, &numVerts);
 
-                               mti->deformVerts(md, ob, NULL, deformedVerts, numVerts);
+                               mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, useRenderParams, useDeform);
                        } else {
                                break;
                        }
@@ -1547,6 +1651,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                 */
                if (deform_r) {
                        *deform_r = CDDM_from_mesh(me, ob);
+
                        if(deformedVerts) {
                                CDDM_apply_vert_coords(*deform_r, deformedVerts);
                                CDDM_calc_normals(*deform_r);
@@ -1572,18 +1677,18 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
 
                md->scene= scene;
                
-               if((md->mode & required_mode) != required_mode) continue;
+               if(!modifier_isEnabled(md, required_mode)) continue;
                if(mti->type == eModifierTypeType_OnlyDeform && !useDeform) continue;
                if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
                        modifier_setError(md, "Modifier requires original data, bad stack position.");
                        continue;
                }
-               if(mti->isDisabled && mti->isDisabled(md)) continue;
                if(needMapping && !modifier_supportsMapping(md)) continue;
+               if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue;
 
                /* add an orco layer if needed by this modifier */
                if(dm && mti->requiredDataMask) {
-                       mask = mti->requiredDataMask(md);
+                       mask = mti->requiredDataMask(ob, md);
                        if(mask & CD_MASK_ORCO)
                                add_orco_dm(ob, NULL, dm, orcodm);
                }
@@ -1611,7 +1716,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                                }
                        }
 
-                       mti->deformVerts(md, ob, dm, deformedVerts, numVerts);
+                       mti->deformVerts(md, ob, dm, deformedVerts, numVerts, useRenderParams, useDeform);
                } else {
                        DerivedMesh *ndm;
 
@@ -1632,6 +1737,9 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                                        CDDM_apply_vert_coords(dm, deformedVerts);
                                        CDDM_calc_normals(dm);
                                }
+
+                               if(dataMask & CD_MASK_WEIGHT_MCOL)
+                                       add_weight_mcol_dm(ob, dm);
                        }
 
                        /* create an orco derivedmesh in parallel */
@@ -1695,14 +1803,21 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
 
                CDDM_apply_vert_coords(finaldm, deformedVerts);
                CDDM_calc_normals(finaldm);
+
+               if(dataMask & CD_MASK_WEIGHT_MCOL)
+                       add_weight_mcol_dm(ob, finaldm);
        } else if(dm) {
                finaldm = dm;
        } else {
                finaldm = CDDM_from_mesh(me, ob);
+
                if(deformedVerts) {
                        CDDM_apply_vert_coords(finaldm, deformedVerts);
                        CDDM_calc_normals(finaldm);
                }
+
+               if(dataMask & CD_MASK_WEIGHT_MCOL)
+                       add_weight_mcol_dm(ob, finaldm);
        }
 
        /* add an orco layer if needed */
@@ -1743,14 +1858,11 @@ static int editmesh_modifier_is_enabled(ModifierData *md, DerivedMesh *dm)
        ModifierTypeInfo *mti = modifierType_getInfo(md->type);
        int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
 
-       if((md->mode & required_mode) != required_mode) return 0;
+       if(!modifier_isEnabled(md, required_mode)) return 0;
        if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
                modifier_setError(md, "Modifier requires original data, bad stack position.");
                return 0;
        }
-       if(mti->isDisabled && mti->isDisabled(md)) return 0;
-       if(!(mti->flags & eModifierTypeFlag_SupportsEditmode)) return 0;
-       if(md->mode & eModifierMode_DisableTemporary) return 0;
        
        return 1;
 }
@@ -1765,6 +1877,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
        DerivedMesh *dm, *orcodm = NULL;
        int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL);
        LinkNode *datamasks, *curr;
+       int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
 
        modifiers_clearErrors(ob);
 
@@ -1778,7 +1891,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
        /* we always want to keep original indices */
        dataMask |= CD_MASK_ORIGINDEX;
 
-       datamasks = modifiers_calcDataMasks(md, dataMask);
+       datamasks = modifiers_calcDataMasks(ob, md, dataMask, required_mode);
 
        curr = datamasks;
        for(i = 0; md; i++, md = md->next, curr = curr->next) {
@@ -1791,7 +1904,7 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
 
                /* add an orco layer if needed by this modifier */
                if(dm && mti->requiredDataMask) {
-                       mask = mti->requiredDataMask(md);
+                       mask = mti->requiredDataMask(ob, md);
                        if(mask & CD_MASK_ORCO)
                                add_orco_dm(ob, em, dm, orcodm);
                }
@@ -1932,96 +2045,6 @@ static void editmesh_calc_modifiers(Scene *scene, Object *ob, EditMesh *em, Deri
                MEM_freeN(deformedVerts);
 }
 
-/***/
-
-
-       /* Something of a hack, at the moment deal with weightpaint
-        * by tucking into colors during modifier eval, only in
-        * wpaint mode. Works ok but need to make sure recalc
-        * happens on enter/exit wpaint.
-        */
-
-void weight_to_rgb(float input, float *fr, float *fg, float *fb)
-{
-       float blend;
-       
-       blend= ((input/2.0f)+0.5f);
-       
-       if (input<=0.25f){      // blue->cyan
-               *fr= 0.0f;
-               *fg= blend*input*4.0f;
-               *fb= blend;
-       }
-       else if (input<=0.50f){ // cyan->green
-               *fr= 0.0f;
-               *fg= blend;
-               *fb= blend*(1.0f-((input-0.25f)*4.0f)); 
-       }
-       else if (input<=0.75){  // green->yellow
-               *fr= blend * ((input-0.50f)*4.0f);
-               *fg= blend;
-               *fb= 0.0f;
-       }
-       else if (input<=1.0){ // yellow->red
-               *fr= blend;
-               *fg= blend * (1.0f-((input-0.75f)*4.0f)); 
-               *fb= 0.0f;
-       }
-}
-static void calc_weightpaint_vert_color(Object *ob, ColorBand *coba, int vert, unsigned char *col)
-{
-       Mesh *me = ob->data;
-       float colf[4], input = 0.0f;
-       int i;
-
-       if (me->dvert) {
-               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;            
-       }
-
-       CLAMP(input, 0.0f, 1.0f);
-       
-       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;
-}
-
-static ColorBand *stored_cb= NULL;
-
-void vDM_ColorBand_store(ColorBand *coba)
-{
-       stored_cb= coba;
-}
-
-static unsigned char *calc_weightpaint_colors(Object *ob) 
-{
-       Mesh *me = ob->data;
-       MFace *mf = me->mface;
-       ColorBand *coba= stored_cb;     /* warning, not a local var */
-       unsigned char *wtcol;
-       int i;
-       
-       wtcol = MEM_callocN (sizeof (unsigned char) * me->totface*4*4, "weightmap");
-       
-       memset(wtcol, 0x55, sizeof (unsigned char) * me->totface*4*4);
-       for (i=0; i<me->totface; i++, mf++) {
-               calc_weightpaint_vert_color(ob, coba, mf->v1, &wtcol[(i*4 + 0)*4]); 
-               calc_weightpaint_vert_color(ob, coba, mf->v2, &wtcol[(i*4 + 1)*4]); 
-               calc_weightpaint_vert_color(ob, coba, mf->v3, &wtcol[(i*4 + 2)*4]); 
-               if (mf->v4)
-                       calc_weightpaint_vert_color(ob, coba, mf->v4, &wtcol[(i*4 + 3)*4]); 
-       }
-       
-       return wtcol;
-}
-
 static void clear_mesh_caches(Object *ob)
 {
        Mesh *me= ob->data;
@@ -2052,42 +2075,16 @@ static void clear_mesh_caches(Object *ob)
 
 static void mesh_build_data(Scene *scene, Object *ob, CustomDataMask dataMask)
 {
-       Mesh *me = ob->data;
-       float min[3], max[3];
-       //int needMapping= 0; 
-       
        Object *obact = scene->basact?scene->basact->object:NULL;
        int editing = (FACESEL_PAINT_TEST)|(G.f & G_PARTICLEEDIT);
        int needMapping = editing && (ob==obact);
+       float min[3], max[3];
        
        clear_mesh_caches(ob);
 
-       if( (G.f & G_WEIGHTPAINT) && ob==obact ) {
-//     if(dataMask & CD_MASK_WEIGHTPAINT) {
-               MCol *wpcol = (MCol*)calc_weightpaint_colors(ob);
-               int layernum = CustomData_number_of_layers(&me->fdata, CD_MCOL);
-               int prevactive = CustomData_get_active_layer(&me->fdata, CD_MCOL);
-               int prevrender = CustomData_get_render_layer(&me->fdata, CD_MCOL);
-
-               /* ugly hack here, we temporarily add a new active mcol layer with
-                  weightpaint colors in it, that is then duplicated in CDDM_from_mesh */
-               CustomData_add_layer(&me->fdata, CD_MCOL, CD_ASSIGN, wpcol, me->totface);
-               CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
-               CustomData_set_layer_render(&me->fdata, CD_MCOL, layernum);
-
-               mesh_calc_modifiers(scene, ob, NULL, &ob->derivedDeform,
-                                                       &ob->derivedFinal, 0, 1,
-                                                       needMapping, dataMask, -1);
-
-               CustomData_free_layer_active(&me->fdata, CD_MCOL, me->totface);
-               CustomData_set_layer_active(&me->fdata, CD_MCOL, prevactive);
-               CustomData_set_layer_render(&me->fdata, CD_MCOL, prevrender);
-       } 
-       else {
-               mesh_calc_modifiers(scene, ob, NULL, &ob->derivedDeform,
-                                                       &ob->derivedFinal, G.rendering, 1,
-                                                       needMapping, dataMask, -1);
-       }
+       mesh_calc_modifiers(scene, ob, NULL, &ob->derivedDeform,
+                                               &ob->derivedFinal, 0, 1,
+                                               needMapping, dataMask, -1);
 
        INIT_MINMAX(min, max);
 
@@ -2207,6 +2204,16 @@ DerivedMesh *mesh_create_derived_no_deform(Scene *scene, Object *ob, float (*ver
        return final;
 }
 
+DerivedMesh *mesh_create_derived_no_virtual(Scene *scene, Object *ob, float (*vertCos)[3],
+                                            CustomDataMask dataMask)
+{
+       DerivedMesh *final;
+       
+       mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 0, dataMask, -1);
+
+       return final;
+}
+
 DerivedMesh *mesh_create_derived_no_deform_render(Scene *scene, Object *ob,
                                                   float (*vertCos)[3],
                                                   CustomDataMask dataMask)