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