Blender  V2.93
draw_cache_impl_particles.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2017 by Blender Foundation.
17  * All rights reserved.
18  */
19 
26 #include "DRW_render.h"
27 
28 #include "MEM_guardedalloc.h"
29 
30 #include "BLI_ghash.h"
31 #include "BLI_math_vector.h"
32 #include "BLI_string.h"
33 #include "BLI_utildefines.h"
34 
35 #include "DNA_customdata_types.h"
36 #include "DNA_mesh_types.h"
37 #include "DNA_meshdata_types.h"
38 #include "DNA_modifier_types.h"
39 #include "DNA_particle_types.h"
40 
41 #include "BKE_customdata.h"
42 #include "BKE_mesh.h"
43 #include "BKE_particle.h"
44 #include "BKE_pointcache.h"
45 
46 #include "ED_particle.h"
47 
48 #include "GPU_batch.h"
49 
50 #include "DEG_depsgraph_query.h"
51 
52 #include "draw_cache_impl.h" /* own include */
53 #include "draw_hair_private.h"
54 
56 
57 /* ---------------------------------------------------------------------- */
58 /* Particle GPUBatch Cache */
59 
60 typedef struct ParticlePointCache {
63  int elems_len;
64  int point_len;
66 
67 typedef struct ParticleBatchCache {
68  /* Object mode strands for hair and points for particle,
69  * strands for paths when in edit mode.
70  */
71  ParticleHairCache hair; /* Used for hair strands */
72  ParticlePointCache point; /* Used for particle points. */
73 
74  /* Control points when in edit mode. */
76 
79 
83 
87 
88  /* Settings to determine if cache is invalid. */
89  bool is_dirty;
92 
93 /* GPUBatch cache management. */
94 
95 typedef struct HairAttributeID {
100 
101 typedef struct EditStrandData {
102  float pos[3];
103  float color;
105 
106 static GPUVertFormat *edit_points_vert_format_get(uint *r_pos_id, uint *r_color_id)
107 {
108  static GPUVertFormat edit_point_format = {0};
109  static uint pos_id, color_id;
110  if (edit_point_format.attr_len == 0) {
111  /* Keep in sync with EditStrandData */
112  pos_id = GPU_vertformat_attr_add(&edit_point_format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
113  color_id = GPU_vertformat_attr_add(
114  &edit_point_format, "color", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
115  }
116  *r_pos_id = pos_id;
117  *r_color_id = color_id;
118  return &edit_point_format;
119 }
120 
122 {
123  ParticleBatchCache *cache = psys->batch_cache;
124 
125  if (cache == NULL) {
126  return false;
127  }
128 
129  if (cache->is_dirty == false) {
130  return true;
131  }
132 
133  return false;
134 
135  return true;
136 }
137 
139 {
140  ParticleBatchCache *cache = psys->batch_cache;
141 
142  if (!cache) {
143  cache = psys->batch_cache = MEM_callocN(sizeof(*cache), __func__);
144  }
145  else {
146  memset(cache, 0, sizeof(*cache));
147  }
148 
149  cache->is_dirty = false;
150 }
151 
153 {
154  if (!particle_batch_cache_valid(psys)) {
157  }
158  return psys->batch_cache;
159 }
160 
162 {
163  ParticleBatchCache *cache = psys->batch_cache;
164  if (cache == NULL) {
165  return;
166  }
167  switch (mode) {
169  cache->is_dirty = true;
170  break;
171  default:
172  BLI_assert(0);
173  }
174 }
175 
177 {
178  GPU_BATCH_DISCARD_SAFE(point_cache->points);
179  GPU_VERTBUF_DISCARD_SAFE(point_cache->pos);
180 }
181 
183 {
184  /* TODO more granular update tagging. */
186  DRW_TEXTURE_FREE_SAFE(hair_cache->point_tex);
187 
190  DRW_TEXTURE_FREE_SAFE(hair_cache->strand_tex);
192 
193  for (int i = 0; i < MAX_MTFACE; i++) {
194  GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_uv_buf[i]);
195  DRW_TEXTURE_FREE_SAFE(hair_cache->uv_tex[i]);
196  }
197  for (int i = 0; i < MAX_MCOL; i++) {
198  GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_col_buf[i]);
199  DRW_TEXTURE_FREE_SAFE(hair_cache->col_tex[i]);
200  }
201  for (int i = 0; i < MAX_HAIR_SUBDIV; i++) {
202  GPU_VERTBUF_DISCARD_SAFE(hair_cache->final[i].proc_buf);
203  DRW_TEXTURE_FREE_SAFE(hair_cache->final[i].proc_tex);
204  for (int j = 0; j < MAX_THICKRES; j++) {
205  GPU_BATCH_DISCARD_SAFE(hair_cache->final[i].proc_hairs[j]);
206  }
207  }
208 
209  /* "Normal" legacy hairs */
210  GPU_BATCH_DISCARD_SAFE(hair_cache->hairs);
211  GPU_VERTBUF_DISCARD_SAFE(hair_cache->pos);
212  GPU_INDEXBUF_DISCARD_SAFE(hair_cache->indices);
213 }
214 
216 {
217  ParticleBatchCache *cache = psys->batch_cache;
218  if (!cache) {
219  return;
220  }
221 
224 
226 
231 }
232 
234 {
236  MEM_SAFE_FREE(psys->batch_cache);
237 }
238 
240  const int num_path_cache_keys,
241  ParticleHairCache *hair_cache)
242 {
243  for (int i = 0; i < num_path_cache_keys; i++) {
244  ParticleCacheKey *path = pathcache[i];
245  if (path->segments > 0) {
246  hair_cache->strands_len++;
247  hair_cache->elems_len += path->segments + 2;
248  hair_cache->point_len += path->segments + 1;
249  }
250  }
251 }
252 
254  ParticleSystem *psys,
255  ParticleHairCache *hair_cache)
256 {
257  if ((hair_cache->pos != NULL && hair_cache->indices != NULL) ||
258  (hair_cache->proc_point_buf != NULL)) {
259  return;
260  }
261 
262  hair_cache->strands_len = 0;
263  hair_cache->elems_len = 0;
264  hair_cache->point_len = 0;
265 
266  if (edit != NULL && edit->pathcache != NULL) {
267  count_cache_segment_keys(edit->pathcache, edit->totcached, hair_cache);
268  }
269  else {
270  if (psys->pathcache && (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) {
271  count_cache_segment_keys(psys->pathcache, psys->totpart, hair_cache);
272  }
273  if (psys->childcache) {
274  const int child_count = psys->totchild * psys->part->disp / 100;
275  count_cache_segment_keys(psys->childcache, child_count, hair_cache);
276  }
277  }
278 }
279 
280 static void particle_pack_mcol(MCol *mcol, ushort r_scol[3])
281 {
282  /* Convert to linear ushort and swizzle */
286 }
287 
288 /* Used by parent particles and simple children. */
291  const int num_uv_layers,
292  const int parent_index,
293  /*const*/ MTFace **mtfaces,
294  float (*r_uv)[2])
295 {
296  if (psmd == NULL) {
297  return;
298  }
299  const int emit_from = psmd->psys->part->from;
300  if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) {
301  return;
302  }
303  ParticleData *particle = &psys->particles[parent_index];
304  int num = particle->num_dmcache;
306  if (particle->num < psmd->mesh_final->totface) {
307  num = particle->num;
308  }
309  }
310  if (!ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
311  MFace *mface = &psmd->mesh_final->mface[num];
312  for (int j = 0; j < num_uv_layers; j++) {
313  psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, r_uv[j]);
314  }
315  }
316 }
317 
320  const int num_col_layers,
321  const int parent_index,
322  /*const*/ MCol **mcols,
323  MCol *r_mcol)
324 {
325  if (psmd == NULL) {
326  return;
327  }
328  const int emit_from = psmd->psys->part->from;
329  if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) {
330  return;
331  }
332  ParticleData *particle = &psys->particles[parent_index];
333  int num = particle->num_dmcache;
335  if (particle->num < psmd->mesh_final->totface) {
336  num = particle->num;
337  }
338  }
339  if (!ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
340  MFace *mface = &psmd->mesh_final->mface[num];
341  for (int j = 0; j < num_col_layers; j++) {
342  /* CustomDataLayer CD_MCOL has 4 structs per face. */
343  psys_interpolate_mcol(mcols[j] + num * 4, mface->v4, particle->fuv, &r_mcol[j]);
344  }
345  }
346 }
347 
348 /* Used by interpolated children. */
351  const int num_uv_layers,
352  const int child_index,
353  /*const*/ MTFace **mtfaces,
354  float (*r_uv)[2])
355 {
356  if (psmd == NULL) {
357  return;
358  }
359  const int emit_from = psmd->psys->part->from;
360  if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) {
361  return;
362  }
363  ChildParticle *particle = &psys->child[child_index];
364  int num = particle->num;
365  if (num != DMCACHE_NOTFOUND) {
366  MFace *mface = &psmd->mesh_final->mface[num];
367  for (int j = 0; j < num_uv_layers; j++) {
368  psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, r_uv[j]);
369  }
370  }
371 }
372 
375  const int num_col_layers,
376  const int child_index,
377  /*const*/ MCol **mcols,
378  MCol *r_mcol)
379 {
380  if (psmd == NULL) {
381  return;
382  }
383  const int emit_from = psmd->psys->part->from;
384  if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) {
385  return;
386  }
387  ChildParticle *particle = &psys->child[child_index];
388  int num = particle->num;
389  if (num != DMCACHE_NOTFOUND) {
390  MFace *mface = &psmd->mesh_final->mface[num];
391  for (int j = 0; j < num_col_layers; j++) {
392  /* CustomDataLayer CD_MCOL has 4 structs per face. */
393  psys_interpolate_mcol(mcols[j] + num * 4, mface->v4, particle->fuv, &r_mcol[j]);
394  }
395  }
396 }
397 
400  const bool is_simple,
401  const int num_uv_layers,
402  const int parent_index,
403  const int child_index,
404  /*const*/ MTFace **mtfaces,
405  float (**r_parent_uvs)[2],
406  float (**r_uv)[2])
407 {
408  if (psmd == NULL) {
409  return;
410  }
411  if (is_simple) {
412  if (r_parent_uvs[parent_index] != NULL) {
413  *r_uv = r_parent_uvs[parent_index];
414  }
415  else {
416  *r_uv = MEM_callocN(sizeof(**r_uv) * num_uv_layers, "Particle UVs");
417  }
418  }
419  else {
420  *r_uv = MEM_callocN(sizeof(**r_uv) * num_uv_layers, "Particle UVs");
421  }
422  if (child_index == -1) {
423  /* Calculate UVs for parent particles. */
424  if (is_simple) {
425  r_parent_uvs[parent_index] = *r_uv;
426  }
427  particle_calculate_parent_uvs(psys, psmd, num_uv_layers, parent_index, mtfaces, *r_uv);
428  }
429  else {
430  /* Calculate UVs for child particles. */
431  if (!is_simple) {
432  particle_interpolate_children_uvs(psys, psmd, num_uv_layers, child_index, mtfaces, *r_uv);
433  }
434  else if (!r_parent_uvs[psys->child[child_index].parent]) {
435  r_parent_uvs[psys->child[child_index].parent] = *r_uv;
436  particle_calculate_parent_uvs(psys, psmd, num_uv_layers, parent_index, mtfaces, *r_uv);
437  }
438  }
439 }
440 
443  const bool is_simple,
444  const int num_col_layers,
445  const int parent_index,
446  const int child_index,
447  /*const*/ MCol **mcols,
448  MCol **r_parent_mcol,
449  MCol **r_mcol)
450 {
451  if (psmd == NULL) {
452  return;
453  }
454  if (is_simple) {
455  if (r_parent_mcol[parent_index] != NULL) {
456  *r_mcol = r_parent_mcol[parent_index];
457  }
458  else {
459  *r_mcol = MEM_callocN(sizeof(**r_mcol) * num_col_layers, "Particle MCol");
460  }
461  }
462  else {
463  *r_mcol = MEM_callocN(sizeof(**r_mcol) * num_col_layers, "Particle MCol");
464  }
465  if (child_index == -1) {
466  /* Calculate MCols for parent particles. */
467  if (is_simple) {
468  r_parent_mcol[parent_index] = *r_mcol;
469  }
470  particle_calculate_parent_mcol(psys, psmd, num_col_layers, parent_index, mcols, *r_mcol);
471  }
472  else {
473  /* Calculate MCols for child particles. */
474  if (!is_simple) {
475  particle_interpolate_children_mcol(psys, psmd, num_col_layers, child_index, mcols, *r_mcol);
476  }
477  else if (!r_parent_mcol[psys->child[child_index].parent]) {
478  r_parent_mcol[psys->child[child_index].parent] = *r_mcol;
479  particle_calculate_parent_mcol(psys, psmd, num_col_layers, parent_index, mcols, *r_mcol);
480  }
481  }
482 }
483 
484 /* Will return last filled index. */
485 typedef enum ParticleSource {
491  ParticleCacheKey **path_cache,
492  const ParticleSource particle_source,
493  const int global_offset,
494  const int start_index,
495  const int num_path_keys,
496  const int num_uv_layers,
497  const int num_col_layers,
498  /*const*/ MTFace **mtfaces,
499  /*const*/ MCol **mcols,
500  uint *uv_id,
501  uint *col_id,
502  float (***r_parent_uvs)[2],
503  MCol ***r_parent_mcol,
504  GPUIndexBufBuilder *elb,
506  ParticleHairCache *hair_cache)
507 {
508  const bool is_simple = (psys->part->childtype == PART_CHILD_PARTICLES);
509  const bool is_child = (particle_source == PARTICLE_SOURCE_CHILDREN);
510  if (is_simple && *r_parent_uvs == NULL) {
511  /* TODO(sergey): For edit mode it should be edit->totcached. */
512  *r_parent_uvs = MEM_callocN(sizeof(*r_parent_uvs) * psys->totpart, "Parent particle UVs");
513  }
514  if (is_simple && *r_parent_mcol == NULL) {
515  *r_parent_mcol = MEM_callocN(sizeof(*r_parent_mcol) * psys->totpart, "Parent particle MCol");
516  }
517  int curr_point = start_index;
518  for (int i = 0; i < num_path_keys; i++) {
519  ParticleCacheKey *path = path_cache[i];
520  if (path->segments <= 0) {
521  continue;
522  }
523  float tangent[3];
524  float(*uv)[2] = NULL;
525  MCol *mcol = NULL;
527  psmd,
528  is_simple,
529  num_col_layers,
530  is_child ? psys->child[i].parent : i,
531  is_child ? i : -1,
532  mcols,
533  *r_parent_mcol,
534  &mcol);
536  psmd,
537  is_simple,
538  num_uv_layers,
539  is_child ? psys->child[i].parent : i,
540  is_child ? i : -1,
541  mtfaces,
542  *r_parent_uvs,
543  &uv);
544  for (int j = 0; j < path->segments; j++) {
545  if (j == 0) {
546  sub_v3_v3v3(tangent, path[j + 1].co, path[j].co);
547  }
548  else {
549  sub_v3_v3v3(tangent, path[j + 1].co, path[j - 1].co);
550  }
551  GPU_vertbuf_attr_set(hair_cache->pos, attr_id->pos, curr_point, path[j].co);
552  GPU_vertbuf_attr_set(hair_cache->pos, attr_id->tan, curr_point, tangent);
553  GPU_vertbuf_attr_set(hair_cache->pos, attr_id->ind, curr_point, &i);
554  if (psmd != NULL) {
555  for (int k = 0; k < num_uv_layers; k++) {
557  hair_cache->pos,
558  uv_id[k],
559  curr_point,
560  (is_simple && is_child) ? (*r_parent_uvs)[psys->child[i].parent][k] : uv[k]);
561  }
562  for (int k = 0; k < num_col_layers; k++) {
563  /* TODO Put the conversion outside the loop */
564  ushort scol[4];
566  (is_simple && is_child) ? &(*r_parent_mcol)[psys->child[i].parent][k] : &mcol[k],
567  scol);
568  GPU_vertbuf_attr_set(hair_cache->pos, col_id[k], curr_point, scol);
569  }
570  }
571  GPU_indexbuf_add_generic_vert(elb, curr_point);
572  curr_point++;
573  }
574  sub_v3_v3v3(tangent, path[path->segments].co, path[path->segments - 1].co);
575 
576  int global_index = i + global_offset;
577  GPU_vertbuf_attr_set(hair_cache->pos, attr_id->pos, curr_point, path[path->segments].co);
578  GPU_vertbuf_attr_set(hair_cache->pos, attr_id->tan, curr_point, tangent);
579  GPU_vertbuf_attr_set(hair_cache->pos, attr_id->ind, curr_point, &global_index);
580 
581  if (psmd != NULL) {
582  for (int k = 0; k < num_uv_layers; k++) {
583  GPU_vertbuf_attr_set(hair_cache->pos,
584  uv_id[k],
585  curr_point,
586  (is_simple && is_child) ? (*r_parent_uvs)[psys->child[i].parent][k] :
587  uv[k]);
588  }
589  for (int k = 0; k < num_col_layers; k++) {
590  /* TODO Put the conversion outside the loop */
591  ushort scol[4];
592  particle_pack_mcol((is_simple && is_child) ? &(*r_parent_mcol)[psys->child[i].parent][k] :
593  &mcol[k],
594  scol);
595  GPU_vertbuf_attr_set(hair_cache->pos, col_id[k], curr_point, scol);
596  }
597  if (!is_simple) {
598  MEM_freeN(uv);
599  MEM_freeN(mcol);
600  }
601  }
602  /* Finish the segment and add restart primitive. */
603  GPU_indexbuf_add_generic_vert(elb, curr_point);
605  curr_point++;
606  }
607  return curr_point;
608 }
609 
611  const int num_path_keys,
612  GPUVertBufRaw *attr_step)
613 {
614  for (int i = 0; i < num_path_keys; i++) {
615  ParticleCacheKey *path = path_cache[i];
616  if (path->segments <= 0) {
617  continue;
618  }
619  float total_len = 0.0f;
620  float *co_prev = NULL, *seg_data_first;
621  for (int j = 0; j <= path->segments; j++) {
622  float *seg_data = (float *)GPU_vertbuf_raw_step(attr_step);
623  copy_v3_v3(seg_data, path[j].co);
624  if (co_prev) {
625  total_len += len_v3v3(co_prev, path[j].co);
626  }
627  else {
628  seg_data_first = seg_data;
629  }
630  seg_data[3] = total_len;
631  co_prev = path[j].co;
632  }
633  if (total_len > 0.0f) {
634  /* Divide by total length to have a [0-1] number. */
635  for (int j = 0; j <= path->segments; j++, seg_data_first += 4) {
636  seg_data_first[3] /= total_len;
637  }
638  }
639  }
640 }
641 
642 static float particle_key_weight(const ParticleData *particle, int strand, float t)
643 {
644  const ParticleData *part = particle + strand;
645  const HairKey *hkeys = part->hair;
646  float edit_key_seg_t = 1.0f / (part->totkey - 1);
647  if (t == 1.0) {
648  return hkeys[part->totkey - 1].weight;
649  }
650 
651  float interp = t / edit_key_seg_t;
652  int index = (int)interp;
653  interp -= floorf(interp); /* Time between 2 edit key */
654  float s1 = hkeys[index].weight;
655  float s2 = hkeys[index + 1].weight;
656  return s1 + interp * (s2 - s1);
657 }
658 
660  const PTCacheEdit *UNUSED(edit), /* NULL for weight data */
661  const ParticleData *particle, /* NULL for select data */
662  ParticleCacheKey **path_cache,
663  const int start_index,
664  const int num_path_keys,
665  GPUIndexBufBuilder *elb,
666  GPUVertBufRaw *attr_step)
667 {
668  int curr_point = start_index;
669  for (int i = 0; i < num_path_keys; i++) {
670  ParticleCacheKey *path = path_cache[i];
671  if (path->segments <= 0) {
672  continue;
673  }
674  for (int j = 0; j <= path->segments; j++) {
675  EditStrandData *seg_data = (EditStrandData *)GPU_vertbuf_raw_step(attr_step);
676  copy_v3_v3(seg_data->pos, path[j].co);
677  float strand_t = (float)(j) / path->segments;
678  if (particle) {
679  float weight = particle_key_weight(particle, i, strand_t);
680  /* NaN or unclamped become 1.0f */
681  seg_data->color = (weight < 1.0f) ? weight : 1.0f;
682  }
683  else {
684  /* Computed in psys_cache_edit_paths_iter(). */
685  seg_data->color = path[j].col[0];
686  }
687  GPU_indexbuf_add_generic_vert(elb, curr_point);
688  curr_point++;
689  }
690  /* Finish the segment and add restart primitive. */
692  }
693  return curr_point;
694 }
695 
697  const int start_index,
698  const int num_path_keys,
699  const int res,
700  GPUIndexBufBuilder *elb)
701 {
702  int curr_point = start_index;
703  for (int i = 0; i < num_path_keys; i++) {
704  ParticleCacheKey *path = path_cache[i];
705  if (path->segments <= 0) {
706  continue;
707  }
708  for (int k = 0; k < res; k++) {
709  GPU_indexbuf_add_generic_vert(elb, curr_point++);
710  }
712  }
713  return curr_point;
714 }
715 
718  ParticleCacheKey **path_cache,
719  const ParticleSource particle_source,
720  const int start_index,
721  const int num_path_keys,
722  GPUVertBufRaw *data_step,
723  GPUVertBufRaw *seg_step,
724  float (***r_parent_uvs)[2],
725  GPUVertBufRaw *uv_step,
726  MTFace **mtfaces,
727  int num_uv_layers,
728  MCol ***r_parent_mcol,
729  GPUVertBufRaw *col_step,
730  MCol **mcols,
731  int num_col_layers)
732 {
733  const bool is_simple = (psys->part->childtype == PART_CHILD_PARTICLES);
734  const bool is_child = (particle_source == PARTICLE_SOURCE_CHILDREN);
735  if (is_simple && *r_parent_uvs == NULL) {
736  /* TODO(sergey): For edit mode it should be edit->totcached. */
737  *r_parent_uvs = MEM_callocN(sizeof(*r_parent_uvs) * psys->totpart, "Parent particle UVs");
738  }
739  if (is_simple && *r_parent_mcol == NULL) {
740  *r_parent_mcol = MEM_callocN(sizeof(*r_parent_mcol) * psys->totpart, "Parent particle MCol");
741  }
742  int curr_point = start_index;
743  for (int i = 0; i < num_path_keys; i++) {
744  ParticleCacheKey *path = path_cache[i];
745  if (path->segments <= 0) {
746  continue;
747  }
748 
749  *(uint *)GPU_vertbuf_raw_step(data_step) = curr_point;
750  *(ushort *)GPU_vertbuf_raw_step(seg_step) = path->segments;
751  curr_point += path->segments + 1;
752 
753  if (psmd != NULL) {
754  float(*uv)[2] = NULL;
755  MCol *mcol = NULL;
756 
758  psmd,
759  is_simple,
760  num_uv_layers,
761  is_child ? psys->child[i].parent : i,
762  is_child ? i : -1,
763  mtfaces,
764  *r_parent_uvs,
765  &uv);
766 
768  psmd,
769  is_simple,
770  num_col_layers,
771  is_child ? psys->child[i].parent : i,
772  is_child ? i : -1,
773  mcols,
774  *r_parent_mcol,
775  &mcol);
776 
777  for (int k = 0; k < num_uv_layers; k++) {
778  float *t_uv = (float *)GPU_vertbuf_raw_step(uv_step + k);
779  copy_v2_v2(t_uv, uv[k]);
780  }
781  for (int k = 0; k < num_col_layers; k++) {
782  ushort *scol = (ushort *)GPU_vertbuf_raw_step(col_step + k);
783  particle_pack_mcol((is_simple && is_child) ? &(*r_parent_mcol)[psys->child[i].parent][k] :
784  &mcol[k],
785  scol);
786  }
787  if (!is_simple) {
788  MEM_freeN(uv);
789  MEM_freeN(mcol);
790  }
791  }
792  }
793  return curr_point;
794 }
795 
797  int subdiv)
798 {
799  /* Same format as point_tex. */
800  GPUVertFormat format = {0};
802 
804 
805  /* Create a destination buffer for the transform feedback. Sized appropriately */
806  /* Those are points! not line segments. */
807  GPU_vertbuf_data_alloc(cache->final[subdiv].proc_buf,
808  cache->final[subdiv].strands_res * cache->strands_len);
809 
810  /* Create vbo immediately to bind to texture buffer. */
811  GPU_vertbuf_use(cache->final[subdiv].proc_buf);
812 
813  cache->final[subdiv].proc_tex = GPU_texture_create_from_vertbuf("part_proc",
814  cache->final[subdiv].proc_buf);
815 }
816 
818  ParticleSystem *psys,
819  ModifierData *md,
820  ParticleHairCache *cache)
821 {
822  int active_uv = 0;
823  int render_uv = 0;
824  int active_col = 0;
825  int render_col = 0;
826 
828 
829  if (psmd != NULL && psmd->mesh_final != NULL) {
834  }
839  }
840  }
841 
842  GPUVertBufRaw data_step, seg_step;
843  GPUVertBufRaw uv_step[MAX_MTFACE];
844  GPUVertBufRaw col_step[MAX_MCOL];
845 
846  MTFace *mtfaces[MAX_MTFACE] = {NULL};
847  MCol *mcols[MAX_MCOL] = {NULL};
848  float(**parent_uvs)[2] = NULL;
849  MCol **parent_mcol = NULL;
850 
851  GPUVertFormat format_data = {0};
852  uint data_id = GPU_vertformat_attr_add(&format_data, "data", GPU_COMP_U32, 1, GPU_FETCH_INT);
853 
854  GPUVertFormat format_seg = {0};
855  uint seg_id = GPU_vertformat_attr_add(&format_seg, "data", GPU_COMP_U16, 1, GPU_FETCH_INT);
856 
857  GPUVertFormat format_uv = {0};
858  uint uv_id = GPU_vertformat_attr_add(&format_uv, "uv", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
859 
860  GPUVertFormat format_col = {0};
861  uint col_id = GPU_vertformat_attr_add(
862  &format_col, "col", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
863 
864  memset(cache->uv_layer_names, 0, sizeof(cache->uv_layer_names));
865  memset(cache->col_layer_names, 0, sizeof(cache->col_layer_names));
866 
867  /* Strand Data */
868  cache->proc_strand_buf = GPU_vertbuf_create_with_format(&format_data);
870  GPU_vertbuf_attr_get_raw_data(cache->proc_strand_buf, data_id, &data_step);
871 
874  GPU_vertbuf_attr_get_raw_data(cache->proc_strand_seg_buf, seg_id, &seg_step);
875 
876  /* UV layers */
877  for (int i = 0; i < cache->num_uv_layers; i++) {
878  cache->proc_uv_buf[i] = GPU_vertbuf_create_with_format(&format_uv);
880  GPU_vertbuf_attr_get_raw_data(cache->proc_uv_buf[i], uv_id, &uv_step[i]);
881 
882  char attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
883  const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i);
885 
886  int n = 0;
887  BLI_snprintf(cache->uv_layer_names[i][n++], MAX_LAYER_NAME_LEN, "u%s", attr_safe_name);
888  BLI_snprintf(cache->uv_layer_names[i][n++], MAX_LAYER_NAME_LEN, "a%s", attr_safe_name);
889 
890  if (i == active_uv) {
891  BLI_strncpy(cache->uv_layer_names[i][n++], "au", MAX_LAYER_NAME_LEN);
892  }
893  if (i == render_uv) {
894  BLI_strncpy(cache->uv_layer_names[i][n++], "u", MAX_LAYER_NAME_LEN);
895  }
896  }
897  /* Vertex colors */
898  for (int i = 0; i < cache->num_col_layers; i++) {
899  cache->proc_col_buf[i] = GPU_vertbuf_create_with_format(&format_col);
901  GPU_vertbuf_attr_get_raw_data(cache->proc_col_buf[i], col_id, &col_step[i]);
902 
903  char attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
904  const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPCOL, i);
906 
907  int n = 0;
908  BLI_snprintf(cache->col_layer_names[i][n++], MAX_LAYER_NAME_LEN, "c%s", attr_safe_name);
909 
910  /* We only do vcols auto name that are not overridden by uvs */
911  if (CustomData_get_named_layer_index(&psmd->mesh_final->ldata, CD_MLOOPUV, name) == -1) {
912  BLI_snprintf(cache->col_layer_names[i][n++], MAX_LAYER_NAME_LEN, "a%s", attr_safe_name);
913  }
914 
915  if (i == active_col) {
916  BLI_strncpy(cache->col_layer_names[i][n++], "ac", MAX_LAYER_NAME_LEN);
917  }
918  if (i == render_col) {
919  BLI_strncpy(cache->col_layer_names[i][n++], "c", MAX_LAYER_NAME_LEN);
920  }
921  }
922 
923  if (cache->num_uv_layers || cache->num_col_layers) {
925  if (cache->num_uv_layers) {
926  for (int j = 0; j < cache->num_uv_layers; j++) {
927  mtfaces[j] = (MTFace *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MTFACE, j);
928  }
929  }
930  if (cache->num_col_layers) {
931  for (int j = 0; j < cache->num_col_layers; j++) {
932  mcols[j] = (MCol *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MCOL, j);
933  }
934  }
935  }
936 
937  if (edit != NULL && edit->pathcache != NULL) {
939  psmd,
940  edit->pathcache,
942  0,
943  edit->totcached,
944  &data_step,
945  &seg_step,
946  &parent_uvs,
947  uv_step,
948  (MTFace **)mtfaces,
949  cache->num_uv_layers,
950  &parent_mcol,
951  col_step,
952  (MCol **)mcols,
953  cache->num_col_layers);
954  }
955  else {
956  int curr_point = 0;
957  if ((psys->pathcache != NULL) &&
958  (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) {
959  curr_point = particle_batch_cache_fill_strands_data(psys,
960  psmd,
961  psys->pathcache,
963  0,
964  psys->totpart,
965  &data_step,
966  &seg_step,
967  &parent_uvs,
968  uv_step,
969  (MTFace **)mtfaces,
970  cache->num_uv_layers,
971  &parent_mcol,
972  col_step,
973  (MCol **)mcols,
974  cache->num_col_layers);
975  }
976  if (psys->childcache) {
977  const int child_count = psys->totchild * psys->part->disp / 100;
978  curr_point = particle_batch_cache_fill_strands_data(psys,
979  psmd,
980  psys->childcache,
982  curr_point,
983  child_count,
984  &data_step,
985  &seg_step,
986  &parent_uvs,
987  uv_step,
988  (MTFace **)mtfaces,
989  cache->num_uv_layers,
990  &parent_mcol,
991  col_step,
992  (MCol **)mcols,
993  cache->num_col_layers);
994  }
995  }
996  /* Cleanup. */
997  if (parent_uvs != NULL) {
998  /* TODO(sergey): For edit mode it should be edit->totcached. */
999  for (int i = 0; i < psys->totpart; i++) {
1000  MEM_SAFE_FREE(parent_uvs[i]);
1001  }
1002  MEM_freeN(parent_uvs);
1003  }
1004  if (parent_mcol != NULL) {
1005  for (int i = 0; i < psys->totpart; i++) {
1006  MEM_SAFE_FREE(parent_mcol[i]);
1007  }
1008  MEM_freeN(parent_mcol);
1009  }
1010 
1011  /* Create vbo immediately to bind to texture buffer. */
1013  cache->strand_tex = GPU_texture_create_from_vertbuf("part_strand", cache->proc_strand_buf);
1014 
1016  cache->strand_seg_tex = GPU_texture_create_from_vertbuf("part_strand_seg",
1017  cache->proc_strand_seg_buf);
1018 
1019  for (int i = 0; i < cache->num_uv_layers; i++) {
1020  GPU_vertbuf_use(cache->proc_uv_buf[i]);
1021  cache->uv_tex[i] = GPU_texture_create_from_vertbuf("part_uv", cache->proc_uv_buf[i]);
1022  }
1023  for (int i = 0; i < cache->num_col_layers; i++) {
1024  GPU_vertbuf_use(cache->proc_col_buf[i]);
1025  cache->col_tex[i] = GPU_texture_create_from_vertbuf("part_col", cache->proc_col_buf[i]);
1026  }
1027 }
1028 
1030  ParticleSystem *psys,
1031  ParticleHairCache *cache,
1032  int thickness_res,
1033  int subdiv)
1034 {
1035  BLI_assert(thickness_res <= MAX_THICKRES); /* Cylinder strip not currently supported. */
1036 
1037  if (cache->final[subdiv].proc_hairs[thickness_res - 1] != NULL) {
1038  return;
1039  }
1040 
1041  int verts_per_hair = cache->final[subdiv].strands_res * thickness_res;
1042  /* +1 for primitive restart */
1043  int element_count = (verts_per_hair + 1) * cache->strands_len;
1044  GPUPrimType prim_type = (thickness_res == 1) ? GPU_PRIM_LINE_STRIP : GPU_PRIM_TRI_STRIP;
1045 
1046  static GPUVertFormat format = {0};
1048 
1049  /* initialize vertex format */
1051 
1053  GPU_vertbuf_data_alloc(vbo, 1);
1054 
1055  GPUIndexBufBuilder elb;
1056  GPU_indexbuf_init_ex(&elb, prim_type, element_count, element_count);
1057 
1058  if (edit != NULL && edit->pathcache != NULL) {
1060  edit->pathcache, 0, edit->totcached, verts_per_hair, &elb);
1061  }
1062  else {
1063  int curr_point = 0;
1064  if ((psys->pathcache != NULL) &&
1065  (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) {
1067  psys->pathcache, 0, psys->totpart, verts_per_hair, &elb);
1068  }
1069  if (psys->childcache) {
1070  const int child_count = psys->totchild * psys->part->disp / 100;
1072  psys->childcache, curr_point, child_count, verts_per_hair, &elb);
1073  }
1074  }
1075 
1076  cache->final[subdiv].proc_hairs[thickness_res - 1] = GPU_batch_create_ex(
1078 }
1079 
1081  ParticleSystem *psys,
1082  ParticleHairCache *cache)
1083 {
1084  if (cache->proc_point_buf != NULL) {
1085  return;
1086  }
1087 
1088  /* initialize vertex format */
1089  GPUVertFormat format = {0};
1090  uint pos_id = GPU_vertformat_attr_add(&format, "posTime", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
1091 
1094 
1095  GPUVertBufRaw pos_step;
1096  GPU_vertbuf_attr_get_raw_data(cache->proc_point_buf, pos_id, &pos_step);
1097 
1098  if (edit != NULL && edit->pathcache != NULL) {
1100  }
1101  else {
1102  if ((psys->pathcache != NULL) &&
1103  (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) {
1105  }
1106  if (psys->childcache) {
1107  const int child_count = psys->totchild * psys->part->disp / 100;
1108  particle_batch_cache_fill_segments_proc_pos(psys->childcache, child_count, &pos_step);
1109  }
1110  }
1111 
1112  /* Create vbo immediately to bind to texture buffer. */
1114 
1115  cache->point_tex = GPU_texture_create_from_vertbuf("part_point", cache->proc_point_buf);
1116 }
1117 
1119  ParticleSystem *psys,
1120  ModifierData *md,
1121  ParticleHairCache *hair_cache)
1122 {
1123  if (hair_cache->pos != NULL && hair_cache->indices != NULL) {
1124  return;
1125  }
1126 
1127  int curr_point = 0;
1129 
1130  GPU_VERTBUF_DISCARD_SAFE(hair_cache->pos);
1131  GPU_INDEXBUF_DISCARD_SAFE(hair_cache->indices);
1132 
1133  static GPUVertFormat format = {0};
1135  uint *uv_id = NULL;
1136  uint *col_id = NULL;
1137  int num_uv_layers = 0;
1138  int num_col_layers = 0;
1139  int active_uv = 0;
1140  int active_col = 0;
1141  MTFace **mtfaces = NULL;
1142  MCol **mcols = NULL;
1143  float(**parent_uvs)[2] = NULL;
1144  MCol **parent_mcol = NULL;
1145 
1146  if (psmd != NULL) {
1148  num_uv_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPUV);
1150  }
1152  num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPCOL);
1154  }
1155  }
1156 
1158 
1159  /* initialize vertex format */
1163 
1164  if (psmd) {
1165  uv_id = MEM_mallocN(sizeof(*uv_id) * num_uv_layers, "UV attr format");
1166  col_id = MEM_mallocN(sizeof(*col_id) * num_col_layers, "Col attr format");
1167 
1168  for (int i = 0; i < num_uv_layers; i++) {
1169 
1170  char uuid[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
1171  const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i);
1173 
1174  BLI_snprintf(uuid, sizeof(uuid), "u%s", attr_safe_name);
1176 
1177  if (i == active_uv) {
1179  }
1180  }
1181 
1182  for (int i = 0; i < num_col_layers; i++) {
1183  char uuid[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
1184  const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPCOL, i);
1186 
1187  BLI_snprintf(uuid, sizeof(uuid), "c%s", attr_safe_name);
1189 
1190  if (i == active_col) {
1192  }
1193  }
1194  }
1195 
1196  hair_cache->pos = GPU_vertbuf_create_with_format(&format);
1197  GPU_vertbuf_data_alloc(hair_cache->pos, hair_cache->point_len);
1198 
1199  GPUIndexBufBuilder elb;
1200  GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, hair_cache->elems_len, hair_cache->point_len);
1201 
1202  if (num_uv_layers || num_col_layers) {
1204  if (num_uv_layers) {
1205  mtfaces = MEM_mallocN(sizeof(*mtfaces) * num_uv_layers, "Faces UV layers");
1206  for (int i = 0; i < num_uv_layers; i++) {
1207  mtfaces[i] = (MTFace *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MTFACE, i);
1208  }
1209  }
1210  if (num_col_layers) {
1211  mcols = MEM_mallocN(sizeof(*mcols) * num_col_layers, "Color layers");
1212  for (int i = 0; i < num_col_layers; i++) {
1213  mcols[i] = (MCol *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MCOL, i);
1214  }
1215  }
1216  }
1217 
1218  if (edit != NULL && edit->pathcache != NULL) {
1219  curr_point = particle_batch_cache_fill_segments(psys,
1220  psmd,
1221  edit->pathcache,
1223  0,
1224  0,
1225  edit->totcached,
1226  num_uv_layers,
1227  num_col_layers,
1228  mtfaces,
1229  mcols,
1230  uv_id,
1231  col_id,
1232  &parent_uvs,
1233  &parent_mcol,
1234  &elb,
1235  &attr_id,
1236  hair_cache);
1237  }
1238  else {
1239  if ((psys->pathcache != NULL) &&
1240  (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) {
1241  curr_point = particle_batch_cache_fill_segments(psys,
1242  psmd,
1243  psys->pathcache,
1245  0,
1246  0,
1247  psys->totpart,
1248  num_uv_layers,
1249  num_col_layers,
1250  mtfaces,
1251  mcols,
1252  uv_id,
1253  col_id,
1254  &parent_uvs,
1255  &parent_mcol,
1256  &elb,
1257  &attr_id,
1258  hair_cache);
1259  }
1260  if (psys->childcache != NULL) {
1261  const int child_count = psys->totchild * psys->part->disp / 100;
1262  curr_point = particle_batch_cache_fill_segments(psys,
1263  psmd,
1264  psys->childcache,
1266  psys->totpart,
1267  curr_point,
1268  child_count,
1269  num_uv_layers,
1270  num_col_layers,
1271  mtfaces,
1272  mcols,
1273  uv_id,
1274  col_id,
1275  &parent_uvs,
1276  &parent_mcol,
1277  &elb,
1278  &attr_id,
1279  hair_cache);
1280  }
1281  }
1282  /* Cleanup. */
1283  if (parent_uvs != NULL) {
1284  /* TODO(sergey): For edit mode it should be edit->totcached. */
1285  for (int i = 0; i < psys->totpart; i++) {
1286  MEM_SAFE_FREE(parent_uvs[i]);
1287  }
1288  MEM_freeN(parent_uvs);
1289  }
1290  if (parent_mcol != NULL) {
1291  for (int i = 0; i < psys->totpart; i++) {
1292  MEM_SAFE_FREE(parent_mcol[i]);
1293  }
1294  MEM_freeN(parent_mcol);
1295  }
1296  if (num_uv_layers) {
1297  MEM_freeN(mtfaces);
1298  }
1299  if (num_col_layers) {
1300  MEM_freeN(mcols);
1301  }
1302  if (psmd != NULL) {
1303  MEM_freeN(uv_id);
1304  }
1305  hair_cache->indices = GPU_indexbuf_build(&elb);
1306 }
1307 
1309  ParticleSystem *psys,
1310  ParticlePointCache *point_cache)
1311 {
1312  if (point_cache->pos != NULL) {
1313  return;
1314  }
1315 
1316  static GPUVertFormat format = {0};
1317  static uint pos_id, rot_id, val_id;
1318  int i, curr_point;
1319  ParticleData *pa;
1321  ParticleSimulationData sim = {NULL};
1322  const DRWContextState *draw_ctx = DRW_context_state_get();
1323 
1324  sim.depsgraph = draw_ctx->depsgraph;
1325  sim.scene = draw_ctx->scene;
1326  sim.ob = object;
1327  sim.psys = psys;
1328  sim.psmd = psys_get_modifier(object, psys);
1330 
1331  GPU_VERTBUF_DISCARD_SAFE(point_cache->pos);
1332 
1333  if (format.attr_len == 0) {
1334  /* initialize vertex format */
1335  pos_id = GPU_vertformat_attr_add(&format, "part_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1336  val_id = GPU_vertformat_attr_add(&format, "part_val", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
1337  rot_id = GPU_vertformat_attr_add(&format, "part_rot", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
1338  }
1339 
1340  point_cache->pos = GPU_vertbuf_create_with_format(&format);
1341  GPU_vertbuf_data_alloc(point_cache->pos, psys->totpart);
1342 
1343  for (curr_point = 0, i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) {
1344  state.time = DEG_get_ctime(draw_ctx->depsgraph);
1345  if (!psys_get_particle_state(&sim, i, &state, 0)) {
1346  continue;
1347  }
1348 
1349  float val;
1350 
1351  GPU_vertbuf_attr_set(point_cache->pos, pos_id, curr_point, state.co);
1352  GPU_vertbuf_attr_set(point_cache->pos, rot_id, curr_point, state.rot);
1353 
1354  switch (psys->part->draw_col) {
1355  case PART_DRAW_COL_VEL:
1356  val = len_v3(state.vel) / psys->part->color_vec_max;
1357  break;
1358  case PART_DRAW_COL_ACC:
1359  val = len_v3v3(state.vel, pa->prev_state.vel) /
1360  ((state.time - pa->prev_state.time) * psys->part->color_vec_max);
1361  break;
1362  default:
1363  val = -1.0f;
1364  break;
1365  }
1366 
1367  GPU_vertbuf_attr_set(point_cache->pos, val_id, curr_point, &val);
1368 
1369  curr_point++;
1370  }
1371 
1372  if (curr_point != psys->totpart) {
1373  GPU_vertbuf_data_resize(point_cache->pos, curr_point);
1374  }
1375 }
1376 
1377 static void drw_particle_update_ptcache_edit(Object *object_eval,
1378  ParticleSystem *psys,
1379  PTCacheEdit *edit)
1380 {
1381  if (edit->psys == NULL) {
1382  return;
1383  }
1384  /* NOTE: Get flag from particle system coming from drawing object.
1385  * this is where depsgraph will be setting flags to.
1386  */
1387  const DRWContextState *draw_ctx = DRW_context_state_get();
1388  Scene *scene_orig = (Scene *)DEG_get_original_id(&draw_ctx->scene->id);
1389  Object *object_orig = DEG_get_original_object(object_eval);
1390  if (psys->flag & PSYS_HAIR_UPDATED) {
1391  PE_update_object(draw_ctx->depsgraph, scene_orig, object_orig, 0);
1392  psys->flag &= ~PSYS_HAIR_UPDATED;
1393  }
1394  if (edit->pathcache == NULL) {
1395  Depsgraph *depsgraph = draw_ctx->depsgraph;
1397  scene_orig,
1398  object_orig,
1399  edit,
1402  }
1403 }
1404 
1405 static void drw_particle_update_ptcache(Object *object_eval, ParticleSystem *psys)
1406 {
1407  if ((object_eval->mode & OB_MODE_PARTICLE_EDIT) == 0) {
1408  return;
1409  }
1410  const DRWContextState *draw_ctx = DRW_context_state_get();
1411  Scene *scene_orig = (Scene *)DEG_get_original_id(&draw_ctx->scene->id);
1412  Object *object_orig = DEG_get_original_object(object_eval);
1413  PTCacheEdit *edit = PE_create_current(draw_ctx->depsgraph, scene_orig, object_orig);
1414  if (edit != NULL) {
1415  drw_particle_update_ptcache_edit(object_eval, psys, edit);
1416  }
1417 }
1418 
1419 typedef struct ParticleDrawSource {
1425 
1427  ParticleSystem *psys,
1428  ModifierData *md,
1429  PTCacheEdit *edit,
1430  ParticleDrawSource *r_draw_source)
1431 {
1432  const DRWContextState *draw_ctx = DRW_context_state_get();
1433  r_draw_source->object = object;
1434  r_draw_source->psys = psys;
1435  r_draw_source->md = md;
1436  r_draw_source->edit = edit;
1437  if (psys_in_edit_mode(draw_ctx->depsgraph, psys)) {
1438  r_draw_source->object = DEG_get_original_object(object);
1439  r_draw_source->psys = psys_orig_get(psys);
1440  }
1441 }
1442 
1444  ParticleSystem *psys,
1445  ModifierData *md)
1446 {
1448  if (cache->hair.hairs == NULL) {
1449  drw_particle_update_ptcache(object, psys);
1450  ParticleDrawSource source;
1451  drw_particle_get_hair_source(object, psys, md, NULL, &source);
1452  ensure_seg_pt_count(source.edit, source.psys, &cache->hair);
1453  particle_batch_cache_ensure_pos_and_seg(source.edit, source.psys, source.md, &cache->hair);
1454  cache->hair.hairs = GPU_batch_create(
1455  GPU_PRIM_LINE_STRIP, cache->hair.pos, cache->hair.indices);
1456  }
1457  return cache->hair.hairs;
1458 }
1459 
1461 {
1463 
1464  if (cache->point.points == NULL) {
1465  particle_batch_cache_ensure_pos(object, psys, &cache->point);
1467  }
1468 
1469  return cache->point.points;
1470 }
1471 
1473  ParticleSystem *psys,
1474  ModifierData *UNUSED(md),
1475  ParticleHairCache *hair_cache,
1476  bool use_weight)
1477 {
1478  if (hair_cache->pos != NULL && hair_cache->indices != NULL) {
1479  return;
1480  }
1481 
1482  ParticleData *particle = (use_weight) ? psys->particles : NULL;
1483 
1484  GPU_VERTBUF_DISCARD_SAFE(hair_cache->pos);
1485  GPU_INDEXBUF_DISCARD_SAFE(hair_cache->indices);
1486 
1487  GPUVertBufRaw data_step;
1488  GPUIndexBufBuilder elb;
1489  uint pos_id, color_id;
1490  GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id);
1491 
1492  hair_cache->pos = GPU_vertbuf_create_with_format(edit_point_format);
1493  GPU_vertbuf_data_alloc(hair_cache->pos, hair_cache->point_len);
1494  GPU_vertbuf_attr_get_raw_data(hair_cache->pos, pos_id, &data_step);
1495 
1496  GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, hair_cache->elems_len, hair_cache->point_len);
1497 
1498  if (edit != NULL && edit->pathcache != NULL) {
1500  edit, particle, edit->pathcache, 0, edit->totcached, &elb, &data_step);
1501  }
1502  else {
1503  BLI_assert(!"Hairs are not in edit mode!");
1504  }
1505  hair_cache->indices = GPU_indexbuf_build(&elb);
1506 }
1507 
1509  ParticleSystem *psys,
1510  PTCacheEdit *edit,
1511  bool use_weight)
1512 {
1514  if (cache->edit_is_weight != use_weight) {
1517  }
1518  if (cache->edit_hair.hairs != NULL) {
1519  return cache->edit_hair.hairs;
1520  }
1521  drw_particle_update_ptcache_edit(object, psys, edit);
1522  ensure_seg_pt_count(edit, psys, &cache->edit_hair);
1523  particle_batch_cache_ensure_edit_pos_and_seg(edit, psys, NULL, &cache->edit_hair, use_weight);
1524  cache->edit_hair.hairs = GPU_batch_create(
1526  cache->edit_is_weight = use_weight;
1527  return cache->edit_hair.hairs;
1528 }
1529 
1531 {
1532  if (cache->edit_inner_pos != NULL) {
1533  return;
1534  }
1535  cache->edit_inner_point_len = 0;
1536  for (int point_index = 0; point_index < edit->totpoint; point_index++) {
1537  const PTCacheEditPoint *point = &edit->points[point_index];
1538  if (point->flag & PEP_HIDE) {
1539  continue;
1540  }
1541  BLI_assert(point->totkey >= 1);
1542  cache->edit_inner_point_len += (point->totkey - 1);
1543  }
1544 }
1545 
1547  ParticleBatchCache *cache)
1548 {
1549  if (cache->edit_inner_pos != NULL) {
1550  return;
1551  }
1552 
1553  uint pos_id, color_id;
1554  GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id);
1555 
1556  cache->edit_inner_pos = GPU_vertbuf_create_with_format(edit_point_format);
1558 
1559  int global_key_index = 0;
1560  for (int point_index = 0; point_index < edit->totpoint; point_index++) {
1561  const PTCacheEditPoint *point = &edit->points[point_index];
1562  if (point->flag & PEP_HIDE) {
1563  continue;
1564  }
1565  for (int key_index = 0; key_index < point->totkey - 1; key_index++) {
1566  PTCacheEditKey *key = &point->keys[key_index];
1567  float color = (key->flag & PEK_SELECT) ? 1.0f : 0.0f;
1568  GPU_vertbuf_attr_set(cache->edit_inner_pos, pos_id, global_key_index, key->world_co);
1569  GPU_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, &color);
1570  global_key_index++;
1571  }
1572  }
1573 }
1574 
1576  ParticleSystem *psys,
1577  PTCacheEdit *edit)
1578 {
1580  if (cache->edit_inner_points != NULL) {
1581  return cache->edit_inner_points;
1582  }
1583  drw_particle_update_ptcache_edit(object, psys, edit);
1584  ensure_edit_inner_points_count(edit, cache);
1587  return cache->edit_inner_points;
1588 }
1589 
1591 {
1592  if (cache->edit_tip_pos != NULL) {
1593  return;
1594  }
1595  cache->edit_tip_point_len = 0;
1596  for (int point_index = 0; point_index < edit->totpoint; point_index++) {
1597  const PTCacheEditPoint *point = &edit->points[point_index];
1598  if (point->flag & PEP_HIDE) {
1599  continue;
1600  }
1601  cache->edit_tip_point_len += 1;
1602  }
1603 }
1604 
1606 {
1607  if (cache->edit_tip_pos != NULL) {
1608  return;
1609  }
1610 
1611  uint pos_id, color_id;
1612  GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id);
1613 
1614  cache->edit_tip_pos = GPU_vertbuf_create_with_format(edit_point_format);
1616 
1617  int global_point_index = 0;
1618  for (int point_index = 0; point_index < edit->totpoint; point_index++) {
1619  const PTCacheEditPoint *point = &edit->points[point_index];
1620  if (point->flag & PEP_HIDE) {
1621  continue;
1622  }
1623  PTCacheEditKey *key = &point->keys[point->totkey - 1];
1624  float color = (key->flag & PEK_SELECT) ? 1.0f : 0.0f;
1625 
1626  GPU_vertbuf_attr_set(cache->edit_tip_pos, pos_id, global_point_index, key->world_co);
1627  GPU_vertbuf_attr_set(cache->edit_tip_pos, color_id, global_point_index, &color);
1628  global_point_index++;
1629  }
1630 }
1631 
1633  ParticleSystem *psys,
1634  PTCacheEdit *edit)
1635 {
1637  if (cache->edit_tip_points != NULL) {
1638  return cache->edit_tip_points;
1639  }
1640  drw_particle_update_ptcache_edit(object, psys, edit);
1641  ensure_edit_tip_points_count(edit, cache);
1644  return cache->edit_tip_points;
1645 }
1646 
1647 /* Ensure all textures and buffers needed for GPU accelerated drawing. */
1649  ParticleSystem *psys,
1650  ModifierData *md,
1651  ParticleHairCache **r_hair_cache,
1652  int subdiv,
1653  int thickness_res)
1654 {
1655  bool need_ft_update = false;
1656 
1657  drw_particle_update_ptcache(object, psys);
1658 
1659  ParticleDrawSource source;
1660  drw_particle_get_hair_source(object, psys, md, NULL, &source);
1661 
1662  ParticleSettings *part = source.psys->part;
1664  *r_hair_cache = &cache->hair;
1665 
1666  (*r_hair_cache)->final[subdiv].strands_res = 1 << (part->draw_step + subdiv);
1667 
1668  /* Refreshed on combing and simulation. */
1669  if ((*r_hair_cache)->proc_point_buf == NULL) {
1670  ensure_seg_pt_count(source.edit, source.psys, &cache->hair);
1671  particle_batch_cache_ensure_procedural_pos(source.edit, source.psys, &cache->hair);
1672  need_ft_update = true;
1673  }
1674 
1675  /* Refreshed if active layer or custom data changes. */
1676  if ((*r_hair_cache)->strand_tex == NULL) {
1678  source.edit, source.psys, source.md, &cache->hair);
1679  }
1680 
1681  /* Refreshed only on subdiv count change. */
1682  if ((*r_hair_cache)->final[subdiv].proc_buf == NULL) {
1684  need_ft_update = true;
1685  }
1686  if ((*r_hair_cache)->final[subdiv].proc_hairs[thickness_res - 1] == NULL) {
1688  source.edit, source.psys, &cache->hair, thickness_res, subdiv);
1689  }
1690 
1691  return need_ft_update;
1692 }
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
const char * CustomData_get_layer_name(const struct CustomData *data, int type, int n)
int CustomData_number_of_layers(const struct CustomData *data, int type)
bool CustomData_has_layer(const struct CustomData *data, int type)
int CustomData_get_named_layer_index(const struct CustomData *data, int type, const char *name)
int CustomData_get_active_layer(const struct CustomData *data, int type)
void * CustomData_get_layer_n(const struct CustomData *data, int type, int n)
int CustomData_get_render_layer(const struct CustomData *data, int type)
void BKE_mesh_tessface_ensure(struct Mesh *mesh)
Definition: mesh.c:1560
void psys_cache_edit_paths(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct PTCacheEdit *edit, float cfra, const bool use_render_params)
Definition: particle.c:3686
#define DMCACHE_NOTFOUND
Definition: BKE_particle.h:606
struct LatticeDeformData * psys_create_lattice_deform_data(struct ParticleSimulationData *sim)
Definition: particle.c:696
struct ParticleSystem * psys_orig_get(struct ParticleSystem *psys)
Definition: particle.c:741
void psys_interpolate_uvs(const struct MTFace *tface, int quad, const float w[4], float uvco[2])
bool psys_in_edit_mode(struct Depsgraph *depsgraph, const struct ParticleSystem *psys)
int psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, int always)
Definition: particle.c:4854
struct ParticleSystemModifierData * psys_get_modifier(struct Object *ob, struct ParticleSystem *psys)
Definition: particle.c:2201
#define DMCACHE_ISCHILD
Definition: BKE_particle.h:607
void psys_interpolate_mcol(const struct MCol *mcol, int quad, const float w[4], struct MCol *mc)
@ BKE_PARTICLE_BATCH_DIRTY_ALL
Definition: BKE_particle.h:620
#define PEP_HIDE
#define PEK_SELECT
#define BLI_assert(a)
Definition: BLI_assert.h:58
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
unsigned int uint
Definition: BLI_sys_types.h:83
unsigned short ushort
Definition: BLI_sys_types.h:84
#define UNUSED(x)
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
@ DAG_EVAL_RENDER
Definition: DEG_depsgraph.h:62
float DEG_get_ctime(const Depsgraph *graph)
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
struct Object * DEG_get_original_object(struct Object *object)
struct ID * DEG_get_original_id(struct ID *id)
#define MAX_MCOL
@ CD_MLOOPCOL
@ CD_MLOOPUV
#define MAX_MTFACE
@ OB_MODE_PARTICLE_EDIT
#define PART_FROM_VOLUME
#define PART_FROM_FACE
#define PART_CHILD_PARTICLES
@ PART_DRAW_PARENT
#define PART_DRAW_COL_ACC
#define PART_DRAW_COL_VEL
#define PSYS_HAIR_UPDATED
#define DRW_TEXTURE_FREE_SAFE(tex)
Definition: DRW_render.h:180
struct PTCacheEdit * PE_create_current(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob)
void PE_update_object(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, int useflag)
GPUBatch
Definition: GPU_batch.h:93
#define GPU_batch_create(prim, verts, elem)
Definition: GPU_batch.h:107
#define GPU_BATCH_DISCARD_SAFE(batch)
Definition: GPU_batch.h:199
GPUBatch * GPU_batch_create_ex(GPUPrimType prim, GPUVertBuf *vert, GPUIndexBuf *elem, eGPUBatchFlag owns_flag)
Definition: gpu_batch.cc:60
@ GPU_BATCH_OWNS_INDEX
Definition: GPU_batch.h:54
@ GPU_BATCH_OWNS_VBO
Definition: GPU_batch.h:45
#define GPU_INDEXBUF_DISCARD_SAFE(elem)
void GPU_indexbuf_add_primitive_restart(GPUIndexBufBuilder *)
GPUIndexBuf * GPU_indexbuf_build(GPUIndexBufBuilder *)
void GPU_indexbuf_add_generic_vert(GPUIndexBufBuilder *, uint v)
void GPU_indexbuf_init_ex(GPUIndexBufBuilder *, GPUPrimType, uint index_len, uint vertex_len)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
GPUPrimType
Definition: GPU_primitive.h:34
@ GPU_PRIM_POINTS
Definition: GPU_primitive.h:35
@ GPU_PRIM_LINE_STRIP
Definition: GPU_primitive.h:38
@ GPU_PRIM_TRI_STRIP
Definition: GPU_primitive.h:40
GPUTexture * GPU_texture_create_from_vertbuf(const char *name, struct GPUVertBuf *vert)
Definition: gpu_texture.cc:315
#define GPU_vertbuf_create_with_format(format)
struct GPUVertBuf GPUVertBuf
void GPU_vertbuf_data_alloc(GPUVertBuf *, uint v_len)
#define GPU_VERTBUF_DISCARD_SAFE(verts)
void GPU_vertbuf_use(GPUVertBuf *)
GPU_INLINE void * GPU_vertbuf_raw_step(GPUVertBufRaw *a)
void GPU_vertbuf_attr_get_raw_data(GPUVertBuf *, uint a_idx, GPUVertBufRaw *access)
void GPU_vertbuf_attr_set(GPUVertBuf *, uint a_idx, uint v_idx, const void *data)
void GPU_vertbuf_data_resize(GPUVertBuf *, uint v_len)
void GPU_vertformat_safe_attr_name(const char *attr_name, char *r_safe_name, uint max_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)
#define GPU_MAX_SAFE_ATTR_NAME
void GPU_vertformat_clear(GPUVertFormat *)
void GPU_vertformat_alias_add(GPUVertFormat *, const char *alias)
@ GPU_COMP_U16
@ GPU_COMP_F32
@ GPU_COMP_I32
@ GPU_COMP_U32
@ GPU_COMP_U8
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
const Depsgraph * depsgraph
static void particle_batch_cache_ensure_procedural_indices(PTCacheEdit *edit, ParticleSystem *psys, ParticleHairCache *cache, int thickness_res, int subdiv)
static void particle_batch_cache_ensure_pos(Object *object, ParticleSystem *psys, ParticlePointCache *point_cache)
static void particle_batch_cache_clear(ParticleSystem *psys)
struct EditStrandData EditStrandData
static void count_cache_segment_keys(ParticleCacheKey **pathcache, const int num_path_cache_keys, ParticleHairCache *hair_cache)
static void particle_pack_mcol(MCol *mcol, ushort r_scol[3])
void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache)
static int particle_batch_cache_fill_segments_edit(const PTCacheEdit *UNUSED(edit), const ParticleData *particle, ParticleCacheKey **path_cache, const int start_index, const int num_path_keys, GPUIndexBufBuilder *elb, GPUVertBufRaw *attr_step)
static void particle_batch_cache_ensure_edit_tip_pos(PTCacheEdit *edit, ParticleBatchCache *cache)
GPUBatch * DRW_particles_batch_cache_get_edit_strands(Object *object, ParticleSystem *psys, PTCacheEdit *edit, bool use_weight)
static void particle_batch_cache_init(ParticleSystem *psys)
static void particle_batch_cache_clear_point(ParticlePointCache *point_cache)
struct ParticleDrawSource ParticleDrawSource
GPUBatch * DRW_particles_batch_cache_get_dots(Object *object, ParticleSystem *psys)
static float particle_key_weight(const ParticleData *particle, int strand, float t)
static ParticleBatchCache * particle_batch_cache_get(ParticleSystem *psys)
static void particle_calculate_mcol(ParticleSystem *psys, ParticleSystemModifierData *psmd, const bool is_simple, const int num_col_layers, const int parent_index, const int child_index, MCol **mcols, MCol **r_parent_mcol, MCol **r_mcol)
static void ensure_edit_tip_points_count(const PTCacheEdit *edit, ParticleBatchCache *cache)
GPUBatch * DRW_particles_batch_cache_get_edit_inner_points(Object *object, ParticleSystem *psys, PTCacheEdit *edit)
GPUBatch * DRW_particles_batch_cache_get_edit_tip_points(Object *object, ParticleSystem *psys, PTCacheEdit *edit)
static void ensure_edit_inner_points_count(const PTCacheEdit *edit, ParticleBatchCache *cache)
struct HairAttributeID HairAttributeID
static void drw_particle_get_hair_source(Object *object, ParticleSystem *psys, ModifierData *md, PTCacheEdit *edit, ParticleDrawSource *r_draw_source)
static void particle_batch_cache_ensure_pos_and_seg(PTCacheEdit *edit, ParticleSystem *psys, ModifierData *md, ParticleHairCache *hair_cache)
static GPUVertFormat * edit_points_vert_format_get(uint *r_pos_id, uint *r_color_id)
bool particles_ensure_procedural_data(Object *object, ParticleSystem *psys, ModifierData *md, ParticleHairCache **r_hair_cache, int subdiv, int thickness_res)
GPUBatch * DRW_particles_batch_cache_get_hair(Object *object, ParticleSystem *psys, ModifierData *md)
void DRW_particle_batch_cache_free(ParticleSystem *psys)
static void particle_calculate_uvs(ParticleSystem *psys, ParticleSystemModifierData *psmd, const bool is_simple, const int num_uv_layers, const int parent_index, const int child_index, MTFace **mtfaces, float(**r_parent_uvs)[2], float(**r_uv)[2])
static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit, ParticleSystem *psys, ModifierData *md, ParticleHairCache *cache)
static void drw_particle_update_ptcache(Object *object_eval, ParticleSystem *psys)
static void particle_batch_cache_fill_segments_proc_pos(ParticleCacheKey **path_cache, const int num_path_keys, GPUVertBufRaw *attr_step)
static int particle_batch_cache_fill_segments_indices(ParticleCacheKey **path_cache, const int start_index, const int num_path_keys, const int res, GPUIndexBufBuilder *elb)
static void particle_calculate_parent_uvs(ParticleSystem *psys, ParticleSystemModifierData *psmd, const int num_uv_layers, const int parent_index, MTFace **mtfaces, float(*r_uv)[2])
static void particle_batch_cache_ensure_procedural_final_points(ParticleHairCache *cache, int subdiv)
static bool particle_batch_cache_valid(ParticleSystem *psys)
static void drw_particle_update_ptcache_edit(Object *object_eval, ParticleSystem *psys, PTCacheEdit *edit)
static int particle_batch_cache_fill_segments(ParticleSystem *psys, ParticleSystemModifierData *psmd, ParticleCacheKey **path_cache, const ParticleSource particle_source, const int global_offset, const int start_index, const int num_path_keys, const int num_uv_layers, const int num_col_layers, MTFace **mtfaces, MCol **mcols, uint *uv_id, uint *col_id, float(***r_parent_uvs)[2], MCol ***r_parent_mcol, GPUIndexBufBuilder *elb, HairAttributeID *attr_id, ParticleHairCache *hair_cache)
static void particle_batch_cache_ensure_edit_pos_and_seg(PTCacheEdit *edit, ParticleSystem *psys, ModifierData *UNUSED(md), ParticleHairCache *hair_cache, bool use_weight)
static int particle_batch_cache_fill_strands_data(ParticleSystem *psys, ParticleSystemModifierData *psmd, ParticleCacheKey **path_cache, const ParticleSource particle_source, const int start_index, const int num_path_keys, GPUVertBufRaw *data_step, GPUVertBufRaw *seg_step, float(***r_parent_uvs)[2], GPUVertBufRaw *uv_step, MTFace **mtfaces, int num_uv_layers, MCol ***r_parent_mcol, GPUVertBufRaw *col_step, MCol **mcols, int num_col_layers)
static void particle_interpolate_children_mcol(ParticleSystem *psys, ParticleSystemModifierData *psmd, const int num_col_layers, const int child_index, MCol **mcols, MCol *r_mcol)
static void particle_interpolate_children_uvs(ParticleSystem *psys, ParticleSystemModifierData *psmd, const int num_uv_layers, const int child_index, MTFace **mtfaces, float(*r_uv)[2])
static void particle_batch_cache_ensure_procedural_pos(PTCacheEdit *edit, ParticleSystem *psys, ParticleHairCache *cache)
static void ensure_seg_pt_count(PTCacheEdit *edit, ParticleSystem *psys, ParticleHairCache *hair_cache)
struct ParticlePointCache ParticlePointCache
struct ParticleBatchCache ParticleBatchCache
void DRW_particle_batch_cache_dirty_tag(ParticleSystem *psys, int mode)
@ PARTICLE_SOURCE_CHILDREN
@ PARTICLE_SOURCE_PARENT
static void particle_calculate_parent_mcol(ParticleSystem *psys, ParticleSystemModifierData *psmd, const int num_col_layers, const int parent_index, MCol **mcols, MCol *r_mcol)
static void particle_batch_cache_ensure_edit_inner_pos(PTCacheEdit *edit, ParticleBatchCache *cache)
#define MAX_THICKRES
#define MAX_LAYER_NAME_LEN
#define MAX_HAIR_SUBDIV
const DRWContextState * DRW_context_state_get(void)
struct @612::@615 attr_id
#define floorf(x)
format
Definition: logImageCore.h:47
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
MINLINE unsigned short unit_float_to_ushort_clamp(float val)
float BLI_color_from_srgb_table[256]
Definition: math_color.c:556
static ulong state[N]
static bool is_child(const Object *ob, const Object *parent)
struct Scene * scene
Definition: DRW_render.h:745
struct Depsgraph * depsgraph
Definition: DRW_render.h:753
unsigned char r
unsigned char g
unsigned char b
unsigned int v4
struct CustomData pdata ldata
int totface
struct CustomData vdata edata fdata
struct MFace * mface
struct PTCacheEditKey * keys
struct ParticleCacheKey ** pathcache
PTCacheEditPoint * points
struct ParticleSystem * psys
ParticleKey prev_state
GPUVertBuf * proc_point_buf
GPUTexture * uv_tex[MAX_MTFACE]
GPUVertBuf * proc_strand_buf
GPUIndexBuf * indices
GPUVertBuf * proc_col_buf[MAX_MCOL]
char uv_layer_names[MAX_MTFACE][MAX_LAYER_NAME_CT][MAX_LAYER_NAME_LEN]
GPUTexture * strand_seg_tex
GPUVertBuf * proc_strand_seg_buf
GPUTexture * point_tex
char col_layer_names[MAX_MCOL][MAX_LAYER_NAME_CT][MAX_LAYER_NAME_LEN]
GPUTexture * strand_tex
GPUVertBuf * proc_uv_buf[MAX_MTFACE]
GPUTexture * col_tex[MAX_MCOL]
ParticleHairFinalCache final[MAX_HAIR_SUBDIV]
GPUBatch * proc_hairs[MAX_THICKRES]
struct Depsgraph * depsgraph
Definition: BKE_particle.h:87
struct ParticleSystemModifierData * psmd
Definition: BKE_particle.h:91
struct Scene * scene
Definition: BKE_particle.h:88
struct ParticleSystem * psys
Definition: BKE_particle.h:90
struct Object * ob
Definition: BKE_particle.h:89
struct ParticleSystem * psys
ChildParticle * child
ParticleData * particles
ParticleSettings * part
struct LatticeDeformData * lattice_deform_data
struct ParticleCacheKey ** childcache
struct ParticleCacheKey ** pathcache
ccl_device_inline float2 interp(const float2 &a, const float2 &b, float t)