Blender V4.3
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
9#include <cmath>
10#include <cstdio>
11#include <cstring>
12
13#include "MEM_guardedalloc.h"
14
15#include "DNA_curve_types.h"
16#include "DNA_mesh_types.h"
17#include "DNA_object_types.h"
18
19#include "BLI_index_range.hh"
20#include "BLI_listbase.h"
21#include "BLI_math_rotation.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 "BLI_sys_types.h" /* For #intptr_t support. */
42
43#include "DEG_depsgraph.hh"
45
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_cnew<DispList>(__func__);
169 /* Add one to the length because of 'BKE_curve_forward_diff_bezier'. */
170 dl->verts = (float *)MEM_mallocN(sizeof(float[3]) * (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_cnew<DispList>(__func__);
224 dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), __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_cnew<DispList>(__func__);
237 dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), __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_cnew<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 = (int *)MEM_mallocN(sizeof(int[3]) * triangles_len, __func__);
336 dlnew->verts = (float *)MEM_mallocN(sizeof(float[3]) * 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_cnew<DispList>(__func__);
383 BLI_addtail(&front, dlnew);
384 dlnew->verts = (float *)MEM_mallocN(sizeof(float[3]) * 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_cnew<DispList>(__func__);
402 BLI_addtail(&back, dlnew);
403 dlnew->verts = (float *)MEM_mallocN(sizeof(float[3]) * 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). */
533 md->mode &= ~eModifierMode_ApplyOnSpline;
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 float(*deformedVerts)[3] = nullptr;
579 int numVerts = 0;
580 if (!editmode) {
581 int numElems = 0;
582 keyVerts = BKE_key_evaluate_object(ob, &numElems);
583
584 if (keyVerts) {
585 BLI_assert(BKE_keyblock_curve_element_count(source_nurb) == numElems);
586
587 /* split coords from key data, the latter also includes
588 * tilts, which is passed through in the modifier stack.
589 * this is also the reason curves do not use a virtual
590 * shape key modifier yet. */
591 deformedVerts = BKE_curve_nurbs_key_vert_coords_alloc(source_nurb, keyVerts, &numVerts);
592 }
593 }
594
595 const ModifierEvalContext mectx = {depsgraph, ob, apply_flag};
596 ModifierData *pretessellatePoint = curve_get_tessellate_point(scene, ob, for_render, editmode);
597
598 if (pretessellatePoint) {
599 VirtualModifierData virtual_modifier_data;
600 for (ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data); md;
601 md = md->next)
602 {
604
605 if (!BKE_modifier_is_enabled(scene, md, required_mode)) {
606 continue;
607 }
609 continue;
610 }
611
612 blender::bke::ScopedModifierTimer modifier_timer{*md};
613
614 if (!deformedVerts) {
615 deformedVerts = BKE_curve_nurbs_vert_coords_alloc(source_nurb, &numVerts);
616 }
617
618 mti->deform_verts(
619 md, &mectx, nullptr, {reinterpret_cast<blender::float3 *>(deformedVerts), numVerts});
620
621 if (md == pretessellatePoint) {
622 break;
623 }
624 }
625 }
626
627 if (deformedVerts) {
628 BKE_curve_nurbs_vert_coords_apply(target_nurb, deformedVerts, false);
629 MEM_freeN(deformedVerts);
630 }
631 if (keyVerts) { /* these are not passed through modifier stack */
632 BKE_curve_nurbs_key_vert_tilts_apply(target_nurb, keyVerts);
633 }
634
635 if (keyVerts) {
636 MEM_freeN(keyVerts);
637 }
638}
639
645 ModifierData *first_modifier,
646 const Scene *scene,
647 const ModifierMode required_mode)
648{
649 /* Skip implicit filling and conversion to mesh when using "fast text editing". */
650 if (curve->flag & CU_FAST) {
651 return false;
652 }
653
654 /* Do implicit conversion to mesh with the object bevel mode. */
655 if (curve->bevel_mode == CU_BEV_MODE_OBJECT && curve->bevobj != nullptr) {
656 return true;
657 }
658
659 /* 2D curves are sometimes implicitly filled and converted to a mesh. */
660 if (CU_DO_2DFILL(curve)) {
661 return true;
662 }
663
664 /* Curve objects with implicit "tube" meshes should convert implicitly to a mesh. */
665 if (curve->extrude != 0.0f || curve->bevel_radius != 0.0f) {
666 return true;
667 }
668
669 /* If a non-geometry-nodes modifier is enabled before a nodes modifier,
670 * force conversion to mesh, since only the nodes modifier supports curve data. */
671 ModifierData *md = first_modifier;
672 for (; md; md = md->next) {
673 if (BKE_modifier_is_enabled(scene, md, required_mode)) {
674 if (md->type == eModifierType_Nodes) {
675 break;
676 }
677 return true;
678 }
679 }
680
681 return false;
682}
683
685 const Scene *scene,
686 Object *ob,
687 const ListBase *dispbase,
688 const bool for_render)
689{
690 const Curve *cu = (const Curve *)ob->data;
691 const bool editmode = (!for_render && (cu->editnurb || cu->editfont));
692 const bool use_cache = !for_render;
693
694 ModifierApplyFlag apply_flag = for_render ? MOD_APPLY_RENDER : ModifierApplyFlag(0);
695 ModifierMode required_mode = for_render ? eModifierMode_Render : eModifierMode_Realtime;
696 if (editmode) {
697 required_mode = ModifierMode(int(required_mode) | eModifierMode_Editmode);
698 }
699
700 const ModifierEvalContext mectx_deform = {
701 depsgraph, ob, editmode ? (apply_flag | MOD_APPLY_USECACHE) : apply_flag};
702 const ModifierEvalContext mectx_apply = {
703 depsgraph, ob, use_cache ? (apply_flag | MOD_APPLY_USECACHE) : apply_flag};
704
705 ModifierData *pretessellatePoint = curve_get_tessellate_point(scene, ob, for_render, editmode);
706
707 VirtualModifierData virtual_modifier_data;
708 ModifierData *md = pretessellatePoint == nullptr ?
709 BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data) :
710 pretessellatePoint->next;
711
712 blender::bke::GeometrySet geometry_set;
713 if (ob->type == OB_SURF || do_curve_implicit_mesh_conversion(cu, md, scene, required_mode)) {
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 = (int *)MEM_mallocN(sizeof(int[4]) * (dl->parts + 1) * (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_cnew<DispList>(__func__);
824 dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), __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_cnew<DispList>(__func__);
847 dl->verts = (float *)MEM_mallocN(len * sizeof(float[3]), __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_cnew<DispList>(__func__);
949 dl->verts = (float *)MEM_mallocN(sizeof(float[3]) * 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_cnew<DispList>("makeDispListbev");
1151 dl->verts = (float *)MEM_mallocN(sizeof(float[3]) * 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_cnew<DispList>(__func__);
1201 dl->verts = data = (float *)MEM_mallocN(sizeof(float[3]) * dlb->nr * steps, __func__);
1202 BLI_addtail(r_dispbase, dl);
1203
1204 dl->type = DL_SURF;
1205
1206 dl->flag = dlb->flag & (DL_FRONT_CURVE | DL_BACK_CURVE);
1207 if (dlb->type == DL_POLY) {
1208 dl->flag |= DL_CYCL_U;
1209 }
1210 if ((bl->poly >= 0) && (steps > 2)) {
1211 dl->flag |= DL_CYCL_V;
1212 }
1213
1214 dl->parts = steps;
1215 dl->nr = dlb->nr;
1216 dl->col = nu->mat_nr;
1217 dl->charidx = nu->charidx;
1218 dl->rt = nu->flag;
1219
1220 /* for each point of poly make a bevel piece */
1221 BevPoint *bevp_first = bl->bevpoints;
1222 BevPoint *bevp_last = &bl->bevpoints[bl->nr - 1];
1223 BevPoint *bevp = &bl->bevpoints[start];
1224 for (int i = start, a = 0; a < steps; i++, bevp++, a++) {
1225 float radius_factor = 1.0;
1226 float *cur_data = data;
1227
1228 if (cu->taperobj == nullptr) {
1229 radius_factor = bevp->radius;
1230 }
1231 else {
1232 float taper_factor;
1233 if (cu->flag & CU_MAP_TAPER) {
1234 float len = (steps - 3) + first_blend + last_blend;
1235
1236 if (a == 0) {
1237 taper_factor = 0.0f;
1238 }
1239 else if (a == steps - 1) {
1240 taper_factor = 1.0f;
1241 }
1242 else {
1243 taper_factor = (float(a) - (1.0f - first_blend)) / len;
1244 }
1245 }
1246 else {
1247 float len = bl->nr - 1;
1248 taper_factor = float(i) / len;
1249
1250 if (a == 0) {
1251 taper_factor += (1.0f - first_blend) / len;
1252 }
1253 else if (a == steps - 1) {
1254 taper_factor -= (1.0f - last_blend) / len;
1255 }
1256 }
1257
1258 radius_factor = displist_calc_taper(depsgraph, scene, cu->taperobj, taper_factor);
1259
1261 radius_factor *= bevp->radius;
1262 }
1263 else if (cu->taper_radius_mode == CU_TAPER_RADIUS_ADD) {
1264 radius_factor += bevp->radius;
1265 }
1266 }
1267
1268 /* rotate bevel piece and write in data */
1269 if ((a == 0) && (bevp != bevp_last)) {
1271 cu, bevp, bevp + 1, dlb, 1.0f - first_blend, widfac, radius_factor, &data);
1272 }
1273 else if ((a == steps - 1) && (bevp != bevp_first)) {
1275 cu, bevp, bevp - 1, dlb, 1.0f - last_blend, widfac, radius_factor, &data);
1276 }
1277 else {
1278 rotateBevelPiece(cu, bevp, nullptr, dlb, 0.0f, widfac, radius_factor, &data);
1279 }
1280
1281 if ((cu->flag & CU_FILL_CAPS) && !(nu->flagu & CU_NURB_CYCLIC)) {
1282 if (a == 1) {
1283 fillBevelCap(nu, dlb, cur_data - 3 * dlb->nr, &bottom_capbase);
1284 copy_v3_v3(bottom_no, bevp->dir);
1285 }
1286 if (a == steps - 1) {
1287 fillBevelCap(nu, dlb, cur_data, &top_capbase);
1288 negate_v3_v3(top_no, bevp->dir);
1289 }
1290 }
1291 }
1292
1293 /* gl array drawing: using indices */
1295 }
1296
1297 if (bottom_capbase.first) {
1298 BKE_displist_fill(&bottom_capbase, r_dispbase, bottom_no, false);
1299 BKE_displist_fill(&top_capbase, r_dispbase, top_no, false);
1300 BKE_displist_free(&bottom_capbase);
1301 BKE_displist_free(&top_capbase);
1302 }
1303 }
1304 }
1305 }
1306
1307 BKE_displist_free(&dlbev);
1308
1309 curve_to_filledpoly(cu, r_dispbase);
1310 return curve_calc_modifiers_post(depsgraph, scene, ob, r_dispbase, for_render);
1311}
1312
1314 const Scene *scene,
1315 Object *ob,
1316 const bool for_render)
1317{
1319
1321
1322 /* It's important to retrieve this after calling #BKE_object_free_derived_caches,
1323 * which may reset the object data pointer in some cases. */
1324 const Curve &original_curve = *static_cast<const Curve *>(ob->data);
1325
1326 ob->runtime->curve_cache = MEM_cnew<CurveCache>(__func__);
1327 ListBase *dispbase = &ob->runtime->curve_cache->disp;
1328
1329 if (ob->type == OB_SURF) {
1331 depsgraph, scene, ob, for_render, dispbase);
1332 ob->runtime->geometry_set_eval = new blender::bke::GeometrySet(std::move(geometry));
1333 }
1334 else {
1336 depsgraph, scene, ob, for_render, dispbase);
1337
1338 if (geometry.has_curves()) {
1339 /* Create a copy of the original curve and add necessary pointers to evaluated and edit mode
1340 * data. This is needed for a few reasons:
1341 * - Existing code from before curve evaluation was changed to use #GeometrySet expected to
1342 * have a copy of the original curve data. (Any evaluated data was placed in
1343 * #Object.runtime->curve_cache).
1344 * - The result of modifier evaluation is not a #Curve data-block but a #Curves data-block,
1345 * which can support constructive modifiers and geometry nodes.
1346 * - The dependency graph has handling of edit mode pointers (see #update_edit_mode_pointers)
1347 * but it doesn't seem to work in this case.
1348 *
1349 * Since the plan is to replace this legacy curve object with the curves data-block
1350 * (see #95355), this somewhat hacky inefficient solution is relatively temporary.
1351 */
1352 Curve &cow_curve = *reinterpret_cast<Curve *>(
1353 BKE_id_copy_ex(nullptr, &original_curve.id, nullptr, LIB_ID_COPY_LOCALIZE));
1354 cow_curve.curve_eval = geometry.get_curves();
1355 /* Copy edit mode pointers necessary for drawing to the duplicated curve. */
1356 cow_curve.editnurb = original_curve.editnurb;
1357 cow_curve.editfont = original_curve.editfont;
1358 cow_curve.edit_data_from_original = true;
1359 BKE_object_eval_assign_data(ob, &cow_curve.id, true);
1360 }
1361
1362 ob->runtime->geometry_set_eval = new blender::bke::GeometrySet(std::move(geometry));
1363 }
1364}
1365
1366void BKE_displist_minmax(const ListBase *dispbase, float min[3], float max[3])
1367{
1368 bool empty = true;
1369
1370 LISTBASE_FOREACH (const DispList *, dl, dispbase) {
1371 const int tot = dl->type == DL_INDEX3 ? dl->nr : dl->nr * dl->parts;
1372 for (const int i : IndexRange(tot)) {
1373 minmax_v3v3_v3(min, max, &dl->verts[i * 3]);
1374 }
1375 if (tot != 0) {
1376 empty = false;
1377 }
1378 }
1379
1380 if (empty) {
1381 zero_v3(min);
1382 zero_v3(max);
1383 }
1384}
void BKE_anim_path_calc_data(struct Object *ob)
Definition anim_path.cc:59
const ListBase * BKE_curve_editNurbs_get_for_read(const Curve *cu)
Definition curve.cc:407
void BKE_nurb_makeFaces(const Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv)
Definition curve.cc:1269
#define CU_DO_2DFILL(cu)
Definition BKE_curve.hh:89
const ListBase * BKE_curve_nurbs_get_for_read(const Curve *cu)
Definition curve.cc:4974
bool BKE_nurb_check_valid_uv(const Nurb *nu)
Definition curve.cc:4789
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:1461
void BKE_curve_nurbs_key_vert_tilts_apply(ListBase *lb, const float *key)
Definition curve.cc:4672
void BKE_nurbList_duplicate(ListBase *lb1, const ListBase *lb2)
Definition curve.cc:673
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:1663
void BKE_curve_nurbs_vert_coords_apply(ListBase *lb, const float(*vert_coords)[3], bool constrain_2d)
Definition curve.cc:4602
bool BKE_nurb_check_valid_u(const Nurb *nu)
Definition curve.cc:4773
#define SEGMENTSU(nu)
Definition BKE_curve.hh:77
float(* BKE_curve_nurbs_key_vert_coords_alloc(const ListBase *lb, float *key, int *r_vert_len))[3]
Definition curve.cc:4638
void BKE_curve_bevelList_make(Object *ob, const ListBase *nurbs, bool for_render)
Definition curve.cc:2528
float(* BKE_curve_nurbs_vert_coords_alloc(const ListBase *lb, int *r_vert_len))[3]
Definition curve.cc:4555
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:2029
float * BKE_key_evaluate_object(Object *ob, int *r_totelem)
Definition key.cc:1645
@ LIB_ID_COPY_LOCALIZE
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:760
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:69
bool BKE_vfont_to_curve_nubase(Object *ob, eEditFontMode mode, ListBase *r_nubase)
Definition vfont.cc:2036
#define BLI_assert(a)
Definition BLI_assert.h:50
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:90
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:251
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])
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)
Definition math_vector.c:36
MINLINE void zero_v3(float r[3])
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
struct MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
@ 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.c:95
struct ScanFillEdge * BLI_scanfill_edge_add(ScanFillContext *sf_ctx, struct ScanFillVert *v1, struct ScanFillVert *v2)
Definition scanfill.c:117
void BLI_scanfill_begin_arena(ScanFillContext *sf_ctx, struct MemArena *arena)
Definition scanfill.c:798
unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, int flag, const float nor_proj[3])
Definition scanfill.c:825
#define BLI_SCANFILL_ARENA_SIZE
void BLI_scanfill_end_arena(ScanFillContext *sf_ctx, struct MemArena *arena)
Definition scanfill.c:815
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define ELEM(...)
@ DAG_EVAL_NEED_CURVE_PATH
uint32_t DEG_get_eval_flags_for_id(const Depsgraph *graph, const ID *id)
@ ID_ME
@ CU_TAPER_RADIUS_MULTIPLY
@ CU_TAPER_RADIUS_ADD
@ CU_SMOOTH
@ CU_BEZIER
@ CU_POLY
@ CU_NURBS
@ CU_FILL_CAPS
@ CU_FAST
@ CU_3D
@ CU_FRONT
@ CU_PATH
@ CU_MAP_TAPER
@ CU_BACK
@ CU_BEV_MODE_OBJECT
@ HD_VECT
@ CU_BEVFAC_MAP_SPLINE
@ CU_BEVFAC_MAP_RESOLU
@ CU_BEVFAC_MAP_SEGMENT
@ CU_NURB_CYCLIC
@ 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.
local_group_size(16, 16) .push_constant(Type b
const Depsgraph * depsgraph
#define fabsf(x)
static void displist_surf_indices(DispList *dl)
Definition displist.cc:761
static bool do_curve_implicit_mesh_conversion(const Curve *curve, ModifierData *first_modifier, const Scene *scene, const ModifierMode required_mode)
Definition displist.cc:644
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:1313
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:684
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 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:1366
int len
static bool is_cyclic(const Nurb *nu)
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
uint col
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
Curves * curve_legacy_to_curves(const Curve &curve_legacy)
static const int steps
#define min(a, b)
Definition sort.c:32
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]
char edit_data_from_original
float bevfac2
const struct Curves * curve_eval
struct EditFont * editfont
char bevfac2_mapping
short resolv_ren
float bevfac1
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[66]
Definition DNA_ID.h:425
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
void replace_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)