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