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