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