spelling cleanup: tesselate -> tessellate (last of these found)
[blender.git] / source / blender / blenkernel / intern / displist.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenkernel/intern/displist.c
29  *  \ingroup bke
30  */
31
32
33 #include <math.h>
34 #include <stdio.h>
35 #include <string.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "DNA_curve_types.h"
40 #include "DNA_meshdata_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_object_types.h"
43 #include "DNA_material_types.h"
44
45 #include "BLI_blenlib.h"
46 #include "BLI_math.h"
47 #include "BLI_scanfill.h"
48 #include "BLI_utildefines.h"
49
50 #include "BKE_global.h"
51 #include "BKE_displist.h"
52 #include "BKE_cdderivedmesh.h"
53 #include "BKE_object.h"
54 #include "BKE_mball.h"
55 #include "BKE_material.h"
56 #include "BKE_curve.h"
57 #include "BKE_key.h"
58 #include "BKE_anim.h"
59 #include "BKE_font.h"
60 #include "BKE_lattice.h"
61 #include "BKE_modifier.h"
62
63 #include "BLO_sys_types.h" // for intptr_t support
64
65 static void boundbox_displist(Object *ob);
66
67 void free_disp_elem(DispList *dl)
68 {
69         if(dl) {
70                 if(dl->verts) MEM_freeN(dl->verts);
71                 if(dl->nors) MEM_freeN(dl->nors);
72                 if(dl->index) MEM_freeN(dl->index);
73                 if(dl->col1) MEM_freeN(dl->col1);
74                 if(dl->col2) MEM_freeN(dl->col2);
75                 if(dl->bevelSplitFlag) MEM_freeN(dl->bevelSplitFlag);
76                 MEM_freeN(dl);
77         }
78 }
79
80 void freedisplist(ListBase *lb)
81 {
82         DispList *dl;
83
84         dl= lb->first;
85         while(dl) {
86                 BLI_remlink(lb, dl);
87                 free_disp_elem(dl);
88                 dl= lb->first;
89         }
90 }
91
92 DispList *find_displist_create(ListBase *lb, int type)
93 {
94         DispList *dl;
95         
96         dl= lb->first;
97         while(dl) {
98                 if(dl->type==type) return dl;
99                 dl= dl->next;
100         }
101
102         dl= MEM_callocN(sizeof(DispList), "find_disp");
103         dl->type= type;
104         BLI_addtail(lb, dl);
105
106         return dl;
107 }
108
109 DispList *find_displist(ListBase *lb, int type)
110 {
111         DispList *dl;
112         
113         dl= lb->first;
114         while(dl) {
115                 if(dl->type==type) return dl;
116                 dl= dl->next;
117         }
118
119         return NULL;
120 }
121
122 int displist_has_faces(ListBase *lb)
123 {
124         DispList *dl;
125         for(dl= lb->first; dl; dl= dl->next) {
126                 if ELEM3(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)
127                         return 1;
128         }
129         return 0;
130 }
131
132 void copy_displist(ListBase *lbn, ListBase *lb)
133 {
134         DispList *dln, *dl;
135         
136         freedisplist(lbn);
137         
138         dl= lb->first;
139         while(dl) {
140                 
141                 dln= MEM_dupallocN(dl);
142                 BLI_addtail(lbn, dln);
143                 dln->verts= MEM_dupallocN(dl->verts);
144                 dln->nors= MEM_dupallocN(dl->nors);
145                 dln->index= MEM_dupallocN(dl->index);
146                 dln->col1= MEM_dupallocN(dl->col1);
147                 dln->col2= MEM_dupallocN(dl->col2);
148
149                 if(dl->bevelSplitFlag)
150                         dln->bevelSplitFlag= MEM_dupallocN(dl->bevelSplitFlag);
151
152                 dl= dl->next;
153         }
154 }
155
156 void addnormalsDispList(ListBase *lb)
157 {
158         DispList *dl = NULL;
159         float *vdata, *ndata, nor[3];
160         float *v1, *v2, *v3, *v4;
161         float *n1, *n2, *n3, *n4;
162         int a, b, p1, p2, p3, p4;
163
164
165         dl= lb->first;
166         
167         while(dl) {
168                 if(dl->type==DL_INDEX3) {
169                         if(dl->nors==NULL) {
170                                 dl->nors= MEM_callocN(sizeof(float)*3, "dlnors");
171                                 if(dl->verts[2] < 0.0f) dl->nors[2]= -1.0f;
172                                 else dl->nors[2]= 1.0f;
173                         }
174                 }
175                 else if(dl->type==DL_SURF) {
176                         if(dl->nors==NULL) {
177                                 dl->nors= MEM_callocN(sizeof(float)*3*dl->nr*dl->parts, "dlnors");
178                                 
179                                 vdata= dl->verts;
180                                 ndata= dl->nors;
181                                 
182                                 for(a=0; a<dl->parts; a++) {
183                                         
184                                         if (surfindex_displist(dl, a, &b, &p1, &p2, &p3, &p4)==0)
185                                                 break;
186         
187                                         v1= vdata+ 3*p1; 
188                                         n1= ndata+ 3*p1;
189                                         v2= vdata+ 3*p2; 
190                                         n2= ndata+ 3*p2;
191                                         v3= vdata+ 3*p3; 
192                                         n3= ndata+ 3*p3;
193                                         v4= vdata+ 3*p4; 
194                                         n4= ndata+ 3*p4;
195                                         
196                                         for(; b<dl->nr; b++) {
197         
198                                                 normal_quad_v3( nor,v1, v3, v4, v2);
199         
200                                                 add_v3_v3(n1, nor);
201                                                 add_v3_v3(n2, nor);
202                                                 add_v3_v3(n3, nor);
203                                                 add_v3_v3(n4, nor);
204         
205                                                 v2= v1; v1+= 3;
206                                                 v4= v3; v3+= 3;
207                                                 n2= n1; n1+= 3;
208                                                 n4= n3; n3+= 3;
209                                         }
210                                 }
211                                 a= dl->parts*dl->nr;
212                                 v1= ndata;
213                                 while(a--) {
214                                         normalize_v3(v1);
215                                         v1+= 3;
216                                 }
217                         }
218                 }
219                 dl= dl->next;
220         }
221 }
222
223 void count_displist(ListBase *lb, int *totvert, int *totface)
224 {
225         DispList *dl;
226         
227         dl= lb->first;
228         while(dl) {
229                 
230                 switch(dl->type) {
231                         case DL_SURF:
232                                 *totvert+= dl->nr*dl->parts;
233                                 *totface+= (dl->nr-1)*(dl->parts-1);
234                                 break;
235                         case DL_INDEX3:
236                         case DL_INDEX4:
237                                 *totvert+= dl->nr;
238                                 *totface+= dl->parts;
239                                 break;
240                         case DL_POLY:
241                         case DL_SEGM:
242                                 *totvert+= dl->nr*dl->parts;
243                 }
244                 
245                 dl= dl->next;
246         }
247 }
248
249 int surfindex_displist(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4)
250 {
251         if((dl->flag & DL_CYCL_V)==0 && a==(dl->parts)-1) {
252                 return 0;
253         }
254         
255         if(dl->flag & DL_CYCL_U) {
256                 (*p1)= dl->nr*a;
257                 (*p2)= (*p1)+ dl->nr-1;
258                 (*p3)= (*p1)+ dl->nr;
259                 (*p4)= (*p2)+ dl->nr;
260                 (*b)= 0;
261         } else {
262                 (*p2)= dl->nr*a;
263                 (*p1)= (*p2)+1;
264                 (*p4)= (*p2)+ dl->nr;
265                 (*p3)= (*p1)+ dl->nr;
266                 (*b)= 1;
267         }
268         
269         if( (dl->flag & DL_CYCL_V) && a==dl->parts-1) {
270                 (*p3)-= dl->nr*dl->parts;
271                 (*p4)-= dl->nr*dl->parts;
272         }
273         
274         return 1;
275 }
276
277 /* ****************** make displists ********************* */
278
279 static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase, int forRender)
280 {
281         Nurb *nu;
282         DispList *dl;
283         BezTriple *bezt, *prevbezt;
284         BPoint *bp;
285         float *data;
286         int a, len, resolu;
287         
288         nu= nubase->first;
289         while(nu) {
290                 if(nu->hide==0) {
291                         
292                         if(forRender && cu->resolu_ren!=0)
293                                 resolu= cu->resolu_ren;
294                         else
295                                 resolu= nu->resolu;
296                         
297                         if(!check_valid_nurb_u(nu));
298                         else if(nu->type == CU_BEZIER) {
299                                 
300                                 /* count */
301                                 len= 0;
302                                 a= nu->pntsu-1;
303                                 if(nu->flagu & CU_NURB_CYCLIC) a++;
304
305                                 prevbezt= nu->bezt;
306                                 bezt= prevbezt+1;
307                                 while(a--) {
308                                         if(a==0 && (nu->flagu & CU_NURB_CYCLIC)) bezt= nu->bezt;
309                                         
310                                         if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) len++;
311                                         else len+= resolu;
312                                         
313                                         if(a==0 && (nu->flagu & CU_NURB_CYCLIC)==0) len++;
314                                         
315                                         prevbezt= bezt;
316                                         bezt++;
317                                 }
318                                 
319                                 dl= MEM_callocN(sizeof(DispList), "makeDispListbez");
320                                 /* len+1 because of 'forward_diff_bezier' function */
321                                 dl->verts= MEM_callocN( (len+1)*3*sizeof(float), "dlverts");
322                                 BLI_addtail(dispbase, dl);
323                                 dl->parts= 1;
324                                 dl->nr= len;
325                                 dl->col= nu->mat_nr;
326                                 dl->charidx= nu->charidx;
327
328                                 data= dl->verts;
329
330                                 if(nu->flagu & CU_NURB_CYCLIC) {
331                                         dl->type= DL_POLY;
332                                         a= nu->pntsu;
333                                 }
334                                 else {
335                                         dl->type= DL_SEGM;
336                                         a= nu->pntsu-1;
337                                 }
338                                 
339                                 prevbezt= nu->bezt;
340                                 bezt= prevbezt+1;
341                                 
342                                 while(a--) {
343                                         if(a==0 && dl->type== DL_POLY) bezt= nu->bezt;
344                                         
345                                         if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) {
346                                                 copy_v3_v3(data, prevbezt->vec[1]);
347                                                 data+= 3;
348                                         }
349                                         else {
350                                                 int j;
351                                                 for(j=0; j<3; j++) {
352                                                         forward_diff_bezier(    prevbezt->vec[1][j],
353                                                                                                         prevbezt->vec[2][j],
354                                                                                                         bezt->vec[0][j],
355                                                                                                         bezt->vec[1][j],
356                                                                                                         data+j, resolu, 3*sizeof(float));
357                                                 }
358                                                 
359                                                 data+= 3*resolu;
360                                         }
361                                         
362                                         if(a==0 && dl->type==DL_SEGM) {
363                                                 copy_v3_v3(data, bezt->vec[1]);
364                                         }
365                                         
366                                         prevbezt= bezt;
367                                         bezt++;
368                                 }
369                         }
370                         else if(nu->type == CU_NURBS) {
371                                 len= (resolu*SEGMENTSU(nu));
372                                 
373                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
374                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
375                                 BLI_addtail(dispbase, dl);
376                                 dl->parts= 1;
377                                 
378                                 dl->nr= len;
379                                 dl->col= nu->mat_nr;
380                                 dl->charidx = nu->charidx;
381
382                                 data= dl->verts;
383                                 if(nu->flagu & CU_NURB_CYCLIC) dl->type= DL_POLY;
384                                 else dl->type= DL_SEGM;
385                                 makeNurbcurve(nu, data, NULL, NULL, NULL, resolu, 3*sizeof(float));
386                         }
387                         else if(nu->type == CU_POLY) {
388                                 len= nu->pntsu;
389                                 dl= MEM_callocN(sizeof(DispList), "makeDispListpoly");
390                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
391                                 BLI_addtail(dispbase, dl);
392                                 dl->parts= 1;
393                                 dl->nr= len;
394                                 dl->col= nu->mat_nr;
395                                 dl->charidx = nu->charidx;
396
397                                 data= dl->verts;
398                                 if(nu->flagu & CU_NURB_CYCLIC) dl->type= DL_POLY;
399                                 else dl->type= DL_SEGM;
400                                 
401                                 a= len;
402                                 bp= nu->bp;
403                                 while(a--) {
404                                         copy_v3_v3(data, bp->vec);
405                                         bp++;
406                                         data+= 3;
407                                 }
408                         }
409                 }
410                 nu= nu->next;
411         }
412 }
413
414
415 void filldisplist(ListBase *dispbase, ListBase *to, int flipnormal)
416 {
417         ScanFillVert *eve, *v1, *vlast;
418         ScanFillFace *efa;
419         DispList *dlnew=NULL, *dl;
420         float *f1;
421         int colnr=0, charidx=0, cont=1, tot, a, *index, nextcol= 0;
422         intptr_t totvert;
423         
424         if(dispbase==NULL) return;
425         if(dispbase->first==NULL) return;
426
427         while(cont) {
428                 cont= 0;
429                 totvert= 0;
430                 nextcol= 0;
431                 
432                 BLI_begin_edgefill();
433                 
434                 dl= dispbase->first;
435                 while(dl) {
436         
437                         if(dl->type==DL_POLY) {
438                                 if(charidx<dl->charidx) cont= 1;
439                                 else if(charidx==dl->charidx) { /* character with needed index */
440                                         if(colnr==dl->col) {
441                                                 /* make editverts and edges */
442                                                 f1= dl->verts;
443                                                 a= dl->nr;
444                                                 eve= v1= NULL;
445                                                 
446                                                 while(a--) {
447                                                         vlast= eve;
448
449                                                         eve= BLI_addfillvert(f1);
450                                                         totvert++;
451
452                                                         if(vlast==NULL) v1= eve;
453                                                         else {
454                                                                 BLI_addfilledge(vlast, eve);
455                                                         }
456                                                         f1+=3;
457                                                 }
458
459                                                 if(eve!=NULL && v1!=NULL) {
460                                                         BLI_addfilledge(eve, v1);
461                                                 }
462                                         } else if (colnr<dl->col) {
463                                                 /* got poly with next material at current char */
464                                                 cont= 1;
465                                                 nextcol= 1;
466                                         }
467                                 }
468                         }
469                         dl= dl->next;
470                 }
471                 
472                 if(totvert && (tot= BLI_edgefill(0))) { // XXX (obedit && obedit->actcol)?(obedit->actcol-1):0)) {
473                         if(tot) {
474                                 dlnew= MEM_callocN(sizeof(DispList), "filldisplist");
475                                 dlnew->type= DL_INDEX3;
476                                 dlnew->col= colnr;
477                                 dlnew->nr= totvert;
478                                 dlnew->parts= tot;
479
480                                 dlnew->index= MEM_mallocN(tot*3*sizeof(int), "dlindex");
481                                 dlnew->verts= MEM_mallocN(totvert*3*sizeof(float), "dlverts");
482                                 
483                                 /* vert data */
484                                 f1= dlnew->verts;
485                                 totvert= 0;
486                                 eve= fillvertbase.first;
487                                 while(eve) {
488                                         copy_v3_v3(f1, eve->co);
489                                         f1+= 3;
490         
491                                         /* index number */
492                                         eve->tmp.l = totvert;
493                                         totvert++;
494                                         
495                                         eve= eve->next;
496                                 }
497                                 
498                                 /* index data */
499                                 efa= fillfacebase.first;
500                                 index= dlnew->index;
501                                 while(efa) {
502                                         index[0]= (intptr_t)efa->v1->tmp.l;
503                                         index[1]= (intptr_t)efa->v2->tmp.l;
504                                         index[2]= (intptr_t)efa->v3->tmp.l;
505
506                                         if(flipnormal)
507                                                 SWAP(int, index[0], index[2]);
508                                         
509                                         index+= 3;
510                                         efa= efa->next;
511                                 }
512                         }
513
514                         BLI_addhead(to, dlnew);
515                         
516                 }
517                 BLI_end_edgefill();
518
519                 if(nextcol) {
520                         /* stay at current char but fill polys with next material */
521                         colnr++;
522                 } else {
523                         /* switch to next char and start filling from first material */
524                         charidx++;
525                         colnr= 0;
526                 }
527         }
528         
529         /* do not free polys, needed for wireframe display */
530         
531 }
532
533 static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
534 {
535         ListBase front, back;
536         DispList *dl, *dlnew;
537         float *fp, *fp1;
538         int a, dpoly;
539         
540         front.first= front.last= back.first= back.last= NULL;
541         
542         dl= dispbase->first;
543         while(dl) {
544                 if(dl->type==DL_SURF) {
545                         if( (dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U)==0 ) {
546                                 if( (cu->flag & CU_BACK) && (dl->flag & DL_BACK_CURVE) ) {
547                                         dlnew= MEM_callocN(sizeof(DispList), "filldisp");
548                                         BLI_addtail(&front, dlnew);
549                                         dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1");
550                                         dlnew->nr= dl->parts;
551                                         dlnew->parts= 1;
552                                         dlnew->type= DL_POLY;
553                                         dlnew->col= dl->col;
554                                         dlnew->charidx = dl->charidx;
555                                         
556                                         fp= dl->verts;
557                                         dpoly= 3*dl->nr;
558                                         
559                                         a= dl->parts;
560                                         while(a--) {
561                                                 copy_v3_v3(fp1, fp);
562                                                 fp1+= 3;
563                                                 fp+= dpoly;
564                                         }
565                                 }
566                                 if( (cu->flag & CU_FRONT) && (dl->flag & DL_FRONT_CURVE) ) {
567                                         dlnew= MEM_callocN(sizeof(DispList), "filldisp");
568                                         BLI_addtail(&back, dlnew);
569                                         dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1");
570                                         dlnew->nr= dl->parts;
571                                         dlnew->parts= 1;
572                                         dlnew->type= DL_POLY;
573                                         dlnew->col= dl->col;
574                                         dlnew->charidx= dl->charidx;
575                                         
576                                         fp= dl->verts+3*(dl->nr-1);
577                                         dpoly= 3*dl->nr;
578                                         
579                                         a= dl->parts;
580                                         while(a--) {
581                                                 copy_v3_v3(fp1, fp);
582                                                 fp1+= 3;
583                                                 fp+= dpoly;
584                                         }
585                                 }
586                         }
587                 }
588                 dl= dl->next;
589         }
590
591         filldisplist(&front, dispbase, 1);
592         filldisplist(&back, dispbase, 0);
593         
594         freedisplist(&front);
595         freedisplist(&back);
596
597         filldisplist(dispbase, dispbase, 0);
598         
599 }
600
601 static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dispbase)
602 {
603         if(cu->flag & CU_3D) return;
604
605         if(dispbase->first && ((DispList*) dispbase->first)->type==DL_SURF) {
606                 bevels_to_filledpoly(cu, dispbase);
607         }
608         else {
609                 filldisplist(dispbase, dispbase, 0);
610         }
611 }
612
613 /* taper rules:
614  * - only 1 curve
615  * - first point left, last point right
616  * - based on subdivided points in original curve, not on points in taper curve (still)
617  */
618 float calc_taper(Scene *scene, Object *taperobj, int cur, int tot)
619 {
620         DispList *dl;
621         
622         if(taperobj==NULL || taperobj->type!=OB_CURVE) return 1.0;
623         
624         dl= taperobj->disp.first;
625         if(dl==NULL) {
626                 makeDispListCurveTypes(scene, taperobj, 0);
627                 dl= taperobj->disp.first;
628         }
629         if(dl) {
630                 float fac= ((float)cur)/(float)(tot-1);
631                 float minx, dx, *fp;
632                 int a;
633                 
634                 /* horizontal size */
635                 minx= dl->verts[0];
636                 dx= dl->verts[3*(dl->nr-1)] - minx;
637                 if(dx > 0.0f) {
638                 
639                         fp= dl->verts;
640                         for(a=0; a<dl->nr; a++, fp+=3) {
641                                 if( (fp[0]-minx)/dx >= fac) {
642                                         /* interpolate with prev */
643                                         if(a>0) {
644                                                 float fac1= (fp[-3]-minx)/dx;
645                                                 float fac2= (fp[0]-minx)/dx;
646                                                 if(fac1!=fac2)
647                                                         return fp[1]*(fac1-fac)/(fac1-fac2) + fp[-2]*(fac-fac2)/(fac1-fac2);
648                                         }
649                                         return fp[1];
650                                 }
651                         }
652                         return fp[-2];  // last y coord
653                 }
654         }
655         
656         return 1.0;
657 }
658
659 void makeDispListMBall(Scene *scene, Object *ob)
660 {
661         if(!ob || ob->type!=OB_MBALL) return;
662
663         // XXX: mball stuff uses plenty of global variables
664         //      while this is unchanged updating during render is unsafe
665         if(G.rendering) return;
666
667         freedisplist(&(ob->disp));
668
669         if(ob->type==OB_MBALL) {
670                 if(ob==find_basis_mball(scene, ob)) {
671                         metaball_polygonize(scene, ob, &ob->disp);
672                         tex_space_mball(ob);
673
674                         object_deform_mball(ob, &ob->disp);
675                 }
676         }
677         
678         boundbox_displist(ob);
679 }
680
681 void makeDispListMBall_forRender(Scene *scene, Object *ob, ListBase *dispbase)
682 {
683         metaball_polygonize(scene, ob, dispbase);
684         tex_space_mball(ob);
685         
686         object_deform_mball(ob, dispbase);
687 }
688
689 static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob, int forRender, int editmode)
690 {
691         ModifierData *md = modifiers_getVirtualModifierList(ob);
692         ModifierData *pretessellatePoint;
693         int required_mode;
694
695         if(forRender) required_mode = eModifierMode_Render;
696         else required_mode = eModifierMode_Realtime;
697
698         if(editmode) required_mode |= eModifierMode_Editmode;
699
700         pretessellatePoint = NULL;
701         for (; md; md=md->next) {
702                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
703
704                 if (!modifier_isEnabled(scene, md, required_mode)) continue;
705                 if (mti->type == eModifierTypeType_Constructive) return pretessellatePoint;
706
707                 if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
708                         pretessellatePoint = md;
709
710                         /* this modifiers are moving point of tessellation automatically
711                          * (some of them even can't be applied on tessellated curve), set flag
712                          * for incformation button in modifier's header */
713                         md->mode |= eModifierMode_ApplyOnSpline;
714                 } else if(md->mode&eModifierMode_ApplyOnSpline) {
715                         pretessellatePoint = md;
716                 }
717         }
718
719         return pretessellatePoint;
720 }
721
722 static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, float (**originalVerts_r)[3], float (**deformedVerts_r)[3], int *numVerts_r)
723 {
724         ModifierData *md = modifiers_getVirtualModifierList(ob);
725         ModifierData *pretessellatePoint;
726         Curve *cu= ob->data;
727         ListBase *nurb= BKE_curve_nurbs(cu);
728         int numVerts = 0;
729         int editmode = (!forRender && cu->editnurb);
730         float (*originalVerts)[3] = NULL;
731         float (*deformedVerts)[3] = NULL;
732         float *keyVerts= NULL;
733         int required_mode;
734
735         if(forRender) required_mode = eModifierMode_Render;
736         else required_mode = eModifierMode_Realtime;
737
738         pretessellatePoint = curve_get_tessellate_point(scene, ob, forRender, editmode);
739         
740         if(editmode) required_mode |= eModifierMode_Editmode;
741
742         if(cu->editnurb==NULL) {
743                 keyVerts= do_ob_key(scene, ob);
744
745                 if(keyVerts) {
746                         /* split coords from key data, the latter also includes
747                          * tilts, which is passed through in the modifier stack.
748                          * this is also the reason curves do not use a virtual
749                          * shape key modifier yet. */
750                         deformedVerts= curve_getKeyVertexCos(cu, nurb, keyVerts);
751                         originalVerts= MEM_dupallocN(deformedVerts);
752                         numVerts = count_curveverts_without_handles(nurb);
753                 }
754         }
755         
756         if (pretessellatePoint) {
757                 for (; md; md=md->next) {
758                         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
759
760                         md->scene= scene;
761                         
762                         if ((md->mode & required_mode) != required_mode) continue;
763                         if (mti->isDisabled && mti->isDisabled(md, forRender)) continue;
764                         if (mti->type!=eModifierTypeType_OnlyDeform) continue;
765
766                         if (!deformedVerts) {
767                                 deformedVerts = curve_getVertexCos(cu, nurb, &numVerts);
768                                 originalVerts = MEM_dupallocN(deformedVerts);
769                         }
770
771                         mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, forRender, editmode);
772
773                         if (md==pretessellatePoint)
774                                 break;
775                 }
776         }
777
778         if (deformedVerts)
779                 curve_applyVertexCos(cu, nurb, deformedVerts);
780         if (keyVerts) /* these are not passed through modifier stack */
781                 curve_applyKeyVertexTilts(cu, nurb, keyVerts);
782
783         if(keyVerts)
784                 MEM_freeN(keyVerts);
785
786         *originalVerts_r = originalVerts;
787         *deformedVerts_r = deformedVerts;
788         *numVerts_r = numVerts;
789 }
790
791 static float (*displist_get_allverts (ListBase *dispbase, int *totvert))[3]
792 {
793         DispList *dl;
794         float (*allverts)[3], *fp;
795
796         *totvert= 0;
797
798         for (dl=dispbase->first; dl; dl=dl->next)
799                 *totvert+= (dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr;
800
801         allverts= MEM_mallocN((*totvert)*sizeof(float)*3, "displist_get_allverts allverts");
802         fp= (float*)allverts;
803         for (dl=dispbase->first; dl; dl=dl->next) {
804                 int offs= 3 * ((dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr);
805                 memcpy(fp, dl->verts, sizeof(float) * offs);
806                 fp+= offs;
807         }
808
809         return allverts;
810 }
811
812 static void displist_apply_allverts(ListBase *dispbase, float (*allverts)[3])
813 {
814         DispList *dl;
815         float *fp;
816
817         fp= (float*)allverts;
818         for (dl=dispbase->first; dl; dl=dl->next) {
819                 int offs= 3 * ((dl->type==DL_INDEX3)?dl->nr:dl->parts*dl->nr);
820                 memcpy(dl->verts, fp, sizeof(float) * offs);
821                 fp+= offs;
822         }
823 }
824
825 static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispbase,
826         DerivedMesh **derivedFinal, int forRender, float (*originalVerts)[3], float (*deformedVerts)[3])
827 {
828         ModifierData *md = modifiers_getVirtualModifierList(ob);
829         ModifierData *pretessellatePoint;
830         Curve *cu= ob->data;
831         ListBase *nurb= BKE_curve_nurbs(cu);
832         int required_mode = 0, totvert = 0;
833         int editmode = (!forRender && cu->editnurb);
834         DerivedMesh *dm= NULL, *ndm;
835         float (*vertCos)[3] = NULL;
836         int useCache = !forRender;
837
838         if(forRender) required_mode = eModifierMode_Render;
839         else required_mode = eModifierMode_Realtime;
840
841         pretessellatePoint = curve_get_tessellate_point(scene, ob, forRender, editmode);
842         
843         if(editmode) required_mode |= eModifierMode_Editmode;
844
845         if (pretessellatePoint) {
846                 md = pretessellatePoint->next;
847         }
848
849         if (derivedFinal && *derivedFinal) {
850                 (*derivedFinal)->release (*derivedFinal);
851         }
852
853         for (; md; md=md->next) {
854                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
855
856                 md->scene= scene;
857
858                 if ((md->mode & required_mode) != required_mode) continue;
859                 if (mti->isDisabled && mti->isDisabled(md, forRender)) continue;
860
861                 if (mti->type == eModifierTypeType_OnlyDeform ||
862                                 (mti->type == eModifierTypeType_DeformOrConstruct && !dm)) {
863                         if (dm) {
864                                 if (!vertCos) {
865                                         totvert = dm->getNumVerts(dm);
866                                         vertCos = MEM_mallocN(sizeof(*vertCos) * totvert, "dfmv");
867                                         dm->getVertCos(dm, vertCos);
868                                 }
869
870                                 mti->deformVerts(md, ob, dm, vertCos, totvert, forRender, editmode);
871                         } else {
872                                 if (!vertCos) {
873                                         vertCos= displist_get_allverts(dispbase, &totvert);
874                                 }
875
876                                 mti->deformVerts(md, ob, NULL, vertCos, totvert, forRender, editmode);
877                         }
878                 } else {
879                         if (!derivedFinal) {
880                                 /* makeDisplistCurveTypes could be used for beveling, where derived mesh */
881                                 /* is totally unnecessary, so we could stop modifiers applying */
882                                 /* when we found constructive modifier but derived mesh is unwanted result */
883                                 break;
884                         }
885
886                         if (dm) {
887                                 if (vertCos) {
888                                         DerivedMesh *tdm = CDDM_copy(dm);
889                                         dm->release(dm);
890                                         dm = tdm;
891
892                                         CDDM_apply_vert_coords(dm, vertCos);
893                                         CDDM_calc_normals_mapping(dm);
894                                 }
895                         } else {
896                                 if (vertCos) {
897                                         displist_apply_allverts(dispbase, vertCos);
898                                 }
899
900                                 if (ELEM(ob->type, OB_CURVE, OB_FONT) && (cu->flag & CU_DEFORM_FILL)) {
901                                         curve_to_filledpoly(cu, nurb, dispbase);
902                                 }
903
904                                 dm= CDDM_from_curve_customDB(ob, dispbase);
905
906                                 CDDM_calc_normals_mapping(dm);
907                         }
908
909                         if (vertCos) {
910                                 /* Vertex coordinates were applied to necessary data, could free it */
911                                 MEM_freeN(vertCos);
912                                 vertCos= NULL;
913                         }
914
915                         ndm = mti->applyModifier(md, ob, dm, forRender, useCache);
916
917                         if (ndm) {
918                                 /* Modifier returned a new derived mesh */
919
920                                 if (dm && dm != ndm) /* Modifier  */
921                                         dm->release (dm);
922                                 dm = ndm;
923                         }
924                 }
925         }
926
927         if (vertCos) {
928                 if (dm) {
929                         DerivedMesh *tdm = CDDM_copy(dm);
930                         dm->release(dm);
931                         dm = tdm;
932
933                         CDDM_apply_vert_coords(dm, vertCos);
934                         CDDM_calc_normals_mapping(dm);
935                         MEM_freeN(vertCos);
936                 } else {
937                         displist_apply_allverts(dispbase, vertCos);
938                         MEM_freeN(vertCos);
939                         vertCos= NULL;
940                 }
941         }
942
943         if (derivedFinal) {
944                 if (dm) DM_ensure_tessface(dm); /* needed for drawing */
945                 (*derivedFinal) = dm;
946         }
947
948         if (deformedVerts) {
949                 curve_applyVertexCos(ob->data, nurb, originalVerts);
950                 MEM_freeN(originalVerts);
951                 MEM_freeN(deformedVerts);
952         }
953 }
954
955 static void displist_surf_indices(DispList *dl)
956 {
957         int a, b, p1, p2, p3, p4;
958         int *index;
959         
960         dl->totindex= 0;
961         
962         index=dl->index= MEM_mallocN( 4*sizeof(int)*(dl->parts+1)*(dl->nr+1), "index array nurbs");
963         
964         for(a=0; a<dl->parts; a++) {
965                 
966                 if (surfindex_displist(dl, a, &b, &p1, &p2, &p3, &p4)==0)
967                         break;
968                 
969                 for(; b<dl->nr; b++, index+=4) {        
970                         index[0]= p1;
971                         index[1]= p2;
972                         index[2]= p4;
973                         index[3]= p3;
974                         
975                         dl->totindex++;
976                         
977                         p2= p1; p1++;
978                         p4= p3; p3++;
979
980                 }
981         }
982         
983 }
984
985 static DerivedMesh *create_orco_dm(Scene *scene, Object *ob)
986 {
987         DerivedMesh *dm;
988         ListBase disp= {NULL, NULL};
989
990         /* OrcoDM should be created from underformed disp lists */
991         makeDispListCurveTypes_forOrco(scene, ob, &disp);
992         dm= CDDM_from_curve_customDB(ob, &disp);
993
994         freedisplist(&disp);
995
996         return dm;
997 }
998
999 static void add_orco_dm(Scene *scene, Object *ob, DerivedMesh *dm, DerivedMesh *orcodm)
1000 {
1001         float (*orco)[3], (*layerorco)[3];
1002         int totvert, a;
1003         Curve *cu= ob->data;
1004
1005         totvert= dm->getNumVerts(dm);
1006
1007         if(orcodm) {
1008                 orco= MEM_callocN(sizeof(float)*3*totvert, "dm orco");
1009
1010                 if(orcodm->getNumVerts(orcodm) == totvert)
1011                         orcodm->getVertCos(orcodm, orco);
1012                 else
1013                         dm->getVertCos(dm, orco);
1014         }
1015         else {
1016                 orco= (float(*)[3])make_orco_curve(scene, ob);
1017         }
1018
1019         for(a=0; a<totvert; a++) {
1020                 float *co = orco[a];
1021                 co[0] = (co[0]-cu->loc[0])/cu->size[0];
1022                 co[1] = (co[1]-cu->loc[1])/cu->size[1];
1023                 co[2] = (co[2]-cu->loc[2])/cu->size[2];
1024         }
1025
1026         if((layerorco = DM_get_vert_data_layer(dm, CD_ORCO))) {
1027                 memcpy(layerorco, orco, sizeof(float)*totvert);
1028                 MEM_freeN(orco);
1029         }
1030         else
1031                 DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco);
1032 }
1033
1034 static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *derivedFinal, int forRender)
1035 {
1036         /* this function represents logic of mesh's orcodm calculation */
1037         /* for displist-based objects */
1038
1039         ModifierData *md = modifiers_getVirtualModifierList(ob);
1040         ModifierData *pretessellatePoint;
1041         Curve *cu= ob->data;
1042         int required_mode;
1043         int editmode = (!forRender && cu->editnurb);
1044         DerivedMesh *ndm, *orcodm= NULL;
1045
1046         if(forRender) required_mode = eModifierMode_Render;
1047         else required_mode = eModifierMode_Realtime;
1048
1049         pretessellatePoint = curve_get_tessellate_point(scene, ob, forRender, editmode);
1050
1051         if(editmode) required_mode |= eModifierMode_Editmode;
1052
1053         if (pretessellatePoint) {
1054                 md = pretessellatePoint->next;
1055         }
1056
1057         for (; md; md=md->next) {
1058                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1059
1060                 md->scene= scene;
1061
1062                 if ((md->mode & required_mode) != required_mode) continue;
1063                 if (mti->isDisabled && mti->isDisabled(md, forRender)) continue;
1064                 if (mti->type!=eModifierTypeType_Constructive) continue;
1065
1066                 if(!orcodm)
1067                         orcodm= create_orco_dm(scene, ob);
1068
1069                 ndm = mti->applyModifier(md, ob, orcodm, forRender, 0);
1070
1071                 if(ndm) {
1072                         /* if the modifier returned a new dm, release the old one */
1073                         if(orcodm && orcodm != ndm) {
1074                                 orcodm->release(orcodm);
1075                         }
1076                         orcodm = ndm;
1077                 }
1078         }
1079
1080         /* add an orco layer if needed */
1081         add_orco_dm(scene, ob, derivedFinal, orcodm);
1082
1083         if(orcodm)
1084                 orcodm->release(orcodm);
1085 }
1086
1087 void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase,
1088         DerivedMesh **derivedFinal, int forRender, int forOrco)
1089 {
1090         ListBase *nubase;
1091         Nurb *nu;
1092         Curve *cu = ob->data;
1093         DispList *dl;
1094         float *data;
1095         int len;
1096         int numVerts;
1097         float (*originalVerts)[3];
1098         float (*deformedVerts)[3];
1099
1100         if(!forRender && cu->editnurb)
1101                 nubase= curve_editnurbs(cu);
1102         else
1103                 nubase= &cu->nurb;
1104
1105         if(!forOrco)
1106                 curve_calc_modifiers_pre(scene, ob, forRender, &originalVerts, &deformedVerts, &numVerts);
1107
1108         for (nu=nubase->first; nu; nu=nu->next) {
1109                 if(forRender || nu->hide==0) {
1110                         int resolu= nu->resolu, resolv= nu->resolv;
1111
1112                         if(forRender) {
1113                                 if(cu->resolu_ren) resolu= cu->resolu_ren;
1114                                 if(cu->resolv_ren) resolv= cu->resolv_ren;
1115                         }
1116
1117                         if(nu->pntsv==1) {
1118                                 len= SEGMENTSU(nu)*resolu;
1119
1120                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
1121                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
1122
1123                                 BLI_addtail(dispbase, dl);
1124                                 dl->parts= 1;
1125                                 dl->nr= len;
1126                                 dl->col= nu->mat_nr;
1127                                 dl->charidx= nu->charidx;
1128
1129                                 /* dl->rt will be used as flag for render face and */
1130                                 /* CU_2D conflicts with R_NOPUNOFLIP */
1131                                 dl->rt= nu->flag & ~CU_2D;
1132
1133                                 data= dl->verts;
1134                                 if(nu->flagu & CU_NURB_CYCLIC) dl->type= DL_POLY;
1135                                 else dl->type= DL_SEGM;
1136
1137                                 makeNurbcurve(nu, data, NULL, NULL, NULL, resolu, 3*sizeof(float));
1138                         }
1139                         else {
1140                                 len= (nu->pntsu*resolu) * (nu->pntsv*resolv);
1141                                 
1142                                 dl= MEM_callocN(sizeof(DispList), "makeDispListsurf");
1143                                 dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts");
1144                                 BLI_addtail(dispbase, dl);
1145
1146                                 dl->col= nu->mat_nr;
1147                                 dl->charidx= nu->charidx;
1148
1149                                 /* dl->rt will be used as flag for render face and */
1150                                 /* CU_2D conflicts with R_NOPUNOFLIP */
1151                                 dl->rt= nu->flag & ~CU_2D;
1152
1153                                 data= dl->verts;
1154                                 dl->type= DL_SURF;
1155
1156                                 dl->parts= (nu->pntsu*resolu);  /* in reverse, because makeNurbfaces works that way */
1157                                 dl->nr= (nu->pntsv*resolv);
1158                                 if(nu->flagv & CU_NURB_CYCLIC) dl->flag|= DL_CYCL_U;    /* reverse too! */
1159                                 if(nu->flagu & CU_NURB_CYCLIC) dl->flag|= DL_CYCL_V;
1160
1161                                 makeNurbfaces(nu, data, 0, resolu, resolv);
1162                                 
1163                                 /* gl array drawing: using indices */
1164                                 displist_surf_indices(dl);
1165                         }
1166                 }
1167         }
1168
1169         /* make copy of 'undeformed" displist for texture space calculation
1170          * actually, it's not totally undeformed -- pre-tessellation modifiers are
1171          * already applied, thats how it worked for years, so keep for compatibility (sergey) */
1172         copy_displist(&cu->disp, dispbase);
1173
1174         if (!forRender) {
1175                 tex_space_curve(cu);
1176         }
1177
1178         if(!forOrco)
1179                 curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal,
1180                         forRender, originalVerts, deformedVerts);
1181 }
1182
1183 static void rotateBevelPiece(Curve *cu, BevPoint *bevp, DispList *dlb, float widfac, float fac, float **data_r)
1184 {
1185         float *fp, *data = *data_r;
1186         int b;
1187
1188         fp = dlb->verts;
1189         for (b = 0; b<dlb->nr; b++,fp += 3,data += 3) {
1190                 if(cu->flag & CU_3D) {
1191                         float vec[3];
1192
1193                         vec[0] = fp[1]+widfac;
1194                         vec[1] = fp[2];
1195                         vec[2 ]= 0.0;
1196
1197                         mul_qt_v3(bevp->quat, vec);
1198
1199                         data[0] = bevp->vec[0] + fac*vec[0];
1200                         data[1] = bevp->vec[1] + fac*vec[1];
1201                         data[2] = bevp->vec[2] + fac*vec[2];
1202                 }
1203                 else {
1204                         data[0] = bevp->vec[0] + fac*(widfac+fp[1])*bevp->sina;
1205                         data[1] = bevp->vec[1] + fac*(widfac+fp[1])*bevp->cosa;
1206                         data[2] = bevp->vec[2] + fac*fp[2];
1207                 }
1208         }
1209
1210         *data_r = data;
1211 }
1212
1213 static void fillBevelCap(Curve *cu, Nurb *nu, BevPoint *bevp, DispList *dlb, float fac, float widfac, ListBase *dispbase)
1214 {
1215         DispList *dl;
1216         float *data;
1217
1218         dl= MEM_callocN(sizeof(DispList), "makeDispListbev2");
1219         dl->verts= data= MEM_callocN(3*sizeof(float)*dlb->nr, "dlverts");
1220
1221         dl->type= DL_POLY;
1222
1223         dl->parts= 1;
1224         dl->nr= dlb->nr;
1225         dl->col= nu->mat_nr;
1226         dl->charidx= nu->charidx;
1227
1228         /* dl->rt will be used as flag for render face and */
1229         /* CU_2D conflicts with R_NOPUNOFLIP */
1230         dl->rt= nu->flag & ~CU_2D;
1231
1232         rotateBevelPiece(cu, bevp, dlb, widfac, fac, &data);
1233
1234         BLI_addtail(dispbase, dl);
1235 }
1236
1237 static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispbase,
1238         DerivedMesh **derivedFinal, int forRender, int forOrco)
1239 {
1240         Curve *cu = ob->data;
1241
1242         /* we do allow duplis... this is only displist on curve level */
1243         if(!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return;
1244
1245         if(ob->type==OB_SURF) {
1246                 makeDispListSurf(scene, ob, dispbase, derivedFinal, forRender, forOrco);
1247         }
1248         else if (ELEM(ob->type, OB_CURVE, OB_FONT)) {
1249                 ListBase dlbev;
1250                 ListBase *nubase;
1251                 float (*originalVerts)[3];
1252                 float (*deformedVerts)[3];
1253                 int numVerts;
1254
1255                 nubase= BKE_curve_nurbs(cu);
1256
1257                 BLI_freelistN(&(cu->bev));
1258
1259                 if(cu->path) free_path(cu->path);
1260                 cu->path= NULL;
1261
1262                 if(ob->type==OB_FONT) BKE_text_to_curve(G.main, scene, ob, 0);
1263
1264                 if(!forOrco) curve_calc_modifiers_pre(scene, ob, forRender, &originalVerts, &deformedVerts, &numVerts);
1265
1266                 makeBevelList(ob);
1267
1268                 /* If curve has no bevel will return nothing */
1269                 makebevelcurve(scene, ob, &dlbev, forRender);
1270
1271                 /* no bevel or extrude, and no width correction? */
1272                 if (!dlbev.first && cu->width==1.0f) {
1273                         curve_to_displist(cu, nubase, dispbase, forRender);
1274                 } else {
1275                         float widfac= cu->width - 1.0f;
1276                         BevList *bl= cu->bev.first;
1277                         Nurb *nu= nubase->first;
1278
1279                         for (; bl && nu; bl=bl->next,nu=nu->next) {
1280                                 DispList *dl;
1281                                 float *data;
1282                                 BevPoint *bevp;
1283                                 int a;
1284
1285                                 if (bl->nr) { /* blank bevel lists can happen */
1286
1287                                         /* exception handling; curve without bevel or extrude, with width correction */
1288                                         if(dlbev.first==NULL) {
1289                                                 dl= MEM_callocN(sizeof(DispList), "makeDispListbev");
1290                                                 dl->verts= MEM_callocN(3*sizeof(float)*bl->nr, "dlverts");
1291                                                 BLI_addtail(dispbase, dl);
1292
1293                                                 if(bl->poly!= -1) dl->type= DL_POLY;
1294                                                 else dl->type= DL_SEGM;
1295
1296                                                 if(dl->type==DL_SEGM) dl->flag = (DL_FRONT_CURVE|DL_BACK_CURVE);
1297
1298                                                 dl->parts= 1;
1299                                                 dl->nr= bl->nr;
1300                                                 dl->col= nu->mat_nr;
1301                                                 dl->charidx= nu->charidx;
1302
1303                                                 /* dl->rt will be used as flag for render face and */
1304                                                 /* CU_2D conflicts with R_NOPUNOFLIP */
1305                                                 dl->rt= nu->flag & ~CU_2D;
1306
1307                                                 a= dl->nr;
1308                                                 bevp= (BevPoint *)(bl+1);
1309                                                 data= dl->verts;
1310                                                 while(a--) {
1311                                                         data[0]= bevp->vec[0]+widfac*bevp->sina;
1312                                                         data[1]= bevp->vec[1]+widfac*bevp->cosa;
1313                                                         data[2]= bevp->vec[2];
1314                                                         bevp++;
1315                                                         data+=3;
1316                                                 }
1317                                         }
1318                                         else {
1319                                                 DispList *dlb;
1320                                                 ListBase bottom_capbase = {NULL, NULL};
1321                                                 ListBase top_capbase = {NULL, NULL};
1322
1323                                                 for (dlb=dlbev.first; dlb; dlb=dlb->next) {
1324                                                         /* for each part of the bevel use a separate displblock */
1325                                                         dl= MEM_callocN(sizeof(DispList), "makeDispListbev1");
1326                                                         dl->verts= data= MEM_callocN(3*sizeof(float)*dlb->nr*bl->nr, "dlverts");
1327                                                         BLI_addtail(dispbase, dl);
1328         
1329                                                         dl->type= DL_SURF;
1330                                                         
1331                                                         dl->flag= dlb->flag & (DL_FRONT_CURVE|DL_BACK_CURVE);
1332                                                         if(dlb->type==DL_POLY) dl->flag |= DL_CYCL_U;
1333                                                         if(bl->poly>=0) dl->flag |= DL_CYCL_V;
1334                                                         
1335                                                         dl->parts= bl->nr;
1336                                                         dl->nr= dlb->nr;
1337                                                         dl->col= nu->mat_nr;
1338                                                         dl->charidx= nu->charidx;
1339
1340                                                         /* dl->rt will be used as flag for render face and */
1341                                                         /* CU_2D conflicts with R_NOPUNOFLIP */
1342                                                         dl->rt= nu->flag & ~CU_2D;
1343
1344                                                         dl->bevelSplitFlag= MEM_callocN(sizeof(*dl->col2)*((bl->nr+0x1F)>>5), "bevelSplitFlag");
1345         
1346                                                         /* for each point of poly make a bevel piece */
1347                                                         bevp= (BevPoint *)(bl+1);
1348                                                         for(a=0; a<bl->nr; a++,bevp++) {
1349                                                                 float fac=1.0;
1350                                                                 if (cu->taperobj==NULL) {
1351                                                                         if ( (cu->bevobj!=NULL) || !((cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) )
1352                                                                                 fac = bevp->radius;
1353                                                                 } else {
1354                                                                         fac = calc_taper(scene, cu->taperobj, a, bl->nr);
1355                                                                 }
1356
1357                                                                 if (bevp->split_tag) {
1358                                                                         dl->bevelSplitFlag[a>>5] |= 1<<(a&0x1F);
1359                                                                 }
1360         
1361                                                                 /* rotate bevel piece and write in data */
1362                                                                 rotateBevelPiece(cu, bevp, dlb, widfac, fac, &data);
1363
1364                                                                 if (cu->bevobj && (cu->flag & CU_FILL_CAPS)) {
1365                                                                         if (a == 0)
1366                                                                                 fillBevelCap(cu, nu, bevp, dlb, fac, widfac, &bottom_capbase);
1367                                                                         else if (a == bl->nr - 1)
1368                                                                                 fillBevelCap(cu, nu, bevp, dlb, fac, widfac, &top_capbase);
1369                                                                 }
1370                                                         }
1371
1372                                                         /* gl array drawing: using indices */
1373                                                         displist_surf_indices(dl);
1374                                                 }
1375
1376                                                 if(bottom_capbase.first) {
1377                                                         filldisplist(&bottom_capbase, dispbase, 1);
1378                                                         filldisplist(&top_capbase, dispbase, 0);
1379                                                         freedisplist(&bottom_capbase);
1380                                                         freedisplist(&top_capbase);
1381                                                 }
1382                                         }
1383                                 }
1384
1385                         }
1386                         freedisplist(&dlbev);
1387                 }
1388
1389                 if (!(cu->flag & CU_DEFORM_FILL)) {
1390                         curve_to_filledpoly(cu, nubase, dispbase);
1391                 }
1392
1393                 if(cu->flag & CU_PATH) calc_curvepath(ob);
1394
1395                 /* make copy of 'undeformed" displist for texture space calculation
1396                  * actually, it's not totally undeformed -- pre-tessellation modifiers are
1397                  * already applied, thats how it worked for years, so keep for compatibility (sergey) */
1398                 copy_displist(&cu->disp, dispbase);
1399
1400                 if (!forRender) {
1401                         tex_space_curve(cu);
1402                 }
1403
1404                 if(!forOrco) curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal, forRender, originalVerts, deformedVerts);
1405
1406                 if (cu->flag & CU_DEFORM_FILL && !ob->derivedFinal) {
1407                         curve_to_filledpoly(cu, nubase, dispbase);
1408                 }
1409         }
1410 }
1411
1412 void makeDispListCurveTypes(Scene *scene, Object *ob, int forOrco)
1413 {
1414         Curve *cu= ob->data;
1415         ListBase *dispbase;
1416
1417         /* The same check for duplis as in do_makeDispListCurveTypes.
1418          * Happens when curve used for constraint/bevel was converted to mesh.
1419          * check there is still needed for render displist and orco displists. */
1420         if(!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return;
1421
1422         freedisplist(&(ob->disp));
1423         dispbase= &(ob->disp);
1424         freedisplist(dispbase);
1425
1426         /* free displist used for textspace */
1427         freedisplist(&cu->disp);
1428
1429         do_makeDispListCurveTypes(scene, ob, dispbase, &ob->derivedFinal, 0, forOrco);
1430
1431         if (ob->derivedFinal) {
1432                 DM_set_object_boundbox (ob, ob->derivedFinal);
1433         } else {
1434                 boundbox_displist (ob);
1435
1436                 /* if there is no derivedMesh, object's boundbox is unneeded */
1437                 if (ob->bb) {
1438                         MEM_freeN(ob->bb);
1439                         ob->bb= NULL;
1440                 }
1441         }
1442 }
1443
1444 void makeDispListCurveTypes_forRender(Scene *scene, Object *ob, ListBase *dispbase,
1445         DerivedMesh **derivedFinal, int forOrco)
1446 {
1447         do_makeDispListCurveTypes(scene, ob, dispbase, derivedFinal, 1, forOrco);
1448 }
1449
1450 void makeDispListCurveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase)
1451 {
1452         do_makeDispListCurveTypes(scene, ob, dispbase, NULL, 1, 1);
1453 }
1454
1455 /* add Orco layer to the displist object which has got derived mesh and return orco */
1456 float *makeOrcoDispList(Scene *scene, Object *ob, DerivedMesh *derivedFinal, int forRender)
1457 {
1458         float *orco;
1459
1460         if (derivedFinal == NULL)
1461                 derivedFinal= ob->derivedFinal;
1462
1463         if (!derivedFinal->getVertDataArray(derivedFinal, CD_ORCO)) {
1464                 curve_calc_orcodm(scene, ob, derivedFinal, forRender);
1465         }
1466
1467         orco= derivedFinal->getVertDataArray(derivedFinal, CD_ORCO);
1468
1469         if(orco) {
1470                 orco= MEM_dupallocN(orco);
1471         }
1472
1473         return orco;
1474 }
1475
1476 /* this is confusing, there's also min_max_object, appplying the obmat... */
1477 static void boundbox_displist(Object *ob)
1478 {
1479         BoundBox *bb=NULL;
1480         float min[3], max[3];
1481         DispList *dl;
1482         float *vert;
1483         int a, tot=0;
1484         
1485         INIT_MINMAX(min, max);
1486
1487         if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
1488                 Curve *cu= ob->data;
1489                 int doit= 0;
1490
1491                 if(cu->bb==NULL) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
1492                 bb= cu->bb;
1493                 
1494                 dl= ob->disp.first;
1495
1496                 while (dl) {
1497                         if(dl->type==DL_INDEX3) tot= dl->nr;
1498                         else tot= dl->nr*dl->parts;
1499                         
1500                         vert= dl->verts;
1501                         for(a=0; a<tot; a++, vert+=3) {
1502                                 doit= 1;
1503                                 DO_MINMAX(vert, min, max);
1504                         }
1505
1506                         dl= dl->next;
1507                 }
1508                 
1509                 if(!doit) {
1510                         /* there's no geometry in displist, use zero-sized boundbox */
1511                         zero_v3(min);
1512                         zero_v3(max);
1513                 }
1514                 
1515         }
1516         
1517         if(bb) {
1518                 boundbox_set_from_min_max(bb, min, max);
1519         }
1520 }
1521