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