Blender  V3.3
draw_cache_impl_curve.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2017 Blender Foundation. All rights reserved. */
3 
10 #include "MEM_guardedalloc.h"
11 
12 #include "BLI_array.hh"
13 #include "BLI_listbase.h"
14 #include "BLI_math_vec_types.hh"
15 #include "BLI_math_vector.h"
16 #include "BLI_span.hh"
17 #include "BLI_utildefines.h"
18 
19 #include "DNA_curve_types.h"
20 
21 #include "BKE_curve.h"
22 #include "BKE_curves.hh"
23 #include "BKE_displist.h"
24 #include "BKE_geometry_set.hh"
25 #include "BKE_vfont.h"
26 
27 #include "GPU_batch.h"
28 #include "GPU_capabilities.h"
29 #include "GPU_material.h"
30 #include "GPU_texture.h"
31 
32 #include "UI_resources.h"
33 
34 #include "DRW_render.h"
35 
36 #include "draw_cache_inline.h"
37 
38 #include "draw_cache_impl.h" /* own include */
39 
40 using blender::Array;
41 using blender::float3;
43 using blender::Span;
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` */
53 enum {
55 
57 };
58 
66 static 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  *r_curve_len = curves.curves_num();
105  *r_vert_len = curves.evaluated_points_num();
106 
107  *r_edge_len = 0;
108  const blender::VArray<bool> cyclic = curves.cyclic();
109  for (const int i : curves.curves_range()) {
110  const IndexRange points = curves.evaluated_points_for_curve(i);
111  *r_edge_len += blender::bke::curves::segments_num(points.size(), cyclic[i]);
112  }
113 }
114 
115 static 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  int nr = bl->nr;
123  int skip = nu->resolu / 16;
124 #if 0
125  while (nr-- > 0) { /* accounts for empty bevel lists */
126  normal_len += 1;
127  nr -= skip;
128  }
129 #else
130  /* Same as loop above */
131  normal_len += (nr / (skip + 1)) + ((nr % (skip + 1)) != 0);
132 #endif
133  }
134  return normal_len;
135 }
136 
137 /* ---------------------------------------------------------------------- */
138 /* Curve Interface, indirect, partially cached access to complex data. */
139 
141  int types;
142 
143  struct {
144  int vert_len;
145  int edge_len;
147 
148  struct {
150  int vert_len;
151  int edge_len;
152  } wire;
153 
154  /* edit mode normal's */
155  struct {
156  /* 'edge_len == len * 2'
157  * 'vert_len == len * 3' */
158  int len;
160 
161  struct {
163  } text;
164 
165  /* borrow from 'Object' */
167 
168  /* Owned by the evaluated object's geometry set (#geometry_set_eval). */
170 
171  /* borrow from 'Curve' */
173 
174  /* edit, index in nurb list */
175  int actnu;
176  /* edit, index in active nurb (BPoint or BezTriple) */
177  int actvert;
178 };
179 
180 enum {
181  /* Wire center-line */
183  /* Edit-mode verts and optionally handles */
185  /* Edit-mode normals */
187  /* Geometry */
189  /* Text */
191 };
192 
193 /*
194  * ob_curve_cache can be NULL
195  */
197  CurveCache *ob_curve_cache,
198  const int types)
199 {
200  CurveRenderData *rdata = (CurveRenderData *)MEM_callocN(sizeof(*rdata), __func__);
201  rdata->types = types;
202  ListBase *nurbs;
203 
204  rdata->actnu = cu->actnu;
205  rdata->actvert = cu->actvert;
206 
207  rdata->ob_curve_cache = ob_curve_cache;
208 
209  rdata->curve_eval = cu->curve_eval;
210 
211  if (types & CU_DATATYPE_WIRE) {
212  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 
225  if (types & CU_DATATYPE_OVERLAY) {
227  nurbs, &rdata->overlay.vert_len, &rdata->overlay.edge_len);
228 
229  rdata->actnu = cu->actnu;
230  rdata->actvert = cu->actvert;
231  }
232  if (types & CU_DATATYPE_NORMAL) {
233  rdata->normal.len = curve_render_normal_len_get(nurbs, rdata->ob_curve_cache);
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 GPUBatch Cache */
295 
297  struct {
300 
301  struct {
303  /* Edit points (beztriples and bpoints) */
306  } edit;
307 
308  struct {
310  /* Edit mode */
313  } ibo;
314 
315  struct {
317  /* control handles and vertices */
321  } batch;
322 
323  /* settings to determine if cache is invalid */
324  bool is_dirty;
326 };
327 
328 /* GPUBatch cache management. */
329 
331 {
333 
334  if (cache == nullptr) {
335  return false;
336  }
337 
338  if (cache->is_dirty) {
339  return false;
340  }
341 
342  if (cache->is_editmode != ((cu->editnurb != nullptr) || (cu->editfont != nullptr))) {
343  return false;
344  }
345 
346  if (cache->is_editmode) {
347  if (cu->editfont) {
348  /* TODO */
349  }
350  }
351 
352  return true;
353 }
354 
356 {
358 
359  if (!cache) {
360  cache = (CurveBatchCache *)MEM_callocN(sizeof(*cache), __func__);
361  cu->batch_cache = cache;
362  }
363  else {
364  memset(cache, 0, sizeof(*cache));
365  }
366 
367 #if 0
368  ListBase *nurbs;
369  if (cu->editnurb) {
370  EditNurb *editnurb = cu->editnurb;
371  nurbs = &editnurb->nurbs;
372  }
373  else {
374  nurbs = &cu->nurb;
375  }
376 #endif
377 
378  cache->is_editmode = (cu->editnurb != nullptr) || (cu->editfont != nullptr);
379 
380  cache->is_dirty = false;
381 }
382 
384 {
385  if (!curve_batch_cache_valid(cu)) {
388  }
389 }
390 
392 {
393  return (CurveBatchCache *)cu->batch_cache;
394 }
395 
397 {
399  if (cache == nullptr) {
400  return;
401  }
402  switch (mode) {
404  cache->is_dirty = true;
405  break;
408 
411  break;
412  default:
413  BLI_assert(0);
414  }
415 }
416 
418 {
420  if (!cache) {
421  return;
422  }
423 
424  for (int i = 0; i < sizeof(cache->ordered) / sizeof(void *); i++) {
425  GPUVertBuf **vbo = (GPUVertBuf **)&cache->ordered;
426  GPU_VERTBUF_DISCARD_SAFE(vbo[i]);
427  }
428  for (int i = 0; i < sizeof(cache->edit) / sizeof(void *); i++) {
429  GPUVertBuf **vbo = (GPUVertBuf **)&cache->edit;
430  GPU_VERTBUF_DISCARD_SAFE(vbo[i]);
431  }
432  for (int i = 0; i < sizeof(cache->ibo) / sizeof(void *); i++) {
433  GPUIndexBuf **ibo = (GPUIndexBuf **)&cache->ibo;
435  }
436  for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) {
437  GPUBatch **batch = (GPUBatch **)&cache->batch;
439  }
440 }
441 
443 {
446 }
447 
448 /* -------------------------------------------------------------------- */
452 /* GPUBatch cache usage. */
453 static void curve_create_curves_pos(CurveRenderData *rdata, GPUVertBuf *vbo_curves_pos)
454 {
455  if (rdata->curve_eval == nullptr) {
456  return;
457  }
458 
459  static GPUVertFormat format = {0};
460  static struct {
461  uint pos;
462  } attr_id;
463  if (format.attr_len == 0) {
465  }
466 
467  const int vert_len = curve_render_data_wire_verts_len_get(rdata);
468  GPU_vertbuf_init_with_format(vbo_curves_pos, &format);
469  GPU_vertbuf_data_alloc(vbo_curves_pos, vert_len);
470 
472  rdata->curve_eval->geometry);
473  const Span<float3> positions = curves.evaluated_positions();
474  GPU_vertbuf_attr_fill(vbo_curves_pos, attr_id.pos, positions.data());
475 }
476 
477 static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_curve_lines)
478 {
479  if (rdata->curve_eval == nullptr) {
480  return;
481  }
482 
483  const int vert_len = curve_render_data_wire_verts_len_get(rdata);
484  const int edge_len = curve_render_data_wire_edges_len_get(rdata);
485  const int curve_len = curve_render_data_wire_curve_len_get(rdata);
486  /* Count the last vertex or each strip and the primitive restart. */
487  const int index_len = edge_len + curve_len * 2;
488 
489  GPUIndexBufBuilder elb;
490  GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, index_len, vert_len);
491 
493  rdata->curve_eval->geometry);
494  const blender::VArray<bool> cyclic = curves.cyclic();
495  for (const int i : curves.curves_range()) {
496  const IndexRange points = curves.evaluated_points_for_curve(i);
497  if (cyclic[i] && points.size() > 1) {
498  GPU_indexbuf_add_generic_vert(&elb, points.last());
499  }
500  for (const int i_point : points) {
501  GPU_indexbuf_add_generic_vert(&elb, i_point);
502  }
504  }
505 
506  GPU_indexbuf_build_in_place(&elb, ibo_curve_lines);
507 }
508 
510  GPUVertBuf *vbo_curves_nor,
511  const Scene *scene)
512 {
513  const bool do_hq_normals = (scene->r.perf_flag & SCE_PERF_HQ_NORMALS) != 0 ||
515 
516  static GPUVertFormat format = {0};
517  static GPUVertFormat format_hq = {0};
518  static struct {
519  uint pos, nor, tan, rad;
520  uint pos_hq, nor_hq, tan_hq, rad_hq;
521  } attr_id;
522  if (format.attr_len == 0) {
523  /* initialize vertex formats */
530 
531  attr_id.pos_hq = GPU_vertformat_attr_add(&format_hq, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
532  attr_id.rad_hq = GPU_vertformat_attr_add(&format_hq, "rad", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
534  &format_hq, "nor", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
536  &format_hq, "tan", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
537  }
538 
539  const GPUVertFormat *format_ptr = do_hq_normals ? &format_hq : &format;
540 
541  int verts_len_capacity = curve_render_data_normal_len_get(rdata) * 2;
542  int vbo_len_used = 0;
543 
544  GPU_vertbuf_init_with_format(vbo_curves_nor, format_ptr);
545  GPU_vertbuf_data_alloc(vbo_curves_nor, verts_len_capacity);
546 
547  const BevList *bl;
548  const Nurb *nu;
549 
550  const uint pos_id = do_hq_normals ? attr_id.pos_hq : attr_id.pos;
551  const uint nor_id = do_hq_normals ? attr_id.nor_hq : attr_id.nor;
552  const uint tan_id = do_hq_normals ? attr_id.tan_hq : attr_id.tan;
553  const uint rad_id = do_hq_normals ? attr_id.rad_hq : attr_id.rad;
554 
555  for (bl = (const BevList *)rdata->ob_curve_cache->bev.first,
556  nu = (const Nurb *)rdata->nurbs->first;
557  nu && bl;
558  bl = bl->next, nu = nu->next) {
559  const BevPoint *bevp = bl->bevpoints;
560  int nr = bl->nr;
561  int skip = nu->resolu / 16;
562 
563  while (nr-- > 0) { /* accounts for empty bevel lists */
564  float nor[3] = {1.0f, 0.0f, 0.0f};
565  mul_qt_v3(bevp->quat, nor);
566 
567  GPUNormal pnor;
568  GPUNormal ptan;
569  GPU_normal_convert_v3(&pnor, nor, do_hq_normals);
570  GPU_normal_convert_v3(&ptan, bevp->dir, do_hq_normals);
571  /* Only set attributes for one vertex. */
572  GPU_vertbuf_attr_set(vbo_curves_nor, pos_id, vbo_len_used, bevp->vec);
573  GPU_vertbuf_attr_set(vbo_curves_nor, rad_id, vbo_len_used, &bevp->radius);
574  GPU_vertbuf_attr_set(vbo_curves_nor, nor_id, vbo_len_used, &pnor);
575  GPU_vertbuf_attr_set(vbo_curves_nor, tan_id, vbo_len_used, &ptan);
576  vbo_len_used++;
577 
578  /* Skip the other vertex (it does not need to be offsetted). */
579  GPU_vertbuf_attr_set(vbo_curves_nor, attr_id.pos, vbo_len_used, bevp->vec);
580  vbo_len_used++;
581 
582  bevp += skip + 1;
583  nr -= skip;
584  }
585  }
586  BLI_assert(vbo_len_used == verts_len_capacity);
587 }
588 
590  uint8_t flag,
591  uint8_t col_id,
592  int v_idx,
593  int nu_id,
594  bool handle_point,
595  const bool handle_selected)
596 {
597  uint8_t vflag = 0;
599  SET_FLAG_FROM_TEST(vflag, (v_idx == rdata->actvert && nu_id == rdata->actnu), VFLAG_VERT_ACTIVE);
600  SET_FLAG_FROM_TEST(vflag, (nu_id == rdata->actnu), ACTIVE_NURB);
601  SET_FLAG_FROM_TEST(vflag, handle_point, BEZIER_HANDLE);
602  SET_FLAG_FROM_TEST(vflag, handle_selected, VFLAG_VERT_SELECTED_BEZT_HANDLE);
603  /* Setting flags that overlap with will cause the color id not to work properly. */
604  BLI_assert((vflag >> COLOR_SHIFT) == 0);
605  /* handle color id */
606  vflag |= col_id << COLOR_SHIFT;
607  return vflag;
608 }
609 
610 static uint8_t bpoint_vflag_get(CurveRenderData *rdata, uint8_t flag, int v_idx, int nu_id, int u)
611 {
612  uint8_t vflag = 0;
614  SET_FLAG_FROM_TEST(vflag, (v_idx == rdata->actvert && nu_id == rdata->actnu), VFLAG_VERT_ACTIVE);
615  SET_FLAG_FROM_TEST(vflag, (nu_id == rdata->actnu), ACTIVE_NURB);
616  SET_FLAG_FROM_TEST(vflag, ((u % 2) == 0), EVEN_U_BIT);
617  /* Setting flags that overlap with will cause the color id not to work properly. */
618  BLI_assert((vflag >> COLOR_SHIFT) == 0);
619  vflag |= COLOR_NURB_ULINE_ID << COLOR_SHIFT;
620  return vflag;
621 }
622 
624  GPUVertBuf *vbo_pos,
625  GPUVertBuf *vbo_data,
626  GPUIndexBuf *ibo_edit_verts_points,
627  GPUIndexBuf *ibo_edit_lines)
628 {
629  static GPUVertFormat format_pos = {0};
630  static GPUVertFormat format_data = {0};
631  static struct {
632  uint pos, data;
633  } attr_id;
634  if (format_pos.attr_len == 0) {
635  /* initialize vertex formats */
636  attr_id.pos = GPU_vertformat_attr_add(&format_pos, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
637  attr_id.data = GPU_vertformat_attr_add(&format_data, "data", GPU_COMP_U8, 1, GPU_FETCH_INT);
638  }
639 
640  int verts_len_capacity = curve_render_data_overlay_verts_len_get(rdata);
641  int edges_len_capacity = curve_render_data_overlay_edges_len_get(rdata) * 2;
642  int vbo_len_used = 0;
643 
644 #define DRW_TEST_ASSIGN_VBO(v) (v = (DRW_vbo_requested(v) ? (v) : nullptr))
645 #define DRW_TEST_ASSIGN_IBO(v) (v = (DRW_ibo_requested(v) ? (v) : nullptr))
646 
647  if (DRW_TEST_ASSIGN_VBO(vbo_pos)) {
648  GPU_vertbuf_init_with_format(vbo_pos, &format_pos);
649  GPU_vertbuf_data_alloc(vbo_pos, verts_len_capacity);
650  }
651  if (DRW_TEST_ASSIGN_VBO(vbo_data)) {
652  GPU_vertbuf_init_with_format(vbo_data, &format_data);
653  GPU_vertbuf_data_alloc(vbo_data, verts_len_capacity);
654  }
655 
656  GPUIndexBufBuilder elb_verts, *elbp_verts = nullptr;
657  GPUIndexBufBuilder elb_lines, *elbp_lines = nullptr;
658  if (DRW_TEST_ASSIGN_IBO(ibo_edit_verts_points)) {
659  elbp_verts = &elb_verts;
660  GPU_indexbuf_init(elbp_verts, GPU_PRIM_POINTS, verts_len_capacity, verts_len_capacity);
661  }
662  if (DRW_TEST_ASSIGN_IBO(ibo_edit_lines)) {
663  elbp_lines = &elb_lines;
664  GPU_indexbuf_init(elbp_lines, GPU_PRIM_LINES, edges_len_capacity, verts_len_capacity);
665  }
666 
667 #undef DRW_TEST_ASSIGN_VBO
668 #undef DRW_TEST_ASSIGN_IBO
669 
670  int nu_id = 0;
671  for (Nurb *nu = (Nurb *)rdata->nurbs->first; nu; nu = nu->next, nu_id++) {
672  const BezTriple *bezt = nu->bezt;
673  const BPoint *bp = nu->bp;
674 
675  if (bezt) {
676  for (int a = 0; a < nu->pntsu; a++, bezt++) {
677  if (bezt->hide != 0) {
678  continue;
679  }
680  const bool handle_selected = BEZT_ISSEL_ANY(bezt);
681 
682  if (elbp_verts) {
683  GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used + 0);
684  GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used + 1);
685  GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used + 2);
686  }
687  if (elbp_lines) {
688  GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used + 1, vbo_len_used + 0);
689  GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used + 1, vbo_len_used + 2);
690  }
691  if (vbo_data) {
692  const uint8_t vflag[3] = {
693  beztriple_vflag_get(rdata, bezt->f1, bezt->h1, a, nu_id, true, handle_selected),
694  beztriple_vflag_get(rdata, bezt->f2, bezt->h1, a, nu_id, false, handle_selected),
695  beztriple_vflag_get(rdata, bezt->f3, bezt->h2, a, nu_id, true, handle_selected),
696  };
697  for (int j = 0; j < 3; j++) {
698  GPU_vertbuf_attr_set(vbo_data, attr_id.data, vbo_len_used + j, &vflag[j]);
699  }
700  }
701  if (vbo_pos) {
702  for (int j = 0; j < 3; j++) {
703  GPU_vertbuf_attr_set(vbo_pos, attr_id.pos, vbo_len_used + j, bezt->vec[j]);
704  }
705  }
706  vbo_len_used += 3;
707  }
708  }
709  else if (bp) {
710  int pt_len = nu->pntsu * nu->pntsv;
711  for (int a = 0; a < pt_len; a++, bp++, vbo_len_used += 1) {
712  if (bp->hide != 0) {
713  continue;
714  }
715  int u = (a % nu->pntsu);
716  int v = (a / nu->pntsu);
717  /* Use indexed rendering for bezier.
718  * Specify all points and use indices to hide/show. */
719  if (elbp_verts) {
720  GPU_indexbuf_add_point_vert(elbp_verts, vbo_len_used);
721  }
722  if (elbp_lines) {
723  const BPoint *bp_next_u = (u < (nu->pntsu - 1)) ? &nu->bp[a + 1] : nullptr;
724  const BPoint *bp_next_v = (v < (nu->pntsv - 1)) ? &nu->bp[a + nu->pntsu] : nullptr;
725  if (bp_next_u && (bp_next_u->hide == false)) {
726  GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used, vbo_len_used + 1);
727  }
728  if (bp_next_v && (bp_next_v->hide == false)) {
729  GPU_indexbuf_add_line_verts(elbp_lines, vbo_len_used, vbo_len_used + nu->pntsu);
730  }
731  }
732  if (vbo_data) {
733  uint8_t vflag = bpoint_vflag_get(rdata, bp->f1, a, nu_id, u);
734  GPU_vertbuf_attr_set(vbo_data, attr_id.data, vbo_len_used, &vflag);
735  }
736  if (vbo_pos) {
737  GPU_vertbuf_attr_set(vbo_pos, attr_id.pos, vbo_len_used, bp->vec);
738  }
739  }
740  }
741  }
742 
743  /* Resize & Finish */
744  if (elbp_verts != nullptr) {
745  GPU_indexbuf_build_in_place(elbp_verts, ibo_edit_verts_points);
746  }
747  if (elbp_lines != nullptr) {
748  GPU_indexbuf_build_in_place(elbp_lines, ibo_edit_lines);
749  }
750  if (vbo_len_used != verts_len_capacity) {
751  if (vbo_pos != nullptr) {
752  GPU_vertbuf_data_resize(vbo_pos, vbo_len_used);
753  }
754  if (vbo_data != nullptr) {
755  GPU_vertbuf_data_resize(vbo_data, vbo_len_used);
756  }
757  }
758 }
759 
762 /* -------------------------------------------------------------------- */
767 {
769  return DRW_batch_request(&cache->batch.curves);
770 }
771 
773 {
775  return DRW_batch_request(&cache->batch.edit_normals);
776 }
777 
779 {
781  return DRW_batch_request(&cache->batch.edit_edges);
782 }
783 
785 {
787  return DRW_batch_request(&cache->batch.edit_verts);
788 }
789 
791 {
792  return max_ii(1, cu->totcol);
793 }
794 
797 /* -------------------------------------------------------------------- */
802 {
804 
805  Curve *cu = (Curve *)ob->data;
807 
808  /* Init batches and request VBOs & IBOs */
809  if (DRW_batch_requested(cache->batch.curves, GPU_PRIM_LINE_STRIP)) {
810  DRW_ibo_request(cache->batch.curves, &cache->ibo.curves_lines);
811  DRW_vbo_request(cache->batch.curves, &cache->ordered.curves_pos);
812  }
813 
814  /* Edit mode */
815  if (DRW_batch_requested(cache->batch.edit_edges, GPU_PRIM_LINES)) {
816  DRW_ibo_request(cache->batch.edit_edges, &cache->ibo.edit_lines);
817  DRW_vbo_request(cache->batch.edit_edges, &cache->edit.pos);
818  DRW_vbo_request(cache->batch.edit_edges, &cache->edit.data);
819  }
820  if (DRW_batch_requested(cache->batch.edit_verts, GPU_PRIM_POINTS)) {
821  DRW_ibo_request(cache->batch.edit_verts, &cache->ibo.edit_verts);
822  DRW_vbo_request(cache->batch.edit_verts, &cache->edit.pos);
823  DRW_vbo_request(cache->batch.edit_verts, &cache->edit.data);
824  }
825  if (DRW_batch_requested(cache->batch.edit_normals, GPU_PRIM_LINES)) {
826  DRW_vbo_request(cache->batch.edit_normals, &cache->edit.curves_nor);
827  }
828 
829 #ifdef DRW_DEBUG_MESH_CACHE_REQUEST
830  printf("-- %s %s --\n", __func__, ob->id.name + 2);
831 #endif
832 
833  /* Generate MeshRenderData flags */
834  int mr_flag = 0;
835  DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.curves_pos, CU_DATATYPE_WIRE);
836  DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.curves_lines, CU_DATATYPE_WIRE);
837 
838  DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.pos, CU_DATATYPE_OVERLAY);
839  DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.data, CU_DATATYPE_OVERLAY);
840  DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->edit.curves_nor, CU_DATATYPE_NORMAL);
841  DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.edit_verts, CU_DATATYPE_OVERLAY);
842  DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.edit_lines, CU_DATATYPE_OVERLAY);
843 
844 #ifdef DRW_DEBUG_MESH_CACHE_REQUEST
845  printf(" mr_flag %d\n\n", mr_flag);
846 #endif
847 
848  CurveRenderData *rdata = curve_render_data_create(cu, ob->runtime.curve_cache, mr_flag);
849 
850  /* Generate VBOs */
851  if (DRW_vbo_requested(cache->ordered.curves_pos)) {
852  curve_create_curves_pos(rdata, cache->ordered.curves_pos);
853  }
854  if (DRW_ibo_requested(cache->ibo.curves_lines)) {
855  curve_create_curves_lines(rdata, cache->ibo.curves_lines);
856  }
857  if (DRW_vbo_requested(cache->edit.pos) || DRW_vbo_requested(cache->edit.data) ||
858  DRW_ibo_requested(cache->ibo.edit_verts) || DRW_ibo_requested(cache->ibo.edit_lines)) {
860  rdata, cache->edit.pos, cache->edit.data, cache->ibo.edit_verts, cache->ibo.edit_lines);
861  }
862  if (DRW_vbo_requested(cache->edit.curves_nor)) {
863  curve_create_edit_curves_nor(rdata, cache->edit.curves_nor, scene);
864  }
865 
866  curve_render_data_free(rdata);
867 
868 #ifdef DEBUG
869  /* Make sure all requested batches have been setup. */
870  for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) {
871  BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], (GPUPrimType)0));
872  }
873 #endif
874 }
875 
@ BKE_CURVE_BATCH_DIRTY_SELECT
Definition: BKE_curve.h:367
@ BKE_CURVE_BATCH_DIRTY_ALL
Definition: BKE_curve.h:366
Low-level operations for curves.
display list (or rather multi purpose list) stuff.
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
MINLINE int max_ii(int a, int b)
void mul_qt_v3(const float q[4], float r[3])
Definition: math_rotation.c:59
unsigned int uint
Definition: BLI_sys_types.h:67
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define BEZT_ISSEL_ANY(bezt)
@ OB_SURF
@ OB_FONT
@ OB_CURVES_LEGACY
@ SCE_PERF_HQ_NORMALS
GPUBatch
Definition: GPU_batch.h:78
#define GPU_BATCH_DISCARD_SAFE(batch)
Definition: GPU_batch.h:216
bool GPU_use_hq_normals_workaround(void)
struct GPUIndexBuf GPUIndexBuf
#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_init_ex(GPUIndexBufBuilder *, GPUPrimType, uint index_len, uint vertex_len)
void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *, GPUIndexBuf *)
GPUPrimType
Definition: GPU_primitive.h:18
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:20
@ GPU_PRIM_POINTS
Definition: GPU_primitive.h:19
@ GPU_PRIM_LINE_STRIP
Definition: GPU_primitive.h:22
struct GPUVertBuf GPUVertBuf
void GPU_vertbuf_data_alloc(GPUVertBuf *, uint v_len)
#define GPU_vertbuf_init_with_format(verts, format)
#define GPU_VERTBUF_DISCARD_SAFE(verts)
void GPU_vertbuf_attr_fill(GPUVertBuf *, uint a_idx, const void *data)
void GPU_vertbuf_attr_set(GPUVertBuf *, uint a_idx, uint v_idx, const void *data)
void GPU_vertbuf_data_resize(GPUVertBuf *, uint v_len)
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT_TO_FLOAT_UNIT
@ GPU_FETCH_INT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
BLI_INLINE void GPU_normal_convert_v3(GPUNormal *gpu_normal, const float data[3], const bool do_hq_normals)
@ GPU_COMP_I10
@ GPU_COMP_F32
@ GPU_COMP_I16
@ GPU_COMP_U8
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
@ TH_HANDLE_FREE
Definition: UI_resources.h:109
@ TH_HANDLE_AUTOCLAMP
Definition: UI_resources.h:113
ATTR_WARN_UNUSED_RESULT const BMVert * v
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
static CurvesGeometry & wrap(::CurvesGeometry &dna_struct)
Definition: BKE_curves.hh:138
Scene scene
@ VFLAG_VERT_SELECTED_BEZT_HANDLE
@ VFLAG_VERT_SELECTED
@ VFLAG_VERT_ACTIVE
static bool curve_batch_cache_valid(Curve *cu)
static void curve_create_edit_data_and_handles(CurveRenderData *rdata, GPUVertBuf *vbo_pos, GPUVertBuf *vbo_data, GPUIndexBuf *ibo_edit_verts_points, GPUIndexBuf *ibo_edit_lines)
static int curve_render_data_wire_verts_len_get(const CurveRenderData *rdata)
static uint8_t bpoint_vflag_get(CurveRenderData *rdata, uint8_t flag, int v_idx, int nu_id, int u)
static void curve_batch_cache_init(Curve *cu)
@ COLOR_NURB_ULINE_ID
@ TOT_HANDLE_COL
#define DRW_TEST_ASSIGN_VBO(v)
GPUBatch * DRW_curve_batch_cache_get_edit_edges(Curve *cu)
static CurveBatchCache * curve_batch_cache_get(Curve *cu)
static int curve_render_data_normal_len_get(const CurveRenderData *rdata)
#define EVEN_U_BIT
static void curve_batch_cache_clear(Curve *cu)
#define DRW_TEST_ASSIGN_IBO(v)
static CurveRenderData * curve_render_data_create(Curve *cu, CurveCache *ob_curve_cache, const int types)
#define SELECT
static void curve_render_data_free(CurveRenderData *rdata)
static void curve_create_edit_curves_nor(CurveRenderData *rdata, GPUVertBuf *vbo_curves_nor, const Scene *scene)
#define COLOR_SHIFT
static int curve_render_normal_len_get(const ListBase *lb, const CurveCache *ob_curve_cache)
static void curve_create_curves_pos(CurveRenderData *rdata, GPUVertBuf *vbo_curves_pos)
static int curve_render_data_wire_edges_len_get(const CurveRenderData *rdata)
int DRW_curve_material_count_get(Curve *cu)
static void curve_create_curves_lines(CurveRenderData *rdata, GPUIndexBuf *ibo_curve_lines)
GPUBatch * DRW_curve_batch_cache_get_normal_edge(Curve *cu)
void DRW_curve_batch_cache_dirty_tag(Curve *cu, int mode)
@ CU_DATATYPE_TEXT_SELECT
@ CU_DATATYPE_NORMAL
@ CU_DATATYPE_OVERLAY
@ CU_DATATYPE_WIRE
@ CU_DATATYPE_SURFACE
static int curve_render_data_wire_curve_len_get(const CurveRenderData *rdata)
static void curve_render_overlay_verts_edges_len_get(ListBase *lb, int *r_vert_len, int *r_edge_len)
#define BEZIER_HANDLE
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)
GPUBatch * DRW_curve_batch_cache_get_edit_verts(Curve *cu)
void DRW_curve_batch_cache_validate(Curve *cu)
void DRW_curve_batch_cache_create_requested(Object *ob, const struct Scene *scene)
#define ACTIVE_NURB
static void curve_eval_render_wire_verts_edges_len_get(const blender::bke::CurvesGeometry &curves, int *r_curve_len, int *r_vert_len, int *r_edge_len)
void DRW_curve_batch_cache_free(Curve *cu)
static int curve_render_data_overlay_verts_len_get(const CurveRenderData *rdata)
static int curve_render_data_overlay_edges_len_get(const CurveRenderData *rdata)
GPUBatch * DRW_curve_batch_cache_get_wire_edge(Curve *cu)
BLI_INLINE void DRW_vbo_request(GPUBatch *batch, GPUVertBuf **vbo)
BLI_INLINE bool DRW_vbo_requested(GPUVertBuf *vbo)
#define DRW_ADD_FLAG_FROM_IBO_REQUEST(flag, ibo, value)
#define DRW_ADD_FLAG_FROM_VBO_REQUEST(flag, vbo, value)
BLI_INLINE void DRW_ibo_request(GPUBatch *batch, GPUIndexBuf **ibo)
BLI_INLINE bool DRW_ibo_requested(GPUIndexBuf *ibo)
BLI_INLINE bool DRW_batch_requested(GPUBatch *batch, GPUPrimType prim_type)
BLI_INLINE GPUBatch * DRW_batch_request(GPUBatch **batch)
uint pos
uint nor
struct @653::@656 attr_id
struct @653::@655 batch
format
Definition: logImageCore.h:38
static char ** types
Definition: makesdna.c:67
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static unsigned a[3]
Definition: RandGen.cpp:78
INLINE Rall1d< T, V, S > tan(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:327
int segments_num(const int points_num, const bool cyclic)
Definition: BKE_curves.hh:462
vec_base< float, 3 > float3
MutableSpan< float3 > positions
unsigned char uint8_t
Definition: stdint.h:78
short hide
struct BevList * next
BevPoint * bevpoints
float radius
float dir[3]
float quat[4]
float vec[3]
uint8_t h1
uint8_t f3
float vec[3][3]
uint8_t f1
uint8_t f2
uint8_t h2
struct CurveBatchCache::@283 ordered
GPUIndexBuf * curves_lines
struct CurveBatchCache::@284 edit
struct CurveBatchCache::@286 batch
struct CurveBatchCache::@285 ibo
ListBase bev
Definition: BKE_curve.h:34
struct CurveRenderData::@280 wire
struct CurveRenderData::@279 overlay
const Curves * curve_eval
struct CurveRenderData::@282 text
struct CurveRenderData::@281 normal
short totcol
void * batch_cache
const struct Curves * curve_eval
struct EditFont * editfont
EditNurb * editnurb
ListBase nurb
CurvesGeometry geometry
ListBase nurbs
char name[66]
Definition: DNA_ID.h:378
void * first
Definition: DNA_listBase.h:31
struct Nurb * next
short resolu
struct CurveCache * curve_cache
Object_Runtime runtime
void * data
struct RenderData r