=bmesh= merge from trunk at r36529
[blender.git] / source / blender / blenkernel / intern / displist.c
index bb020c936a651c4970c7f2c738b4e460b5879f62..48192546b0f58013802f9d044efdcccd4a2410fe 100644 (file)
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/blenkernel/intern/displist.c
+ *  \ingroup bke
+ */
+
+
 #include <math.h>
 #include <stdio.h>
 #include <string.h>
 
 #include "MEM_guardedalloc.h"
 
-
 #include "DNA_curve_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_object_types.h"
 #include "DNA_material_types.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_math.h"
 #include "BLI_editVert.h"
+#include "BLI_scanfill.h"
+#include "BLI_utildefines.h"
 
 #include "BKE_global.h"
 #include "BKE_displist.h"
@@ -63,6 +70,7 @@
 
 #include "BLO_sys_types.h" // for intptr_t support
 
+#include "ED_curve.h" /* for BKE_curve_nurbs */
 
 static void boundbox_displist(Object *ob);
 
@@ -118,7 +126,7 @@ DispList *find_displist(ListBase *lb, int type)
                dl= dl->next;
        }
 
-       return 0;
+       return NULL;
 }
 
 int displist_has_faces(ListBase *lb)
@@ -135,7 +143,7 @@ void copy_displist(ListBase *lbn, ListBase *lb)
 {
        DispList *dln, *dl;
        
-       lbn->first= lbn->last= 0;
+       freedisplist(lbn);
        
        dl= lb->first;
        while(dl) {
@@ -147,12 +155,15 @@ void copy_displist(ListBase *lbn, ListBase *lb)
                dln->index= MEM_dupallocN(dl->index);
                dln->col1= MEM_dupallocN(dl->col1);
                dln->col2= MEM_dupallocN(dl->col2);
-               
+
+               if(dl->bevelSplitFlag)
+                       dln->bevelSplitFlag= MEM_dupallocN(dl->bevelSplitFlag);
+
                dl= dl->next;
        }
 }
 
