Blender  V3.3
displist.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include <cmath>
9 #include <cstdio>
10 #include <cstring>
11 
12 #include "MEM_guardedalloc.h"
13 
14 #include "DNA_curve_types.h"
15 #include "DNA_mesh_types.h"
16 #include "DNA_object_types.h"
17 #include "DNA_scene_types.h"
18 #include "DNA_vfont_types.h"
19 
20 #include "BLI_bitmap.h"
21 #include "BLI_index_range.hh"
22 #include "BLI_linklist.h"
23 #include "BLI_listbase.h"
24 #include "BLI_math.h"
25 #include "BLI_memarena.h"
26 #include "BLI_scanfill.h"
27 #include "BLI_span.hh"
28 #include "BLI_string.h"
29 #include "BLI_utildefines.h"
30 
31 #include "BKE_anim_path.h"
32 #include "BKE_curve.h"
34 #include "BKE_displist.h"
35 #include "BKE_geometry_set.hh"
36 #include "BKE_key.h"
37 #include "BKE_lattice.h"
38 #include "BKE_lib_id.h"
39 #include "BKE_mball.h"
40 #include "BKE_mball_tessellate.h"
41 #include "BKE_mesh.h"
42 #include "BKE_modifier.h"
43 #include "BKE_object.h"
44 #include "BKE_vfont.h"
45 
46 #include "BLI_sys_types.h" /* For #intptr_t support. */
47 
48 #include "DEG_depsgraph.h"
49 #include "DEG_depsgraph_query.h"
50 
52 
53 static void displist_elem_free(DispList *dl)
54 {
55  if (dl) {
56  if (dl->verts) {
57  MEM_freeN(dl->verts);
58  }
59  if (dl->nors) {
60  MEM_freeN(dl->nors);
61  }
62  if (dl->index) {
63  MEM_freeN(dl->index);
64  }
65  MEM_freeN(dl);
66  }
67 }
68 
70 {
71  DispList *dl;
72 
73  while ((dl = (DispList *)BLI_pophead(lb))) {
75  }
76 }
77 
79 {
80  LISTBASE_FOREACH (DispList *, dl, lb) {
81  if (dl->type == type) {
82  return dl;
83  }
84  }
85 
86  return nullptr;
87 }
88 
89 void BKE_displist_copy(ListBase *lbn, const ListBase *lb)
90 {
91  BKE_displist_free(lbn);
92 
93  LISTBASE_FOREACH (const DispList *, dl, lb) {
94  DispList *dln = (DispList *)MEM_dupallocN(dl);
95  BLI_addtail(lbn, dln);
96  dln->verts = (float *)MEM_dupallocN(dl->verts);
97  dln->nors = (float *)MEM_dupallocN(dl->nors);
98  dln->index = (int *)MEM_dupallocN(dl->index);
99  }
100 }
101 
103 {
104  float *vdata, *ndata, nor[3];
105  float *v1, *v2, *v3, *v4;
106  float *n1, *n2, *n3, *n4;
107  int a, b, p1, p2, p3, p4;
108 
109  LISTBASE_FOREACH (DispList *, dl, lb) {
110  if (dl->type == DL_INDEX3) {
111  if (dl->nors == nullptr) {
112  dl->nors = (float *)MEM_callocN(sizeof(float[3]), __func__);
113 
114  if (dl->flag & DL_BACK_CURVE) {
115  dl->nors[2] = -1.0f;
116  }
117  else {
118  dl->nors[2] = 1.0f;
119  }
120  }
121  }
122  else if (dl->type == DL_SURF) {
123  if (dl->nors == nullptr) {
124  dl->nors = (float *)MEM_callocN(sizeof(float[3]) * dl->nr * dl->parts, __func__);
125 
126  vdata = dl->verts;
127  ndata = dl->nors;
128 
129  for (a = 0; a < dl->parts; a++) {
130 
131  if (BKE_displist_surfindex_get(dl, a, &b, &p1, &p2, &p3, &p4) == 0) {
132  break;
133  }
134 
135  v1 = vdata + 3 * p1;
136  n1 = ndata + 3 * p1;
137  v2 = vdata + 3 * p2;
138  n2 = ndata + 3 * p2;
139  v3 = vdata + 3 * p3;
140  n3 = ndata + 3 * p3;
141  v4 = vdata + 3 * p4;
142  n4 = ndata + 3 * p4;
143 
144  for (; b < dl->nr; b++) {
145  normal_quad_v3(nor, v1, v3, v4, v2);
146 
147  add_v3_v3(n1, nor);
148  add_v3_v3(n2, nor);
149  add_v3_v3(n3, nor);
150  add_v3_v3(n4, nor);
151 
152  v2 = v1;
153  v1 += 3;
154  v4 = v3;
155  v3 += 3;
156  n2 = n1;
157  n1 += 3;
158  n4 = n3;
159  n3 += 3;
160  }
161  }
162  a = dl->parts * dl->nr;
163  v1 = ndata;
164  while (a--) {
165  normalize_v3(v1);
166  v1 += 3;
167  }
168  }
169  }
170  }
171 }
172 
173 void BKE_displist_count(const ListBase *lb, int *totvert, int *totface, int *tottri)
174 {
175  LISTBASE_FOREACH (const DispList *, dl, lb) {
176  int vert_tot = 0;
177  int face_tot = 0;
178  int tri_tot = 0;
179  bool cyclic_u = dl->flag & DL_CYCL_U;
180  bool cyclic_v = dl->flag & DL_CYCL_V;
181 
182  switch (dl->type) {
183  case DL_SURF: {
184  int segments_u = dl->nr - (cyclic_u == false);
185  int segments_v = dl->parts - (cyclic_v == false);
186  vert_tot = dl->nr * dl->parts;
187  face_tot = segments_u * segments_v;
188  tri_tot = face_tot * 2;
189  break;
190  }
191  case DL_INDEX3: {
192  vert_tot = dl->nr;
193  face_tot = dl->parts;
194  tri_tot = face_tot;
195  break;
196  }
197  case DL_INDEX4: {
198  vert_tot = dl->nr;
199  face_tot = dl->parts;
200  tri_tot = face_tot * 2;
201  break;
202  }
203  case DL_POLY:
204  case DL_SEGM: {
205  vert_tot = dl->nr * dl->parts;
206  break;
207  }
208  }
209 
210  *totvert += vert_tot;
211  *totface += face_tot;
212  *tottri += tri_tot;
213  }
214 }
215 
217  const DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4)
218 {
219  if ((dl->flag & DL_CYCL_V) == 0 && a == (dl->parts) - 1) {
220  return false;
221  }
222 
223  if (dl->flag & DL_CYCL_U) {
224  (*p1) = dl->nr * a;
225  (*p2) = (*p1) + dl->nr - 1;
226  (*p3) = (*p1) + dl->nr;
227  (*p4) = (*p2) + dl->nr;
228  (*b) = 0;
229  }
230  else {
231  (*p2) = dl->nr * a;
232  (*p1) = (*p2) + 1;
233  (*p4) = (*p2) + dl->nr;
234  (*p3) = (*p1) + dl->nr;
235  (*b) = 1;
236  }
237 
238  if ((dl->flag & DL_CYCL_V) && a == dl->parts - 1) {
239  (*p3) -= dl->nr * dl->parts;
240  (*p4) -= dl->nr * dl->parts;
241  }
242 
243  return true;
244 }
245 
246 /* ****************** Make #DispList ********************* */
247 #ifdef __INTEL_COMPILER
248 /* ICC with the optimization -02 causes crashes. */
249 # pragma intel optimization_level 1
250 #endif
251 
252 static void curve_to_displist(const Curve *cu,
253  const ListBase *nubase,
254  const bool for_render,
255  ListBase *r_dispbase)
256 {
257  const bool editmode = (!for_render && (cu->editnurb || cu->editfont));
258 
259  LISTBASE_FOREACH (Nurb *, nu, nubase) {
260  if (nu->hide != 0 && editmode) {
261  continue;
262  }
263  if (!BKE_nurb_check_valid_u(nu)) {
264  continue;
265  }
266 
267  const int resolution = (for_render && cu->resolu_ren != 0) ? cu->resolu_ren : nu->resolu;
268  const bool is_cyclic = nu->flagu & CU_NURB_CYCLIC;
269  const BezTriple *bezt_first = &nu->bezt[0];
270  const BezTriple *bezt_last = &nu->bezt[nu->pntsu - 1];
271 
272  if (nu->type == CU_BEZIER) {
273  int samples_len = 0;
274  for (int i = 1; i < nu->pntsu; i++) {
275  const BezTriple *prevbezt = &nu->bezt[i - 1];
276  const BezTriple *bezt = &nu->bezt[i];
277  if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) {
278  samples_len++;
279  }
280  else {
281  samples_len += resolution;
282  }
283  }
284  if (is_cyclic) {
285  /* If the curve is cyclic, sample the last edge between the last and first points. */
286  if (bezt_first->h1 == HD_VECT && bezt_last->h2 == HD_VECT) {
287  samples_len++;
288  }
289  else {
290  samples_len += resolution;
291  }
292  }
293  else {
294  /* Otherwise, we only need one additional sample to complete the last edge. */
295  samples_len++;
296  }
297 
298  /* Check that there are more than two points so the curve doesn't loop back on itself. This
299  * needs to be separate from `is_cyclic` because cyclic sampling can work with two points
300  * and resolution > 1. */
301  const bool use_cyclic_sample = is_cyclic && (samples_len != 2);
302 
303  DispList *dl = MEM_cnew<DispList>(__func__);
304  /* Add one to the length because of 'BKE_curve_forward_diff_bezier'. */
305  dl->verts = (float *)MEM_mallocN(sizeof(float[3]) * (samples_len + 1), __func__);
306  BLI_addtail(r_dispbase, dl);
307  dl->parts = 1;
308  dl->nr = samples_len;
309  dl->col = nu->mat_nr;
310  dl->charidx = nu->charidx;
311 
312  dl->type = use_cyclic_sample ? DL_POLY : DL_SEGM;
313 
314  float *data = dl->verts;
315  for (int i = 1; i < nu->pntsu; i++) {
316  const BezTriple *prevbezt = &nu->bezt[i - 1];
317  const BezTriple *bezt = &nu->bezt[i];
318 
319  if (prevbezt->h2 == HD_VECT && bezt->h1 == HD_VECT) {
320  copy_v3_v3(data, prevbezt->vec[1]);
321  data += 3;
322  }
323  else {
324  for (int j = 0; j < 3; j++) {
325  BKE_curve_forward_diff_bezier(prevbezt->vec[1][j],
326  prevbezt->vec[2][j],
327  bezt->vec[0][j],
328  bezt->vec[1][j],
329  data + j,
330  resolution,
331  sizeof(float[3]));
332  }
333  data += 3 * resolution;
334  }
335  }
336  if (is_cyclic) {
337  if (bezt_first->h1 == HD_VECT && bezt_last->h2 == HD_VECT) {
338  copy_v3_v3(data, bezt_last->vec[1]);
339  }
340  else {
341  for (int j = 0; j < 3; j++) {
342  BKE_curve_forward_diff_bezier(bezt_last->vec[1][j],
343  bezt_last->vec[2][j],
344  bezt_first->vec[0][j],
345  bezt_first->vec[1][j],
346  data + j,
347  resolution,
348  sizeof(float[3]));
349  }
350  }
351  }
352  else {
353  copy_v3_v3(data, bezt_last->vec[1]);
354  }
355  }
356  else if (nu->type == CU_NURBS) {
357  const int len = (resolution * SEGMENTSU(nu));
358  DispList *dl = MEM_cnew<DispList>(__func__);
359  dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), __func__);
360  BLI_addtail(r_dispbase, dl);
361  dl->parts = 1;
362  dl->nr = len;
363  dl->col = nu->mat_nr;
364  dl->charidx = nu->charidx;
365  dl->type = is_cyclic ? DL_POLY : DL_SEGM;
366 
367  BKE_nurb_makeCurve(nu, dl->verts, nullptr, nullptr, nullptr, resolution, sizeof(float[3]));
368  }
369  else if (nu->type == CU_POLY) {
370  const int len = nu->pntsu;
371  DispList *dl = MEM_cnew<DispList>(__func__);
372  dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), __func__);
373  BLI_addtail(r_dispbase, dl);
374  dl->parts = 1;
375  dl->nr = len;
376  dl->col = nu->mat_nr;
377  dl->charidx = nu->charidx;
378  dl->type = (is_cyclic && (dl->nr != 2)) ? DL_POLY : DL_SEGM;
379 
380  float(*coords)[3] = (float(*)[3])dl->verts;
381  for (int i = 0; i < len; i++) {
382  const BPoint *bp = &nu->bp[i];
383  copy_v3_v3(coords[i], bp->vec);
384  }
385  }
386  }
387 }
388 
389 void BKE_displist_fill(const ListBase *dispbase,
390  ListBase *to,
391  const float normal_proj[3],
392  const bool flip_normal)
393 {
394  if (dispbase == nullptr) {
395  return;
396  }
397  if (BLI_listbase_is_empty(dispbase)) {
398  return;
399  }
400 
401  const int scanfill_flag = BLI_SCANFILL_CALC_REMOVE_DOUBLES | BLI_SCANFILL_CALC_POLYS |
403 
404  MemArena *sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__);
405 
406  short colnr = 0;
407  int charidx = 0;
408  bool should_continue = true;
409  while (should_continue) {
410  should_continue = false;
411  bool nextcol = false;
412 
413  ScanFillContext sf_ctx;
414  BLI_scanfill_begin_arena(&sf_ctx, sf_arena);
415 
416  int totvert = 0;
417  short dl_flag_accum = 0;
418  short dl_rt_accum = 0;
419  LISTBASE_FOREACH (const DispList *, dl, dispbase) {
420  if (dl->type == DL_POLY) {
421  if (charidx < dl->charidx) {
422  should_continue = true;
423  }
424  else if (charidx == dl->charidx) { /* character with needed index */
425  if (colnr == dl->col) {
426 
427  sf_ctx.poly_nr++;
428 
429  /* Make verts and edges. */
430  ScanFillVert *sf_vert = nullptr;
431  ScanFillVert *sf_vert_last = nullptr;
432  ScanFillVert *sf_vert_new = nullptr;
433  for (int i = 0; i < dl->nr; i++) {
434  sf_vert_last = sf_vert;
435  sf_vert = BLI_scanfill_vert_add(&sf_ctx, &dl->verts[3 * i]);
436  totvert++;
437  if (sf_vert_last == nullptr) {
438  sf_vert_new = sf_vert;
439  }
440  else {
441  BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
442  }
443  }
444 
445  if (sf_vert != nullptr && sf_vert_new != nullptr) {
446  BLI_scanfill_edge_add(&sf_ctx, sf_vert, sf_vert_new);
447  }
448  }
449  else if (colnr < dl->col) {
450  /* got poly with next material at current char */
451  should_continue = true;
452  nextcol = true;
453  }
454  }
455  dl_flag_accum |= dl->flag;
456  dl_rt_accum |= dl->rt;
457  }
458  }
459 
460  const int triangles_len = BLI_scanfill_calc_ex(&sf_ctx, scanfill_flag, normal_proj);
461  if (totvert != 0 && triangles_len != 0) {
462  DispList *dlnew = MEM_cnew<DispList>(__func__);
463  dlnew->type = DL_INDEX3;
464  dlnew->flag = (dl_flag_accum & (DL_BACK_CURVE | DL_FRONT_CURVE));
465  dlnew->rt = (dl_rt_accum & CU_SMOOTH);
466  dlnew->col = colnr;
467  dlnew->nr = totvert;
468  dlnew->parts = triangles_len;
469 
470  dlnew->index = (int *)MEM_mallocN(sizeof(int[3]) * triangles_len, __func__);
471  dlnew->verts = (float *)MEM_mallocN(sizeof(float[3]) * totvert, __func__);
472 
473  /* vert data */
474  int i;
475  LISTBASE_FOREACH_INDEX (ScanFillVert *, sf_vert, &sf_ctx.fillvertbase, i) {
476  copy_v3_v3(&dlnew->verts[3 * i], sf_vert->co);
477  sf_vert->tmp.i = i; /* Index number. */
478  }
479 
480  /* index data */
481  int *index = dlnew->index;
482  LISTBASE_FOREACH (ScanFillFace *, sf_tri, &sf_ctx.fillfacebase) {
483  index[0] = sf_tri->v1->tmp.i;
484  index[1] = flip_normal ? sf_tri->v3->tmp.i : sf_tri->v2->tmp.i;
485  index[2] = flip_normal ? sf_tri->v2->tmp.i : sf_tri->v3->tmp.i;
486  index += 3;
487  }
488 
489  BLI_addhead(to, dlnew);
490  }
491  BLI_scanfill_end_arena(&sf_ctx, sf_arena);
492 
493  if (nextcol) {
494  /* stay at current char but fill polys with next material */
495  colnr++;
496  }
497  else {
498  /* switch to next char and start filling from first material */
499  charidx++;
500  colnr = 0;
501  }
502  }
503 
504  BLI_memarena_free(sf_arena);
505  /* do not free polys, needed for wireframe display */
506 }
507 
508 static void bevels_to_filledpoly(const Curve *cu, ListBase *dispbase)
509 {
510  ListBase front = {nullptr, nullptr};
511  ListBase back = {nullptr, nullptr};
512 
513  LISTBASE_FOREACH (const DispList *, dl, dispbase) {
514  if (dl->type == DL_SURF) {
515  if ((dl->flag & DL_CYCL_V) && (dl->flag & DL_CYCL_U) == 0) {
516  if ((cu->flag & CU_BACK) && (dl->flag & DL_BACK_CURVE)) {
517  DispList *dlnew = MEM_cnew<DispList>(__func__);
518  BLI_addtail(&front, dlnew);
519  dlnew->verts = (float *)MEM_mallocN(sizeof(float[3]) * dl->parts, __func__);
520  dlnew->nr = dl->parts;
521  dlnew->parts = 1;
522  dlnew->type = DL_POLY;
523  dlnew->flag = DL_BACK_CURVE;
524  dlnew->col = dl->col;
525  dlnew->charidx = dl->charidx;
526 
527  const float *old_verts = dl->verts;
528  float *new_verts = dlnew->verts;
529  for (int i = 0; i < dl->parts; i++) {
530  copy_v3_v3(new_verts, old_verts);
531  new_verts += 3;
532  old_verts += 3 * dl->nr;
533  }
534  }
535  if ((cu->flag & CU_FRONT) && (dl->flag & DL_FRONT_CURVE)) {
536  DispList *dlnew = MEM_cnew<DispList>(__func__);
537  BLI_addtail(&back, dlnew);
538  dlnew->verts = (float *)MEM_mallocN(sizeof(float[3]) * dl->parts, __func__);
539  dlnew->nr = dl->parts;
540  dlnew->parts = 1;
541  dlnew->type = DL_POLY;
542  dlnew->flag = DL_FRONT_CURVE;
543  dlnew->col = dl->col;
544  dlnew->charidx = dl->charidx;
545 
546  const float *old_verts = dl->verts + 3 * (dl->nr - 1);
547  float *new_verts = dlnew->verts;
548  for (int i = 0; i < dl->parts; i++) {
549  copy_v3_v3(new_verts, old_verts);
550  new_verts += 3;
551  old_verts += 3 * dl->nr;
552  }
553  }
554  }
555  }
556  }
557 
558  const float z_up[3] = {0.0f, 0.0f, -1.0f};
559  BKE_displist_fill(&front, dispbase, z_up, true);
560  BKE_displist_fill(&back, dispbase, z_up, false);
561 
562  BKE_displist_free(&front);
563  BKE_displist_free(&back);
564 
565  BKE_displist_fill(dispbase, dispbase, z_up, false);
566 }
567 
568 static void curve_to_filledpoly(const Curve *cu, ListBase *dispbase)
569 {
570  if (!CU_DO_2DFILL(cu)) {
571  return;
572  }
573 
574  if (dispbase->first && ((DispList *)dispbase->first)->type == DL_SURF) {
575  bevels_to_filledpoly(cu, dispbase);
576  }
577  else {
578  const float z_up[3] = {0.0f, 0.0f, -1.0f};
579  BKE_displist_fill(dispbase, dispbase, z_up, false);
580  }
581 }
582 
583 /* taper rules:
584  * - only 1 curve
585  * - first point left, last point right
586  * - based on subdivided points in original curve, not on points in taper curve (still)
587  */
589  const Scene *scene,
590  Object *taperobj,
591  float fac)
592 {
593  if (taperobj == nullptr || taperobj->type != OB_CURVES_LEGACY) {
594  return 1.0;
595  }
596 
597  DispList *dl = taperobj->runtime.curve_cache ?
598  (DispList *)taperobj->runtime.curve_cache->disp.first :
599  nullptr;
600  if (dl == nullptr) {
601  BKE_displist_make_curveTypes(depsgraph, scene, taperobj, false);
602  dl = (DispList *)taperobj->runtime.curve_cache->disp.first;
603  }
604  if (dl) {
605  float minx, dx, *fp;
606  int a;
607 
608  /* horizontal size */
609  minx = dl->verts[0];
610  dx = dl->verts[3 * (dl->nr - 1)] - minx;
611  if (dx > 0.0f) {
612  fp = dl->verts;
613  for (a = 0; a < dl->nr; a++, fp += 3) {
614  if ((fp[0] - minx) / dx >= fac) {
615  /* interpolate with prev */
616  if (a > 0) {
617  float fac1 = (fp[-3] - minx) / dx;
618  float fac2 = (fp[0] - minx) / dx;
619  if (fac1 != fac2) {
620  return fp[1] * (fac1 - fac) / (fac1 - fac2) + fp[-2] * (fac - fac2) / (fac1 - fac2);
621  }
622  }
623  return fp[1];
624  }
625  }
626  return fp[-2]; /* Last y coordinate. */
627  }
628  }
629 
630  return 1.0;
631 }
632 
634  Depsgraph *depsgraph, const Scene *scene, Object *taperobj, int cur, int tot)
635 {
636  const float fac = ((float)cur) / (float)(tot - 1);
637 
638  return displist_calc_taper(depsgraph, scene, taperobj, fac);
639 }
640 
642 {
643  if (!ob || ob->type != OB_MBALL) {
644  return;
645  }
646 
647  if (ob == BKE_mball_basis_find(scene, ob)) {
648  if (ob->runtime.curve_cache) {
650  }
651  else {
652  ob->runtime.curve_cache = MEM_cnew<CurveCache>(__func__);
653  }
654 
657 
659  }
660 }
661 
663  const Object *ob,
664  const bool for_render,
665  const bool editmode)
666 {
667  VirtualModifierData virtualModifierData;
668  ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData);
669 
670  ModifierMode required_mode = for_render ? eModifierMode_Render : eModifierMode_Realtime;
671  if (editmode) {
672  required_mode = (ModifierMode)((int)required_mode | eModifierMode_Editmode);
673  }
674 
675  ModifierData *pretessellatePoint = nullptr;
676  for (; md; md = md->next) {
678 
679  if (!BKE_modifier_is_enabled(scene, md, required_mode)) {
680  continue;
681  }
682  if (mti->type == eModifierTypeType_Constructive) {
683  return pretessellatePoint;
684  }
685 
687  pretessellatePoint = md;
688 
689  /* this modifiers are moving point of tessellation automatically
690  * (some of them even can't be applied on tessellated curve), set flag
691  * for information button in modifier's header. */
693  }
694  else if (md->mode & eModifierMode_ApplyOnSpline) {
695  pretessellatePoint = md;
696  }
697  }
698 
699  return pretessellatePoint;
700 }
701 
703  const Scene *scene,
704  Object *ob,
705  ListBase *source_nurb,
706  ListBase *target_nurb,
707  const bool for_render)
708 {
709  const Curve *cu = (const Curve *)ob->data;
710 
712 
713  const bool editmode = (!for_render && (cu->editnurb || cu->editfont));
714  ModifierMode required_mode = for_render ? eModifierMode_Render : eModifierMode_Realtime;
715  if (editmode) {
716  required_mode = (ModifierMode)((int)required_mode | eModifierMode_Editmode);
717  }
718 
719  ModifierApplyFlag apply_flag = (ModifierApplyFlag)0;
720  if (editmode) {
721  apply_flag = MOD_APPLY_USECACHE;
722  }
723  if (for_render) {
724  apply_flag = MOD_APPLY_RENDER;
725  }
726 
727  float *keyVerts = nullptr;
728  float(*deformedVerts)[3] = nullptr;
729  int numVerts = 0;
730  if (!editmode) {
731  int numElems = 0;
732  keyVerts = BKE_key_evaluate_object(ob, &numElems);
733 
734  if (keyVerts) {
735  BLI_assert(BKE_keyblock_curve_element_count(source_nurb) == numElems);
736 
737  /* split coords from key data, the latter also includes
738  * tilts, which is passed through in the modifier stack.
739  * this is also the reason curves do not use a virtual
740  * shape key modifier yet. */
741  deformedVerts = BKE_curve_nurbs_key_vert_coords_alloc(source_nurb, keyVerts, &numVerts);
742  }
743  }
744 
745  const ModifierEvalContext mectx = {depsgraph, ob, apply_flag};
746  ModifierData *pretessellatePoint = curve_get_tessellate_point(scene, ob, for_render, editmode);
747 
748  if (pretessellatePoint) {
749  VirtualModifierData virtualModifierData;
750  for (ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); md;
751  md = md->next) {
752  const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type);
753 
754  if (!BKE_modifier_is_enabled(scene, md, required_mode)) {
755  continue;
756  }
757  if (mti->type != eModifierTypeType_OnlyDeform) {
758  continue;
759  }
760 
761  if (!deformedVerts) {
762  deformedVerts = BKE_curve_nurbs_vert_coords_alloc(source_nurb, &numVerts);
763  }
764 
765  mti->deformVerts(md, &mectx, nullptr, deformedVerts, numVerts);
766 
767  if (md == pretessellatePoint) {
768  break;
769  }
770  }
771  }
772 
773  if (deformedVerts) {
774  BKE_curve_nurbs_vert_coords_apply(target_nurb, deformedVerts, false);
775  MEM_freeN(deformedVerts);
776  }
777  if (keyVerts) { /* these are not passed through modifier stack */
778  BKE_curve_nurbs_key_vert_tilts_apply(target_nurb, keyVerts);
779  }
780 
781  if (keyVerts) {
782  MEM_freeN(keyVerts);
783  }
784 }
785 
791  ModifierData *first_modifier,
792  const Scene *scene,
793  const ModifierMode required_mode)
794 {
795  /* Skip implicit filling and conversion to mesh when using "fast text editing". */
796  if (curve->flag & CU_FAST) {
797  return false;
798  }
799 
800  /* Do implicit conversion to mesh with the object bevel mode. */
801  if (curve->bevel_mode == CU_BEV_MODE_OBJECT && curve->bevobj != nullptr) {
802  return true;
803  }
804 
805  /* 2D curves are sometimes implicitly filled and converted to a mesh. */
806  if (CU_DO_2DFILL(curve)) {
807  return true;
808  }
809 
810  /* Curve objects with implicit "tube" meshes should convert implicitly to a mesh. */
811  if (curve->extrude != 0.0f || curve->bevel_radius != 0.0f) {
812  return true;
813  }
814 
815  /* If a non-geometry-nodes modifier is enabled before a nodes modifier,
816  * force conversion to mesh, since only the nodes modifier supports curve data. */
817  ModifierData *md = first_modifier;
818  for (; md; md = md->next) {
819  if (BKE_modifier_is_enabled(scene, md, required_mode)) {
820  if (md->type == eModifierType_Nodes) {
821  break;
822  }
823  return true;
824  }
825  }
826 
827  return false;
828 }
829 
831  const Scene *scene,
832  Object *ob,
833  const ListBase *dispbase,
834  const bool for_render)
835 {
836  const Curve *cu = (const Curve *)ob->data;
837  const bool editmode = (!for_render && (cu->editnurb || cu->editfont));
838  const bool use_cache = !for_render;
839 
840  ModifierApplyFlag apply_flag = for_render ? MOD_APPLY_RENDER : (ModifierApplyFlag)0;
841  ModifierMode required_mode = for_render ? eModifierMode_Render : eModifierMode_Realtime;
842  if (editmode) {
843  required_mode = (ModifierMode)((int)required_mode | eModifierMode_Editmode);
844  }
845 
846  const ModifierEvalContext mectx_deform = {
847  depsgraph, ob, editmode ? (ModifierApplyFlag)(apply_flag | MOD_APPLY_USECACHE) : apply_flag};
848  const ModifierEvalContext mectx_apply = {
849  depsgraph,
850  ob,
851  use_cache ? (ModifierApplyFlag)(apply_flag | MOD_APPLY_USECACHE) : apply_flag};
852 
853  ModifierData *pretessellatePoint = curve_get_tessellate_point(scene, ob, for_render, editmode);
854 
855  VirtualModifierData virtualModifierData;
856  ModifierData *md = pretessellatePoint == nullptr ?
857  BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData) :
858  pretessellatePoint->next;
859 
860  GeometrySet geometry_set;
861  if (ob->type == OB_SURF || do_curve_implicit_mesh_conversion(cu, md, scene, required_mode)) {
863  geometry_set.replace_mesh(mesh);
864  }
865  else {
866  geometry_set.replace_curves(
868  }
869 
870  for (; md; md = md->next) {
872  if (!BKE_modifier_is_enabled(scene, md, required_mode)) {
873  continue;
874  }
875 
876  if (md->type == eModifierType_Nodes) {
877  mti->modifyGeometrySet(md, &mectx_apply, &geometry_set);
878  continue;
879  }
880 
881  if (!geometry_set.has_mesh()) {
882  geometry_set.replace_mesh(BKE_mesh_new_nomain(0, 0, 0, 0, 0));
883  }
884  Mesh *mesh = geometry_set.get_mesh_for_write();
885 
886  if (mti->type == eModifierTypeType_OnlyDeform) {
887  int totvert;
888  float(*vertex_coords)[3] = BKE_mesh_vert_coords_alloc(mesh, &totvert);
889  mti->deformVerts(md, &mectx_deform, mesh, vertex_coords, totvert);
890  BKE_mesh_vert_coords_apply(mesh, vertex_coords);
891  MEM_freeN(vertex_coords);
892  }
893  else {
894  Mesh *output_mesh = mti->modifyMesh(md, &mectx_apply, mesh);
895  if (mesh != output_mesh) {
896  geometry_set.replace_mesh(output_mesh);
897  }
898  }
899  }
900 
901  if (geometry_set.has_mesh()) {
902  Mesh *final_mesh = geometry_set.get_mesh_for_write();
903 
905 
906  BLI_strncpy(final_mesh->id.name, cu->id.name, sizeof(final_mesh->id.name));
907  *((short *)final_mesh->id.name) = ID_ME;
908  }
909 
910  return geometry_set;
911 }
912 
914 {
915  int b, p1, p2, p3, p4;
916 
917  dl->totindex = 0;
918 
919  int *index = dl->index = (int *)MEM_mallocN(sizeof(int[4]) * (dl->parts + 1) * (dl->nr + 1),
920  __func__);
921 
922  for (int a = 0; a < dl->parts; a++) {
923 
924  if (BKE_displist_surfindex_get(dl, a, &b, &p1, &p2, &p3, &p4) == 0) {
925  break;
926  }
927 
928  for (; b < dl->nr; b++, index += 4) {
929  index[0] = p1;
930  index[1] = p2;
931  index[2] = p4;
932  index[3] = p3;
933 
934  dl->totindex++;
935 
936  p2 = p1;
937  p1++;
938  p4 = p3;
939  p3++;
940  }
941  }
942 }
943 
945  const Scene *scene,
946  Object *ob,
947  const bool for_render,
948  ListBase *r_dispbase)
949 {
950  BLI_assert(ob->type == OB_SURF);
951  const Curve *cu = (const Curve *)ob->data;
952 
953  ListBase *deformed_nurbs = &ob->runtime.curve_cache->deformed_nurbs;
954 
955  if (!for_render && cu->editnurb) {
957  }
958  else {
959  BKE_nurbList_duplicate(deformed_nurbs, &cu->nurb);
960  }
961 
962  BKE_curve_calc_modifiers_pre(depsgraph, scene, ob, deformed_nurbs, deformed_nurbs, for_render);
963 
964  LISTBASE_FOREACH (const Nurb *, nu, deformed_nurbs) {
965  if (!(for_render || nu->hide == 0) || !BKE_nurb_check_valid_uv(nu)) {
966  continue;
967  }
968 
969  const int resolu = (for_render && cu->resolu_ren) ? cu->resolu_ren : nu->resolu;
970  const int resolv = (for_render && cu->resolv_ren) ? cu->resolv_ren : nu->resolv;
971 
972  if (nu->pntsv == 1) {
973  const int len = SEGMENTSU(nu) * resolu;
974 
975  DispList *dl = MEM_cnew<DispList>(__func__);
976  dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), __func__);
977 
978  BLI_addtail(r_dispbase, dl);
979  dl->parts = 1;
980  dl->nr = len;
981  dl->col = nu->mat_nr;
982  dl->charidx = nu->charidx;
983  dl->rt = nu->flag;
984 
985  float *data = dl->verts;
986  if (nu->flagu & CU_NURB_CYCLIC) {
987  dl->type = DL_POLY;
988  }
989  else {
990  dl->type = DL_SEGM;
991  }
992 
993  BKE_nurb_makeCurve(nu, data, nullptr, nullptr, nullptr, resolu, sizeof(float[3]));
994  }
995  else {
996  const int len = (nu->pntsu * resolu) * (nu->pntsv * resolv);
997 
998  DispList *dl = MEM_cnew<DispList>(__func__);
999  dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), __func__);
1000  BLI_addtail(r_dispbase, dl);
1001 
1002  dl->col = nu->mat_nr;
1003  dl->charidx = nu->charidx;
1004  dl->rt = nu->flag;
1005 
1006  float *data = dl->verts;
1007  dl->type = DL_SURF;
1008 
1009  dl->parts = (nu->pntsu * resolu); /* in reverse, because makeNurbfaces works that way */
1010  dl->nr = (nu->pntsv * resolv);
1011  if (nu->flagv & CU_NURB_CYCLIC) {
1012  dl->flag |= DL_CYCL_U; /* reverse too! */
1013  }
1014  if (nu->flagu & CU_NURB_CYCLIC) {
1015  dl->flag |= DL_CYCL_V;
1016  }
1017 
1018  BKE_nurb_makeFaces(nu, data, 0, resolu, resolv);
1019 
1020  /* gl array drawing: using indices */
1022  }
1023  }
1024 
1025  curve_to_filledpoly(cu, r_dispbase);
1026  GeometrySet geometry_set = curve_calc_modifiers_post(
1027  depsgraph, scene, ob, r_dispbase, for_render);
1028  if (!geometry_set.has_mesh()) {
1029  geometry_set.replace_mesh(BKE_mesh_new_nomain(0, 0, 0, 0, 0));
1030  }
1031  return geometry_set;
1032 }
1033 
1034 static void rotateBevelPiece(const Curve *cu,
1035  const BevPoint *bevp,
1036  const BevPoint *nbevp,
1037  const DispList *dlb,
1038  const float bev_blend,
1039  const float widfac,
1040  const float radius_factor,
1041  float **r_data)
1042 {
1043  float *data = *r_data;
1044  const float *fp = dlb->verts;
1045  for (int b = 0; b < dlb->nr; b++, fp += 3, data += 3) {
1046  if (cu->flag & CU_3D) {
1047  float vec[3], quat[4];
1048 
1049  vec[0] = fp[1] + widfac;
1050  vec[1] = fp[2];
1051  vec[2] = 0.0;
1052 
1053  if (nbevp == nullptr) {
1054  copy_v3_v3(data, bevp->vec);
1055  copy_qt_qt(quat, bevp->quat);
1056  }
1057  else {
1058  interp_v3_v3v3(data, bevp->vec, nbevp->vec, bev_blend);
1059  interp_qt_qtqt(quat, bevp->quat, nbevp->quat, bev_blend);
1060  }
1061 
1062  mul_qt_v3(quat, vec);
1063 
1064  data[0] += radius_factor * vec[0];
1065  data[1] += radius_factor * vec[1];
1066  data[2] += radius_factor * vec[2];
1067  }
1068  else {
1069  float sina, cosa;
1070 
1071  if (nbevp == nullptr) {
1072  copy_v3_v3(data, bevp->vec);
1073  sina = bevp->sina;
1074  cosa = bevp->cosa;
1075  }
1076  else {
1077  interp_v3_v3v3(data, bevp->vec, nbevp->vec, bev_blend);
1078 
1079  /* perhaps we need to interpolate angles instead. but the thing is
1080  * cosa and sina are not actually sine and cosine
1081  */
1082  sina = nbevp->sina * bev_blend + bevp->sina * (1.0f - bev_blend);
1083  cosa = nbevp->cosa * bev_blend + bevp->cosa * (1.0f - bev_blend);
1084  }
1085 
1086  data[0] += radius_factor * (widfac + fp[1]) * sina;
1087  data[1] += radius_factor * (widfac + fp[1]) * cosa;
1088  data[2] += radius_factor * fp[2];
1089  }
1090  }
1091 
1092  *r_data = data;
1093 }
1094 
1095 static void fillBevelCap(const Nurb *nu,
1096  const DispList *dlb,
1097  const float *prev_fp,
1098  ListBase *dispbase)
1099 {
1100  DispList *dl = MEM_cnew<DispList>(__func__);
1101  dl->verts = (float *)MEM_mallocN(sizeof(float[3]) * dlb->nr, __func__);
1102  memcpy(dl->verts, prev_fp, sizeof(float[3]) * dlb->nr);
1103 
1104  dl->type = DL_POLY;
1105 
1106  dl->parts = 1;
1107  dl->nr = dlb->nr;
1108  dl->col = nu->mat_nr;
1109  dl->charidx = nu->charidx;
1110  dl->rt = nu->flag;
1111 
1112  BLI_addtail(dispbase, dl);
1113 }
1114 
1116  const BevList *bl, float bevfac, float spline_length, int *r_bev, float *r_blend)
1117 {
1118  float normsum = 0.0f;
1119  float *seglen = bl->seglen;
1120  int *segbevcount = bl->segbevcount;
1121  int bevcount = 0, nr = bl->nr;
1122 
1123  float bev_fl = bevfac * (bl->nr - 1);
1124  *r_bev = (int)bev_fl;
1125 
1126  while (bevcount < nr - 1) {
1127  float normlen = *seglen / spline_length;
1128  if (normsum + normlen > bevfac) {
1129  bev_fl = bevcount + (bevfac - normsum) / normlen * *segbevcount;
1130  *r_bev = (int)bev_fl;
1131  *r_blend = bev_fl - *r_bev;
1132  break;
1133  }
1134  normsum += normlen;
1135  bevcount += *segbevcount;
1136  segbevcount++;
1137  seglen++;
1138  }
1139 }
1140 
1142  const BevList *bl, float bevfac, float spline_length, int *r_bev, float *r_blend)
1143 {
1144  const float len_target = bevfac * spline_length;
1145  BevPoint *bevp = bl->bevpoints;
1146  float len_next = 0.0f, len = 0.0f;
1147  int i = 0, nr = bl->nr;
1148 
1149  while (nr--) {
1150  bevp++;
1151  len_next = len + bevp->offset;
1152  if (len_next > len_target) {
1153  break;
1154  }
1155  len = len_next;
1156  i++;
1157  }
1158 
1159  *r_bev = i;
1160  *r_blend = (len_target - len) / bevp->offset;
1161 }
1162 
1164  const BevList *bl, int *r_start, float *r_firstblend, int *r_steps, float *r_lastblend)
1165 {
1166  *r_start = 0;
1167  *r_steps = bl->nr;
1168  *r_firstblend = 1.0f;
1169  *r_lastblend = 1.0f;
1170 }
1171 
1172 static void calc_bevfac_mapping(const Curve *cu,
1173  const BevList *bl,
1174  const Nurb *nu,
1175  int *r_start,
1176  float *r_firstblend,
1177  int *r_steps,
1178  float *r_lastblend)
1179 {
1180  float tmpf, total_length = 0.0f;
1181  int end = 0, i;
1182 
1183  if ((BKE_nurb_check_valid_u(nu) == false) ||
1184  /* not essential, but skips unnecessary calculation */
1185  (min_ff(cu->bevfac1, cu->bevfac2) == 0.0f && max_ff(cu->bevfac1, cu->bevfac2) == 1.0f)) {
1186  calc_bevfac_mapping_default(bl, r_start, r_firstblend, r_steps, r_lastblend);
1187  return;
1188  }
1189 
1192  for (i = 0; i < SEGMENTSU(nu); i++) {
1193  total_length += bl->seglen[i];
1194  }
1195  }
1196 
1197  switch (cu->bevfac1_mapping) {
1198  case CU_BEVFAC_MAP_RESOLU: {
1199  const float start_fl = cu->bevfac1 * (bl->nr - 1);
1200  *r_start = (int)start_fl;
1201  *r_firstblend = 1.0f - (start_fl - (*r_start));
1202  break;
1203  }
1204  case CU_BEVFAC_MAP_SEGMENT: {
1205  calc_bevfac_segment_mapping(bl, cu->bevfac1, total_length, r_start, r_firstblend);
1206  *r_firstblend = 1.0f - *r_firstblend;
1207  break;
1208  }
1209  case CU_BEVFAC_MAP_SPLINE: {
1210  calc_bevfac_spline_mapping(bl, cu->bevfac1, total_length, r_start, r_firstblend);
1211  *r_firstblend = 1.0f - *r_firstblend;
1212  break;
1213  }
1214  }
1215 
1216  switch (cu->bevfac2_mapping) {
1217  case CU_BEVFAC_MAP_RESOLU: {
1218  const float end_fl = cu->bevfac2 * (bl->nr - 1);
1219  end = (int)end_fl;
1220 
1221  *r_steps = 2 + end - *r_start;
1222  *r_lastblend = end_fl - end;
1223  break;
1224  }
1225  case CU_BEVFAC_MAP_SEGMENT: {
1226  calc_bevfac_segment_mapping(bl, cu->bevfac2, total_length, &end, r_lastblend);
1227  *r_steps = end - *r_start + 2;
1228  break;
1229  }
1230  case CU_BEVFAC_MAP_SPLINE: {
1231  calc_bevfac_spline_mapping(bl, cu->bevfac2, total_length, &end, r_lastblend);
1232  *r_steps = end - *r_start + 2;
1233  break;
1234  }
1235  }
1236 
1237  if (end < *r_start || (end == *r_start && *r_lastblend < 1.0f - *r_firstblend)) {
1238  SWAP(int, *r_start, end);
1239  tmpf = *r_lastblend;
1240  *r_lastblend = 1.0f - *r_firstblend;
1241  *r_firstblend = 1.0f - tmpf;
1242  *r_steps = end - *r_start + 2;
1243  }
1244 
1245  if (*r_start + *r_steps > bl->nr) {
1246  *r_steps = bl->nr - *r_start;
1247  *r_lastblend = 1.0f;
1248  }
1249 }
1250 
1252  const Scene *scene,
1253  Object *ob,
1254  const bool for_render,
1255  ListBase *r_dispbase)
1256 {
1258  const Curve *cu = (const Curve *)ob->data;
1259 
1260  ListBase *deformed_nurbs = &ob->runtime.curve_cache->deformed_nurbs;
1261 
1262  if (ob->type == OB_FONT) {
1263  BKE_vfont_to_curve_nubase(ob, FO_EDIT, deformed_nurbs);
1264  }
1265  else {
1267  }
1268 
1269  BKE_curve_calc_modifiers_pre(depsgraph, scene, ob, deformed_nurbs, deformed_nurbs, for_render);
1270 
1271  BKE_curve_bevelList_make(ob, deformed_nurbs, for_render);
1272 
1273  if ((cu->flag & CU_PATH) ||
1276  }
1277 
1278  /* If curve has no bevel will return nothing */
1279  ListBase dlbev = BKE_curve_bevel_make(cu);
1280 
1281  /* no bevel or extrude, and no width correction? */
1282  if (BLI_listbase_is_empty(&dlbev) && cu->offset == 1.0f) {
1283  curve_to_displist(cu, deformed_nurbs, for_render, r_dispbase);
1284  }
1285  else {
1286  const float widfac = cu->offset - 1.0f;
1287 
1288  const BevList *bl = (BevList *)ob->runtime.curve_cache->bev.first;
1289  const Nurb *nu = (Nurb *)deformed_nurbs->first;
1290  for (; bl && nu; bl = bl->next, nu = nu->next) {
1291  float *data;
1292 
1293  if (bl->nr == 0) { /* blank bevel lists can happen */
1294  continue;
1295  }
1296 
1297  /* exception handling; curve without bevel or extrude, with width correction */
1298  if (BLI_listbase_is_empty(&dlbev)) {
1299  DispList *dl = MEM_cnew<DispList>("makeDispListbev");
1300  dl->verts = (float *)MEM_mallocN(sizeof(float[3]) * bl->nr, "dlverts");
1301  BLI_addtail(r_dispbase, dl);
1302 
1303  if (bl->poly != -1) {
1304  dl->type = DL_POLY;
1305  }
1306  else {
1307  dl->type = DL_SEGM;
1308  dl->flag = (DL_FRONT_CURVE | DL_BACK_CURVE);
1309  }
1310 
1311  dl->parts = 1;
1312  dl->nr = bl->nr;
1313  dl->col = nu->mat_nr;
1314  dl->charidx = nu->charidx;
1315  dl->rt = nu->flag;
1316 
1317  int a = dl->nr;
1318  BevPoint *bevp = bl->bevpoints;
1319  data = dl->verts;
1320  while (a--) {
1321  data[0] = bevp->vec[0] + widfac * bevp->sina;
1322  data[1] = bevp->vec[1] + widfac * bevp->cosa;
1323  data[2] = bevp->vec[2];
1324  bevp++;
1325  data += 3;
1326  }
1327  }
1328  else {
1329  ListBase bottom_capbase = {nullptr, nullptr};
1330  ListBase top_capbase = {nullptr, nullptr};
1331  float bottom_no[3] = {0.0f};
1332  float top_no[3] = {0.0f};
1333  float first_blend = 0.0f, last_blend = 0.0f;
1334  int start, steps = 0;
1335 
1336  if (nu->flagu & CU_NURB_CYCLIC) {
1337  calc_bevfac_mapping_default(bl, &start, &first_blend, &steps, &last_blend);
1338  }
1339  else {
1340  if (fabsf(cu->bevfac2 - cu->bevfac1) < FLT_EPSILON) {
1341  continue;
1342  }
1343 
1344  calc_bevfac_mapping(cu, bl, nu, &start, &first_blend, &steps, &last_blend);
1345  }
1346 
1347  LISTBASE_FOREACH (DispList *, dlb, &dlbev) {
1348  /* for each part of the bevel use a separate displblock */
1349  DispList *dl = MEM_cnew<DispList>(__func__);
1350  dl->verts = data = (float *)MEM_mallocN(sizeof(float[3]) * dlb->nr * steps, __func__);
1351  BLI_addtail(r_dispbase, dl);
1352 
1353  dl->type = DL_SURF;
1354 
1355  dl->flag = dlb->flag & (DL_FRONT_CURVE | DL_BACK_CURVE);
1356  if (dlb->type == DL_POLY) {
1357  dl->flag |= DL_CYCL_U;
1358  }
1359  if ((bl->poly >= 0) && (steps > 2)) {
1360  dl->flag |= DL_CYCL_V;
1361  }
1362 
1363  dl->parts = steps;
1364  dl->nr = dlb->nr;
1365  dl->col = nu->mat_nr;
1366  dl->charidx = nu->charidx;
1367  dl->rt = nu->flag;
1368 
1369  /* for each point of poly make a bevel piece */
1370  BevPoint *bevp_first = bl->bevpoints;
1371  BevPoint *bevp_last = &bl->bevpoints[bl->nr - 1];
1372  BevPoint *bevp = &bl->bevpoints[start];
1373  for (int i = start, a = 0; a < steps; i++, bevp++, a++) {
1374  float radius_factor = 1.0;
1375  float *cur_data = data;
1376 
1377  if (cu->taperobj == nullptr) {
1378  radius_factor = bevp->radius;
1379  }
1380  else {
1381  float taper_factor;
1382  if (cu->flag & CU_MAP_TAPER) {
1383  float len = (steps - 3) + first_blend + last_blend;
1384 
1385  if (a == 0) {
1386  taper_factor = 0.0f;
1387  }
1388  else if (a == steps - 1) {
1389  taper_factor = 1.0f;
1390  }
1391  else {
1392  taper_factor = ((float)a - (1.0f - first_blend)) / len;
1393  }
1394  }
1395  else {
1396  float len = bl->nr - 1;
1397  taper_factor = (float)i / len;
1398 
1399  if (a == 0) {
1400  taper_factor += (1.0f - first_blend) / len;
1401  }
1402  else if (a == steps - 1) {
1403  taper_factor -= (1.0f - last_blend) / len;
1404  }
1405  }
1406 
1407  radius_factor = displist_calc_taper(depsgraph, scene, cu->taperobj, taper_factor);
1408 
1410  radius_factor *= bevp->radius;
1411  }
1412  else if (cu->taper_radius_mode == CU_TAPER_RADIUS_ADD) {
1413  radius_factor += bevp->radius;
1414  }
1415  }
1416 
1417  /* rotate bevel piece and write in data */
1418  if ((a == 0) && (bevp != bevp_last)) {
1420  cu, bevp, bevp + 1, dlb, 1.0f - first_blend, widfac, radius_factor, &data);
1421  }
1422  else if ((a == steps - 1) && (bevp != bevp_first)) {
1424  cu, bevp, bevp - 1, dlb, 1.0f - last_blend, widfac, radius_factor, &data);
1425  }
1426  else {
1427  rotateBevelPiece(cu, bevp, nullptr, dlb, 0.0f, widfac, radius_factor, &data);
1428  }
1429 
1430  if ((cu->flag & CU_FILL_CAPS) && !(nu->flagu & CU_NURB_CYCLIC)) {
1431  if (a == 1) {
1432  fillBevelCap(nu, dlb, cur_data - 3 * dlb->nr, &bottom_capbase);
1433  copy_v3_v3(bottom_no, bevp->dir);
1434  }
1435  if (a == steps - 1) {
1436  fillBevelCap(nu, dlb, cur_data, &top_capbase);
1437  negate_v3_v3(top_no, bevp->dir);
1438  }
1439  }
1440  }
1441 
1442  /* gl array drawing: using indices */
1444  }
1445 
1446  if (bottom_capbase.first) {
1447  BKE_displist_fill(&bottom_capbase, r_dispbase, bottom_no, false);
1448  BKE_displist_fill(&top_capbase, r_dispbase, top_no, false);
1449  BKE_displist_free(&bottom_capbase);
1450  BKE_displist_free(&top_capbase);
1451  }
1452  }
1453  }
1454  }
1455 
1456  BKE_displist_free(&dlbev);
1457 
1458  curve_to_filledpoly(cu, r_dispbase);
1459  return curve_calc_modifiers_post(depsgraph, scene, ob, r_dispbase, for_render);
1460 }
1461 
1463  const Scene *scene,
1464  Object *ob,
1465  const bool for_render)
1466 {
1468 
1470 
1471  /* It's important to retrieve this after calling #BKE_object_free_derived_caches,
1472  * which may reset the object data pointer in some cases. */
1473  const Curve &original_curve = *static_cast<const Curve *>(ob->data);
1474 
1475  ob->runtime.curve_cache = MEM_cnew<CurveCache>(__func__);
1476  ListBase *dispbase = &ob->runtime.curve_cache->disp;
1477 
1478  if (ob->type == OB_SURF) {
1479  GeometrySet geometry = evaluate_surface_object(depsgraph, scene, ob, for_render, dispbase);
1480  ob->runtime.geometry_set_eval = new GeometrySet(std::move(geometry));
1481  }
1482  else {
1483  GeometrySet geometry = evaluate_curve_type_object(depsgraph, scene, ob, for_render, dispbase);
1484 
1485  if (geometry.has_curves()) {
1486  /* Create a copy of the original curve and add necessary pointers to evaluated and edit mode
1487  * data. This is needed for a few reasons:
1488  * - Existing code from before curve evaluation was changed to use #GeometrySet expected to
1489  * have a copy of the original curve data. (Any evaluated data was placed in
1490  * #Object.runtime.curve_cache).
1491  * - The result of modifier evaluation is not a #Curve data-block but a #Curves data-block,
1492  * which can support constructive modifiers and geometry nodes.
1493  * - The dependency graph has handling of edit mode pointers (see #update_edit_mode_pointers)
1494  * but it doesn't seem to work in this case.
1495  *
1496  * Since the the plan is to replace this legacy curve object with the curves data-block
1497  * (see T95355), this somewhat hacky inefficient solution is relatively temporary.
1498  */
1499  Curve &cow_curve = *reinterpret_cast<Curve *>(
1500  BKE_id_copy_ex(nullptr, &original_curve.id, nullptr, LIB_ID_COPY_LOCALIZE));
1501  cow_curve.curve_eval = geometry.get_curves_for_read();
1502  /* Copy edit mode pointers necessary for drawing to the duplicated curve. */
1503  cow_curve.editnurb = original_curve.editnurb;
1504  cow_curve.editfont = original_curve.editfont;
1505  cow_curve.edit_data_from_original = true;
1506  BKE_object_eval_assign_data(ob, &cow_curve.id, true);
1507  }
1508 
1509  ob->runtime.geometry_set_eval = new GeometrySet(std::move(geometry));
1510  }
1511 
1513 }
1514 
1515 void BKE_displist_minmax(const ListBase *dispbase, float min[3], float max[3])
1516 {
1517  bool doit = false;
1518 
1519  LISTBASE_FOREACH (const DispList *, dl, dispbase) {
1520  const int tot = (ELEM(dl->type, DL_INDEX3, DL_INDEX4)) ? dl->nr : dl->nr * dl->parts;
1521  for (const int i : IndexRange(tot)) {
1522  minmax_v3v3_v3(min, max, &dl->verts[i * 3]);
1523  }
1524  if (tot != 0) {
1525  doit = true;
1526  }
1527  }
1528 
1529  if (!doit) {
1530  /* there's no geometry in displist, use zero-sized boundbox */
1531  zero_v3(min);
1532  zero_v3(max);
1533  }
1534 }
typedef float(TangentPoint)[2]
void BKE_anim_path_calc_data(struct Object *ob)
Definition: anim_path.c:56
float(* BKE_curve_nurbs_vert_coords_alloc(const struct ListBase *lb, int *r_vert_len))[3]
void BKE_curve_bevelList_make(struct Object *ob, const struct ListBase *nurbs, bool for_render)
#define CU_DO_2DFILL(cu)
Definition: BKE_curve.h:70
ListBase BKE_curve_bevel_make(const struct Curve *curve)
const struct ListBase * BKE_curve_editNurbs_get_for_read(const struct Curve *cu)
void BKE_nurb_makeFaces(const struct Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv)
bool BKE_nurb_check_valid_u(const struct Nurb *nu)
void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride)
Definition: curve.cc:1717
void BKE_nurb_makeCurve(const struct Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, float *weight_array, int resolu, int stride)
void BKE_nurbList_duplicate(struct ListBase *lb1, const struct ListBase *lb2)
const ListBase * BKE_curve_nurbs_get_for_read(const struct Curve *cu)
void BKE_curve_nurbs_key_vert_tilts_apply(struct ListBase *lb, const float *key)
Definition: curve.cc:4687
bool BKE_nurb_check_valid_uv(const struct Nurb *nu)
#define SEGMENTSU(nu)
Definition: BKE_curve.h:58
void BKE_curve_nurbs_vert_coords_apply(struct ListBase *lb, const float(*vert_coords)[3], bool constrain_2d)
Definition: curve.cc:4617
float(* BKE_curve_nurbs_key_vert_coords_alloc(const struct ListBase *lb, float *key, int *r_vert_len))[3]
display list (or rather multi purpose list) stuff.
@ DL_CYCL_V
Definition: BKE_displist.h:38
@ DL_BACK_CURVE
Definition: BKE_displist.h:41
@ DL_FRONT_CURVE
Definition: BKE_displist.h:40
@ DL_CYCL_U
Definition: BKE_displist.h:37
@ DL_SURF
Definition: BKE_displist.h:24
@ DL_INDEX4
Definition: BKE_displist.h:28
@ DL_INDEX3
Definition: BKE_displist.h:26
@ DL_POLY
Definition: BKE_displist.h:20
@ DL_SEGM
Definition: BKE_displist.h:22
float * BKE_key_evaluate_object(struct Object *ob, int *r_totelem)
Definition: key.c:1632
int BKE_keyblock_curve_element_count(const struct ListBase *nurb)
bool object_deform_mball(struct Object *ob, struct ListBase *dispbase)
Definition: lattice.c:401
@ LIB_ID_COPY_LOCALIZE
Definition: BKE_lib_id.h:187
struct ID * BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, int flag)
struct Object * BKE_mball_basis_find(struct Scene *scene, struct Object *ob)
Definition: mball.c:508
void BKE_mball_texspace_calc(struct Object *ob)
Definition: mball.c:255
void BKE_mball_polygonize(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct ListBase *dispbase)
struct Mesh * BKE_mesh_new_nomain_from_curve_displist(const struct Object *ob, const struct ListBase *dispbase)
void BKE_mesh_vert_coords_apply(struct Mesh *mesh, const float(*vert_coords)[3])
Definition: mesh.cc:1834
struct Mesh * BKE_mesh_new_nomain(int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len)
Definition: mesh.cc:991
float(* BKE_mesh_vert_coords_alloc(const struct Mesh *mesh, int *r_vert_len))[3]
void BKE_mesh_ensure_normals_for_display(struct Mesh *mesh)
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
bool BKE_modifier_is_enabled(const struct Scene *scene, struct ModifierData *md, int required_mode)
struct ModifierData * BKE_modifiers_get_virtual_modifierlist(const struct Object *ob, struct VirtualModifierData *data)
@ eModifierTypeType_OnlyDeform
Definition: BKE_modifier.h:44
@ eModifierTypeType_Constructive
Definition: BKE_modifier.h:47
void BKE_modifiers_clear_errors(struct Object *ob)
ModifierApplyFlag
Definition: BKE_modifier.h:113
@ MOD_APPLY_USECACHE
Definition: BKE_modifier.h:118
@ MOD_APPLY_RENDER
Definition: BKE_modifier.h:115
General operations, lookup, etc. for blender objects.
void BKE_object_free_derived_caches(struct Object *ob)
Definition: object.cc:1774
bool BKE_object_boundbox_calc_from_evaluated_geometry(struct Object *ob)
Definition: object.cc:3743
void BKE_object_eval_assign_data(struct Object *object, struct ID *data, bool is_owned)
Definition: object.cc:1745
bool BKE_vfont_to_curve_nubase(struct Object *ob, int mode, struct ListBase *r_nubase)
Definition: vfont.c:1737
#define BLI_assert(a)
Definition: BLI_assert.h:46
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:221
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:60
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
Definition: BLI_listbase.h:344
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:50
void interp_qt_qtqt(float q[4], const float a[4], const float b[4], float t)
void mul_qt_v3(const float q[4], float r[3])
Definition: math_rotation.c:59
void copy_qt_qt(float q[4], const float a[4])
Definition: math_rotation.c:33
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
Definition: math_vector.c:867
MINLINE float normalize_v3(float r[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
Definition: BLI_memarena.c:94
struct MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
Definition: BLI_memarena.c:64
struct ScanFillVert * BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3])
Definition: scanfill.c:112
struct ScanFillEdge * BLI_scanfill_edge_add(ScanFillContext *sf_ctx, struct ScanFillVert *v1, struct ScanFillVert *v2)
Definition: scanfill.c:134
void BLI_scanfill_begin_arena(ScanFillContext *sf_ctx, struct MemArena *arena)
Definition: scanfill.c:786
unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, int flag, const float nor_proj[3])
Definition: scanfill.c:813
#define BLI_SCANFILL_ARENA_SIZE
Definition: BLI_scanfill.h:29
void BLI_scanfill_end_arena(ScanFillContext *sf_ctx, struct MemArena *arena)
Definition: scanfill.c:803
@ BLI_SCANFILL_CALC_POLYS
Definition: BLI_scanfill.h:91
@ BLI_SCANFILL_CALC_HOLES
Definition: BLI_scanfill.h:95
@ BLI_SCANFILL_CALC_REMOVE_DOUBLES
Definition: BLI_scanfill.h:88
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
#define SWAP(type, a, b)
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
@ DAG_EVAL_NEED_CURVE_PATH
Definition: DEG_depsgraph.h:54
uint32_t DEG_get_eval_flags_for_id(const struct Depsgraph *graph, const struct ID *id)
@ ID_ME
Definition: DNA_ID_enums.h:48
@ CU_BEV_MODE_OBJECT
@ CU_BEZIER
@ CU_POLY
@ CU_NURBS
@ CU_SMOOTH
@ CU_BEVFAC_MAP_SPLINE
@ CU_BEVFAC_MAP_RESOLU
@ CU_BEVFAC_MAP_SEGMENT
@ CU_NURB_CYCLIC
@ CU_TAPER_RADIUS_MULTIPLY
@ CU_TAPER_RADIUS_ADD
@ HD_VECT
@ CU_FILL_CAPS
@ CU_FAST
@ CU_3D
@ CU_FRONT
@ CU_PATH
@ CU_MAP_TAPER
@ CU_BACK
ModifierMode
@ eModifierMode_Render
@ eModifierMode_ApplyOnSpline
@ eModifierMode_Editmode
@ eModifierMode_Realtime
ModifierType
@ eModifierType_MeshDeform
@ eModifierType_Hook
@ eModifierType_Nodes
@ eModifierType_Softbody
Object is a sort of wrapper for general info.
@ OB_MBALL
@ OB_SURF
@ OB_FONT
@ OB_CURVES_LEGACY
#define FO_EDIT
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v2
Scene scene
Curve curve
const Depsgraph * depsgraph
static GeometrySet evaluate_surface_object(Depsgraph *depsgraph, const Scene *scene, Object *ob, const bool for_render, ListBase *r_dispbase)
Definition: displist.cc:944
static void displist_surf_indices(DispList *dl)
Definition: displist.cc:913
static bool do_curve_implicit_mesh_conversion(const Curve *curve, ModifierData *first_modifier, const Scene *scene, const ModifierMode required_mode)
Definition: displist.cc:790
static void curve_to_filledpoly(const Curve *cu, ListBase *dispbase)
Definition: displist.cc:568
static void bevels_to_filledpoly(const Curve *cu, ListBase *dispbase)
Definition: displist.cc:508
void BKE_displist_normals_add(ListBase *lb)
Definition: displist.cc:102
float BKE_displist_calc_taper(Depsgraph *depsgraph, const Scene *scene, Object *taperobj, int cur, int tot)
Definition: displist.cc:633
static float displist_calc_taper(Depsgraph *depsgraph, const Scene *scene, Object *taperobj, float fac)
Definition: displist.cc:588
void BKE_displist_make_curveTypes(Depsgraph *depsgraph, const Scene *scene, Object *ob, const bool for_render)
Definition: displist.cc:1462
void BKE_displist_fill(const ListBase *dispbase, ListBase *to, const float normal_proj[3], const bool flip_normal)
Definition: displist.cc:389
static void calc_bevfac_mapping_default(const BevList *bl, int *r_start, float *r_firstblend, int *r_steps, float *r_lastblend)
Definition: displist.cc:1163
static void calc_bevfac_spline_mapping(const BevList *bl, float bevfac, float spline_length, int *r_bev, float *r_blend)
Definition: displist.cc:1141
static void rotateBevelPiece(const Curve *cu, const BevPoint *bevp, const BevPoint *nbevp, const DispList *dlb, const float bev_blend, const float widfac, const float radius_factor, float **r_data)
Definition: displist.cc:1034
void BKE_displist_copy(ListBase *lbn, const ListBase *lb)
Definition: displist.cc:89
static void calc_bevfac_mapping(const Curve *cu, const BevList *bl, const Nurb *nu, int *r_start, float *r_firstblend, int *r_steps, float *r_lastblend)
Definition: displist.cc:1172
static void displist_elem_free(DispList *dl)
Definition: displist.cc:53
bool BKE_displist_surfindex_get(const DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4)
Definition: displist.cc:216
static void fillBevelCap(const Nurb *nu, const DispList *dlb, const float *prev_fp, ListBase *dispbase)
Definition: displist.cc:1095
void BKE_displist_count(const ListBase *lb, int *totvert, int *totface, int *tottri)
Definition: displist.cc:173
void BKE_displist_free(ListBase *lb)
Definition: displist.cc:69
void BKE_curve_calc_modifiers_pre(Depsgraph *depsgraph, const Scene *scene, Object *ob, ListBase *source_nurb, ListBase *target_nurb, const bool for_render)
Definition: displist.cc:702
void BKE_displist_make_mball(Depsgraph *depsgraph, Scene *scene, Object *ob)
Definition: displist.cc:641
DispList * BKE_displist_find(ListBase *lb, int type)
Definition: displist.cc:78
static void calc_bevfac_segment_mapping(const BevList *bl, float bevfac, float spline_length, int *r_bev, float *r_blend)
Definition: displist.cc:1115
static GeometrySet evaluate_curve_type_object(Depsgraph *depsgraph, const Scene *scene, Object *ob, const bool for_render, ListBase *r_dispbase)
Definition: displist.cc:1251
static GeometrySet curve_calc_modifiers_post(Depsgraph *depsgraph, const Scene *scene, Object *ob, const ListBase *dispbase, const bool for_render)
Definition: displist.cc:830
static ModifierData * curve_get_tessellate_point(const Scene *scene, const Object *ob, const bool for_render, const bool editmode)
Definition: displist.cc:662
static void curve_to_displist(const Curve *cu, const ListBase *nubase, const bool for_render, ListBase *r_dispbase)
Definition: displist.cc:252
void BKE_displist_minmax(const ListBase *dispbase, float min[3], float max[3])
Definition: displist.cc:1515
int len
Definition: draw_manager.c:108
static bool is_cyclic(const Nurb *nu)
uint nor
uint col
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
#define fabsf(x)
Definition: metal/compat.h:219
static unsigned a[3]
Definition: RandGen.cpp:78
Curves * curve_legacy_to_curves(const Curve &curve_legacy)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static const int steps
Definition: sky_nishita.cpp:19
#define min(a, b)
Definition: sort.c:35
float vec[4]
struct BevList * next
float * seglen
BevPoint * bevpoints
int * segbevcount
float offset
float radius
float dir[3]
float quat[4]
float vec[3]
uint8_t h1
float vec[3][3]
uint8_t h2
ListBase bev
Definition: BKE_curve.h:34
ListBase disp
Definition: BKE_curve.h:33
ListBase deformed_nurbs
Definition: BKE_curve.h:35
struct Object * bevobj
char edit_data_from_original
float bevfac2
const struct Curves * curve_eval
struct EditFont * editfont
char bevfac2_mapping
short resolv_ren
float extrude
float bevfac1
float bevel_radius
char bevel_mode
EditNurb * editnurb
float offset
ListBase nurb
char taper_radius_mode
char bevfac1_mapping
struct Object * taperobj
short resolu_ren
short type
Definition: BKE_displist.h:55
int totindex
Definition: BKE_displist.h:61
short col
Definition: BKE_displist.h:57
float * verts
Definition: BKE_displist.h:58
int * index
Definition: BKE_displist.h:59
short rt
Definition: BKE_displist.h:57
float * nors
Definition: BKE_displist.h:58
short flag
Definition: BKE_displist.h:55
int charidx
Definition: BKE_displist.h:60
void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void replace_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
const Curves * get_curves_for_read() const
Mesh * get_mesh_for_write()
bool has_mesh() const
bool has_curves() const
char name[66]
Definition: DNA_ID.h:378
void * first
Definition: DNA_listBase.h:31
struct ModifierData * next
void(* modifyGeometrySet)(struct ModifierData *md, const struct ModifierEvalContext *ctx, struct GeometrySet *geometry_set)
Definition: BKE_modifier.h:240
ModifierTypeType type
Definition: BKE_modifier.h:160
struct Mesh *(* modifyMesh)(struct ModifierData *md, const struct ModifierEvalContext *ctx, struct Mesh *mesh)
Definition: BKE_modifier.h:231
void(* deformVerts)(struct ModifierData *md, const struct ModifierEvalContext *ctx, struct Mesh *mesh, float(*vertexCos)[3], int numVerts)
Definition: BKE_modifier.h:184
int charidx
short flag
short mat_nr
struct CurveCache * curve_cache
struct GeometrySet * geometry_set_eval
Object_Runtime runtime
void * data
ListBase fillvertbase
Definition: BLI_scanfill.h:17
unsigned short poly_nr
Definition: BLI_scanfill.h:23
ListBase fillfacebase
Definition: BLI_scanfill.h:19
float max