Merge branch 'blender2.7'
[blender.git] / source / blender / blenkernel / intern / displist.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup bke
22  */
23
24
25 #include <math.h>
26 #include <stdio.h>
27 #include <string.h>
28
29 #include "MEM_guardedalloc.h"
30
31 #include "DNA_curve_types.h"
32 #include "DNA_mesh_types.h"
33 #include "DNA_scene_types.h"
34 #include "DNA_object_types.h"
35 #include "DNA_vfont_types.h"
36
37 #include "BLI_blenlib.h"
38 #include "BLI_memarena.h"
39 #include "BLI_math.h"
40 #include "BLI_scanfill.h"
41 #include "BLI_utildefines.h"
42 #include "BLI_linklist.h"
43
44 #include "BKE_displist.h"
45 #include "BKE_cdderivedmesh.h"
46 #include "BKE_object.h"
47 #include "BKE_library.h"
48 #include "BKE_mball.h"
49 #include "BKE_mball_tessellate.h"
50 #include "BKE_mesh.h"
51 #include "BKE_curve.h"
52 #include "BKE_key.h"
53 #include "BKE_anim.h"
54 #include "BKE_font.h"
55 #include "BKE_lattice.h"
56 #include "BKE_modifier.h"
57
58 #include "BLI_sys_types.h" // for intptr_t support
59
60 #include "DEG_depsgraph.h"
61 #include "DEG_depsgraph_query.h"
62
63 static void boundbox_displist_object(Object *ob);
64
65 void BKE_displist_elem_free(DispList *dl)
66 {
67         if (dl) {
68                 if (dl->verts) MEM_freeN(dl->verts);
69                 if (dl->nors) MEM_freeN(dl->nors);
70                 if (dl->index) MEM_freeN(dl->index);
71                 if (dl->bevel_split) MEM_freeN(dl->bevel_split);
72                 MEM_freeN(dl);
73         }
74 }
75
76 void BKE_displist_free(ListBase *lb)
77 {
78         DispList *dl;
79
80         while ((dl = BLI_pophead(lb))) {
81                 BKE_displist_elem_free(dl);
82         }
83 }
84
85 DispList *BKE_displist_find_or_create(ListBase *lb, int type)
86 {
87         DispList *dl;
88
89         dl = lb->first;
90         while (dl) {
91                 if (dl->type == type)
92                         return dl;
93                 dl = dl->next;
94         }
95
96         dl = MEM_callocN(sizeof(DispList), "find_disp");
97         dl->type = type;
98         BLI_addtail(lb, dl);
99
100         return dl;
101 }
102
103 DispList *BKE_displist_find(ListBase *lb, int type)
104 {
105         DispList *dl;
106
107         dl = lb->first;
108         while (dl) {
109                 if (dl->type == type)
110                         return dl;
111                 dl = dl->next;
112         }
113
114         return NULL;
115 }
116
117 bool BKE_displist_has_faces(ListBase *lb)
118 {
119         DispList *dl;
120
121         for (dl = lb->first; dl; dl = dl->next) {
122                 if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
123                         return true;
124                 }
125         }
126
127         return false;
128 }
129
130 void BKE_displist_copy(ListBase *lbn, ListBase *lb)
131 {
132         DispList *dln, *dl;
133
134         BKE_displist_free(lbn);
135
136         dl = lb->first;
137         while (dl) {
138                 dln = MEM_dupallocN(dl);
139                 BLI_addtail(lbn, dln);
140                 dln->verts = MEM_dupallocN(dl->verts);
141                 dln->nors = MEM_dupallocN(dl->nors);
142                 dln->index = MEM_dupallocN(dl->index);
143
144                 if (dl->bevel_split) {
145                         dln->bevel_split = MEM_dupallocN(dl->bevel_split);
146                 }
147
148                 dl = dl->next;
149         }
150 }
151
152 void BKE_displist_normals_add(ListBase *lb)
153 {
154         DispList *dl = NULL;
155         float *vdata, *ndata, nor[3];
156         float *v1, *v2, *v3, *v4;
157         float *n1, *n2, *n3, *n4;
158         int a, b, p1, p2, p3, p4;
159
160         dl = lb->first;
161
162         while (dl) {
163                 if (dl->type == DL_INDEX3) {
164                         if (dl->nors == NULL) {
165                                 dl->nors = MEM_callocN(sizeof(float) * 3, "dlnors");
166
167                                 if (dl->flag & DL_BACK_CURVE) {
168                                         dl->nors[2] = -1.0f;
169                                 }
170                                 else {
171                                         dl->nors[2] = 1.0f;
172                                 }
173                         }
174                 }
175                 else if (dl->type == DL_SURF) {
176                         if (dl->nors == NULL) {
177                                 dl->nors = MEM_callocN(sizeof(float) * 3 * dl->nr * dl->parts, "dlnors");
178
179                                 vdata = dl->verts;
180                                 ndata = dl->nors;
181
182                                 for (a = 0; a < dl->parts; a++) {
183
184                                         if (BKE_displist_surfindex_get(dl, a, &b, &p1, &p2, &p3, &p4) == 0)
185                                                 break;
186
187                                         v1 = vdata + 3 * p1;
188                                         n1 = ndata + 3 * p1;
189                                         v2 = vdata + 3 * p2;
190                                         n2 = ndata + 3 * p2;
191                                         v3 = vdata + 3 * p3;
192                                         n3 = ndata + 3 * p3;
193                                         v4 = vdata + 3 * p4;
194                                         n4 = ndata + 3 * p4;
195
196                                         for (; b < dl->nr; b++) {
197                                                 normal_quad_v3(nor, v1, v3, v4, v2);
198
199                                                 add_v3_v3(n1, nor);
200                                                 add_v3_v3(n2, nor);
201                                                 add_v3_v3(n3, nor);
202                                                 add_v3_v3(n4, nor);
203
204                                                 v2 = v1; v1 += 3;
205                                                 v4 = v3; v3 += 3;
206                                                 n2 = n1; n1 += 3;
207                                                 n4 = n3; n3 += 3;
208                                         }
209                                 }
210                                 a = dl->parts * dl->nr;
211                                 v1 = ndata;
212                                 while (a--) {
213                                         normalize_v3(v1);
214                                         v1 += 3;
215                                 }
216                         }
217                 }
218                 dl = dl->next;
219         }
220 }
221
222 void BKE_displist_count(ListBase *lb, int *totvert, int *totface, int *tottri)
223 {
224         DispList *dl;
225
226         for (dl = lb->first; dl; dl = dl->next) {
227                 int vert_tot = 0;
228                 int face_tot = 0;
229                 int tri_tot = 0;
230                 bool cyclic_u = dl->flag & DL_CYCL_U;
231                 bool cyclic_v = dl->flag & DL_CYCL_V;
232
233                 switch (dl->type) {
234                         case DL_SURF:
235                         {
236                                 int segments_u = dl->nr - (cyclic_u == false);
237                                 int segments_v = dl->parts - (cyclic_v == false);
238                                 vert_tot = dl->nr * dl->parts;
239                                 face_tot = segments_u * segments_v;
240                                 tri_tot  = face_tot * 2;
241                                 break;
242                         }
243                         case DL_INDEX3:
244                         {
245                                 vert_tot = dl->nr;
246                                 face_tot = dl->parts;
247                                 tri_tot  = face_tot;
248                                 break;
249                         }
250                         case DL_INDEX4:
251                         {
252                                 vert_tot = dl->nr;
253                                 face_tot = dl->parts;
254                                 tri_tot  = face_tot * 2;
255                                 break;
256                         }
257                         case DL_POLY:
258                         case DL_SEGM:
259                         {
260                                 vert_tot = dl->nr * dl->parts;
261                                 break;
262                         }
263                 }
264
265                 *totvert += vert_tot;
266                 *totface += face_tot;
267                 *tottri  += tri_tot;
268         }
269 }
270
271 bool BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4)
272 {
273         if ((dl->flag & DL_CYCL_V) == 0 && a == (dl->parts) - 1) {
274                 return false;
275         }
276
277         if (dl->flag & DL_CYCL_U) {
278                 (*p1) = dl->nr * a;
279                 (*p2) = (*p1) + dl->nr - 1;
280                 (*p3) = (*p1) + dl->nr;
281                 (*p4) = (*p2) + dl->nr;
282                 (*b) = 0;
283         }
284         else {
285                 (*p2) = dl->nr * a;
286                 (*p1) = (*p2) + 1;
287                 (*p4) = (*p2) + dl->nr;
288                 (*p3) = (*p1) + dl->nr;
289                 (*b) = 1;
290         }
291
292         if ((dl->flag & DL_CYCL_V) && a == dl->parts - 1) {
293                 (*p3) -= dl->nr * dl->parts;
294                 (*p4) -= dl->nr * dl->parts;
295         }
296
297         return true;
298 }
299
300 /* ****************** make displists ********************* */
301 #ifdef __INTEL_COMPILER
302 /* ICC with the optimization -02 causes crashes. */
303 #   pragma intel optimization_level 1
304 #endif
305 static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase,
306                               const bool for_render, const bool use_render_resolution)
307 {
308         Nurb *nu;
309         DispList *dl;
310         BezTriple *bezt, *prevbezt;
311         BPoint *bp;
312         float *data;
313         int a, len, resolu;
314         const bool editmode = (!for_render && (cu->editnurb || cu->editfont));
315
316         nu = nubase->first;
317         while (nu) {
318                 if (nu->hide == 0 || editmode == false) {
319                         if (use_render_resolution && cu->resolu_ren != 0)
320                                 resolu = cu->resolu_ren;
321                         else
322                                 resolu = nu->resolu;
323
324                         if (!BKE_nurb_check_valid_u(nu)) {
325                                 /* pass */
326                         }
327                         else if (nu->type == CU_BEZIER) {
328                                 /* count */
329                                 len = 0;
330                                 a = nu->pntsu - 1;
331                                 if (nu->flagu & CU_NURB_CYCLIC) a++;
332
333                                 prevbezt = nu->bezt;
334                                 bezt = prevbezt + 1;
335                                 while (a--) {
336                                         if (a == 0 && (nu->flagu & CU_NURB_CYCLIC))
337                                                 bezt = nu->bezt;
338
339                                         if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT)
340                                                 len++;
341                                         else
342                                                 len += resolu;
343
344                                         if (a == 0 && (nu->flagu & CU_NURB_CYCLIC) == 0)
345                                                 len++;
346
347                                         prevbezt = bezt;
348                                         bezt++;
349                                 }
350
351                                 dl = MEM_callocN(sizeof(DispList), "makeDispListbez");
352                                 /* len+1 because of 'forward_diff_bezier' function */
353                                 dl->verts = MEM_mallocN((len + 1) * sizeof(float[3]), "dlverts");
354                                 BLI_addtail(dispbase, dl);
355                                 dl->parts = 1;
356                                 dl->nr = len;
357                                 dl->col = nu->mat_nr;
358                                 dl->charidx = nu->charidx;
359
360                                 data = dl->verts;
361
362                                 /* check that (len != 2) so we don't immediately loop back on ourselves */
363                                 if (nu->flagu & CU_NURB_CYCLIC && (dl->nr != 2)) {
364                                         dl->type = DL_POLY;
365                                         a = nu->pntsu;
366                                 }
367                                 else {
368                                         dl->type = DL_SEGM;
369                                         a = nu->pntsu - 1;
370                                 }
371
372                                 prevbezt = nu->bezt;
373                                 bezt = prevbezt + 1;
374
375                                 while (a--) {
376                                         if (a == 0 && dl->type == DL_POLY)
377                                                 bezt = nu->bezt;
378
379                                         if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) {
380                                                 copy_v3_v3(data, prevbezt->vec[1]);
381                                                 data += 3;
382                                         }
383                                         else {
384                                                 int j;
385                                                 for (j = 0; j < 3; j++) {
386                                                         BKE_curve_forward_diff_bezier(prevbezt->vec[1][j],
387                                                                                       prevbezt->vec[2][j],
388                                                                                       bezt->vec[0][j],
389                                                                                       bezt->vec[1][j],
390                                                                                       data + j, resolu, 3 * sizeof(float));
391                                                 }
392
393                                                 data += 3 * resolu;
394                                         }
395
396                                         if (a == 0 && dl->type == DL_SEGM) {
397                                                 copy_v3_v3(data, bezt->vec[1]);
398                                         }
399
400                                         prevbezt = bezt;
401                                         bezt++;
402                                 }
403                         }
404                         else if (nu->type == CU_NURBS) {
405                                 len = (resolu * SEGMENTSU(nu));
406
407                                 dl = MEM_callocN(sizeof(DispList), "makeDispListsurf");
408                                 dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts");
409                                 BLI_addtail(dispbase, dl);
410                                 dl->parts = 1;
411
412                                 dl->nr = len;
413                                 dl->col = nu->mat_nr;
414                                 dl->charidx = nu->charidx;
415
416                                 data = dl->verts;
417                                 if (nu->flagu & CU_NURB_CYCLIC)
418                                         dl->type = DL_POLY;
419                                 else dl->type = DL_SEGM;
420                                 BKE_nurb_makeCurve(nu, data, NULL, NULL, NULL, resolu, 3 * sizeof(float));
421                         }
422                         else if (nu->type == CU_POLY) {
423                                 len = nu->pntsu;
424                                 dl = MEM_callocN(sizeof(DispList), "makeDispListpoly");
425                                 dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts");
426                                 BLI_addtail(dispbase, dl);
427                                 dl->parts = 1;
428                                 dl->nr = len;
429                                 dl->col = nu->mat_nr;
430                                 dl->charidx = nu->charidx;
431
432                                 data = dl->verts;
433                                 if ((nu->flagu & CU_NURB_CYCLIC) && (dl->nr != 2)) {
434                                         dl->type = DL_POLY;
435                                 }
436                                 else {
437                                         dl->type = DL_SEGM;
438                                 }
439
440                                 a = len;
441                                 bp = nu->bp;
442                                 while (a--) {
443                                         copy_v3_v3(data, bp->vec);
444                                         bp++;
445                                         data += 3;
446                                 }
447                         }
448                 }
449                 nu = nu->next;
450         }
451 }
452
453 /**
454  * \param normal_proj: Optional normal thats used to project the scanfill verts into 2d coords.
455  * Pass this along if known since it saves time calculating the normal.
456  * \param flipnormal: Flip the normal (same as passing \a normal_proj negated)
457  */
458 void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj[3], const bool flipnormal)
459 {
460         ScanFillContext sf_ctx;
461         ScanFillVert *sf_vert, *sf_vert_new, *sf_vert_last;
462         ScanFillFace *sf_tri;
463         MemArena *sf_arena;
464         DispList *dlnew = NULL, *dl;
465         float *f1;
466         int colnr = 0, charidx = 0, cont = 1, tot, a, *index, nextcol = 0;
467         int totvert;
468         const int scanfill_flag = BLI_SCANFILL_CALC_REMOVE_DOUBLES | BLI_SCANFILL_CALC_POLYS | BLI_SCANFILL_CALC_HOLES;
469
470         if (dispbase == NULL)
471                 return;
472         if (BLI_listbase_is_empty(dispbase))
473                 return;
474
475         sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__);
476
477         while (cont) {
478                 int dl_flag_accum = 0;
479                 cont = 0;
480                 totvert = 0;
481                 nextcol = 0;
482
483                 BLI_scanfill_begin_arena(&sf_ctx, sf_arena);
484
485                 dl = dispbase->first;
486                 while (dl) {
487                         if (dl->type == DL_POLY) {
488                                 if (charidx < dl->charidx)
489                                         cont = 1;
490                                 else if (charidx == dl->charidx) { /* character with needed index */
491                                         if (colnr == dl->col) {
492
493                                                 sf_ctx.poly_nr++;
494
495                                                 /* make editverts and edges */
496                                                 f1 = dl->verts;
497                                                 a = dl->nr;
498                                                 sf_vert = sf_vert_new = NULL;
499
500                                                 while (a--) {
501                                                         sf_vert_last = sf_vert;
502
503                                                         sf_vert = BLI_scanfill_vert_add(&sf_ctx, f1);
504                                                         totvert++;
505
506                                                         if (sf_vert_last == NULL)
507                                                                 sf_vert_new = sf_vert;
508                                                         else {
509                                                                 BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
510                                                         }
511                                                         f1 += 3;
512                                                 }
513
514                                                 if (sf_vert != NULL && sf_vert_new != NULL) {
515                                                         BLI_scanfill_edge_add(&sf_ctx, sf_vert, sf_vert_new);
516                                                 }
517                                         }
518                                         else if (colnr < dl->col) {
519                                                 /* got poly with next material at current char */
520                                                 cont = 1;
521                                                 nextcol = 1;
522                                         }
523                                 }
524                                 dl_flag_accum |= dl->flag;
525                         }
526                         dl = dl->next;
527                 }
528
529                 /* XXX (obedit && obedit->actcol) ? (obedit->actcol - 1) : 0)) { */
530                 if (totvert && (tot = BLI_scanfill_calc_ex(&sf_ctx,
531                                                            scanfill_flag,
532                                                            normal_proj)))
533                 {
534                         if (tot) {
535                                 dlnew = MEM_callocN(sizeof(DispList), "filldisplist");
536                                 dlnew->type = DL_INDEX3;
537                                 dlnew->flag = (dl_flag_accum & (DL_BACK_CURVE | DL_FRONT_CURVE));
538                                 dlnew->col = colnr;
539                                 dlnew->nr = totvert;
540                                 dlnew->parts = tot;
541
542                                 dlnew->index = MEM_mallocN(tot * 3 * sizeof(int), "dlindex");
543                                 dlnew->verts = MEM_mallocN(totvert * 3 * sizeof(float), "dlverts");
544
545                                 /* vert data */
546                                 f1 = dlnew->verts;
547                                 totvert = 0;
548
549                                 for (sf_vert = sf_ctx.fillvertbase.first; sf_vert; sf_vert = sf_vert->next) {
550                                         copy_v3_v3(f1, sf_vert->co);
551                                         f1 += 3;
552
553                                         /* index number */
554                                         sf_vert->tmp.i = totvert;
555                                         totvert++;
556                                 }
557
558                                 /* index data */
559
560                                 index = dlnew->index;
561                                 for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) {
562                                         index[0] = sf_tri->v1->tmp.i;
563                                         index[1] = sf_tri->v2->tmp.i;
564                                         index[2] = sf_tri->v3->tmp.i;
565
566                                         if (flipnormal)
567                                                 SWAP(int, index[0], index[2]);
568
569                                         index += 3;
570                                 }
571                         }
572
573                         BLI_addhead(to, dlnew);
574                 }
575                 BLI_scanfill_end_arena(&sf_ctx, sf_arena);
576
577                 if (nextcol) {
578                         /* stay at current char but fill polys with next material */
579                         colnr++;
580                 }
581                 else {
582                         /* switch to next char and start filling from first material */
583                         charidx++;
584                         colnr = 0;
585                 }
586         }
587
588         BLI_memarena_free(sf_arena);
589
590         /* do not free polys, needed for wireframe display */
591 }
592
593 static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase)
594 {
595         const float z_up[3] = {0.0f, 0.0f, 1.0f};
596         ListBase front, back;
597         DispList *dl, *dlnew;
598         float *fp, *fp1;
599         int a, dpoly;
600
601         BLI_listbase_clear(&front);
602         BLI_listbase_clear(&back);
603
604         dl = dispbase->first;
605         while (dl) {
606                 if (dl->type == DL_SURF) {
607                         if ((dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U) == 0) {
608                                 if ((cu->flag & CU_BACK) && (dl->flag & DL_BACK_CURVE)) {
609                                         dlnew = MEM_callocN(sizeof(DispList), "filldisp");
610                                         BLI_addtail(&front, dlnew);
611                                         dlnew->verts = fp1 = MEM_mallocN(sizeof(float) * 3 * dl->parts, "filldisp1");
612                                         dlnew->nr = dl->parts;
613                                         dlnew->parts = 1;
614                                         dlnew->type = DL_POLY;
615                                         dlnew->flag = DL_BACK_CURVE;
616                                         dlnew->col = dl->col;
617                                         dlnew->charidx = dl->charidx;
618
619                                         fp = dl->verts;
620                                         dpoly = 3 * dl->nr;
621
622                                         a = dl->parts;
623                                         while (a--) {
624                                                 copy_v3_v3(fp1, fp);
625                                                 fp1 += 3;
626                                                 fp += dpoly;
627                                         }
628                                 }
629                                 if ((cu->flag & CU_FRONT) && (dl->flag & DL_FRONT_CURVE)) {
630                                         dlnew = MEM_callocN(sizeof(DispList), "filldisp");
631                                         BLI_addtail(&back, dlnew);
632                                         dlnew->verts = fp1 = MEM_mallocN(sizeof(float) * 3 * dl->parts, "filldisp1");
633                                         dlnew->nr = dl->parts;
634                                         dlnew->parts = 1;
635                                         dlnew->type = DL_POLY;
636                                         dlnew->flag = DL_FRONT_CURVE;
637                                         dlnew->col = dl->col;
638                                         dlnew->charidx = dl->charidx;
639
640                                         fp = dl->verts + 3 * (dl->nr - 1);
641                                         dpoly = 3 * dl->nr;
642
643                                         a = dl->parts;
644                                         while (a--) {
645                                                 copy_v3_v3(fp1, fp);
646                                                 fp1 += 3;
647                                                 fp += dpoly;
648                                         }
649                                 }
650                         }
651                 }
652                 dl = dl->next;
653         }
654
655         BKE_displist_fill(&front, dispbase, z_up, true);
656         BKE_displist_fill(&back, dispbase, z_up, false);
657
658         BKE_displist_free(&front);
659         BKE_displist_free(&back);
660
661         BKE_displist_fill(dispbase, dispbase, z_up, false);
662 }
663
664 static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dispbase)
665 {
666         if (!CU_DO_2DFILL(cu))
667                 return;
668
669         if (dispbase->first && ((DispList *) dispbase->first)->type == DL_SURF) {
670                 bevels_to_filledpoly(cu, dispbase);
671         }
672         else {
673                 const float z_up[3] = {0.0f, 0.0f, 1.0f};
674                 BKE_displist_fill(dispbase, dispbase, z_up, false);
675         }
676 }
677
678 /* taper rules:
679  * - only 1 curve
680  * - first point left, last point right
681  * - based on subdivided points in original curve, not on points in taper curve (still)
682  */
683 static float displist_calc_taper(Depsgraph *depsgraph, Scene *scene, Object *taperobj, float fac)
684 {
685         DispList *dl;
686
687         if (taperobj == NULL || taperobj->type != OB_CURVE)
688                 return 1.0;
689
690         dl = taperobj->runtime.curve_cache ? taperobj->runtime.curve_cache->disp.first : NULL;
691         if (dl == NULL) {
692                 BKE_displist_make_curveTypes(depsgraph, scene, taperobj, false, false, NULL);
693                 dl = taperobj->runtime.curve_cache->disp.first;
694         }
695         if (dl) {
696                 float minx, dx, *fp;
697                 int a;
698
699                 /* horizontal size */
700                 minx = dl->verts[0];
701                 dx = dl->verts[3 * (dl->nr - 1)] - minx;
702                 if (dx > 0.0f) {
703                         fp = dl->verts;
704                         for (a = 0; a < dl->nr; a++, fp += 3) {
705                                 if ((fp[0] - minx) / dx >= fac) {
706                                         /* interpolate with prev */
707                                         if (a > 0) {
708                                                 float fac1 = (fp[-3] - minx) / dx;
709                                                 float fac2 = (fp[0] - minx) / dx;
710                                                 if (fac1 != fac2)
711                                                         return fp[1] * (fac1 - fac) / (fac1 - fac2) + fp[-2] * (fac - fac2) / (fac1 - fac2);
712                                         }
713                                         return fp[1];
714                                 }
715                         }
716                         return fp[-2];  // last y coord
717                 }
718         }
719
720         return 1.0;
721 }
722
723 float BKE_displist_calc_taper(Depsgraph *depsgraph, Scene *scene, Object *taperobj, int cur, int tot)
724 {
725         float fac = ((float)cur) / (float)(tot - 1);
726
727         return displist_calc_taper(depsgraph, scene, taperobj, fac);
728 }
729
730 void BKE_displist_make_mball(Depsgraph *depsgraph, Scene *scene, Object *ob)
731 {
732         if (!ob || ob->type != OB_MBALL)
733                 return;
734
735         if (ob == BKE_mball_basis_find(scene, ob)) {
736                 if (ob->runtime.curve_cache) {
737                         BKE_displist_free(&(ob->runtime.curve_cache->disp));
738                 }
739                 else {
740                         ob->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall");
741                 }
742
743                 BKE_mball_polygonize(depsgraph, scene, ob, &ob->runtime.curve_cache->disp);
744                 BKE_mball_texspace_calc(ob);
745
746                 object_deform_mball(ob, &ob->runtime.curve_cache->disp);
747
748                 /* NOP for MBALLs anyway... */
749                 boundbox_displist_object(ob);
750         }
751 }
752
753 void BKE_displist_make_mball_forRender(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *dispbase)
754 {
755         BKE_mball_polygonize(depsgraph, scene, ob, dispbase);
756         BKE_mball_texspace_calc(ob);
757
758         object_deform_mball(ob, dispbase);
759 }
760
761 static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob,
762                                                 const bool use_render_resolution, const bool editmode)
763 {
764         VirtualModifierData virtualModifierData;
765         ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
766         ModifierData *pretessellatePoint;
767         int required_mode;
768
769         if (use_render_resolution)
770                 required_mode = eModifierMode_Render;
771         else
772                 required_mode = eModifierMode_Realtime;
773
774         if (editmode)
775                 required_mode |= eModifierMode_Editmode;
776
777         pretessellatePoint = NULL;
778         for (; md; md = md->next) {
779                 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
780
781                 if (!modifier_isEnabled(scene, md, required_mode))
782                         continue;
783                 if (mti->type == eModifierTypeType_Constructive)
784                         return pretessellatePoint;
785
786                 if (ELEM(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
787                         pretessellatePoint = md;
788
789                         /* this modifiers are moving point of tessellation automatically
790                          * (some of them even can't be applied on tessellated curve), set flag
791                          * for information button in modifier's header
792                          */
793                         md->mode |= eModifierMode_ApplyOnSpline;
794                 }
795                 else if (md->mode & eModifierMode_ApplyOnSpline) {
796                         pretessellatePoint = md;
797                 }
798         }
799
800         return pretessellatePoint;
801 }
802
803 static void curve_calc_modifiers_pre(
804         Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *nurb,
805         const bool for_render, const bool use_render_resolution)
806 {
807         VirtualModifierData virtualModifierData;
808         ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
809         ModifierData *pretessellatePoint;
810         Curve *cu = ob->data;
811         int numElems = 0, numVerts = 0;
812         const bool editmode = (!for_render && (cu->editnurb || cu->editfont));
813         ModifierApplyFlag app_flag = 0;
814         float (*deformedVerts)[3] = NULL;
815         float *keyVerts = NULL;
816         int required_mode;
817
818         modifiers_clearErrors(ob);
819
820         if (editmode)
821                 app_flag |= MOD_APPLY_USECACHE;
822         if (use_render_resolution) {
823                 app_flag |= MOD_APPLY_RENDER;
824                 required_mode = eModifierMode_Render;
825         }
826         else
827                 required_mode = eModifierMode_Realtime;
828
829         const ModifierEvalContext mectx = {depsgraph, ob, app_flag};
830
831         pretessellatePoint = curve_get_tessellate_point(scene, ob, use_render_resolution, editmode);
832
833         if (editmode)
834                 required_mode |= eModifierMode_Editmode;
835
836         if (!editmode) {
837                 keyVerts = BKE_key_evaluate_object(ob, &numElems);
838
839                 if (keyVerts) {
840                         BLI_assert(BKE_keyblock_curve_element_count(nurb) == numElems);
841
842                         /* split coords from key data, the latter also includes
843                          * tilts, which is passed through in the modifier stack.
844                          * this is also the reason curves do not use a virtual
845                          * shape key modifier yet. */
846                         deformedVerts = BKE_curve_nurbs_keyVertexCos_get(nurb, keyVerts);
847                         numVerts = BKE_nurbList_verts_count(nurb);
848                 }
849         }
850
851         if (pretessellatePoint) {
852                 for (; md; md = md->next) {
853                         const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
854
855                         if (!modifier_isEnabled(scene, md, required_mode))
856                                 continue;
857                         if (mti->type != eModifierTypeType_OnlyDeform)
858                                 continue;
859
860                         if (!deformedVerts) {
861                                 deformedVerts = BKE_curve_nurbs_vertexCos_get(nurb, &numVerts);
862                         }
863
864                         mti->deformVerts(md, &mectx, NULL, deformedVerts, numVerts);
865
866                         if (md == pretessellatePoint)
867                                 break;
868                 }
869         }
870
871         if (deformedVerts) {
872                 BK_curve_nurbs_vertexCos_apply(nurb, deformedVerts);
873                 MEM_freeN(deformedVerts);
874         }
875         if (keyVerts) /* these are not passed through modifier stack */
876                 BKE_curve_nurbs_keyVertexTilts_apply(nurb, keyVerts);
877
878         if (keyVerts)
879                 MEM_freeN(keyVerts);
880 }
881
882 static float (*displist_get_allverts(ListBase *dispbase, int *totvert))[3]
883 {
884         DispList *dl;
885         float (*allverts)[3], *fp;
886
887         *totvert = 0;
888
889         for (dl = dispbase->first; dl; dl = dl->next)
890                 *totvert += (dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr;
891
892         allverts = MEM_mallocN((*totvert) * sizeof(float) * 3, "displist_get_allverts allverts");
893         fp = (float *)allverts;
894         for (dl = dispbase->first; dl; dl = dl->next) {
895                 int offs = 3 * ((dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr);
896                 memcpy(fp, dl->verts, sizeof(float) * offs);
897                 fp += offs;
898         }
899
900         return allverts;
901 }
902
903 static void displist_apply_allverts(ListBase *dispbase, float (*allverts)[3])
904 {
905         DispList *dl;
906         const float *fp;
907
908         fp = (float *)allverts;
909         for (dl = dispbase->first; dl; dl = dl->next) {
910                 int offs = 3 * ((dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr);
911                 memcpy(dl->verts, fp, sizeof(float) * offs);
912                 fp += offs;
913         }
914 }
915
916 static void curve_calc_modifiers_post(
917         Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *nurb,
918         ListBase *dispbase, Mesh **r_final,
919         const bool for_render, const bool use_render_resolution)
920 {
921         VirtualModifierData virtualModifierData;
922         ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
923         ModifierData *pretessellatePoint;
924         Curve *cu = ob->data;
925         int required_mode = 0, totvert = 0;
926         const bool editmode = (!for_render && (cu->editnurb || cu->editfont));
927         Mesh *modified = NULL, *mesh_applied;
928         float (*vertCos)[3] = NULL;
929         int useCache = !for_render;
930         ModifierApplyFlag app_flag = 0;
931
932         if (use_render_resolution) {
933                 app_flag |= MOD_APPLY_RENDER;
934                 required_mode = eModifierMode_Render;
935         }
936         else
937                 required_mode = eModifierMode_Realtime;
938
939         const ModifierEvalContext mectx_deform = {depsgraph, ob,
940                                                   editmode ? app_flag | MOD_APPLY_USECACHE : app_flag};
941         const ModifierEvalContext mectx_apply = {depsgraph, ob,
942                                                  useCache ? app_flag | MOD_APPLY_USECACHE : app_flag};
943
944         pretessellatePoint = curve_get_tessellate_point(scene, ob, use_render_resolution, editmode);
945
946         if (editmode)
947                 required_mode |= eModifierMode_Editmode;
948
949         if (pretessellatePoint) {
950                 md = pretessellatePoint->next;
951         }
952
953         if (r_final && *r_final) {
954                 BKE_id_free(NULL, r_final);
955         }
956
957         for (; md; md = md->next) {
958                 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
959
960                 if (!modifier_isEnabled(scene, md, required_mode))
961                         continue;
962
963                 /* If we need normals, no choice, have to convert to mesh now. */
964                 if (mti->dependsOnNormals != NULL && mti->dependsOnNormals(md) && modified == NULL) {
965                         if (vertCos != NULL) {
966                                 displist_apply_allverts(dispbase, vertCos);
967                         }
968
969                         if (ELEM(ob->type, OB_CURVE, OB_FONT) && (cu->flag & CU_DEFORM_FILL)) {
970                                 curve_to_filledpoly(cu, nurb, dispbase);
971                         }
972
973                         modified = BKE_mesh_new_nomain_from_curve_displist(ob, dispbase);
974                 }
975
976                 if (mti->type == eModifierTypeType_OnlyDeform ||
977                     (mti->type == eModifierTypeType_DeformOrConstruct && !modified))
978                 {
979                         if (modified) {
980                                 if (!vertCos) {
981                                         vertCos = BKE_mesh_vertexCos_get(modified, &totvert);
982                                 }
983                                 if (mti->dependsOnNormals != NULL && mti->dependsOnNormals(md)) {
984                                         BKE_mesh_ensure_normals(modified);
985                                 }
986                                 mti->deformVerts(md, &mectx_deform, modified, vertCos, totvert);
987                         }
988                         else {
989                                 if (!vertCos) {
990                                         vertCos = displist_get_allverts(dispbase, &totvert);
991                                 }
992                                 mti->deformVerts(md, &mectx_deform, NULL, vertCos, totvert);
993                         }
994                 }
995                 else {
996                         if (!r_final) {
997                                 /* makeDisplistCurveTypes could be used for beveling, where derived mesh
998                                  * is totally unnecessary, so we could stop modifiers applying
999                                  * when we found constructive modifier but derived mesh is unwanted result
1000                                  */
1001                                 break;
1002                         }
1003
1004                         if (modified) {
1005                                 if (vertCos) {
1006                                         Mesh *temp_mesh;
1007                                         BKE_id_copy_ex(NULL, &modified->id, (ID **)&temp_mesh, LIB_ID_COPY_LOCALIZE);
1008                                         BKE_id_free(NULL, modified);
1009                                         modified = temp_mesh;
1010
1011                                         BKE_mesh_apply_vert_coords(modified, vertCos);
1012                                 }
1013                         }
1014                         else {
1015                                 if (vertCos) {
1016                                         displist_apply_allverts(dispbase, vertCos);
1017                                 }
1018
1019                                 if (ELEM(ob->type, OB_CURVE, OB_FONT) && (cu->flag & CU_DEFORM_FILL)) {
1020                                         curve_to_filledpoly(cu, nurb, dispbase);
1021                                 }
1022
1023                                 modified = BKE_mesh_new_nomain_from_curve_displist(ob, dispbase);
1024                         }
1025
1026                         if (vertCos) {
1027                                 /* Vertex coordinates were applied to necessary data, could free it */
1028                                 MEM_freeN(vertCos);
1029                                 vertCos = NULL;
1030                         }
1031
1032                         if (mti->dependsOnNormals != NULL && mti->dependsOnNormals(md)) {
1033                                 BKE_mesh_ensure_normals(modified);
1034                         }
1035                         mesh_applied = mti->applyModifier(md, &mectx_apply, modified);
1036
1037                         if (mesh_applied) {
1038                                 /* Modifier returned a new derived mesh */
1039
1040                                 if (modified && modified != mesh_applied) /* Modifier  */
1041                                         BKE_id_free(NULL, modified);
1042                                 modified = mesh_applied;
1043                         }
1044                 }
1045         }
1046
1047         if (vertCos) {
1048                 if (modified) {
1049                         Mesh *temp_mesh;
1050                         BKE_id_copy_ex(NULL, &modified->id, (ID **)&temp_mesh, LIB_ID_COPY_LOCALIZE);
1051                         BKE_id_free(NULL, modified);
1052                         modified = temp_mesh;
1053
1054                         BKE_mesh_apply_vert_coords(modified, vertCos);
1055                         BKE_mesh_calc_normals_mapping_simple(modified);
1056
1057                         MEM_freeN(vertCos);
1058                 }
1059                 else {
1060                         displist_apply_allverts(dispbase, vertCos);
1061                         MEM_freeN(vertCos);
1062                         vertCos = NULL;
1063                 }
1064         }
1065
1066         if (r_final) {
1067                 if (modified) {
1068                         /* see: mesh_calc_modifiers */
1069                         if (modified->totface == 0) {
1070                                 BKE_mesh_tessface_calc(modified);
1071                         }
1072                         /* Even if tessellation is not needed, some modifiers might have modified CD layers
1073                          * (like mloopcol or mloopuv), hence we have to update those. */
1074                         else if (modified->runtime.cd_dirty_vert & CD_MASK_TESSLOOPNORMAL) {
1075                                 BKE_mesh_tessface_calc(modified);
1076                         }
1077
1078                         /* XXX2.8(Sybren): make sure the face normals are recalculated as well */
1079                         BKE_mesh_ensure_normals(modified);
1080
1081                         /* Special tweaks, needed since neither BKE_mesh_new_nomain_from_template() nor
1082                          * BKE_mesh_new_nomain_from_curve_displist() properly duplicate mat info...
1083                          */
1084                         BLI_strncpy(modified->id.name, cu->id.name, sizeof(modified->id.name));
1085                         *((short *)modified->id.name) = ID_ME;
1086                         MEM_SAFE_FREE(modified->mat);
1087                         /* Set flag which makes it easier to see what's going on in a debugger. */
1088                         modified->id.tag |= LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT;
1089                         modified->mat = MEM_dupallocN(cu->mat);
1090                         modified->totcol = cu->totcol;
1091
1092                         (*r_final) = modified;
1093                 }
1094                 else {
1095                         (*r_final) = NULL;
1096                 }
1097         }
1098 }
1099
1100 static void displist_surf_indices(DispList *dl)
1101 {
1102         int a, b, p1, p2, p3, p4;
1103         int *index;
1104
1105         dl->totindex = 0;
1106
1107         index = dl->index = MEM_mallocN(4 * sizeof(int) * (dl->parts + 1) * (dl->nr + 1), "index array nurbs");
1108
1109         for (a = 0; a < dl->parts; a++) {
1110
1111                 if (BKE_displist_surfindex_get(dl, a, &b, &p1, &p2, &p3, &p4) == 0)
1112                         break;
1113
1114                 for (; b < dl->nr; b++, index += 4) {
1115                         index[0] = p1;
1116                         index[1] = p2;
1117                         index[2] = p4;
1118                         index[3] = p3;
1119
1120                         dl->totindex++;
1121
1122                         p2 = p1; p1++;
1123                         p4 = p3; p3++;
1124                 }
1125         }
1126 }
1127
1128 /* XXX2.8(Sybren): unused function; impossible to test after porting to Mesh */
1129 #ifdef WITH_DERIVEDMESH_DEPRECATED_FUNCS
1130 static DerivedMesh *create_orco_dm(Depsgraph *depsgraph, Scene *scene, Object *ob)
1131 {
1132         DerivedMesh *dm;
1133         ListBase disp = {NULL, NULL};
1134
1135         /* OrcoDM should be created from underformed disp lists */
1136         BKE_displist_make_curveTypes_forOrco(depsgraph, scene, ob, &disp);
1137         dm = CDDM_from_curve_displist(ob, &disp);
1138
1139         BKE_displist_free(&disp);
1140
1141         return dm;
1142 }
1143
1144 static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm)
1145 {
1146         float (*orco)[3], (*layerorco)[3];
1147         int totvert, a;
1148         Curve *cu = ob->data;
1149
1150         totvert = dm->getNumVerts(dm);
1151
1152         orco = MEM_callocN(sizeof(float) * 3 * totvert, "dm orco");
1153
1154         if (orcodm->getNumVerts(orcodm) == totvert)
1155                 orcodm->getVertCos(orcodm, orco);
1156         else
1157                 dm->getVertCos(dm, orco);
1158
1159         for (a = 0; a < totvert; a++) {
1160                 float *co = orco[a];
1161                 co[0] = (co[0] - cu->loc[0]) / cu->size[0];
1162                 co[1] = (co[1] - cu->loc[1]) / cu->size[1];
1163                 co[2] = (co[2] - cu->loc[2]) / cu->size[2];
1164         }
1165
1166         if ((layerorco = DM_get_vert_data_layer(dm, CD_ORCO))) {
1167                 memcpy(layerorco, orco, sizeof(float) * totvert);
1168                 MEM_freeN(orco);
1169         }
1170         else
1171                 DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco);
1172 }
1173 #endif
1174
1175 /* XXX2.8(Sybren): unused function; impossible to test after porting to Mesh */
1176 #ifdef WITH_DERIVEDMESH_DEPRECATED_FUNCS
1177 static void curve_calc_orcodm(
1178         Depsgraph *depsgraph, Scene *scene, Object *ob, DerivedMesh *dm_final,
1179         const bool for_render, const bool use_render_resolution)
1180 {
1181         /* this function represents logic of mesh's orcodm calculation
1182          * for displist-based objects
1183          */
1184         VirtualModifierData virtualModifierData;
1185         ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
1186         ModifierData *pretessellatePoint;
1187         Curve *cu = ob->data;
1188         int required_mode;
1189         const bool editmode = (!for_render && (cu->editnurb || cu->editfont));
1190         DerivedMesh *ndm, *orcodm = NULL;
1191         ModifierApplyFlag app_flag = MOD_APPLY_ORCO;
1192
1193         if (use_render_resolution) {
1194                 app_flag |= MOD_APPLY_RENDER;
1195                 required_mode = eModifierMode_Render;
1196         }
1197         else
1198                 required_mode = eModifierMode_Realtime;
1199
1200         const ModifierEvalContext mectx = {depsgraph, ob, app_flag};
1201
1202         pretessellatePoint = curve_get_tessellate_point(scene, ob, use_render_resolution, editmode);
1203
1204         if (editmode)
1205                 required_mode |= eModifierMode_Editmode;
1206
1207         if (pretessellatePoint) {
1208                 md = pretessellatePoint->next;
1209         }
1210
1211         /* If modifiers are disabled, we wouldn't be here because
1212          * this function is only called if there're enabled constructive
1213          * modifiers applied on the curve.
1214          *
1215          * This means we can create ORCO DM in advance and assume it's
1216          * never NULL.
1217          */
1218         orcodm = create_orco_dm(depsgraph, scene, ob);
1219
1220         for (; md; md = md->next) {
1221                 const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
1222
1223                 md->scene = scene;
1224
1225                 if (!modifier_isEnabled(scene, md, required_mode))
1226                         continue;
1227                 if (mti->type != eModifierTypeType_Constructive)
1228                         continue;
1229
1230                 ndm = modwrap_applyModifier(md, &mectx, orcodm);
1231
1232                 if (ndm) {
1233                         /* if the modifier returned a new dm, release the old one */
1234                         if (orcodm && orcodm != ndm) {
1235                                 orcodm->release(orcodm);
1236                         }
1237                         orcodm = ndm;
1238                 }
1239         }
1240
1241         /* add an orco layer if needed */
1242         add_orco_dm(ob, dm_final, orcodm);
1243
1244         orcodm->release(orcodm);
1245 }
1246 #endif
1247
1248 void BKE_displist_make_surf(
1249         Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *dispbase,
1250         Mesh **r_final,
1251         const bool for_render, const bool for_orco, const bool use_render_resolution)
1252 {
1253         ListBase nubase = {NULL, NULL};
1254         Nurb *nu;
1255         Curve *cu = ob->data;
1256         DispList *dl;
1257         float *data;
1258         int len;
1259
1260         if (!for_render && cu->editnurb) {
1261                 BKE_nurbList_duplicate(&nubase, BKE_curve_editNurbs_get(cu));
1262         }
1263         else {
1264                 BKE_nurbList_duplicate(&nubase, &cu->nurb);
1265         }
1266
1267         if (!for_orco)
1268                 curve_calc_modifiers_pre(depsgraph, scene, ob, &nubase, for_render, use_render_resolution);
1269
1270         for (nu = nubase.first; nu; nu = nu->next) {
1271                 if ((for_render || nu->hide == 0) && BKE_nurb_check_valid_uv(nu)) {
1272                         int resolu = nu->resolu, resolv = nu->resolv;
1273
1274                         if (use_render_resolution) {
1275                                 if (cu->resolu_ren)
1276                                         resolu = cu->resolu_ren;
1277                                 if (cu->resolv_ren)
1278                                         resolv = cu->resolv_ren;
1279                         }
1280
1281                         if (nu->pntsv == 1) {
1282                                 len = SEGMENTSU(nu) * resolu;
1283
1284                                 dl = MEM_callocN(sizeof(DispList), "makeDispListsurf");
1285                                 dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts");
1286
1287                                 BLI_addtail(dispbase, dl);
1288                                 dl->parts = 1;
1289                                 dl->nr = len;
1290                                 dl->col = nu->mat_nr;
1291                                 dl->charidx = nu->charidx;
1292
1293                                 /* dl->rt will be used as flag for render face and */
1294                                 /* CU_2D conflicts with R_NOPUNOFLIP */
1295                                 dl->rt = nu->flag & ~CU_2D;
1296
1297                                 data = dl->verts;
1298                                 if (nu->flagu & CU_NURB_CYCLIC) dl->type = DL_POLY;
1299                                 else dl->type = DL_SEGM;
1300
1301                                 BKE_nurb_makeCurve(nu, data, NULL, NULL, NULL, resolu, 3 * sizeof(float));
1302                         }
1303                         else {
1304                                 len = (nu->pntsu * resolu) * (nu->pntsv * resolv);
1305
1306                                 dl = MEM_callocN(sizeof(DispList), "makeDispListsurf");
1307                                 dl->verts = MEM_mallocN(len * sizeof(float[3]), "dlverts");
1308                                 BLI_addtail(dispbase, dl);
1309
1310                                 dl->col = nu->mat_nr;
1311                                 dl->charidx = nu->charidx;
1312
1313                                 /* dl->rt will be used as flag for render face and */
1314                                 /* CU_2D conflicts with R_NOPUNOFLIP */
1315                                 dl->rt = nu->flag & ~CU_2D;
1316
1317                                 data = dl->verts;
1318                                 dl->type = DL_SURF;
1319
1320                                 dl->parts = (nu->pntsu * resolu);  /* in reverse, because makeNurbfaces works that way */
1321                                 dl->nr = (nu->pntsv * resolv);
1322                                 if (nu->flagv & CU_NURB_CYCLIC) dl->flag |= DL_CYCL_U;  /* reverse too! */
1323                                 if (nu->flagu & CU_NURB_CYCLIC) dl->flag |= DL_CYCL_V;
1324
1325                                 BKE_nurb_makeFaces(nu, data, 0, resolu, resolv);
1326
1327                                 /* gl array drawing: using indices */
1328                                 displist_surf_indices(dl);
1329                         }
1330                 }
1331         }
1332
1333         if (!for_orco) {
1334                 BKE_nurbList_duplicate(&ob->runtime.curve_cache->deformed_nurbs, &nubase);
1335                 curve_calc_modifiers_post(depsgraph, scene, ob, &nubase, dispbase, r_final,
1336                                           for_render, use_render_resolution);
1337         }
1338
1339         BKE_nurbList_free(&nubase);
1340 }
1341
1342 static void rotateBevelPiece(Curve *cu, BevPoint *bevp, BevPoint *nbevp, DispList *dlb, float bev_blend, float widfac, float fac, float **r_data)
1343 {
1344         float *fp, *data = *r_data;
1345         int b;
1346
1347         fp = dlb->verts;
1348         for (b = 0; b < dlb->nr; b++, fp += 3, data += 3) {
1349                 if (cu->flag & CU_3D) {
1350                         float vec[3], quat[4];
1351
1352                         vec[0] = fp[1] + widfac;
1353                         vec[1] = fp[2];
1354                         vec[2] = 0.0;
1355
1356                         if (nbevp == NULL) {
1357                                 copy_v3_v3(data, bevp->vec);
1358                                 copy_qt_qt(quat, bevp->quat);
1359                         }
1360                         else {
1361                                 interp_v3_v3v3(data, bevp->vec, nbevp->vec, bev_blend);
1362                                 interp_qt_qtqt(quat, bevp->quat, nbevp->quat, bev_blend);
1363                         }
1364
1365                         mul_qt_v3(quat, vec);
1366
1367                         data[0] += fac * vec[0];
1368                         data[1] += fac * vec[1];
1369                         data[2] += fac * vec[2];
1370                 }
1371                 else {
1372                         float sina, cosa;
1373
1374                         if (nbevp == NULL) {
1375                                 copy_v3_v3(data, bevp->vec);
1376                                 sina = bevp->sina;
1377                                 cosa = bevp->cosa;
1378                         }
1379                         else {
1380                                 interp_v3_v3v3(data, bevp->vec, nbevp->vec, bev_blend);
1381
1382                                 /* perhaps we need to interpolate angles instead. but the thing is
1383                                  * cosa and sina are not actually sine and cosine
1384                                  */
1385                                 sina = nbevp->sina * bev_blend + bevp->sina * (1.0f - bev_blend);
1386                                 cosa = nbevp->cosa * bev_blend + bevp->cosa * (1.0f - bev_blend);
1387                         }
1388
1389                         data[0] += fac * (widfac + fp[1]) * sina;
1390                         data[1] += fac * (widfac + fp[1]) * cosa;
1391                         data[2] += fac * fp[2];
1392                 }
1393         }
1394
1395         *r_data = data;
1396 }
1397
1398 static void fillBevelCap(Nurb *nu, DispList *dlb, float *prev_fp, ListBase *dispbase)
1399 {
1400         DispList *dl;
1401
1402         dl = MEM_callocN(sizeof(DispList), "makeDispListbev2");
1403         dl->verts = MEM_mallocN(sizeof(float[3]) * dlb->nr, "dlverts");
1404         memcpy(dl->verts, prev_fp, 3 * sizeof(float) * dlb->nr);
1405
1406         dl->type = DL_POLY;
1407
1408         dl->parts = 1;
1409         dl->nr = dlb->nr;
1410         dl->col = nu->mat_nr;
1411         dl->charidx = nu->charidx;
1412
1413         /* dl->rt will be used as flag for render face and */
1414         /* CU_2D conflicts with R_NOPUNOFLIP */
1415         dl->rt = nu->flag & ~CU_2D;
1416
1417         BLI_addtail(dispbase, dl);
1418 }
1419
1420 static void calc_bevfac_segment_mapping(BevList *bl, float bevfac, float spline_length, int *r_bev, float *r_blend)
1421 {
1422         float normlen, normsum = 0.0f;
1423         float *seglen = bl->seglen;
1424         int *segbevcount = bl->segbevcount;
1425         int bevcount = 0, nr = bl->nr;
1426
1427         float bev_fl = bevfac * (bl->nr - 1);
1428         *r_bev = (int)bev_fl;
1429
1430         while (bevcount < nr - 1) {
1431                 normlen = *seglen / spline_length;
1432                 if (normsum + normlen > bevfac) {
1433                         bev_fl = bevcount + (bevfac - normsum) / normlen * *segbevcount;
1434                         *r_bev = (int) bev_fl;
1435                         *r_blend = bev_fl - *r_bev;
1436                         break;
1437                 }
1438                 normsum += normlen;
1439                 bevcount += *segbevcount;
1440                 segbevcount++;
1441                 seglen++;
1442         }
1443 }
1444
1445 static void calc_bevfac_spline_mapping(BevList *bl, float bevfac,
1446                                        float spline_length,
1447                                        int *r_bev, float *r_blend)
1448 {
1449         const float len_target = bevfac * spline_length;
1450         BevPoint *bevp = bl->bevpoints;
1451         float len_next = 0.0f, len = 0.0f;
1452         int i = 0, nr = bl->nr;
1453
1454         while (nr--) {
1455                 bevp++;
1456                 len_next = len + bevp->offset;
1457                 if (len_next > len_target) {
1458                         break;
1459                 }
1460                 len = len_next;
1461                 i++;
1462         }
1463
1464         *r_bev = i;
1465         *r_blend = (len_target - len) / bevp->offset;
1466 }
1467
1468 static void calc_bevfac_mapping_default(BevList *bl,
1469                                         int *r_start, float *r_firstblend,
1470                                         int *r_steps, float *r_lastblend)
1471 {
1472         *r_start = 0;
1473         *r_steps = bl->nr;
1474         *r_firstblend = 1.0f;
1475         *r_lastblend = 1.0f;
1476 }
1477
1478 static void calc_bevfac_mapping(Curve *cu, BevList *bl, Nurb *nu,
1479         int *r_start, float *r_firstblend, int *r_steps, float *r_lastblend)
1480 {
1481         float tmpf, total_length = 0.0f;
1482         int end = 0, i;
1483
1484         if ((BKE_nurb_check_valid_u(nu) == false) ||
1485             /* not essential, but skips unnecessary calculation */
1486             (min_ff(cu->bevfac1, cu->bevfac2) == 0.0f &&
1487              max_ff(cu->bevfac1, cu->bevfac2) == 1.0f))
1488         {
1489                 calc_bevfac_mapping_default(bl, r_start, r_firstblend, r_steps, r_lastblend);
1490                 return;
1491         }
1492
1493         if (ELEM(cu->bevfac1_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE) ||
1494             ELEM(cu->bevfac2_mapping, CU_BEVFAC_MAP_SEGMENT, CU_BEVFAC_MAP_SPLINE))
1495         {
1496                 for (i = 0; i < SEGMENTSU(nu); i++) {
1497                         total_length += bl->seglen[i];
1498                 }
1499         }
1500
1501         switch (cu->bevfac1_mapping) {
1502                 case CU_BEVFAC_MAP_RESOLU:
1503                 {
1504                         const float start_fl = cu->bevfac1 * (bl->nr - 1);
1505                         *r_start = (int)start_fl;
1506                         *r_firstblend = 1.0f - (start_fl - (*r_start));
1507                         break;
1508                 }
1509                 case CU_BEVFAC_MAP_SEGMENT:
1510                 {
1511                         calc_bevfac_segment_mapping(bl, cu->bevfac1, total_length, r_start, r_firstblend);
1512                         *r_firstblend = 1.0f - *r_firstblend;
1513                         break;
1514                 }
1515                 case CU_BEVFAC_MAP_SPLINE:
1516                 {
1517                         calc_bevfac_spline_mapping(bl, cu->bevfac1, total_length, r_start, r_firstblend);
1518                         *r_firstblend = 1.0f - *r_firstblend;
1519                         break;
1520                 }
1521         }
1522
1523         switch (cu->bevfac2_mapping) {
1524                 case CU_BEVFAC_MAP_RESOLU:
1525                 {
1526                         const float end_fl = cu->bevfac2 * (bl->nr - 1);
1527                         end = (int)end_fl;
1528
1529                         *r_steps = 2 + end - *r_start;
1530                         *r_lastblend = end_fl - end;
1531                         break;
1532                 }
1533                 case CU_BEVFAC_MAP_SEGMENT:
1534                 {
1535                         calc_bevfac_segment_mapping(bl, cu->bevfac2, total_length, &end, r_lastblend);
1536                         *r_steps = end - *r_start + 2;
1537                         break;
1538                 }
1539                 case CU_BEVFAC_MAP_SPLINE:
1540                 {
1541                         calc_bevfac_spline_mapping(bl, cu->bevfac2, total_length, &end, r_lastblend);
1542                         *r_steps = end - *r_start + 2;
1543                         break;
1544                 }
1545         }
1546
1547         if (end < *r_start || (end == *r_start && *r_lastblend < 1.0f - *r_firstblend )) {
1548                 SWAP(int, *r_start, end);
1549                 tmpf = *r_lastblend;
1550                 *r_lastblend = 1.0f - *r_firstblend;
1551                 *r_firstblend = 1.0f - tmpf;
1552                 *r_steps = end - *r_start + 2;
1553         }
1554
1555         if (*r_start + *r_steps > bl->nr) {
1556                 *r_steps = bl->nr - *r_start;
1557                 *r_lastblend = 1.0f;
1558         }
1559 }
1560
1561 static void do_makeDispListCurveTypes(
1562         Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *dispbase,
1563         const bool for_render, const bool for_orco, const bool use_render_resolution,
1564         LinkNode *ob_cyclic_list,
1565         Mesh **r_final)
1566 {
1567         Curve *cu = ob->data;
1568
1569         /* we do allow duplis... this is only displist on curve level */
1570         if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return;
1571
1572         if (ob->type == OB_SURF) {
1573                 BKE_displist_make_surf(depsgraph, scene, ob, dispbase, r_final, for_render, for_orco, use_render_resolution);
1574         }
1575         else if (ELEM(ob->type, OB_CURVE, OB_FONT)) {
1576                 ListBase dlbev;
1577                 ListBase nubase = {NULL, NULL};
1578
1579                 BKE_curve_bevelList_free(&ob->runtime.curve_cache->bev);
1580
1581                 /* We only re-evaluate path if evaluation is not happening for orco.
1582                  * If the calculation happens for orco, we should never free data which
1583                  * was needed before and only not needed for orco calculation.
1584                  */
1585                 if (!for_orco) {
1586                         if (ob->runtime.curve_cache->path) free_path(ob->runtime.curve_cache->path);
1587                         ob->runtime.curve_cache->path = NULL;
1588                 }
1589
1590                 if (ob->type == OB_FONT) {
1591                         BKE_vfont_to_curve_nubase(ob, FO_EDIT, &nubase);
1592                 }
1593                 else {
1594                         BKE_nurbList_duplicate(&nubase, BKE_curve_nurbs_get(cu));
1595                 }
1596
1597                 if (!for_orco)
1598                         curve_calc_modifiers_pre(depsgraph, scene, ob, &nubase, for_render, use_render_resolution);
1599
1600                 BKE_curve_bevelList_make(ob, &nubase, use_render_resolution);
1601
1602                 /* If curve has no bevel will return nothing */
1603                 BKE_curve_bevel_make(
1604                         depsgraph, scene, ob, &dlbev, for_render, use_render_resolution,
1605                         ob_cyclic_list);
1606
1607                 /* no bevel or extrude, and no width correction? */
1608                 if (!dlbev.first && cu->width == 1.0f) {
1609                         curve_to_displist(cu, &nubase, dispbase, for_render, use_render_resolution);
1610                 }
1611                 else {
1612                         float widfac = cu->width - 1.0f;
1613                         BevList *bl = ob->runtime.curve_cache->bev.first;
1614                         Nurb *nu = nubase.first;
1615
1616                         for (; bl && nu; bl = bl->next, nu = nu->next) {
1617                                 DispList *dl;
1618                                 float *data;
1619                                 int a;
1620
1621                                 if (bl->nr) { /* blank bevel lists can happen */
1622
1623                                         /* exception handling; curve without bevel or extrude, with width correction */
1624                                         if (BLI_listbase_is_empty(&dlbev)) {
1625                                                 BevPoint *bevp;
1626                                                 dl = MEM_callocN(sizeof(DispList), "makeDispListbev");
1627                                                 dl->verts = MEM_mallocN(sizeof(float[3]) * bl->nr, "dlverts");
1628                                                 BLI_addtail(dispbase, dl);
1629
1630                                                 if (bl->poly != -1) dl->type = DL_POLY;
1631                                                 else dl->type = DL_SEGM;
1632
1633                                                 if (dl->type == DL_SEGM) dl->flag = (DL_FRONT_CURVE | DL_BACK_CURVE);
1634
1635                                                 dl->parts = 1;
1636                                                 dl->nr = bl->nr;
1637                                                 dl->col = nu->mat_nr;
1638                                                 dl->charidx = nu->charidx;
1639
1640                                                 /* dl->rt will be used as flag for render face and */
1641                                                 /* CU_2D conflicts with R_NOPUNOFLIP */
1642                                                 dl->rt = nu->flag & ~CU_2D;
1643
1644                                                 a = dl->nr;
1645                                                 bevp = bl->bevpoints;
1646                                                 data = dl->verts;
1647                                                 while (a--) {
1648                                                         data[0] = bevp->vec[0] + widfac * bevp->sina;
1649                                                         data[1] = bevp->vec[1] + widfac * bevp->cosa;
1650                                                         data[2] = bevp->vec[2];
1651                                                         bevp++;
1652                                                         data += 3;
1653                                                 }
1654                                         }
1655                                         else {
1656                                                 DispList *dlb;
1657                                                 ListBase bottom_capbase = {NULL, NULL};
1658                                                 ListBase top_capbase = {NULL, NULL};
1659                                                 float bottom_no[3] = {0.0f};
1660                                                 float top_no[3] = {0.0f};
1661                                                 float firstblend = 0.0f, lastblend = 0.0f;
1662                                                 int i, start, steps = 0;
1663
1664                                                 if (nu->flagu & CU_NURB_CYCLIC) {
1665                                                         calc_bevfac_mapping_default(bl,
1666                                                                                     &start, &firstblend, &steps, &lastblend);
1667                                                 }
1668                                                 else {
1669                                                         if (fabsf(cu->bevfac2 - cu->bevfac1) < FLT_EPSILON) {
1670                                                                 continue;
1671                                                         }
1672
1673                                                         calc_bevfac_mapping(cu, bl, nu, &start, &firstblend, &steps, &lastblend);
1674                                                 }
1675
1676                                                 for (dlb = dlbev.first; dlb; dlb = dlb->next) {
1677                                                         BevPoint *bevp_first, *bevp_last;
1678                                                         BevPoint *bevp;
1679
1680                                                         /* for each part of the bevel use a separate displblock */
1681                                                         dl = MEM_callocN(sizeof(DispList), "makeDispListbev1");
1682                                                         dl->verts = data = MEM_mallocN(sizeof(float[3]) * dlb->nr * steps, "dlverts");
1683                                                         BLI_addtail(dispbase, dl);
1684
1685                                                         dl->type = DL_SURF;
1686
1687                                                         dl->flag = dlb->flag & (DL_FRONT_CURVE | DL_BACK_CURVE);
1688                                                         if (dlb->type == DL_POLY) {
1689                                                                 dl->flag |= DL_CYCL_U;
1690                                                         }
1691                                                         if ((bl->poly >= 0) && (steps > 2)) {
1692                                                                 dl->flag |= DL_CYCL_V;
1693                                                         }
1694
1695                                                         dl->parts = steps;
1696                                                         dl->nr = dlb->nr;
1697                                                         dl->col = nu->mat_nr;
1698                                                         dl->charidx = nu->charidx;
1699
1700                                                         /* dl->rt will be used as flag for render face and */
1701                                                         /* CU_2D conflicts with R_NOPUNOFLIP */
1702                                                         dl->rt = nu->flag & ~CU_2D;
1703
1704                                                         dl->bevel_split = BLI_BITMAP_NEW(steps, "bevel_split");
1705
1706                                                         /* for each point of poly make a bevel piece */
1707                                                         bevp_first =  bl->bevpoints;
1708                                                         bevp_last  = &bl->bevpoints[bl->nr - 1];
1709                                                         bevp       = &bl->bevpoints[start];
1710                                                         for (i = start, a = 0; a < steps; i++, bevp++, a++) {
1711                                                                 float fac = 1.0;
1712                                                                 float *cur_data = data;
1713
1714                                                                 if (cu->taperobj == NULL) {
1715                                                                         fac = bevp->radius;
1716                                                                 }
1717                                                                 else {
1718                                                                         float len, taper_fac;
1719
1720                                                                         if (cu->flag & CU_MAP_TAPER) {
1721                                                                                 len = (steps - 3) + firstblend + lastblend;
1722
1723                                                                                 if (a == 0)
1724                                                                                         taper_fac = 0.0f;
1725                                                                                 else if (a == steps - 1)
1726                                                                                         taper_fac = 1.0f;
1727                                                                                 else
1728                                                                                         taper_fac = ((float) a - (1.0f - firstblend)) / len;
1729                                                                         }
1730                                                                         else {
1731                                                                                 len = bl->nr - 1;
1732                                                                                 taper_fac = (float) i / len;
1733
1734                                                                                 if (a == 0)
1735                                                                                         taper_fac += (1.0f - firstblend) / len;
1736                                                                                 else if (a == steps - 1)
1737                                                                                         taper_fac -= (1.0f - lastblend) / len;
1738                                                                         }
1739
1740                                                                         fac = displist_calc_taper(depsgraph, scene, cu->taperobj, taper_fac);
1741                                                                 }
1742
1743                                                                 if (bevp->split_tag) {
1744                                                                         BLI_BITMAP_ENABLE(dl->bevel_split, a);
1745                                                                 }
1746
1747                                                                 /* rotate bevel piece and write in data */
1748                                                                 if ((a == 0) && (bevp != bevp_last)) {
1749                                                                         rotateBevelPiece(cu, bevp, bevp + 1, dlb, 1.0f - firstblend, widfac, fac, &data);
1750                                                                 }
1751                                                                 else if ((a == steps - 1) && (bevp != bevp_first) ) {
1752                                                                         rotateBevelPiece(cu, bevp, bevp - 1, dlb, 1.0f - lastblend, widfac, fac, &data);
1753                                                                 }
1754                                                                 else {
1755                                                                         rotateBevelPiece(cu, bevp, NULL, dlb, 0.0f, widfac, fac, &data);
1756                                                                 }
1757
1758                                                                 if (cu->bevobj && (cu->flag & CU_FILL_CAPS) && !(nu->flagu & CU_NURB_CYCLIC)) {
1759                                                                         if (a == 1) {
1760                                                                                 fillBevelCap(nu, dlb, cur_data - 3 * dlb->nr, &bottom_capbase);
1761                                                                                 negate_v3_v3(bottom_no, bevp->dir);
1762                                                                         }
1763                                                                         if (a == steps - 1) {
1764                                                                                 fillBevelCap(nu, dlb, cur_data, &top_capbase);
1765                                                                                 copy_v3_v3(top_no, bevp->dir);
1766                                                                         }
1767                                                                 }
1768                                                         }
1769
1770                                                         /* gl array drawing: using indices */
1771                                                         displist_surf_indices(dl);
1772                                                 }
1773
1774                                                 if (bottom_capbase.first) {
1775                                                         BKE_displist_fill(&bottom_capbase, dispbase, bottom_no, false);
1776                                                         BKE_displist_fill(&top_capbase, dispbase, top_no, false);
1777                                                         BKE_displist_free(&bottom_capbase);
1778                                                         BKE_displist_free(&top_capbase);
1779                                                 }
1780                                         }
1781                                 }
1782
1783                         }
1784                         BKE_displist_free(&dlbev);
1785                 }
1786
1787                 if (!(cu->flag & CU_DEFORM_FILL)) {
1788                         curve_to_filledpoly(cu, &nubase, dispbase);
1789                 }
1790
1791                 if (!for_orco) {
1792                         if ((cu->flag & CU_PATH) ||
1793                             DEG_get_eval_flags_for_id(depsgraph, &ob->id) & DAG_EVAL_NEED_CURVE_PATH)
1794                         {
1795                                 calc_curvepath(ob, &nubase);
1796                         }
1797                 }
1798
1799                 if (!for_orco) {
1800                         BKE_nurbList_duplicate(&ob->runtime.curve_cache->deformed_nurbs, &nubase);
1801                         curve_calc_modifiers_post(depsgraph, scene, ob, &nubase, dispbase, r_final, for_render, use_render_resolution);
1802                 }
1803
1804                 if (cu->flag & CU_DEFORM_FILL && !ob->runtime.mesh_eval) {
1805                         curve_to_filledpoly(cu, &nubase, dispbase);
1806                 }
1807
1808                 BKE_nurbList_free(&nubase);
1809         }
1810 }
1811
1812 void BKE_displist_make_curveTypes(
1813         Depsgraph *depsgraph, Scene *scene, Object *ob, const bool for_render, const bool for_orco,
1814         LinkNode *ob_cyclic_list)
1815 {
1816         ListBase *dispbase;
1817
1818         /* The same check for duplis as in do_makeDispListCurveTypes.
1819          * Happens when curve used for constraint/bevel was converted to mesh.
1820          * check there is still needed for render displist and orco displists. */
1821         if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT))
1822                 return;
1823
1824         BKE_object_free_derived_caches(ob);
1825
1826         if (!ob->runtime.curve_cache) {
1827                 ob->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for curve types");
1828         }
1829
1830         dispbase = &(ob->runtime.curve_cache->disp);
1831
1832         do_makeDispListCurveTypes(
1833                 depsgraph, scene, ob, dispbase, for_render, for_orco, false,
1834                 ob_cyclic_list,
1835                 &ob->runtime.mesh_eval);
1836
1837         boundbox_displist_object(ob);
1838 }
1839
1840 void BKE_displist_make_curveTypes_forRender(
1841         Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *dispbase,
1842         Mesh **r_final, const bool for_orco,
1843         const bool use_render_resolution,
1844         LinkNode *ob_cyclic_list)
1845 {
1846         if (ob->runtime.curve_cache == NULL) {
1847                 ob->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve");
1848         }
1849
1850         do_makeDispListCurveTypes(
1851                 depsgraph, scene, ob, dispbase, true, for_orco, use_render_resolution,
1852                 ob_cyclic_list,
1853                 r_final);
1854 }
1855
1856 void BKE_displist_make_curveTypes_forOrco(
1857         Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *dispbase,
1858         LinkNode *ob_cyclic_list)
1859 {
1860         if (ob->runtime.curve_cache == NULL) {
1861                 ob->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve");
1862         }
1863
1864         do_makeDispListCurveTypes(
1865                 depsgraph, scene, ob, dispbase, 1, 1, 1,
1866                 ob_cyclic_list,
1867                 NULL);
1868 }
1869
1870 void BKE_displist_minmax(ListBase *dispbase, float min[3], float max[3])
1871 {
1872         DispList *dl;
1873         const float *vert;
1874         int a, tot = 0;
1875         int doit = 0;
1876
1877         for (dl = dispbase->first; dl; dl = dl->next) {
1878                 tot = (dl->type == DL_INDEX3) ? dl->nr : dl->nr * dl->parts;
1879                 vert = dl->verts;
1880                 for (a = 0; a < tot; a++, vert += 3) {
1881                         minmax_v3v3_v3(min, max, vert);
1882                 }
1883                 doit |= (tot != 0);
1884         }
1885
1886         if (!doit) {
1887                 /* there's no geometry in displist, use zero-sized boundbox */
1888                 zero_v3(min);
1889                 zero_v3(max);
1890         }
1891 }
1892
1893 /* this is confusing, there's also min_max_object, appplying the obmat... */
1894 static void boundbox_displist_object(Object *ob)
1895 {
1896         if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
1897                 /* Curve's BB is already calculated as a part of modifier stack,
1898                  * here we only calculate object BB based on final display list.
1899                  */
1900
1901                 /* object's BB is calculated from final displist */
1902                 if (ob->runtime.bb == NULL)
1903                         ob->runtime.bb = MEM_callocN(sizeof(BoundBox), "boundbox");
1904
1905                 if (ob->runtime.mesh_eval) {
1906                         BKE_object_boundbox_calc_from_mesh(ob, ob->runtime.mesh_eval);
1907                 }
1908                 else {
1909                         float min[3], max[3];
1910
1911                         INIT_MINMAX(min, max);
1912                         BKE_displist_minmax(&ob->runtime.curve_cache->disp, min, max);
1913                         BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
1914
1915                         ob->runtime.bb->flag &= ~BOUNDBOX_DIRTY;
1916                 }
1917         }
1918 }