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