Blender  V2.59
displist.c
Go to the documentation of this file.
00001 /*  displist.c
00002  * 
00003  * 
00004  * $Id: displist.c 37504 2011-06-15 10:17:06Z blendix $
00005  *
00006  * ***** BEGIN GPL LICENSE BLOCK *****
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License
00010  * as published by the Free Software Foundation; either version 2
00011  * of the License, or (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software Foundation,
00020  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00021  *
00022  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00023  * All rights reserved.
00024  *
00025  * The Original Code is: all of this file.
00026  *
00027  * Contributor(s): none yet.
00028  *
00029  * ***** END GPL LICENSE BLOCK *****
00030  */
00031 
00037 #include <math.h>
00038 #include <stdio.h>
00039 #include <string.h>
00040 
00041 #include "MEM_guardedalloc.h"
00042 
00043 #include "DNA_curve_types.h"
00044 #include "DNA_meshdata_types.h"
00045 #include "DNA_scene_types.h"
00046 #include "DNA_object_types.h"
00047 #include "DNA_material_types.h"
00048 
00049 #include "BLI_blenlib.h"
00050 #include "BLI_math.h"
00051 #include "BLI_editVert.h"
00052 #include "BLI_scanfill.h"
00053 #include "BLI_utildefines.h"
00054 
00055 #include "BKE_global.h"
00056 #include "BKE_displist.h"
00057 #include "BKE_cdderivedmesh.h"
00058 #include "BKE_object.h"
00059 #include "BKE_mball.h"
00060 #include "BKE_material.h"
00061 #include "BKE_curve.h"
00062 #include "BKE_key.h"
00063 #include "BKE_anim.h"
00064 #include "BKE_font.h"
00065 #include "BKE_lattice.h"
00066 #include "BKE_modifier.h"
00067 
00068 #include "BLO_sys_types.h" // for intptr_t support
00069 
00070 #include "ED_curve.h" /* for BKE_curve_nurbs */
00071 
00072 extern Material defmaterial;    /* material.c */
00073 
00074 static void boundbox_displist(Object *ob);
00075 
00076 void free_disp_elem(DispList *dl)
00077 {
00078         if(dl) {
00079                 if(dl->verts) MEM_freeN(dl->verts);
00080                 if(dl->nors) MEM_freeN(dl->nors);
00081                 if(dl->index) MEM_freeN(dl->index);
00082                 if(dl->col1) MEM_freeN(dl->col1);
00083                 if(dl->col2) MEM_freeN(dl->col2);
00084                 if(dl->bevelSplitFlag) MEM_freeN(dl->bevelSplitFlag);
00085                 MEM_freeN(dl);
00086         }
00087 }
00088 
00089 void freedisplist(ListBase *lb)
00090 {
00091         DispList *dl;
00092 
00093         dl= lb->first;
00094         while(dl) {
00095                 BLI_remlink(lb, dl);
00096                 free_disp_elem(dl);
00097                 dl= lb->first;
00098         }
00099 }
00100 
00101 DispList *find_displist_create(ListBase *lb, int type)
00102 {
00103         DispList *dl;
00104         
00105         dl= lb->first;
00106         while(dl) {
00107                 if(dl->type==type) return dl;
00108                 dl= dl->next;
00109         }
00110 
00111         dl= MEM_callocN(sizeof(DispList), "find_disp");
00112         dl->type= type;
00113         BLI_addtail(lb, dl);
00114 
00115         return dl;
00116 }
00117 
00118 DispList *find_displist(ListBase *lb, int type)
00119 {
00120         DispList *dl;
00121         
00122         dl= lb->first;
00123         while(dl) {
00124                 if(dl->type==type) return dl;
00125                 dl= dl->next;
00126         }
00127 
00128         return NULL;
00129 }
00130 
00131 int displist_has_faces(ListBase *lb)
00132 {
00133         DispList *dl;
00134         for(dl= lb->first; dl; dl= dl->next) {
00135                 if ELEM3(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)
00136                         return 1;
00137         }
00138         return 0;
00139 }
00140 
00141 void copy_displist(ListBase *lbn, ListBase *lb)
00142 {
00143         DispList *dln, *dl;
00144         
00145         freedisplist(lbn);
00146         
00147         dl= lb->first;
00148         while(dl) {
00149                 
00150                 dln= MEM_dupallocN(dl);
00151                 BLI_addtail(lbn, dln);
00152                 dln->verts= MEM_dupallocN(dl->verts);
00153                 dln->nors= MEM_dupallocN(dl->nors);
00154                 dln->index= MEM_dupallocN(dl->index);
00155                 dln->col1= MEM_dupallocN(dl->col1);
00156                 dln->col2= MEM_dupallocN(dl->col2);
00157 
00158                 if(dl->bevelSplitFlag)
00159                         dln->bevelSplitFlag= MEM_dupallocN(dl->bevelSplitFlag);
00160 
00161                 dl= dl->next;
00162         }
00163 }
00164 
00165 void addnormalsDispList(ListBase *lb)
00166 {
00167         DispList *dl = NULL;
00168         float *vdata, *ndata, nor[3];
00169         float *v1, *v2, *v3, *v4;
00170         float *n1, *n2, *n3, *n4;
00171         int a, b, p1, p2, p3, p4;
00172 
00173 
00174         dl= lb->first;
00175         
00176         while(dl) {
00177                 if(dl->type==DL_INDEX3) {
00178                         if(dl->nors==NULL) {
00179                                 dl->nors= MEM_callocN(sizeof(float)*3, "dlnors");
00180                                 if(dl->verts[2] < 0.0f) dl->nors[2]= -1.0f;
00181                                 else dl->nors[2]= 1.0f;
00182                         }
00183                 }
00184                 else if(dl->type==DL_SURF) {
00185                         if(dl->nors==NULL) {
00186                                 dl->nors= MEM_callocN(sizeof(float)*3*dl->nr*dl->parts, "dlnors");
00187                                 
00188                                 vdata= dl->verts;
00189                                 ndata= dl->nors;
00190                                 
00191                                 for(a=0; a<dl->parts; a++) {
00192                                         
00193                                         if (surfindex_displist(dl, a, &b, &p1, &p2, &p3, &p4)==0)
00194                                                 break;
00195         
00196                                         v1= vdata+ 3*p1; 
00197                                         n1= ndata+ 3*p1;
00198                                         v2= vdata+ 3*p2; 
00199                                         n2= ndata+ 3*p2;
00200                                         v3= vdata+ 3*p3; 
00201                                         n3= ndata+ 3*p3;
00202                                         v4= vdata+ 3*p4; 
00203                                         n4= ndata+ 3*p4;
00204                                         
00205                                         for(; b<dl->nr; b++) {
00206         
00207                                                 normal_quad_v3( nor,v1, v3, v4, v2);
00208         
00209                                                 add_v3_v3(n1, nor);
00210                                                 add_v3_v3(n2, nor);
00211                                                 add_v3_v3(n3, nor);
00212                                                 add_v3_v3(n4, nor);
00213         
00214                                                 v2= v1; v1+= 3;
00215                                                 v4= v3; v3+= 3;
00216                                                 n2= n1; n1+= 3;
00217                                                 n4= n3; n3+= 3;
00218                                         }
00219                                 }
00220                                 a= dl->parts*dl->nr;
00221                                 v1= ndata;
00222                                 while(a--) {
00223                                         normalize_v3(v1);
00224                                         v1+= 3;
00225                                 }
00226                         }
00227                 }
00228                 dl= dl->next;
00229         }
00230 }
00231 
00232 void count_displist(ListBase *lb, int *totvert, int *totface)
00233 {
00234         DispList *dl;
00235         
00236         dl= lb->first;
00237         while(dl) {
00238                 
00239                 switch(dl->type) {
00240                         case DL_SURF:
00241                                 *totvert+= dl->nr*dl->parts;
00242                                 *totface+= (dl->nr-1)*(dl->parts-1);
00243                                 break;
00244                         case DL_INDEX3:
00245                         case DL_INDEX4:
00246                                 *totvert+= dl->nr;
00247                                 *totface+= dl->parts;
00248                                 break;
00249                         case DL_POLY:
00250                         case DL_SEGM:
00251                                 *totvert+= dl->nr*dl->parts;
00252                 }
00253                 
00254                 dl= dl->next;
00255         }
00256 }
00257 
00258 int surfindex_displist(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4)
00259 {
00260         if((dl->flag & DL_CYCL_V)==0 && a==(dl->parts)-1) {
00261                 return 0;
00262         }
00263         
00264         if(dl->flag & DL_CYCL_U) {
00265                 (*p1)= dl->nr*a;
00266                 (*p2)= (*p1)+ dl->nr-1;
00267                 (*p3)= (*p1)+ dl->nr;
00268                 (*p4)= (*p2)+ dl->nr;
00269                 (*b)= 0;
00270         } else {
00271                 (*p2)= dl->nr*a;
00272                 (*p1)= (*p2)+1;
00273                 (*p4)= (*p2)+ dl->nr;
00274                 (*p3)= (*p1)+ dl->nr;
00275                 (*b)= 1;
00276         }
00277         
00278         if( (dl->flag & DL_CYCL_V) && a==dl->parts-1) {                     \
00279                 (*p3)-= dl->nr*dl->parts;                                   \
00280                 (*p4)-= dl->nr*dl->parts;                                   \
00281         }
00282         
00283         return 1;
00284 }
00285 
00286 /* ****************** make displists ********************* */
00287 
00288 static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase, int forRender)
00289 {
00290         Nurb *nu;
00291         DispList *dl;
00292         BezTriple *bezt, *prevbezt;
00293         BPoint *bp;
00294         float *data;
00295         int a, len, resolu;
00296         
00297         nu= nubase->first;
00298         while(nu) {
00299                 if(nu->hide==0) {
00300                         
00301                         if(forRender && cu->resolu_ren!=0)
00302                                 resolu= cu->resolu_ren;
00303                         else
00304                                 resolu= nu->resolu;
00305                         
00306                         if(!check_valid_nurb_u(nu));
00307                         else if(nu->type == CU_BEZIER) {
00308                                 
00309                                 /* count */
00310                                 len= 0;
00311                                 a= nu->pntsu-1;
00312                                 if(nu->flagu & CU_NURB_CYCLIC) a++;
00313 
00314                                 prevbezt= nu->bezt;
00315                                 bezt= prevbezt+1;
00316                                 while(a--) {
00317                                         if(a==0 && (nu->flagu & CU_NURB_CYCLIC)) bezt= nu->bezt;
00318                                         
00319                                         if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) len++;
00320                                         else len+= resolu;
00321                                         
00322                                         if(a==0 && (nu->flagu & CU_NURB_CYCLIC)==0) len++;
00323                                         
00324                                         prevbezt= bezt;
00325                                         bezt++;
00326                                 }
00327                                 
00328                                 dl= MEM_callocN(sizeof(DispList), "makeDispListbez");
00329                                 /* len+1 because of 'forward_diff_bezier' function */
00330                                 dl->verts= MEM_callocN( (len+1)*3*sizeof(float), "dlverts");
00331                                 BLI_addtail(dispbase, dl);
00332                                 dl->parts= 1;
00333                                 dl->nr= len;
00334                                 dl->col= nu->mat_nr;
00335                                 dl->charidx= nu->charidx;
00336 
00337                                 data= dl->verts;
00338 
00339                                 if(nu->flagu & CU_NURB_CYCLIC) {
00340                                         dl->type= DL_POLY;
00341                                         a= nu->pntsu;
00342                                 }
00343                                 else {
00344                                         dl->type= DL_SEGM;
00345                                         a= nu->pntsu-1;
00346                                 }
00347                                 
00348                                 prevbezt= nu->bezt;
00349                                 bezt= prevbezt+1;
00350                                 
00351                                 while(a--) {
00352                                         if(a==0 && dl->type== DL_POLY) bezt= nu->bezt;
00353                                         
00354                                         if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) {
00355                                                 VECCOPY(data, prevbezt->vec[1]);
00356                                                 data+= 3;
00357                                         }
00358                                         else {
00359                                                 int j;
00360                                                 for(j=0; j<3; j++) {
00361                                                         forward_diff_bezier(    prevbezt->vec[1][j],
00362                                                                                                         prevbezt->vec[2][j],
00363                                                                                                         bezt->vec[0][j],
00364                                                                                                         bezt->vec[1][j],
00365                                                                                                         data+j, resolu, 3*sizeof(float));
00366                                                 }
00367                                                 
00368                                                 data+= 3*resolu;
00369                                         }
00370                                         
00371                                         if(a==0 && dl->type==DL_SEGM) {
00372                                                 VECCOPY(data, bezt->vec[1]);
00373                                         }
00374                                         
00375                                         prevbezt= bezt;
00376                                         bezt++;
00377                                 }
00378                         }
00379                         else if(nu->type == CU_NURBS) {
00380                                 len= (resolu*SEGMENTSU(nu));
00381                                 
00382                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
00383                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
00384                                 BLI_addtail(dispbase, dl);
00385                                 dl->parts= 1;
00386                                 
00387                                 dl->nr= len;
00388                                 dl->col= nu->mat_nr;
00389                                 dl->charidx = nu->charidx;
00390 
00391                                 data= dl->verts;
00392                                 if(nu->flagu & CU_NURB_CYCLIC) dl->type= DL_POLY;
00393                                 else dl->type= DL_SEGM;
00394                                 makeNurbcurve(nu, data, NULL, NULL, NULL, resolu, 3*sizeof(float));
00395                         }
00396                         else if(nu->type == CU_POLY) {
00397                                 len= nu->pntsu;
00398                                 dl= MEM_callocN(sizeof(DispList), "makeDispListpoly");
00399                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
00400                                 BLI_addtail(dispbase, dl);
00401                                 dl->parts= 1;
00402                                 dl->nr= len;
00403                                 dl->col= nu->mat_nr;
00404                                 dl->charidx = nu->charidx;
00405 
00406                                 data= dl->verts;
00407                                 if(nu->flagu & CU_NURB_CYCLIC) dl->type= DL_POLY;
00408                                 else dl->type= DL_SEGM;
00409                                 
00410                                 a= len;
00411                                 bp= nu->bp;
00412                                 while(a--) {
00413                                         VECCOPY(data, bp->vec);
00414                                         bp++;
00415                                         data+= 3;
00416                                 }
00417                         }
00418                 }
00419                 nu= nu->next;
00420         }
00421 }
00422 
00423 
00424 void filldisplist(ListBase *dispbase, ListBase *to, int flipnormal)
00425 {
00426         EditVert *eve, *v1, *vlast;
00427         EditFace *efa;
00428         DispList *dlnew=NULL, *dl;
00429         float *f1;
00430         int colnr=0, charidx=0, cont=1, tot, a, *index, nextcol= 0;
00431         intptr_t totvert;
00432         
00433         if(dispbase==NULL) return;
00434         if(dispbase->first==NULL) return;
00435 
00436         while(cont) {
00437                 cont= 0;
00438                 totvert= 0;
00439                 nextcol= 0;
00440                 
00441                 dl= dispbase->first;
00442                 while(dl) {
00443         
00444                         if(dl->type==DL_POLY) {
00445                                 if(charidx<dl->charidx) cont= 1;
00446                                 else if(charidx==dl->charidx) { /* character with needed index */
00447                                         if(colnr==dl->col) {
00448                                                 /* make editverts and edges */
00449                                                 f1= dl->verts;
00450                                                 a= dl->nr;
00451                                                 eve= v1= NULL;
00452                                                 
00453                                                 while(a--) {
00454                                                         vlast= eve;
00455 
00456                                                         eve= BLI_addfillvert(f1);
00457                                                         totvert++;
00458 
00459                                                         if(vlast==NULL) v1= eve;
00460                                                         else {
00461                                                                 BLI_addfilledge(vlast, eve);
00462                                                         }
00463                                                         f1+=3;
00464                                                 }
00465 
00466                                                 if(eve!=NULL && v1!=NULL) {
00467                                                         BLI_addfilledge(eve, v1);
00468                                                 }
00469                                         } else if (colnr<dl->col) {
00470                                                 /* got poly with next material at current char */
00471                                                 cont= 1;
00472                                                 nextcol= 1;
00473                                         }
00474                                 }
00475                         }
00476                         dl= dl->next;
00477                 }
00478                 
00479                 if(totvert && (tot= BLI_edgefill(0))) { // XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) {
00480                         if(tot) {
00481                                 dlnew= MEM_callocN(sizeof(DispList), "filldisplist");
00482                                 dlnew->type= DL_INDEX3;
00483                                 dlnew->col= colnr;
00484                                 dlnew->nr= totvert;
00485                                 dlnew->parts= tot;
00486 
00487                                 dlnew->index= MEM_mallocN(tot*3*sizeof(int), "dlindex");
00488                                 dlnew->verts= MEM_mallocN(totvert*3*sizeof(float), "dlverts");
00489                                 
00490                                 /* vert data */
00491                                 f1= dlnew->verts;
00492                                 totvert= 0;
00493                                 eve= fillvertbase.first;
00494                                 while(eve) {
00495                                         VECCOPY(f1, eve->co);
00496                                         f1+= 3;
00497         
00498                                         /* index number */
00499                                         eve->tmp.l = totvert;
00500                                         totvert++;
00501                                         
00502                                         eve= eve->next;
00503                                 }
00504                                 
00505                                 /* index data */
00506                                 efa= fillfacebase.first;
00507                                 index= dlnew->index;
00508                                 while(efa) {
00509                                         index[0]= (intptr_t)efa->v1->tmp.l;
00510                                         index[1]= (intptr_t)efa->v2->tmp.l;
00511                                         index[2]= (intptr_t)efa->v3->tmp.l;
00512 
00513                                         if(flipnormal)
00514                                                 SWAP(int, index[0], index[2]);
00515                                         
00516                                         index+= 3;
00517                                         efa= efa->next;
00518                                 }
00519                         }
00520 
00521                         BLI_addhead(to, dlnew);
00522                         
00523                 }
00524                 BLI_end_edgefill();
00525 
00526                 if(nextcol) {
00527                         /* stay at current char but fill polys with next material */
00528                         colnr++;
00529                 } else {
00530                         /* switch to next char and start filling from first material */
00531                         charidx++;
00532                         colnr= 0;
00533                 }
00534         }
00535         
00536         /* do not free polys, needed for wireframe display */
00537         
00538 }
00539 
00540 static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
00541 {
00542         ListBase front, back;
00543         DispList *dl, *dlnew;
00544         float *fp, *fp1;
00545         int a, dpoly;
00546         
00547         front.first= front.last= back.first= back.last= NULL;
00548         
00549         dl= dispbase->first;
00550         while(dl) {
00551                 if(dl->type==DL_SURF) {
00552                         if( (dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U)==0 ) {
00553                                 if( (cu->flag & CU_BACK) && (dl->flag & DL_BACK_CURVE) ) {
00554                                         dlnew= MEM_callocN(sizeof(DispList), "filldisp");
00555                                         BLI_addtail(&front, dlnew);
00556                                         dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1");
00557                                         dlnew->nr= dl->parts;
00558                                         dlnew->parts= 1;
00559                                         dlnew->type= DL_POLY;
00560                                         dlnew->col= dl->col;
00561                                         dlnew->charidx = dl->charidx;
00562                                         
00563                                         fp= dl->verts;
00564                                         dpoly= 3*dl->nr;
00565                                         
00566                                         a= dl->parts;
00567                                         while(a--) {
00568                                                 VECCOPY(fp1, fp);
00569                                                 fp1+= 3;
00570                                                 fp+= dpoly;
00571                                         }
00572                                 }
00573                                 if( (cu->flag & CU_FRONT) && (dl->flag & DL_FRONT_CURVE) ) {
00574                                         dlnew= MEM_callocN(sizeof(DispList), "filldisp");
00575                                         BLI_addtail(&back, dlnew);
00576                                         dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1");
00577                                         dlnew->nr= dl->parts;
00578                                         dlnew->parts= 1;
00579                                         dlnew->type= DL_POLY;
00580                                         dlnew->col= dl->col;
00581                                         dlnew->charidx= dl->charidx;
00582                                         
00583                                         fp= dl->verts+3*(dl->nr-1);
00584                                         dpoly= 3*dl->nr;
00585                                         
00586                                         a= dl->parts;
00587                                         while(a--) {
00588                                                 VECCOPY(fp1, fp);
00589                                                 fp1+= 3;
00590                                                 fp+= dpoly;
00591                                         }
00592                                 }
00593                         }
00594                 }
00595                 dl= dl->next;
00596         }
00597 
00598         filldisplist(&front, dispbase, 1);
00599         filldisplist(&back, dispbase, 0);
00600         
00601         freedisplist(&front);
00602         freedisplist(&back);
00603 
00604         filldisplist(dispbase, dispbase, 0);
00605         
00606 }
00607 
00608 static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dispbase)
00609 {
00610         if(cu->flag & CU_3D) return;
00611 
00612         if(dispbase->first && ((DispList*) dispbase->first)->type==DL_SURF) {
00613                 bevels_to_filledpoly(cu, dispbase);
00614         }
00615         else {
00616                 filldisplist(dispbase, dispbase, 0);
00617         }
00618 }
00619 
00620 /* taper rules:
00621   - only 1 curve
00622   - first point left, last point right
00623   - based on subdivided points in original curve, not on points in taper curve (still)
00624 */
00625 float calc_taper(Scene *scene, Object *taperobj, int cur, int tot)
00626 {
00627         DispList *dl;
00628         
00629         if(taperobj==NULL || taperobj->type!=OB_CURVE) return 1.0;
00630         
00631         dl= taperobj->disp.first;
00632         if(dl==NULL) {
00633                 makeDispListCurveTypes(scene, taperobj, 0);
00634                 dl= taperobj->disp.first;
00635         }
00636         if(dl) {
00637                 float fac= ((float)cur)/(float)(tot-1);
00638                 float minx, dx, *fp;
00639                 int a;
00640                 
00641                 /* horizontal size */
00642                 minx= dl->verts[0];
00643                 dx= dl->verts[3*(dl->nr-1)] - minx;
00644                 if(dx > 0.0f) {
00645                 
00646                         fp= dl->verts;
00647                         for(a=0; a<dl->nr; a++, fp+=3) {
00648                                 if( (fp[0]-minx)/dx >= fac) {
00649                                         /* interpolate with prev */
00650                                         if(a>0) {
00651                                                 float fac1= (fp[-3]-minx)/dx;
00652                                                 float fac2= (fp[0]-minx)/dx;
00653                                                 if(fac1!=fac2)
00654                                                         return fp[1]*(fac1-fac)/(fac1-fac2) + fp[-2]*(fac-fac2)/(fac1-fac2);
00655                                         }
00656                                         return fp[1];
00657                                 }
00658                         }
00659                         return fp[-2];  // last y coord
00660                 }
00661         }
00662         
00663         return 1.0;
00664 }
00665 
00666 void makeDispListMBall(Scene *scene, Object *ob)
00667 {
00668         if(!ob || ob->type!=OB_MBALL) return;
00669 
00670         // XXX: mball stuff uses plenty of global variables
00671         //      while this is unchanged updating during render is unsafe
00672         if(G.rendering) return;
00673 
00674         freedisplist(&(ob->disp));
00675 
00676         if(ob->type==OB_MBALL) {
00677                 if(ob==find_basis_mball(scene, ob)) {
00678                         metaball_polygonize(scene, ob, &ob->disp);
00679                         tex_space_mball(ob);
00680 
00681                         object_deform_mball(ob, &ob->disp);
00682                 }
00683         }
00684         
00685         boundbox_displist(ob);
00686 }
00687 
00688 void makeDispListMBall_forRender(Scene *scene, Object *ob, ListBase *dispbase)
00689 {
00690         metaball_polygonize(scene, ob, dispbase);
00691         tex_space_mball(ob);
00692         
00693         object_deform_mball(ob, dispbase);
00694 }
00695 
00696 static ModifierData *curve_get_tesselate_point(Scene *scene, Object *ob, int forRender, int editmode)
00697 {
00698         ModifierData *md = modifiers_getVirtualModifierList(ob);
00699         ModifierData *preTesselatePoint;
00700         int required_mode;
00701 
00702         if(forRender) required_mode = eModifierMode_Render;
00703         else required_mode = eModifierMode_Realtime;
00704 
00705         if(editmode) required_mode |= eModifierMode_Editmode;
00706 
00707         preTesselatePoint = NULL;
00708         for (; md; md=md->next) {
00709                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
00710 
00711                 if (!modifier_isEnabled(scene, md, required_mode)) continue;
00712                 if (mti->type == eModifierTypeType_Constructive) return preTesselatePoint;
00713 
00714                 if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
00715                         preTesselatePoint = md;
00716 
00717                         /* this modifiers are moving point of tesselation automatically
00718                            (some of them even can't be applied on tesselated curve), set flag
00719                            for incformation button in modifier's header */
00720                         md->mode |= eModifierMode_ApplyOnSpline;
00721                 } else if(md->mode&eModifierMode_ApplyOnSpline) {
00722                         preTesselatePoint = md;
00723                 }
00724         }
00725 
00726         return preTesselatePoint;
00727 }
00728 
00729 static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, float (**originalVerts_r)[3], float (**deformedVerts_r)[3], int *numVerts_r)
00730 {
00731         ModifierData *md = modifiers_getVirtualModifierList(ob);
00732         ModifierData *preTesselatePoint;
00733         Curve *cu= ob->data;
00734         ListBase *nurb= BKE_curve_nurbs(cu);
00735         int numVerts = 0;
00736         int editmode = (!forRender && cu->editnurb);
00737         float (*originalVerts)[3] = NULL;
00738         float (*deformedVerts)[3] = NULL;
00739         float *keyVerts= NULL;
00740         int required_mode;
00741 
00742         if(forRender) required_mode = eModifierMode_Render;
00743         else required_mode = eModifierMode_Realtime;
00744 
00745         preTesselatePoint = curve_get_tesselate_point(scene, ob, forRender, editmode);
00746         
00747         if(editmode) required_mode |= eModifierMode_Editmode;
00748 
00749         if(cu->editnurb==NULL) {
00750                 keyVerts= do_ob_key(scene, ob);
00751 
00752                 if(keyVerts) {
00753                         /* split coords from key data, the latter also includes
00754                            tilts, which is passed through in the modifier stack.
00755                            this is also the reason curves do not use a virtual
00756                            shape key modifier yet. */
00757                         deformedVerts= curve_getKeyVertexCos(cu, nurb, keyVerts);
00758                         originalVerts= MEM_dupallocN(deformedVerts);
00759                 }
00760         }
00761         
00762         if (preTesselatePoint) {
00763                 for (; md; md=md->next) {
00764                         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
00765 
00766                         md->scene= scene;
00767                         
00768                         if ((md->mode & required_mode) != required_mode) continue;
00769                         if (mti->isDisabled && mti->isDisabled(md, forRender)) continue;
00770                         if (mti->type!=eModifierTypeType_OnlyDeform) continue;
00771 
00772                         if (!deformedVerts) {
00773                                 deformedVerts = curve_getVertexCos(cu, nurb, &numVerts);
00774                                 originalVerts = MEM_dupallocN(deformedVerts);
00775                         }
00776 
00777                         mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, forRender, editmode);
00778 
00779                         if (md==preTesselatePoint)
00780                                 break;
00781                 }
00782         }
00783 
00784         if (deformedVerts)
00785                 curve_applyVertexCos(cu, nurb, deformedVerts);
00786         if (keyVerts) /* these are not passed through modifier stack */
00787                 curve_applyKeyVertexTilts(cu, nurb, keyVerts);
00788 
00789         if(keyVerts)
00790                 MEM_freeN(keyVerts);
00791 
00792         *originalVerts_r = originalVerts;
00793         *deformedVerts_r = deformedVerts;
00794         *numVerts_r = numVerts;
00795 }
00796 
00797 static float (*displist_get_allverts (ListBase *dispbase, int *totvert))[3]
00798 {
00799         DispList *dl;
00800         float (*allverts)[3], *fp;
00801 
00802         *totvert= 0;
00803 
00804         for (dl=dispbase->first; dl; dl=dl->next)
00805                 *totvert+= (dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr;
00806 
00807         allverts= MEM_mallocN((*totvert)*sizeof(float)*3, "displist_get_allverts allverts");
00808         fp= (float*)allverts;
00809         for (dl=dispbase->first; dl; dl=dl->next) {
00810                 int offs= 3 * ((dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr);
00811                 memcpy(fp, dl->verts, sizeof(float) * offs);
00812                 fp+= offs;
00813         }
00814 
00815         return allverts;
00816 }
00817 
00818 static void displist_apply_allverts(ListBase *dispbase, float (*allverts)[3])
00819 {
00820         DispList *dl;
00821         float *fp;
00822 
00823         fp= (float*)allverts;
00824         for (dl=dispbase->first; dl; dl=dl->next) {
00825                 int offs= 3 * ((dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr);
00826                 memcpy(dl->verts, fp, sizeof(float) * offs);
00827                 fp+= offs;
00828         }
00829 }
00830 
00831 static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispbase,
00832         DerivedMesh **derivedFinal, int forRender, float (*originalVerts)[3], float (*deformedVerts)[3])
00833 {
00834         ModifierData *md = modifiers_getVirtualModifierList(ob);
00835         ModifierData *preTesselatePoint;
00836         Curve *cu= ob->data;
00837         ListBase *nurb= BKE_curve_nurbs(cu);
00838         int required_mode = 0, totvert = 0;
00839         int editmode = (!forRender && cu->editnurb);
00840         DerivedMesh *dm= NULL, *ndm;
00841         float (*vertCos)[3] = NULL;
00842 
00843         if(forRender) required_mode = eModifierMode_Render;
00844         else required_mode = eModifierMode_Realtime;
00845 
00846         preTesselatePoint = curve_get_tesselate_point(scene, ob, forRender, editmode);
00847         
00848         if(editmode) required_mode |= eModifierMode_Editmode;
00849 
00850         if (preTesselatePoint) {
00851                 md = preTesselatePoint->next;
00852         }
00853 
00854         if (derivedFinal && *derivedFinal) {
00855                 (*derivedFinal)->release (*derivedFinal);
00856         }
00857 
00858         for (; md; md=md->next) {
00859                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
00860 
00861                 md->scene= scene;
00862 
00863                 if ((md->mode & required_mode) != required_mode) continue;
00864                 if (mti->isDisabled && mti->isDisabled(md, forRender)) continue;
00865 
00866                 if (mti->type == eModifierTypeType_OnlyDeform ||
00867                                 (mti->type == eModifierTypeType_DeformOrConstruct && !dm)) {
00868                         if (dm) {
00869                                 if (!vertCos) {
00870                                         totvert = dm->getNumVerts(dm);
00871                                         vertCos = MEM_mallocN(sizeof(*vertCos) * totvert, "dfmv");
00872                                         dm->getVertCos(dm, vertCos);
00873                                 }
00874 
00875                                 mti->deformVerts(md, ob, dm, vertCos, totvert, forRender, editmode);
00876                         } else {
00877                                 if (!vertCos) {
00878                                         vertCos= displist_get_allverts(dispbase, &totvert);
00879                                 }
00880 
00881                                 mti->deformVerts(md, ob, NULL, vertCos, totvert, forRender, editmode);
00882                         }
00883                 } else {
00884                         if (!derivedFinal) {
00885                                 /* makeDisplistCurveTypes could be used for beveling, where derived mesh */
00886                                 /* is totally unnecessary, so we could stop modifiers applying */
00887                                 /* when we found constructive modifier but derived mesh is unwanted result */
00888                                 break;
00889                         }
00890 
00891                         if (dm) {
00892                                 if (vertCos) {
00893                                         DerivedMesh *tdm = CDDM_copy(dm);
00894                                         dm->release(dm);
00895                                         dm = tdm;
00896 
00897                                         CDDM_apply_vert_coords(dm, vertCos);
00898                                         CDDM_calc_normals(dm);
00899                                 }
00900                         } else {
00901                                 if (vertCos) {
00902                                         displist_apply_allverts(dispbase, vertCos);
00903                                 }
00904 
00905                                 if (ELEM(ob->type, OB_CURVE, OB_FONT) && (cu->flag & CU_DEFORM_FILL)) {
00906                                         curve_to_filledpoly(cu, nurb, dispbase);
00907                                 }
00908 
00909                                 dm= CDDM_from_curve_customDB(ob, dispbase);
00910 
00911                                 CDDM_calc_normals(dm);
00912                         }
00913 
00914                         if (vertCos) {
00915                                 /* Vertex coordinates were applied to necessary data, could free it */
00916                                 MEM_freeN(vertCos);
00917                                 vertCos= NULL;
00918                         }
00919 
00920                         ndm = mti->applyModifier(md, ob, dm, forRender, editmode);
00921 
00922                         if (ndm) {
00923                                 /* Modifier returned a new derived mesh */
00924 
00925                                 if (dm && dm != ndm) /* Modifier  */
00926                                         dm->release (dm);
00927                                 dm = ndm;
00928                         }
00929                 }
00930         }
00931 
00932         if (vertCos) {
00933                 if (dm) {
00934                         DerivedMesh *tdm = CDDM_copy(dm);
00935                         dm->release(dm);
00936                         dm = tdm;
00937 
00938                         CDDM_apply_vert_coords(dm, vertCos);
00939                         CDDM_calc_normals(dm);
00940                         MEM_freeN(vertCos);
00941                 } else {
00942                         displist_apply_allverts(dispbase, vertCos);
00943                         MEM_freeN(vertCos);
00944                         vertCos= NULL;
00945                 }
00946         }
00947 
00948         if (derivedFinal) {
00949                 (*derivedFinal) = dm;
00950         }
00951 
00952         if (deformedVerts) {
00953                 curve_applyVertexCos(ob->data, nurb, originalVerts);
00954                 MEM_freeN(originalVerts);
00955                 MEM_freeN(deformedVerts);
00956         }
00957 }
00958 
00959 static void displist_surf_indices(DispList *dl)
00960 {
00961         int a, b, p1, p2, p3, p4;
00962         int *index;
00963         
00964         dl->totindex= 0;
00965         
00966         index=dl->index= MEM_mallocN( 4*sizeof(int)*(dl->parts+1)*(dl->nr+1), "index array nurbs");
00967         
00968         for(a=0; a<dl->parts; a++) {
00969                 
00970                 if (surfindex_displist(dl, a, &b, &p1, &p2, &p3, &p4)==0)
00971                         break;
00972                 
00973                 for(; b<dl->nr; b++, index+=4) {        
00974                         index[0]= p1;
00975                         index[1]= p2;
00976                         index[2]= p4;
00977                         index[3]= p3;
00978                         
00979                         dl->totindex++;
00980                         
00981                         p2= p1; p1++;
00982                         p4= p3; p3++;
00983 
00984                 }
00985         }
00986         
00987 }
00988 
00989 static DerivedMesh *create_orco_dm(Scene *scene, Object *ob)
00990 {
00991         DerivedMesh *dm;
00992         ListBase disp= {NULL, NULL};
00993 
00994         /* OrcoDM should be created from underformed disp lists */
00995         makeDispListCurveTypes_forOrco(scene, ob, &disp);
00996         dm= CDDM_from_curve_customDB(ob, &disp);
00997 
00998         freedisplist(&disp);
00999 
01000         return dm;
01001 }
01002 
01003 static void add_orco_dm(Scene *scene, Object *ob, DerivedMesh *dm, DerivedMesh *orcodm)
01004 {
01005         float (*orco)[3], (*layerorco)[3];
01006         int totvert, a;
01007         Curve *cu= ob->data;
01008 
01009         totvert= dm->getNumVerts(dm);
01010 
01011         if(orcodm) {
01012                 orco= MEM_callocN(sizeof(float)*3*totvert, "dm orco");
01013 
01014                 if(orcodm->getNumVerts(orcodm) == totvert)
01015                         orcodm->getVertCos(orcodm, orco);
01016                 else
01017                         dm->getVertCos(dm, orco);
01018         }
01019         else {
01020                 orco= (float(*)[3])make_orco_curve(scene, ob);
01021         }
01022 
01023         for(a=0; a<totvert; a++) {
01024                 float *co = orco[a];
01025                 co[0] = (co[0]-cu->loc[0])/cu->size[0];
01026                 co[1] = (co[1]-cu->loc[1])/cu->size[1];
01027                 co[2] = (co[2]-cu->loc[2])/cu->size[2];
01028         }
01029 
01030         if((layerorco = DM_get_vert_data_layer(dm, CD_ORCO))) {
01031                 memcpy(layerorco, orco, sizeof(float)*totvert);
01032                 MEM_freeN(orco);
01033         }
01034         else
01035                 DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco);
01036 }
01037 
01038 static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *derivedFinal, int forRender)
01039 {
01040         /* this function represents logic of mesh's orcodm calculation */
01041         /* for displist-based objects */
01042 
01043         ModifierData *md = modifiers_getVirtualModifierList(ob);
01044         ModifierData *preTesselatePoint;
01045         Curve *cu= ob->data;
01046         int required_mode;
01047         int editmode = (!forRender && cu->editnurb);
01048         DerivedMesh *ndm, *orcodm= NULL;
01049 
01050         if(forRender) required_mode = eModifierMode_Render;
01051         else required_mode = eModifierMode_Realtime;
01052 
01053         preTesselatePoint = curve_get_tesselate_point(scene, ob, forRender, editmode);
01054 
01055         if(editmode) required_mode |= eModifierMode_Editmode;
01056 
01057         if (preTesselatePoint) {
01058                 md = preTesselatePoint->next;
01059         }
01060 
01061         for (; md; md=md->next) {
01062                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
01063 
01064                 md->scene= scene;
01065 
01066                 if ((md->mode & required_mode) != required_mode) continue;
01067                 if (mti->isDisabled && mti->isDisabled(md, forRender)) continue;
01068                 if (mti->type!=eModifierTypeType_Constructive) continue;
01069 
01070                 if(!orcodm)
01071                         orcodm= create_orco_dm(scene, ob);
01072 
01073                 ndm = mti->applyModifier(md, ob, orcodm, forRender, 0);
01074 
01075                 if(ndm) {
01076                         /* if the modifier returned a new dm, release the old one */
01077                         if(orcodm && orcodm != ndm) {
01078                                 orcodm->release(orcodm);
01079                         }
01080                         orcodm = ndm;
01081                 }
01082         }
01083 
01084         /* add an orco layer if needed */
01085         add_orco_dm(scene, ob, derivedFinal, orcodm);
01086 
01087         if(orcodm)
01088                 orcodm->release(orcodm);
01089 }
01090 
01091 void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase,
01092         DerivedMesh **derivedFinal, int forRender, int forOrco)
01093 {
01094         ListBase *nubase;
01095         Nurb *nu;
01096         Curve *cu = ob->data;
01097         DispList *dl;
01098         float *data;
01099         int len;
01100         int numVerts;
01101         float (*originalVerts)[3];
01102         float (*deformedVerts)[3];
01103 
01104         if(!forRender && cu->editnurb)
01105                 nubase= ED_curve_editnurbs(cu);
01106         else
01107                 nubase= &cu->nurb;
01108 
01109         if(!forOrco)
01110                 curve_calc_modifiers_pre(scene, ob, forRender, &originalVerts, &deformedVerts, &numVerts);
01111 
01112         for (nu=nubase->first; nu; nu=nu->next) {
01113                 if(forRender || nu->hide==0) {
01114                         int resolu= nu->resolu, resolv= nu->resolv;
01115 
01116                         if(forRender){
01117                                 if(cu->resolu_ren) resolu= cu->resolu_ren;
01118                                 if(cu->resolv_ren) resolv= cu->resolv_ren;
01119                         }
01120 
01121                         if(nu->pntsv==1) {
01122                                 len= SEGMENTSU(nu)*resolu;
01123 
01124                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
01125                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
01126 
01127                                 BLI_addtail(dispbase, dl);
01128                                 dl->parts= 1;
01129                                 dl->nr= len;
01130                                 dl->col= nu->mat_nr;
01131                                 dl->charidx= nu->charidx;
01132 
01133                                 /* dl->rt will be used as flag for render face and */
01134                                 /* CU_2D conflicts with R_NOPUNOFLIP */
01135                                 dl->rt= nu->flag & ~CU_2D;
01136 
01137                                 data= dl->verts;
01138                                 if(nu->flagu & CU_NURB_CYCLIC) dl->type= DL_POLY;
01139                                 else dl->type= DL_SEGM;
01140 
01141                                 makeNurbcurve(nu, data, NULL, NULL, NULL, resolu, 3*sizeof(float));
01142                         }
01143                         else {
01144                                 len= (nu->pntsu*resolu) * (nu->pntsv*resolv);
01145                                 
01146                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
01147                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
01148                                 BLI_addtail(dispbase, dl);
01149 
01150                                 dl->col= nu->mat_nr;
01151                                 dl->charidx= nu->charidx;
01152 
01153                                 /* dl->rt will be used as flag for render face and */
01154                                 /* CU_2D conflicts with R_NOPUNOFLIP */
01155                                 dl->rt= nu->flag & ~CU_2D;
01156 
01157                                 data= dl->verts;
01158                                 dl->type= DL_SURF;
01159 
01160                                 dl->parts= (nu->pntsu*resolu);  /* in reverse, because makeNurbfaces works that way */
01161                                 dl->nr= (nu->pntsv*resolv);
01162                                 if(nu->flagv & CU_NURB_CYCLIC) dl->flag|= DL_CYCL_U;    /* reverse too! */
01163                                 if(nu->flagu & CU_NURB_CYCLIC) dl->flag|= DL_CYCL_V;
01164 
01165                                 makeNurbfaces(nu, data, 0, resolu, resolv);
01166                                 
01167                                 /* gl array drawing: using indices */
01168                                 displist_surf_indices(dl);
01169                         }
01170                 }
01171         }
01172 
01173         /* make copy of 'undeformed" displist for texture space calculation
01174            actually, it's not totally undeformed -- pre-tesselation modifiers are
01175            already applied, thats how it worked for years, so keep for compatibility (sergey) */
01176         copy_displist(&cu->disp, dispbase);
01177 
01178         if (!forRender) {
01179                 tex_space_curve(cu);
01180         }
01181 
01182         if(!forOrco)
01183                 curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal,
01184                         forRender, originalVerts, deformedVerts);
01185 }
01186 
01187 static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispbase,
01188         DerivedMesh **derivedFinal, int forRender, int forOrco)
01189 {
01190         Curve *cu = ob->data;
01191 
01192         /* we do allow duplis... this is only displist on curve level */
01193         if(!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return;
01194 
01195         if(ob->type==OB_SURF) {
01196                 makeDispListSurf(scene, ob, dispbase, derivedFinal, forRender, forOrco);
01197         }
01198         else if (ELEM(ob->type, OB_CURVE, OB_FONT)) {
01199                 ListBase dlbev;
01200                 ListBase *nubase;
01201                 float (*originalVerts)[3];
01202                 float (*deformedVerts)[3];
01203                 int numVerts;
01204 
01205                 nubase= BKE_curve_nurbs(cu);
01206 
01207                 BLI_freelistN(&(cu->bev));
01208 
01209                 if(cu->path) free_path(cu->path);
01210                 cu->path= NULL;
01211 
01212                 if(ob->type==OB_FONT) BKE_text_to_curve(scene, ob, 0);
01213 
01214                 if(!forOrco) curve_calc_modifiers_pre(scene, ob, forRender, &originalVerts, &deformedVerts, &numVerts);
01215 
01216                 makeBevelList(ob);
01217 
01218                 /* If curve has no bevel will return nothing */
01219                 makebevelcurve(scene, ob, &dlbev, forRender);
01220 
01221                 /* no bevel or extrude, and no width correction? */
01222                 if (!dlbev.first && cu->width==1.0f) {
01223                         curve_to_displist(cu, nubase, dispbase, forRender);
01224                 } else {
01225                         float widfac= cu->width - 1.0f;
01226                         BevList *bl= cu->bev.first;
01227                         Nurb *nu= nubase->first;
01228 
01229                         for (; bl && nu; bl=bl->next,nu=nu->next) {
01230                                 DispList *dl;
01231                                 float *fp1, *data;
01232                                 BevPoint *bevp;
01233                                 int a,b;
01234 
01235                                 if (bl->nr) { /* blank bevel lists can happen */
01236 
01237                                         /* exception handling; curve without bevel or extrude, with width correction */
01238                                         if(dlbev.first==NULL) {
01239                                                 dl= MEM_callocN(sizeof(DispList), "makeDispListbev");
01240                                                 dl->verts= MEM_callocN(3*sizeof(float)*bl->nr, "dlverts");
01241                                                 BLI_addtail(dispbase, dl);
01242 
01243                                                 if(bl->poly!= -1) dl->type= DL_POLY;
01244                                                 else dl->type= DL_SEGM;
01245 
01246                                                 if(dl->type==DL_SEGM) dl->flag = (DL_FRONT_CURVE|DL_BACK_CURVE);
01247 
01248                                                 dl->parts= 1;
01249                                                 dl->nr= bl->nr;
01250                                                 dl->col= nu->mat_nr;
01251                                                 dl->charidx= nu->charidx;
01252 
01253                                                 /* dl->rt will be used as flag for render face and */
01254                                                 /* CU_2D conflicts with R_NOPUNOFLIP */
01255                                                 dl->rt= nu->flag & ~CU_2D;
01256 
01257                                                 a= dl->nr;
01258                                                 bevp= (BevPoint *)(bl+1);
01259                                                 data= dl->verts;
01260                                                 while(a--) {
01261                                                         data[0]= bevp->vec[0]+widfac*bevp->sina;
01262                                                         data[1]= bevp->vec[1]+widfac*bevp->cosa;
01263                                                         data[2]= bevp->vec[2];
01264                                                         bevp++;
01265                                                         data+=3;
01266                                                 }
01267                                         }
01268                                         else {
01269                                                 DispList *dlb;
01270 
01271                                                 for (dlb=dlbev.first; dlb; dlb=dlb->next) {
01272         
01273                                                         /* for each part of the bevel use a separate displblock */
01274                                                         dl= MEM_callocN(sizeof(DispList), "makeDispListbev1");
01275                                                         dl->verts= data= MEM_callocN(3*sizeof(float)*dlb->nr*bl->nr, "dlverts");
01276                                                         BLI_addtail(dispbase, dl);
01277         
01278                                                         dl->type= DL_SURF;
01279                                                         
01280                                                         dl->flag= dlb->flag & (DL_FRONT_CURVE|DL_BACK_CURVE);
01281                                                         if(dlb->type==DL_POLY) dl->flag |= DL_CYCL_U;
01282                                                         if(bl->poly>=0) dl->flag |= DL_CYCL_V;
01283                                                         
01284                                                         dl->parts= bl->nr;
01285                                                         dl->nr= dlb->nr;
01286                                                         dl->col= nu->mat_nr;
01287                                                         dl->charidx= nu->charidx;
01288 
01289                                                         /* dl->rt will be used as flag for render face and */
01290                                                         /* CU_2D conflicts with R_NOPUNOFLIP */
01291                                                         dl->rt= nu->flag & ~CU_2D;
01292 
01293                                                         dl->bevelSplitFlag= MEM_callocN(sizeof(*dl->col2)*((bl->nr+0x1F)>>5), "bevelSplitFlag");
01294         
01295                                                         /* for each point of poly make a bevel piece */
01296                                                         bevp= (BevPoint *)(bl+1);
01297                                                         for(a=0; a<bl->nr; a++,bevp++) {
01298                                                                 float fac=1.0;
01299                                                                 if (cu->taperobj==NULL) {
01300                                                                         if ( (cu->bevobj!=NULL) || !((cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) )
01301                                                                                 fac = bevp->radius;
01302                                                                 } else {
01303                                                                         fac = calc_taper(scene, cu->taperobj, a, bl->nr);
01304                                                                 }
01305 
01306                                                                 if (bevp->split_tag) {
01307                                                                         dl->bevelSplitFlag[a>>5] |= 1<<(a&0x1F);
01308                                                                 }
01309         
01310                                                                         /* rotate bevel piece and write in data */
01311                                                                 fp1= dlb->verts;
01312                                                                 for (b=0; b<dlb->nr; b++,fp1+=3,data+=3) {
01313                                                                         if(cu->flag & CU_3D) {
01314                                                                                 float vec[3];
01315         
01316                                                                                 vec[0]= fp1[1]+widfac;
01317                                                                                 vec[1]= fp1[2];
01318                                                                                 vec[2]= 0.0;
01319 
01320                                                                                 mul_qt_v3(bevp->quat, vec);
01321 
01322                                                                                 data[0]= bevp->vec[0] + fac*vec[0];
01323                                                                                 data[1]= bevp->vec[1] + fac*vec[1];
01324                                                                                 data[2]= bevp->vec[2] + fac*vec[2];
01325                                                                         }
01326                                                                         else {
01327                                                                                 data[0]= bevp->vec[0] + fac*(widfac+fp1[1])*bevp->sina;
01328                                                                                 data[1]= bevp->vec[1] + fac*(widfac+fp1[1])*bevp->cosa;
01329                                                                                 data[2]= bevp->vec[2] + fac*fp1[2];
01330                                                                         }
01331                                                                 }
01332                                                         }
01333                                                         
01334                                                         /* gl array drawing: using indices */
01335                                                         displist_surf_indices(dl);
01336                                                 }
01337                                         }
01338                                 }
01339 
01340                         }
01341                         freedisplist(&dlbev);
01342                 }
01343 
01344                 if (!(cu->flag & CU_DEFORM_FILL)) {
01345                         curve_to_filledpoly(cu, nubase, dispbase);
01346                 }
01347 
01348                 if(cu->flag & CU_PATH) calc_curvepath(ob);
01349 
01350                 /* make copy of 'undeformed" displist for texture space calculation
01351                    actually, it's not totally undeformed -- pre-tesselation modifiers are
01352                    already applied, thats how it worked for years, so keep for compatibility (sergey) */
01353                 copy_displist(&cu->disp, dispbase);
01354 
01355                 if (!forRender) {
01356                         tex_space_curve(cu);
01357                 }
01358 
01359                 if(!forOrco) curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal, forRender, originalVerts, deformedVerts);
01360 
01361                 if (cu->flag & CU_DEFORM_FILL && !ob->derivedFinal) {
01362                         curve_to_filledpoly(cu, nubase, dispbase);
01363                 }
01364         }
01365 }
01366 
01367 void makeDispListCurveTypes(Scene *scene, Object *ob, int forOrco)
01368 {
01369         Curve *cu= ob->data;
01370         ListBase *dispbase;
01371 
01372         freedisplist(&(ob->disp));
01373         dispbase= &(ob->disp);
01374         freedisplist(dispbase);
01375 
01376         /* free displist used for textspace */
01377         freedisplist(&cu->disp);
01378 
01379         do_makeDispListCurveTypes(scene, ob, dispbase, &ob->derivedFinal, 0, forOrco);
01380 
01381         if (ob->derivedFinal) {
01382                 DM_set_object_boundbox (ob, ob->derivedFinal);
01383         } else {
01384                 boundbox_displist (ob);
01385 
01386                 /* if there is no derivedMesh, object's boundbox is unneeded */
01387                 if (ob->bb) {
01388                         MEM_freeN(ob->bb);
01389                         ob->bb= NULL;
01390                 }
01391         }
01392 }
01393 
01394 void makeDispListCurveTypes_forRender(Scene *scene, Object *ob, ListBase *dispbase,
01395         DerivedMesh **derivedFinal, int forOrco)
01396 {
01397         do_makeDispListCurveTypes(scene, ob, dispbase, derivedFinal, 1, forOrco);
01398 }
01399 
01400 void makeDispListCurveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase)
01401 {
01402         do_makeDispListCurveTypes(scene, ob, dispbase, NULL, 1, 1);
01403 }
01404 
01405 /* add Orco layer to the displist object which has got derived mesh and return orco */
01406 float *makeOrcoDispList(Scene *scene, Object *ob, DerivedMesh *derivedFinal, int forRender) {
01407         float *orco;
01408 
01409         if (derivedFinal == NULL)
01410                 derivedFinal= ob->derivedFinal;
01411 
01412         if (!derivedFinal->getVertDataArray(derivedFinal, CD_ORCO)) {
01413                 curve_calc_orcodm(scene, ob, derivedFinal, forRender);
01414         }
01415 
01416         orco= derivedFinal->getVertDataArray(derivedFinal, CD_ORCO);
01417 
01418         if(orco) {
01419                 orco= MEM_dupallocN(orco);
01420         }
01421 
01422         return orco;
01423 }
01424 
01425 /* this is confusing, there's also min_max_object, appplying the obmat... */
01426 static void boundbox_displist(Object *ob)
01427 {
01428         BoundBox *bb=NULL;
01429         float min[3], max[3];
01430         DispList *dl;
01431         float *vert;
01432         int a, tot=0;
01433         
01434         INIT_MINMAX(min, max);
01435 
01436         if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
01437                 Curve *cu= ob->data;
01438                 int doit= 0;
01439 
01440                 if(cu->bb==NULL) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
01441                 bb= cu->bb;
01442                 
01443                 dl= ob->disp.first;
01444 
01445                 while (dl) {
01446                         if(dl->type==DL_INDEX3) tot= dl->nr;
01447                         else tot= dl->nr*dl->parts;
01448                         
01449                         vert= dl->verts;
01450                         for(a=0; a<tot; a++, vert+=3) {
01451                                 doit= 1;
01452                                 DO_MINMAX(vert, min, max);
01453                         }
01454 
01455                         dl= dl->next;
01456                 }
01457                 
01458                 if(!doit) {
01459                         /* there's no geometry in displist, use zero-sized boundbox */
01460                         zero_v3(min);
01461                         zero_v3(max);
01462                 }
01463                 
01464         }
01465         
01466         if(bb) {
01467                 boundbox_set_from_min_max(bb, min, max);
01468         }
01469 }
01470