-void addnormalsDispList(Object *ob, ListBase *lb)
+void addnormalsDispList(ListBase *lb)
 {
        DispList *dl = NULL;
        float *vdata, *ndata, nor[3];
@@ -167,8 +178,8 @@ void addnormalsDispList(Object *ob, ListBase *lb)
                if(dl->type==DL_INDEX3) {
                        if(dl->nors==NULL) {
                                dl->nors= MEM_callocN(sizeof(float)*3, "dlnors");
-                               if(dl->verts[2]<0.0) dl->nors[2]= -1.0;
-                               else dl->nors[2]= 1.0;
+                               if(dl->verts[2] < 0.0f) dl->nors[2]= -1.0f;
+                               else dl->nors[2]= 1.0f;
                        }
                }
                else if(dl->type==DL_SURF) {
@@ -287,7 +298,7 @@ static void init_fastshade_shadeinput(Render *re)
        shi.combinedflag= -1;
 }
 
-static Render *fastshade_get_render(Scene *scene)
+static Render *fastshade_get_render(Scene *UNUSED(scene))
 {
        // XXX 2.5: this crashes combined with previewrender
        // due to global R so disabled for now
@@ -402,10 +413,10 @@ static void fastshade(float *co, float *nor, float *orco, Material *ma, char *co
                        VECCOPY(shi.orn, shi.vn);
                }
                if(ma->texco & TEXCO_REFL) {
-                       float inp= 2.0*(shi.vn[2]);
+                       float inp= 2.0f * (shi.vn[2]);
                        shi.ref[0]= (inp*shi.vn[0]);
                        shi.ref[1]= (inp*shi.vn[1]);
-                       shi.ref[2]= (-1.0+inp*shi.vn[2]);
+                       shi.ref[2]= (-1.0f + inp*shi.vn[2]);
                }
        }
        
@@ -504,10 +515,10 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un
                dm = mesh_get_derived_final(RE_GetScene(re), ob, dataMask);
        
        mvert = dm->getVertArray(dm);
-       mface = dm->getFaceArray(dm);
-       nors = dm->getFaceDataArray(dm, CD_NORMAL);
+       mface = dm->getTessFaceArray(dm);
+       nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
        totvert = dm->getNumVerts(dm);
-       totface = dm->getNumFaces(dm);
+       totface = dm->getNumTessFaces(dm);
        orco= dm->getVertDataArray(dm, CD_ORCO);
 
        if (onlyForMesh) {
@@ -578,9 +589,7 @@ static void mesh_create_shadedColors(Render *re, Object *ob, int onlyForMesh, un
 
                        mul_v3_m4v3(vec, mat, mv->co);
 
-                       vec[0]+= 0.001*vn[0];
-                       vec[1]+= 0.001*vn[1];
-                       vec[2]+= 0.001*vn[2];
+                       mul_v3_v3fl(vec, vn, 0.001f);
 
                        fastshade_customdata(&dm->faceData, i, j, ma);
                        fastshade(vec, vn, orco?&orco[vidx[j]*3]:mv->co, ma, col1, col2);
@@ -619,7 +628,6 @@ void shadeDispList(Scene *scene, Base *base)
        Object *ob= base->object;
        DispList *dl, *dlob;
        Material *ma = NULL;
-       Curve *cu;
        Render *re;
        float imat[3][3], mat[4][4], vec[3];
        float *fp, *nor, n1[3];
@@ -653,8 +661,7 @@ void shadeDispList(Scene *scene, Base *base)
                if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
                
                        /* now we need the normals */
-                       cu= ob->data;
-                       dl= cu->disp.first;
+                       dl= ob->disp.first;
                        
                        while(dl) {
                                extern Material defmaterial;    /* material.c */
@@ -786,7 +793,7 @@ void reshadeall_displist(Scene *scene)
 
 /* ****************** make displists ********************* */
 
-static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase)
+static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase, int forRender)
 {
        Nurb *nu;
        DispList *dl;
@@ -799,7 +806,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase)
        while(nu) {
                if(nu->hide==0) {
                        
-                       if(G.rendering && cu->resolu_ren!=0) 
+                       if(forRender && cu->resolu_ren!=0)
                                resolu= cu->resolu_ren;
                        else
                                resolu= nu->resolu;
@@ -926,55 +933,60 @@ void filldisplist(ListBase *dispbase, ListBase *to, int flipnormal)
 {
        EditVert *eve, *v1, *vlast;
        EditFace *efa;
-       DispList *dlnew=0, *dl;
+       DispList *dlnew=NULL, *dl;
        float *f1;
-       int colnr=0, charidx=0, cont=1, tot, a, *index;
+       int colnr=0, charidx=0, cont=1, tot, a, *index, nextcol= 0;
        intptr_t totvert;
        
-       if(dispbase==0) return;
-       if(dispbase->first==0) return;
+       if(dispbase==NULL) return;
+       if(dispbase->first==NULL) return;
 
        while(cont) {
                cont= 0;
-               totvert=0;
+               totvert= 0;
+               nextcol= 0;
+               
+               BLI_begin_edgefill();
                
                dl= dispbase->first;
                while(dl) {
        
                        if(dl->type==DL_POLY) {
                                if(charidx<dl->charidx) cont= 1;
-                               else if(charidx==dl->charidx) {
-                       
-                                       colnr= dl->col;
-                                       charidx= dl->charidx;
-               
-                                       /* make editverts and edges */
-                                       f1= dl->verts;
-                                       a= dl->nr;
-                                       eve= v1= 0;
-                                       
-                                       while(a--) {
-                                               vlast= eve;
-                                               
-                                               eve= BLI_addfillvert(f1);
-                                               totvert++;
+                               else if(charidx==dl->charidx) { /* character with needed index */
+                                       if(colnr==dl->col) {
+                                               /* make editverts and edges */
+                                               f1= dl->verts;
+                                               a= dl->nr;
+                                               eve= v1= NULL;
                                                
-                                               if(vlast==0) v1= eve;
-                                               else {
-                                                       BLI_addfilledge(vlast, eve);
+                                               while(a--) {
+                                                       vlast= eve;
+
+                                                       eve= BLI_addfillvert(f1);
+                                                       totvert++;
+
+                                                       if(vlast==NULL) v1= eve;
+                                                       else {
+                                                               BLI_addfilledge(vlast, eve);
+                                                       }
+                                                       f1+=3;
                                                }
-                                               f1+=3;
-                                       }
-                               
-                                       if(eve!=0 && v1!=0) {
-                                               BLI_addfilledge(eve, v1);
+
+                                               if(eve!=NULL && v1!=NULL) {
+                                                       BLI_addfilledge(eve, v1);
+                                               }
+                                       } else if (colnr<dl->col) {
+                                               /* got poly with next material at current char */
+                                               cont= 1;
+                                               nextcol= 1;
                                        }
                                }
                        }
                        dl= dl->next;
                }
                
-               if(totvert && BLI_edgefill(0, 0)) { // XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) {
+               if(totvert && BLI_edgefill(0)) { // XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) {
 
                        /* count faces  */
                        tot= 0;
@@ -1030,7 +1042,14 @@ void filldisplist(ListBase *dispbase, ListBase *to, int flipnormal)
                }
                BLI_end_edgefill();
 
-               charidx++;
+               if(nextcol) {
+                       /* stay at current char but fill polys with next material */
+                       colnr++;
+               } else {
+                       /* switch to next char and start filling from first material */
+                       charidx++;
+                       colnr= 0;
+               }
        }
        
        /* do not free polys, needed for wireframe display */
@@ -1044,7 +1063,7 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
        float *fp, *fp1;
        int a, dpoly;
        
-       front.first= front.last= back.first= back.last= 0;
+       front.first= front.last= back.first= back.last= NULL;
        
        dl= dispbase->first;
        while(dl) {
@@ -1105,7 +1124,7 @@ static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
        
 }
 
-static void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase)
+static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dispbase)
 {
        if(cu->flag & CU_3D) return;
 
@@ -1124,16 +1143,14 @@ static void curve_to_filledpoly(Curve *cu, ListBase *nurb, ListBase *dispbase)
 */
 float calc_taper(Scene *scene, Object *taperobj, int cur, int tot)
 {
-       Curve *cu;
        DispList *dl;
        
-       if(taperobj==NULL) return 1.0;
+       if(taperobj==NULL || taperobj->type!=OB_CURVE) return 1.0;
        
-       cu= taperobj->data;
-       dl= cu->disp.first;
+       dl= taperobj->disp.first;
        if(dl==NULL) {
                makeDispListCurveTypes(scene, taperobj, 0);
-               dl= cu->disp.first;
+               dl= taperobj->disp.first;
        }
        if(dl) {
                float fac= ((float)cur)/(float)(tot-1);
@@ -1143,7 +1160,7 @@ float calc_taper(Scene *scene, Object *taperobj, int cur, int tot)
                /* horizontal size */
                minx= dl->verts[0];
                dx= dl->verts[3*(dl->nr-1)] - minx;
-               if(dx>0.0) {
+               if(dx > 0.0f) {
                
                        fp= dl->verts;
                        for(a=0; a<dl->nr; a++, fp+=3) {
@@ -1190,6 +1207,8 @@ void makeDispListMBall(Scene *scene, Object *ob)
 void makeDispListMBall_forRender(Scene *scene, Object *ob, ListBase *dispbase)
 {
        metaball_polygonize(scene, ob, dispbase);
+       tex_space_mball(ob);
+       
        object_deform_mball(ob, dispbase);
 }
 
@@ -1206,10 +1225,20 @@ static ModifierData *curve_get_tesselate_point(Scene *scene, Object *ob, int for
 
        preTesselatePoint = NULL;
        for (; md; md=md->next) {
+               ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+
                if (!modifier_isEnabled(scene, md, required_mode)) continue;
+               if (mti->type == eModifierTypeType_Constructive) return preTesselatePoint;
 
                if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
-                       preTesselatePoint  = md;
+                       preTesselatePoint = md;
+
+                       /* this modifiers are moving point of tesselation automatically
+                          (some of them even can't be applied on tesselated curve), set flag
+                          for incformation button in modifier's header */
+                       md->mode |= eModifierMode_ApplyOnSpline;
+               } else if(md->mode&eModifierMode_ApplyOnSpline) {
+                       preTesselatePoint = md;
                }
        }
 
@@ -1221,7 +1250,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl
        ModifierData *md = modifiers_getVirtualModifierList(ob);
        ModifierData *preTesselatePoint;
        Curve *cu= ob->data;
-       ListBase *nurb= cu->editnurb?cu->editnurb:&cu->nurb;
+       ListBase *nurb= BKE_curve_nurbs(cu);
        int numVerts = 0;
        int editmode = (!forRender && cu->editnurb);
        float (*originalVerts)[3] = NULL;
@@ -1324,8 +1353,8 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba
        ModifierData *md = modifiers_getVirtualModifierList(ob);
        ModifierData *preTesselatePoint;
        Curve *cu= ob->data;
-       ListBase *nurb= cu->editnurb?cu->editnurb:&cu->nurb;
-       int required_mode, totvert = 0;
+       ListBase *nurb= BKE_curve_nurbs(cu);
+       int required_mode = 0, totvert = 0;
        int editmode = (!forRender && cu->editnurb);
        DerivedMesh *dm= NULL, *ndm;
        float (*vertCos)[3] = NULL;
@@ -1380,7 +1409,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba
 
                        if (dm) {
                                if (vertCos) {
-                                       DerivedMesh *tdm = CDDM_copy(dm);
+                                       DerivedMesh *tdm = CDDM_copy(dm, 0);
                                        dm->release(dm);
                                        dm = tdm;
 
@@ -1421,7 +1450,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba
 
        if (vertCos) {
                if (dm) {
-                       DerivedMesh *tdm = CDDM_copy(dm);
+                       DerivedMesh *tdm = CDDM_copy(dm, 0);
                        dm->release(dm);
                        dm = tdm;
 
@@ -1590,9 +1619,9 @@ void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase,
        int numVerts;
        float (*originalVerts)[3];
        float (*deformedVerts)[3];
-               
+
        if(!forRender && cu->editnurb)
-               nubase= cu->editnurb;
+               nubase= ED_curve_editnurbs(cu);
        else
                nubase= &cu->nurb;
 
@@ -1601,8 +1630,15 @@ void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase,
 
        for (nu=nubase->first; nu; nu=nu->next) {
                if(forRender || nu->hide==0) {
+                       int resolu= nu->resolu, resolv= nu->resolv;
+
+                       if(forRender){
+                               if(cu->resolu_ren) resolu= cu->resolu_ren;
+                               if(cu->resolv_ren) resolv= cu->resolv_ren;
+                       }
+
                        if(nu->pntsv==1) {
-                               len= SEGMENTSU(nu)*nu->resolu;
+                               len= SEGMENTSU(nu)*resolu;
 
                                dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
                                dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
@@ -1621,10 +1657,10 @@ void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase,
                                if(nu->flagu & CU_NURB_CYCLIC) dl->type= DL_POLY;
                                else dl->type= DL_SEGM;
 
-                               makeNurbcurve(nu, data, NULL, NULL, NULL, nu->resolu, 3*sizeof(float));
+                               makeNurbcurve(nu, data, NULL, NULL, NULL, resolu, 3*sizeof(float));
                        }
                        else {
-                               len= (nu->pntsu*nu->resolu) * (nu->pntsv*nu->resolv);
+                               len= (nu->pntsu*resolu) * (nu->pntsv*resolv);
                                
                                dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
                                dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
@@ -1640,12 +1676,12 @@ void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase,
                                data= dl->verts;
                                dl->type= DL_SURF;
 
-                               dl->parts= (nu->pntsu*nu->resolu);      /* in reverse, because makeNurbfaces works that way */
-                               dl->nr= (nu->pntsv*nu->resolv);
+                               dl->parts= (nu->pntsu*resolu);  /* in reverse, because makeNurbfaces works that way */
+                               dl->nr= (nu->pntsv*resolv);
                                if(nu->flagv & CU_NURB_CYCLIC) dl->flag|= DL_CYCL_U;    /* reverse too! */
                                if(nu->flagu & CU_NURB_CYCLIC) dl->flag|= DL_CYCL_V;
 
-                               makeNurbfaces(nu, data, 0);
+                               makeNurbfaces(nu, data, 0, resolu, resolv);
                                
                                /* gl array drawing: using indices */
                                displist_surf_indices(dl);
@@ -1653,6 +1689,11 @@ void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase,
                }
        }
 
+       /* make copy of 'undeformed" displist for texture space calculation
+          actually, it's not totally undeformed -- pre-tesselation modifiers are
+          already applied, thats how it worked for years, so keep for compatibility (sergey) */
+       copy_displist(&cu->disp, dispbase);
+
        if (!forRender) {
                tex_space_curve(cu);
        }
@@ -1680,19 +1721,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
                float (*deformedVerts)[3];
                int numVerts;
 
-               /* Bevel and taper objects should always be curves */
-               if (cu->bevobj && cu->bevobj->type != OB_CURVE) {
-                       cu->bevobj = NULL;
-               }
-
-               if (cu->taperobj && cu->taperobj->type != OB_CURVE) {
-                       cu->taperobj = NULL;
-               }
-
-               if(cu->editnurb)
-                       nubase= cu->editnurb;
-               else
-                       nubase= &cu->nurb;
+               nubase= BKE_curve_nurbs(cu);
 
                BLI_freelistN(&(cu->bev));
 
@@ -1710,9 +1739,9 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
 
                /* no bevel or extrude, and no width correction? */
                if (!dlbev.first && cu->width==1.0f) {
-                       curve_to_displist(cu, nubase, dispbase);
+                       curve_to_displist(cu, nubase, dispbase, forRender);
                } else {
-                       float widfac= cu->width-1.0;
+                       float widfac= cu->width - 1.0f;
                        BevList *bl= cu->bev.first;
                        Nurb *nu= nubase->first;
 
@@ -1780,8 +1809,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
                                                        /* CU_2D conflicts with R_NOPUNOFLIP */
                                                        dl->rt= nu->flag & ~CU_2D;
 
-                                                       dl->bevelSplitFlag= MEM_callocN(sizeof(*dl->col2)*((bl->nr+0x1F)>>5), "col2");
-                                                       bevp= (BevPoint *)(bl+1);
+                                                       dl->bevelSplitFlag= MEM_callocN(sizeof(*dl->col2)*((bl->nr+0x1F)>>5), "bevelSplitFlag");
        
                                                        /* for each point of poly make a bevel piece */
                                                        bevp= (BevPoint *)(bl+1);
@@ -1838,9 +1866,14 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
 
                if(cu->flag & CU_PATH) calc_curvepath(ob);
 
-                if (!forRender) {
-                        tex_space_curve(cu);
-                }
+               /* make copy of 'undeformed" displist for texture space calculation
+                  actually, it's not totally undeformed -- pre-tesselation modifiers are
+                  already applied, thats how it worked for years, so keep for compatibility (sergey) */
+               copy_displist(&cu->disp, dispbase);
+
+               if (!forRender) {
+                       tex_space_curve(cu);
+               }
 
                if(!forOrco) curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal, forRender, originalVerts, deformedVerts);
 
@@ -1852,13 +1885,16 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
 
 void makeDispListCurveTypes(Scene *scene, Object *ob, int forOrco)
 {
-       Curve *cu = ob->data;
+       Curve *cu= ob->data;
        ListBase *dispbase;
 
        freedisplist(&(ob->disp));
-       dispbase= &(cu->disp);
+       dispbase= &(ob->disp);
        freedisplist(dispbase);
 
+       /* free displist used for textspace */
+       freedisplist(&cu->disp);
+
        do_makeDispListCurveTypes(scene, ob, dispbase, &ob->derivedFinal, 0, forOrco);
 
        if (ob->derivedFinal) {
@@ -1905,15 +1941,10 @@ float *makeOrcoDispList(Scene *scene, Object *ob, DerivedMesh *derivedFinal, int
        return orco;
 }
 
-void imagestodisplist(void)
-{
-       /* removed */
-}
-
 /* this is confusing, there's also min_max_object, appplying the obmat... */
 static void boundbox_displist(Object *ob)
 {
-       BoundBox *bb=0;
+       BoundBox *bb=NULL;
        float min[3], max[3];
        DispList *dl;
        float *vert;
@@ -1925,10 +1956,10 @@ static void boundbox_displist(Object *ob)
                Curve *cu= ob->data;
                int doit= 0;
 
-               if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
+               if(cu->bb==NULL) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
                bb= cu->bb;
                
-               dl= cu->disp.first;
+               dl= ob->disp.first;
 
                while (dl) {
                        if(dl->type==DL_INDEX3) tot= dl->nr;