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