Blender V5.0
draw_cache_impl_curve.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2017 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include "MEM_guardedalloc.h"
12
13#include "BLI_color.hh"
14#include "BLI_listbase.h"
15#include "BLI_math_rotation.h"
17#include "BLI_span.hh"
18#include "BLI_utildefines.h"
19
20#include "DNA_curve_types.h"
21#include "DNA_object_types.h"
22#include "DNA_scene_types.h"
23
24#include "BKE_curve.hh"
25#include "BKE_curves.hh"
26#include "BKE_geometry_set.hh"
27#include "BKE_object_types.hh"
28#include "BKE_vfont.hh"
29
31#include "GPU_batch.hh"
32#include "GPU_capabilities.hh"
33#include "GPU_texture.hh"
34
35#include "UI_resources.hh"
36
37#include "DRW_render.hh"
38
39#include "draw_cache_inline.hh"
40
41#include "draw_cache_impl.hh" /* own include */
42
43namespace blender::draw {
44
45/* See: edit_curve_point_vert.glsl for duplicate includes. */
46#define SELECT 1
47#define ACTIVE_NURB (1 << 2)
48#define BEZIER_HANDLE (1 << 3)
49#define EVEN_U_BIT (1 << 4) /* Alternate this bit for every U vert. */
50#define COLOR_SHIFT 5
51
52/* Used as values of `color_id` in `edit_curve_overlay_handle_geom.glsl` */
53enum {
55
57};
58
65
66static void curve_batch_cache_clear(Curve *cu);
67
68/* ---------------------------------------------------------------------- */
69/* Curve Interface, direct access to basic data. */
70
72 int *r_vert_len,
73 int *r_edge_len)
74{
75 BLI_assert(r_vert_len || r_edge_len);
76 int vert_len = 0;
77 int edge_len = 0;
78 LISTBASE_FOREACH (Nurb *, nu, lb) {
79 if (nu->bezt) {
80 vert_len += nu->pntsu * 3;
81 /* 2x handles per point. */
82 edge_len += 2 * nu->pntsu;
83 }
84 else if (nu->bp) {
85 vert_len += nu->pntsu * nu->pntsv;
86 /* segments between points */
87 edge_len += (nu->pntsu - 1) * nu->pntsv;
88 edge_len += (nu->pntsv - 1) * nu->pntsu;
89 }
90 }
91 if (r_vert_len) {
92 *r_vert_len = vert_len;
93 }
94 if (r_edge_len) {
95 *r_edge_len = edge_len;
96 }
97}
98
100 int *r_curve_len,
101 int *r_vert_len,
102 int *r_edge_len)
103{
104 const OffsetIndices points_by_curve = curves.evaluated_points_by_curve();
105 const VArray<bool> cyclic = curves.cyclic();
106
107 *r_curve_len = curves.curves_num();
108 *r_vert_len = points_by_curve.total_size();
109 *r_edge_len = 0;
110 for (const int i : curves.curves_range()) {
111 *r_edge_len += bke::curves::segments_num(points_by_curve[i].size(), cyclic[i]);
112 }
113}
114
115static int curve_render_normal_len_get(const ListBase *lb, const CurveCache *ob_curve_cache)
116{
117 int normal_len = 0;
118 const BevList *bl;
119 const Nurb *nu;
120 for (bl = (const BevList *)ob_curve_cache->bev.first, nu = (const Nurb *)lb->first; nu && bl;
121 bl = bl->next, nu = nu->next)
122 {
123 int nr = bl->nr;
124 int skip = nu->resolu / 16;
125#if 0
126 while (nr-- > 0) { /* accounts for empty bevel lists */
127 normal_len += 1;
128 nr -= skip;
129 }
130#else
131 /* Same as loop above */
132 normal_len += (nr / (skip + 1)) + ((nr % (skip + 1)) != 0);
133#endif
134 }
135 return normal_len;
136}
137
138/* ---------------------------------------------------------------------- */
139/* Curve Interface, indirect, partially cached access to complex data. */
140
142 int types;
143
144 struct {
148
149 struct {
151 int vert_len;
152 int edge_len;
154
155 /* edit mode normal's */
156 struct {
157 /* 'edge_len == len * 2'
158 * 'vert_len == len * 3' */
159 int len;
161
162 struct {
165
166 /* borrow from 'Object' */
168
169 /* Owned by the evaluated object's geometry set (#geometry_set_eval). */
171
172 /* borrow from 'Curve' */
174
175 /* edit, index in nurb list */
176 int actnu;
177 /* edit, index in active nurb (BPoint or BezTriple) */
179};
180
181enum {
182 /* Wire center-line */
184 /* Edit-mode verts and optionally handles */
186 /* Edit-mode normals */
188 /* Geometry */
190 /* Text */
192};
193
198 CurveCache *ob_curve_cache,
199 const int types)
200{
201 CurveRenderData *rdata = (CurveRenderData *)MEM_callocN(sizeof(*rdata), __func__);
202 rdata->types = types;
203 ListBase *nurbs;
204
205 rdata->actnu = cu->actnu;
206 rdata->actvert = cu->actvert;
207
208 rdata->ob_curve_cache = ob_curve_cache;
209
210 rdata->curve_eval = cu->curve_eval;
211
212 if (types & CU_DATATYPE_WIRE) {
213 if (rdata->curve_eval != nullptr) {
215 &rdata->wire.curve_len,
216 &rdata->wire.vert_len,
217 &rdata->wire.edge_len);
218 }
219 }
220
221 if (cu->editnurb) {
222 EditNurb *editnurb = cu->editnurb;
223 nurbs = &editnurb->nurbs;
224
227 nurbs, &rdata->overlay.vert_len, &rdata->overlay.edge_len);
228
229 rdata->actnu = cu->actnu;
230 rdata->actvert = cu->actvert;
231 }
234 }
235 }
236 else {
237 nurbs = &cu->nurb;
238 }
239
240 rdata->nurbs = nurbs;
241
242 rdata->text.edit_font = cu->editfont;
243
244 return rdata;
245}
246
248{
249#if 0
250 if (rdata->loose_verts) {
251 MEM_freeN(rdata->loose_verts);
252 }
253#endif
254 MEM_freeN(rdata);
255}
256
258{
260 return rdata->overlay.vert_len;
261}
262
264{
266 return rdata->overlay.edge_len;
267}
268
270{
272 return rdata->wire.vert_len;
273}
274
276{
278 return rdata->wire.edge_len;
279}
280
282{
284 return rdata->wire.curve_len;
285}
286
288{
290 return rdata->normal.len;
291}
292
293/* ---------------------------------------------------------------------- */
294/* Curve gpu::Batch Cache */
295
297 struct {
301
302 struct {
304 /* Edit points (beztriples and bpoints) */
308
309 struct {
311 /* Edit mode */
315
316 struct {
317 gpu::Batch *curves;
319 /* control handles and vertices */
320 gpu::Batch *edit_edges;
321 gpu::Batch *edit_verts;
322 gpu::Batch *edit_normals;
324
325 /* settings to determine if cache is invalid */
328};
329
330/* gpu::Batch cache management. */
331
333{
335
336 if (cache == nullptr) {
337 return false;
338 }
339
340 if (cache->is_dirty) {
341 return false;
342 }
343
344 if (cache->is_editmode != ((cu->editnurb != nullptr) || (cu->editfont != nullptr))) {
345 return false;
346 }
347
348 if (cache->is_editmode) {
349 if (cu->editfont) {
350 /* TODO */
351 }
352 }
353
354 return true;
355}
356
358{
360
361 if (!cache) {
362 cache = (CurveBatchCache *)MEM_callocN(sizeof(*cache), __func__);
363 cu->batch_cache = cache;
364 }
365 else {
366 memset(cache, 0, sizeof(*cache));
367 }
368
369#if 0
370 ListBase *nurbs;
371 if (cu->editnurb) {
372 EditNurb *editnurb = cu->editnurb;
373 nurbs = &editnurb->nurbs;
374 }
375 else {
376 nurbs = &cu->nurb;
377 }
378#endif
379
380 cache->is_editmode = (cu->editnurb != nullptr) || (cu->editfont != nullptr);
381
382 cache->is_dirty = false;
383}
384
392
397
399{
401 if (cache == nullptr) {
402 return;
403 }
404 switch (mode) {
406 cache->is_dirty = true;
407 break;
410
413 break;
414 default:
415 BLI_assert(0);
416 }
417}
418
420{
422 if (!cache) {
423 return;
424 }
425
426 for (int i = 0; i < sizeof(cache->ordered) / sizeof(void *); i++) {
427 gpu::VertBuf **vbo = (gpu::VertBuf **)&cache->ordered;
429 }
430 for (int i = 0; i < sizeof(cache->edit) / sizeof(void *); i++) {
431 gpu::VertBuf **vbo = (gpu::VertBuf **)&cache->edit;
433 }
434 for (int i = 0; i < sizeof(cache->ibo) / sizeof(void *); i++) {
435 gpu::IndexBuf **ibo = (gpu::IndexBuf **)&cache->ibo;
437 }
438 for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) {
439 gpu::Batch **batch = (gpu::Batch **)&cache->batch;
441 }
442}
443
449
450/* -------------------------------------------------------------------- */
453
454/* gpu::Batch cache usage. */
455static void curve_create_curves_pos(CurveRenderData *rdata, gpu::VertBuf *vbo_curves_pos)
456{
457 if (rdata->curve_eval == nullptr) {
458 return;
459 }
460
461 static struct {
462 uint pos;
463 } attr_id;
464
465 static const GPUVertFormat format = [&]() {
467 attr_id.pos = GPU_vertformat_attr_add(&format, "pos", gpu::VertAttrType::SFLOAT_32_32_32);
468 return format;
469 }();
470
471 const int vert_len = curve_render_data_wire_verts_len_get(rdata);
472 GPU_vertbuf_init_with_format(*vbo_curves_pos, format);
473 GPU_vertbuf_data_alloc(*vbo_curves_pos, vert_len);
474
475 const bke::CurvesGeometry &curves = rdata->curve_eval->geometry.wrap();
476 const Span<float3> positions = curves.evaluated_positions();
477 GPU_vertbuf_attr_fill(vbo_curves_pos, attr_id.pos, positions.data());
478}
479
481{
482 if (rdata->curve_eval == nullptr) {
483 return;
484 }
485
486 static const GPUVertFormat format = []() {
488 GPU_vertformat_attr_add(&format, "attribute_value", gpu::VertAttrType::SFLOAT_32_32_32_32);
489 return format;
490 }();
491
492 const int vert_len = curve_render_data_wire_verts_len_get(rdata);
494 GPU_vertbuf_data_alloc(vbo_attr, vert_len);
495
496 const bke::CurvesGeometry &curves = rdata->curve_eval->geometry.wrap();
498 const VArraySpan colors = *curves.attributes().lookup<ColorGeometry4f>(".viewer",
500 curves.interpolate_to_evaluated(colors, vbo_attr.data<ColorGeometry4f>());
501}
502
503static void curve_create_curves_lines(CurveRenderData *rdata, gpu::IndexBuf *ibo_curve_lines)
504{
505 if (rdata->curve_eval == nullptr) {
506 return;
507 }
508
509 const int vert_len = curve_render_data_wire_verts_len_get(rdata);
510 const int edge_len = curve_render_data_wire_edges_len_get(rdata);
511 const int curve_len = curve_render_data_wire_curve_len_get(rdata);
512 /* Count the last vertex or each strip and the primitive restart. */
513 const int index_len = edge_len + curve_len * 2;
514
516 GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, index_len, vert_len);
517
518 const bke::CurvesGeometry &curves = rdata->curve_eval->geometry.wrap();
519 const OffsetIndices points_by_curve = curves.evaluated_points_by_curve();
520 const VArray<bool> cyclic = curves.cyclic();
521
522 for (const int i : curves.curves_range()) {
523 const IndexRange points = points_by_curve[i];
524 if (cyclic[i] && points.size() > 1) {
525 GPU_indexbuf_add_generic_vert(&elb, points.last());
526 }
527 for (const int i_point : points) {
528 GPU_indexbuf_add_generic_vert(&elb, i_point);
529 }
531 }
532
533 GPU_indexbuf_build_in_place(&elb, ibo_curve_lines);
534}
535
537 gpu::VertBuf &vbo_curves_nor,
538 const Scene *scene)
539{
540 const bool do_hq_normals = (scene->r.perf_flag & SCE_PERF_HQ_NORMALS) != 0 ||
542
543 static struct {
544 uint pos, nor, tan, rad;
545 uint pos_hq, nor_hq, tan_hq, rad_hq;
546 } attr_id;
547
548 static const GPUVertFormat format = [&]() {
550 attr_id.pos = GPU_vertformat_attr_add(&format, "pos", gpu::VertAttrType::SFLOAT_32_32_32);
551 attr_id.rad = GPU_vertformat_attr_add(&format, "rad", gpu::VertAttrType::SFLOAT_32);
553 &format, "nor", blender::gpu::VertAttrType::SNORM_10_10_10_2);
555 &format, "tangent", blender::gpu::VertAttrType::SNORM_10_10_10_2);
556 return format;
557 }();
558
559 static const GPUVertFormat format_hq = [&]() {
561 attr_id.pos_hq = GPU_vertformat_attr_add(&format, "pos", gpu::VertAttrType::SFLOAT_32_32_32);
562 attr_id.rad_hq = GPU_vertformat_attr_add(&format, "rad", gpu::VertAttrType::SFLOAT_32);
563 attr_id.nor_hq = GPU_vertformat_attr_add(&format, "nor", gpu::VertAttrType::SNORM_16_16_16_16);
565 &format, "tangent", gpu::VertAttrType::SNORM_16_16_16_16);
566 return format;
567 }();
568
569 const GPUVertFormat &format_ptr = do_hq_normals ? format_hq : format;
570
571 int verts_len_capacity = curve_render_data_normal_len_get(rdata) * 2;
572 int vbo_len_used = 0;
573
574 GPU_vertbuf_init_with_format(vbo_curves_nor, format_ptr);
575 GPU_vertbuf_data_alloc(vbo_curves_nor, verts_len_capacity);
576
577 const BevList *bl;
578 const Nurb *nu;
579
580 const uint pos_id = do_hq_normals ? attr_id.pos_hq : attr_id.pos;
581 const uint nor_id = do_hq_normals ? attr_id.nor_hq : attr_id.nor;
582 const uint tan_id = do_hq_normals ? attr_id.tan_hq : attr_id.tan;
583 const uint rad_id = do_hq_normals ? attr_id.rad_hq : attr_id.rad;
584
585 for (bl = (const BevList *)rdata->ob_curve_cache->bev.first,
586 nu = (const Nurb *)rdata->nurbs->first;
587 nu && bl;
588 bl = bl->next, nu = nu->next)
589 {
590 const BevPoint *bevp = bl->bevpoints;
591 int nr = bl->nr;
592 int skip = nu->resolu / 16;
593
594 while (nr-- > 0) { /* accounts for empty bevel lists */
595 float nor[3] = {1.0f, 0.0f, 0.0f};
596 mul_qt_v3(bevp->quat, nor);
597
598 /* Only set attributes for one vertex. */
599 GPU_vertbuf_attr_set(&vbo_curves_nor, pos_id, vbo_len_used, bevp->vec);
600 GPU_vertbuf_attr_set(&vbo_curves_nor, rad_id, vbo_len_used, &bevp->radius);
601 if (do_hq_normals) {
603 const short4 ptan = gpu::convert_normal<short4>(bevp->dir);
604 GPU_vertbuf_attr_set(&vbo_curves_nor, nor_id, vbo_len_used, &pnor);
605 GPU_vertbuf_attr_set(&vbo_curves_nor, tan_id, vbo_len_used, &ptan);
606 }
607 else {
610 GPU_vertbuf_attr_set(&vbo_curves_nor, nor_id, vbo_len_used, &pnor);
611 GPU_vertbuf_attr_set(&vbo_curves_nor, tan_id, vbo_len_used, &ptan);
612 }
613 vbo_len_used++;
614
615 /* Skip the other vertex (it does not need to be offsetted). */
616 GPU_vertbuf_attr_set(&vbo_curves_nor, attr_id.pos, vbo_len_used, bevp->vec);
617 vbo_len_used++;
618
619 bevp += skip + 1;
620 nr -= skip;
621 }
622 }
623 BLI_assert(vbo_len_used == verts_len_capacity);
624}
625
627 uint8_t flag,
628 uint8_t col_id,
629 int v_idx,
630 int nu_id,
631 bool handle_point,
632 const bool handle_selected)
633{
634 uint8_t vflag = 0;
636 SET_FLAG_FROM_TEST(vflag, (v_idx == rdata->actvert && nu_id == rdata->actnu), VFLAG_VERT_ACTIVE);
637 SET_FLAG_FROM_TEST(vflag, (nu_id == rdata->actnu), ACTIVE_NURB);
638 SET_FLAG_FROM_TEST(vflag, handle_point, BEZIER_HANDLE);
640 /* Setting flags that overlap with will cause the color id not to work properly. */
641 BLI_assert((vflag >> COLOR_SHIFT) == 0);
642 /* handle color id */
643 vflag |= col_id << COLOR_SHIFT;
644 return vflag;
645}
646
647static uint8_t bpoint_vflag_get(CurveRenderData *rdata, uint8_t flag, int v_idx, int nu_id, int u)
648{
649 uint8_t vflag = 0;
651 SET_FLAG_FROM_TEST(vflag, (v_idx == rdata->actvert && nu_id == rdata->actnu), VFLAG_VERT_ACTIVE);
652 SET_FLAG_FROM_TEST(vflag, (nu_id == rdata->actnu), ACTIVE_NURB);
653 SET_FLAG_FROM_TEST(vflag, ((u % 2) == 0), EVEN_U_BIT);
654 /* Setting flags that overlap with will cause the color id not to work properly. */
655 BLI_assert((vflag >> COLOR_SHIFT) == 0);
657 return vflag;
658}
659
661 gpu::VertBuf *vbo_pos,
662 gpu::VertBuf *vbo_data,
663 gpu::IndexBuf *ibo_edit_verts_points,
664 gpu::IndexBuf *ibo_edit_lines)
665{
666 static struct {
667 uint pos, data;
668 } attr_id;
669
670 static const GPUVertFormat format_pos = [&]() {
672 attr_id.pos = GPU_vertformat_attr_add(&format, "pos", gpu::VertAttrType::SFLOAT_32_32_32);
673 return format;
674 }();
675
676 static const GPUVertFormat format_data = [&]() {
678 attr_id.data = GPU_vertformat_attr_add(&format, "data", gpu::VertAttrType::UINT_32);
679 return format;
680 }();
681
682 int verts_len_capacity = curve_render_data_overlay_verts_len_get(rdata);
683 int edges_len_capacity = curve_render_data_overlay_edges_len_get(rdata) * 2;
684 int vbo_len_used = 0;
685
686#define DRW_TEST_ASSIGN_VBO(v) (v = (DRW_vbo_requested(v) ? (v) : nullptr))
687#define DRW_TEST_ASSIGN_IBO(v) (v = (DRW_ibo_requested(v) ? (v) : nullptr))
688
689 if (DRW_TEST_ASSIGN_VBO(vbo_pos)) {
690 GPU_vertbuf_init_with_format(*vbo_pos, format_pos);
691 GPU_vertbuf_data_alloc(*vbo_pos, verts_len_capacity);
692 }
693 if (DRW_TEST_ASSIGN_VBO(vbo_data)) {
694 GPU_vertbuf_init_with_format(*vbo_data, format_data);
695 GPU_vertbuf_data_alloc(*vbo_data, verts_len_capacity);
696 }
697
698 GPUIndexBufBuilder elb_verts, *elbp_verts = nullptr;
699 GPUIndexBufBuilder elb_lines, *elbp_lines = nullptr;
700 if (DRW_TEST_ASSIGN_IBO(ibo_edit_verts_points)) {
701 elbp_verts = &elb_verts;
702 GPU_indexbuf_init(elbp_verts, GPU_PRIM_POINTS, verts_len_capacity, verts_len_capacity);
703 }
704 if (DRW_TEST_ASSIGN_IBO(ibo_edit_lines)) {
705 elbp_lines = &elb_lines;
706 GPU_indexbuf_init(elbp_lines, GPU_PRIM_LINES, edges_len_capacity, verts_len_capacity);
707 }
708
709#undef DRW_TEST_ASSIGN_VBO
710#undef DRW_TEST_ASSIGN_IBO
711
712 int nu_id = 0;
713 for (Nurb *nu = (Nurb *)rdata->nurbs->first; nu; nu = nu->next, nu_id++) {
714 const BezTriple *bezt = nu->bezt;
715 const BPoint *bp = nu->bp;
716
717 if (bezt) {
718 for (int a = 0; a < nu->pntsu; a++, bezt++) {
719 if (bezt->hide != 0) {
720 continue;
721 }
722 const bool handle_selected = BEZT_ISSEL_ANY(bezt);
723
724 if (elbp_verts) {
725 GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used + 0);
726 GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used + 1);
727 GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used + 2);
728 }
729 if (elbp_lines) {
730 GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used + 1, vbo_len_used + 0);
731 GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used + 1, vbo_len_used + 2);
732 }
733 if (vbo_data) {
734 const uint32_t vflag[3] = {
735 beztriple_vflag_get(rdata, bezt->f1, bezt->h1, a, nu_id, true, handle_selected),
736 beztriple_vflag_get(rdata, bezt->f2, bezt->h1, a, nu_id, false, handle_selected),
737 beztriple_vflag_get(rdata, bezt->f3, bezt->h2, a, nu_id, true, handle_selected),
738 };
739 for (int j = 0; j < 3; j++) {
740 GPU_vertbuf_attr_set(vbo_data, attr_id.data, vbo_len_used + j, &vflag[j]);
741 }
742 }
743 if (vbo_pos) {
744 for (int j = 0; j < 3; j++) {
745 GPU_vertbuf_attr_set(vbo_pos, attr_id.pos, vbo_len_used + j, bezt->vec[j]);
746 }
747 }
748 vbo_len_used += 3;
749 }
750 }
751 else if (bp) {
752 int pt_len = nu->pntsu * nu->pntsv;
753 for (int a = 0; a < pt_len; a++, bp++, vbo_len_used += 1) {
754 if (bp->hide != 0) {
755 continue;
756 }
757 int u = (a % nu->pntsu);
758 int v = (a / nu->pntsu);
759 /* Use indexed rendering for bezier.
760 * Specify all points and use indices to hide/show. */
761 if (elbp_verts) {
762 GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used);
763 }
764 if (elbp_lines) {
765 const BPoint *bp_next_u = (u < (nu->pntsu - 1)) ? &nu->bp[a + 1] : nullptr;
766 const BPoint *bp_next_v = (v < (nu->pntsv - 1)) ? &nu->bp[a + nu->pntsu] : nullptr;
767 if (bp_next_u && (bp_next_u->hide == false)) {
768 GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used, vbo_len_used + 1);
769 }
770 if (bp_next_v && (bp_next_v->hide == false)) {
771 GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used, vbo_len_used + nu->pntsu);
772 }
773 }
774 if (vbo_data) {
775 uint32_t vflag = bpoint_vflag_get(rdata, bp->f1, a, nu_id, u);
776 GPU_vertbuf_attr_set(vbo_data, attr_id.data, vbo_len_used, &vflag);
777 }
778 if (vbo_pos) {
779 GPU_vertbuf_attr_set(vbo_pos, attr_id.pos, vbo_len_used, bp->vec);
780 }
781 }
782 }
783 }
784
785 /* Resize & Finish */
786 if (elbp_verts != nullptr) {
787 GPU_indexbuf_build_in_place(elbp_verts, ibo_edit_verts_points);
788 }
789 if (elbp_lines != nullptr) {
790 GPU_indexbuf_build_in_place(elbp_lines, ibo_edit_lines);
791 }
792 if (vbo_len_used != verts_len_capacity) {
793 if (vbo_pos != nullptr) {
794 GPU_vertbuf_data_resize(*vbo_pos, vbo_len_used);
795 }
796 if (vbo_data != nullptr) {
797 GPU_vertbuf_data_resize(*vbo_data, vbo_len_used);
798 }
799 }
800}
801
803
804/* -------------------------------------------------------------------- */
807
809{
811 return DRW_batch_request(&cache->batch.curves);
812}
813
819
825
831
837
839
840/* -------------------------------------------------------------------- */
843
845{
847
848 Curve *cu = (Curve *)ob->data;
850
851 /* Init batches and request VBOs & IBOs */
855 }
860 }
861
862 /* Edit mode */
865 DRW_vbo_request(cache->batch.edit_edges, &cache->edit.pos);
866 DRW_vbo_request(cache->batch.edit_edges, &cache->edit.data);
867 }
870 DRW_vbo_request(cache->batch.edit_verts, &cache->edit.pos);
871 DRW_vbo_request(cache->batch.edit_verts, &cache->edit.data);
872 }
875 }
876
877#ifdef DRW_DEBUG_MESH_CACHE_REQUEST
878 printf("-- %s %s --\n", __func__, ob->id.name + 2);
879#endif
880
881 /* Generate MeshRenderData flags */
882 int mr_flag = 0;
887
893
894#ifdef DRW_DEBUG_MESH_CACHE_REQUEST
895 printf(" mr_flag %d\n\n", mr_flag);
896#endif
897
898 CurveRenderData *rdata = curve_render_data_create(cu, ob->runtime->curve_cache, mr_flag);
899
900 /* Generate VBOs */
903 }
906 }
907 if (DRW_ibo_requested(cache->ibo.curves_lines)) {
909 }
910 if (DRW_vbo_requested(cache->edit.pos) || DRW_vbo_requested(cache->edit.data) ||
912 {
914 rdata, cache->edit.pos, cache->edit.data, cache->ibo.edit_verts, cache->ibo.edit_lines);
915 }
916 if (DRW_vbo_requested(cache->edit.curves_nor)) {
917 curve_create_edit_curves_nor(rdata, *cache->edit.curves_nor, scene);
918 }
919
921
922#ifndef NDEBUG
923 /* Make sure all requested batches have been setup. */
924 for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) {
925 BLI_assert(!DRW_batch_requested(((gpu::Batch **)&cache->batch)[i], (GPUPrimType)0));
926 }
927#endif
928}
929
931
932} // namespace blender::draw
@ BKE_CURVE_BATCH_DIRTY_SELECT
Definition BKE_curve.hh:380
@ BKE_CURVE_BATCH_DIRTY_ALL
Definition BKE_curve.hh:379
Low-level operations for curves.
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
void mul_qt_v3(const float q[4], float r[3])
unsigned int uint
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define BEZT_ISSEL_ANY(bezt)
Object is a sort of wrapper for general info.
@ OB_SURF
@ OB_FONT
@ OB_CURVES_LEGACY
@ SCE_PERF_HQ_NORMALS
#define GPU_BATCH_DISCARD_SAFE(batch)
Definition GPU_batch.hh:197
bool GPU_use_hq_normals_workaround()
#define GPU_INDEXBUF_DISCARD_SAFE(elem)
void GPU_indexbuf_init(GPUIndexBufBuilder *, GPUPrimType, uint prim_len, uint vertex_len)
void GPU_indexbuf_add_primitive_restart(GPUIndexBufBuilder *)
void GPU_indexbuf_add_point_vert(GPUIndexBufBuilder *, uint v)
void GPU_indexbuf_add_line_verts(GPUIndexBufBuilder *, uint v1, uint v2)
void GPU_indexbuf_add_generic_vert(GPUIndexBufBuilder *, uint v)
void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *, blender::gpu::IndexBuf *)
void GPU_indexbuf_init_ex(GPUIndexBufBuilder *, GPUPrimType, uint index_len, uint vertex_len)
GPUPrimType
@ GPU_PRIM_LINES
@ GPU_PRIM_POINTS
@ GPU_PRIM_LINE_STRIP
void GPU_vertbuf_data_resize(blender::gpu::VertBuf &verts, uint v_len)
void GPU_vertbuf_attr_fill(blender::gpu::VertBuf *, uint a_idx, const void *data)
void GPU_vertbuf_attr_set(blender::gpu::VertBuf *, uint a_idx, uint v_idx, const void *data)
#define GPU_vertbuf_init_with_format(verts, format)
#define GPU_VERTBUF_DISCARD_SAFE(verts)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
uint GPU_vertformat_attr_add(GPUVertFormat *format, blender::StringRef name, blender::gpu::VertAttrType type)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
@ TH_HANDLE_FREE
@ TH_HANDLE_AUTOCLAMP
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr const T * data() const
Definition BLI_span.hh:215
GAttributeReader lookup(const StringRef attribute_id) const
void ensure_can_interpolate_to_evaluated() const
IndexRange curves_range() const
void interpolate_to_evaluated(int curve_index, GSpan src, GMutableSpan dst) const
OffsetIndices< int > evaluated_points_by_curve() const
AttributeAccessor attributes() const
Span< float3 > evaluated_positions() const
VArray< bool > cyclic() const
MutableSpan< T > data()
#define SELECT
#define DRW_TEST_ASSIGN_VBO(v)
#define EVEN_U_BIT
#define DRW_TEST_ASSIGN_IBO(v)
#define COLOR_SHIFT
#define BEZIER_HANDLE
#define ACTIVE_NURB
bool DRW_batch_requested(blender::gpu::Batch *batch, GPUPrimType prim_type)
#define DRW_ADD_FLAG_FROM_IBO_REQUEST(flag, ibo, value)
#define DRW_ADD_FLAG_FROM_VBO_REQUEST(flag, vbo, value)
blender::gpu::Batch * DRW_batch_request(blender::gpu::Batch **batch)
void DRW_vbo_request(blender::gpu::Batch *batch, blender::gpu::VertBuf **vbo)
bool DRW_vbo_requested(blender::gpu::VertBuf *vbo)
void DRW_ibo_request(blender::gpu::Batch *batch, blender::gpu::IndexBuf **ibo)
bool DRW_ibo_requested(blender::gpu::IndexBuf *ibo)
struct @021025263243242147216143265077100330027142264337::@225245033123204053237120173316075113304004012000 batch
uint pos
uint nor
struct @021025263243242147216143265077100330027142264337::@240232116316110053135047106323056371161236243121 attr_id
#define printf(...)
format
static char ** types
Definition makesdna.cc:71
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
int segments_num(const int points_num, const bool cyclic)
static void curve_batch_cache_init(Curve *cu)
static void curve_create_curves_lines(CurveRenderData *rdata, gpu::IndexBuf *ibo_curve_lines)
static uint8_t beztriple_vflag_get(CurveRenderData *rdata, uint8_t flag, uint8_t col_id, int v_idx, int nu_id, bool handle_point, const bool handle_selected)
blender::gpu::Batch * DRW_curve_batch_cache_get_wire_edge(Curve *cu)
blender::gpu::Batch * DRW_curve_batch_cache_get_edit_verts(Curve *cu)
static int curve_render_data_wire_verts_len_get(const CurveRenderData *rdata)
static int curve_render_data_normal_len_get(const CurveRenderData *rdata)
blender::gpu::Batch * DRW_curve_batch_cache_get_edit_edges(Curve *cu)
void DRW_curve_batch_cache_validate(Curve *cu)
static void curve_create_curves_pos(CurveRenderData *rdata, gpu::VertBuf *vbo_curves_pos)
void DRW_curve_batch_cache_create_requested(Object *ob, const Scene *scene)
static int curve_render_data_overlay_edges_len_get(const CurveRenderData *rdata)
blender::gpu::Batch * DRW_curve_batch_cache_get_normal_edge(Curve *cu)
static void curve_render_overlay_verts_edges_len_get(ListBase *lb, int *r_vert_len, int *r_edge_len)
static int curve_render_data_overlay_verts_len_get(const CurveRenderData *rdata)
static void curve_batch_cache_clear(Curve *cu)
void DRW_curve_batch_cache_free(Curve *cu)
static CurveRenderData * curve_render_data_create(Curve *cu, CurveCache *ob_curve_cache, const int types)
static void curve_create_edit_data_and_handles(CurveRenderData *rdata, gpu::VertBuf *vbo_pos, gpu::VertBuf *vbo_data, gpu::IndexBuf *ibo_edit_verts_points, gpu::IndexBuf *ibo_edit_lines)
static void curve_render_data_free(CurveRenderData *rdata)
static void curve_create_edit_curves_nor(CurveRenderData *rdata, gpu::VertBuf &vbo_curves_nor, const Scene *scene)
static void curve_eval_render_wire_verts_edges_len_get(const bke::CurvesGeometry &curves, int *r_curve_len, int *r_vert_len, int *r_edge_len)
static CurveBatchCache * curve_batch_cache_get(Curve *cu)
static int curve_render_data_wire_edges_len_get(const CurveRenderData *rdata)
static void curve_create_attribute(CurveRenderData *rdata, gpu::VertBuf &vbo_attr)
static bool curve_batch_cache_valid(Curve *cu)
static uint8_t bpoint_vflag_get(CurveRenderData *rdata, uint8_t flag, int v_idx, int nu_id, int u)
static int curve_render_data_wire_curve_len_get(const CurveRenderData *rdata)
blender::gpu::Batch * DRW_curve_batch_cache_get_wire_edge_viewer_attribute(Curve *cu)
static int curve_render_normal_len_get(const ListBase *lb, const CurveCache *ob_curve_cache)
void DRW_curve_batch_cache_dirty_tag(Curve *cu, int mode)
GPUType convert_normal(const float3 &src)
T tan(const AngleRadianBase< T > &a)
blender::VecBase< int16_t, 4 > short4
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
struct BevList * next
BevPoint * bevpoints
float dir[3]
float quat[4]
float vec[3]
float vec[3][3]
ListBase bev
Definition BKE_curve.hh:41
void * batch_cache
const struct Curves * curve_eval
struct EditFont * editfont
EditNurb * editnurb
ListBase nurb
CurvesGeometry geometry
ListBase nurbs
char name[258]
Definition DNA_ID.h:432
void * first
struct Nurb * next
short resolu
ObjectRuntimeHandle * runtime
struct RenderData r
struct blender::draw::CurveBatchCache::@312205073163315253307202052205133100013110033055 edit
struct blender::draw::CurveBatchCache::@315126015106367235231311237374341020143156112115 batch
struct blender::draw::CurveBatchCache::@073053223252371303042153262013226335324253043315 ibo
struct blender::draw::CurveBatchCache::@071026276370372045157133366165211214356344347354 ordered
struct blender::draw::CurveRenderData::@145251267312362064345170074174210160167064064227 wire
struct blender::draw::CurveRenderData::@037067172015002275154223215154037373112276015040 text
struct blender::draw::CurveRenderData::@141010375164230177146153004237102010277074022342 overlay
struct blender::draw::CurveRenderData::@110121043272336260250327375123345371232202304200 normal
i
Definition text_draw.cc:230
uint8_t flag
Definition wm_window.cc:145