diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/draw/intern/draw_cache_impl_particles.c | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/draw/intern/draw_cache_impl_particles.c')
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_particles.c | 2882 |
1 files changed, 1433 insertions, 1449 deletions
diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c index b23d5e0fb9c..e998b17a44f 100644 --- a/source/blender/draw/intern/draw_cache_impl_particles.c +++ b/source/blender/draw/intern/draw_cache_impl_particles.c @@ -48,7 +48,7 @@ #include "DEG_depsgraph_query.h" -#include "draw_cache_impl.h" /* own include */ +#include "draw_cache_impl.h" /* own include */ #include "draw_hair_private.h" static void particle_batch_cache_clear(ParticleSystem *psys); @@ -57,1640 +57,1624 @@ static void particle_batch_cache_clear(ParticleSystem *psys); /* Particle GPUBatch Cache */ typedef struct ParticlePointCache { - GPUVertBuf *pos; - GPUBatch *points; - int elems_len; - int point_len; + GPUVertBuf *pos; + GPUBatch *points; + int elems_len; + int point_len; } ParticlePointCache; typedef struct ParticleBatchCache { - /* Object mode strands for hair and points for particle, - * strands for paths when in edit mode. - */ - ParticleHairCache hair; /* Used for hair strands */ - ParticlePointCache point; /* Used for particle points. */ + /* Object mode strands for hair and points for particle, + * strands for paths when in edit mode. + */ + ParticleHairCache hair; /* Used for hair strands */ + ParticlePointCache point; /* Used for particle points. */ - /* Control points when in edit mode. */ - ParticleHairCache edit_hair; + /* Control points when in edit mode. */ + ParticleHairCache edit_hair; - GPUVertBuf *edit_pos; - GPUBatch *edit_strands; + GPUVertBuf *edit_pos; + GPUBatch *edit_strands; - GPUVertBuf *edit_inner_pos; - GPUBatch *edit_inner_points; - int edit_inner_point_len; + GPUVertBuf *edit_inner_pos; + GPUBatch *edit_inner_points; + int edit_inner_point_len; - GPUVertBuf *edit_tip_pos; - GPUBatch *edit_tip_points; - int edit_tip_point_len; + GPUVertBuf *edit_tip_pos; + GPUBatch *edit_tip_points; + int edit_tip_point_len; - /* Settings to determine if cache is invalid. */ - bool is_dirty; - bool edit_is_weight; + /* Settings to determine if cache is invalid. */ + bool is_dirty; + bool edit_is_weight; } ParticleBatchCache; /* GPUBatch cache management. */ typedef struct HairAttributeID { - uint pos; - uint tan; - uint ind; + uint pos; + uint tan; + uint ind; } HairAttributeID; typedef struct EditStrandData { - float pos[3]; - uchar color; + float pos[3]; + uchar color; } EditStrandData; static GPUVertFormat *edit_points_vert_format_get(uint *r_pos_id, uint *r_color_id) { - static GPUVertFormat edit_point_format = { 0 }; - static uint pos_id, color_id; - if (edit_point_format.attr_len == 0) { - /* Keep in sync with EditStrandData */ - pos_id = GPU_vertformat_attr_add(&edit_point_format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - color_id = GPU_vertformat_attr_add(&edit_point_format, "color", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); - } - *r_pos_id = pos_id; - *r_color_id = color_id; - return &edit_point_format; + static GPUVertFormat edit_point_format = {0}; + static uint pos_id, color_id; + if (edit_point_format.attr_len == 0) { + /* Keep in sync with EditStrandData */ + pos_id = GPU_vertformat_attr_add(&edit_point_format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + color_id = GPU_vertformat_attr_add( + &edit_point_format, "color", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); + } + *r_pos_id = pos_id; + *r_color_id = color_id; + return &edit_point_format; } static bool particle_batch_cache_valid(ParticleSystem *psys) { - ParticleBatchCache *cache = psys->batch_cache; + ParticleBatchCache *cache = psys->batch_cache; - if (cache == NULL) { - return false; - } + if (cache == NULL) { + return false; + } - if (cache->is_dirty == false) { - return true; - } - else { - return false; - } + if (cache->is_dirty == false) { + return true; + } + else { + return false; + } - return true; + return true; } static void particle_batch_cache_init(ParticleSystem *psys) { - ParticleBatchCache *cache = psys->batch_cache; + ParticleBatchCache *cache = psys->batch_cache; - if (!cache) { - cache = psys->batch_cache = MEM_callocN(sizeof(*cache), __func__); - } - else { - memset(cache, 0, sizeof(*cache)); - } + if (!cache) { + cache = psys->batch_cache = MEM_callocN(sizeof(*cache), __func__); + } + else { + memset(cache, 0, sizeof(*cache)); + } - cache->is_dirty = false; + cache->is_dirty = false; } static ParticleBatchCache *particle_batch_cache_get(ParticleSystem *psys) { - if (!particle_batch_cache_valid(psys)) { - particle_batch_cache_clear(psys); - particle_batch_cache_init(psys); - } - return psys->batch_cache; + if (!particle_batch_cache_valid(psys)) { + particle_batch_cache_clear(psys); + particle_batch_cache_init(psys); + } + return psys->batch_cache; } void DRW_particle_batch_cache_dirty_tag(ParticleSystem *psys, int mode) { - ParticleBatchCache *cache = psys->batch_cache; - if (cache == NULL) { - return; - } - switch (mode) { - case BKE_PARTICLE_BATCH_DIRTY_ALL: - cache->is_dirty = true; - break; - default: - BLI_assert(0); - } + ParticleBatchCache *cache = psys->batch_cache; + if (cache == NULL) { + return; + } + switch (mode) { + case BKE_PARTICLE_BATCH_DIRTY_ALL: + cache->is_dirty = true; + break; + default: + BLI_assert(0); + } } static void particle_batch_cache_clear_point(ParticlePointCache *point_cache) { - GPU_BATCH_DISCARD_SAFE(point_cache->points); - GPU_VERTBUF_DISCARD_SAFE(point_cache->pos); + GPU_BATCH_DISCARD_SAFE(point_cache->points); + GPU_VERTBUF_DISCARD_SAFE(point_cache->pos); } static void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache) { - /* TODO more granular update tagging. */ - GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_point_buf); - DRW_TEXTURE_FREE_SAFE(hair_cache->point_tex); - - GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_strand_buf); - GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_strand_seg_buf); - DRW_TEXTURE_FREE_SAFE(hair_cache->strand_tex); - DRW_TEXTURE_FREE_SAFE(hair_cache->strand_seg_tex); - - for (int i = 0; i < MAX_MTFACE; ++i) { - GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_uv_buf[i]); - DRW_TEXTURE_FREE_SAFE(hair_cache->uv_tex[i]); - } - for (int i = 0; i < MAX_MCOL; ++i) { - GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_col_buf[i]); - DRW_TEXTURE_FREE_SAFE(hair_cache->col_tex[i]); - } - for (int i = 0; i < MAX_HAIR_SUBDIV; ++i) { - GPU_VERTBUF_DISCARD_SAFE(hair_cache->final[i].proc_buf); - DRW_TEXTURE_FREE_SAFE(hair_cache->final[i].proc_tex); - for (int j = 0; j < MAX_THICKRES; ++j) { - GPU_BATCH_DISCARD_SAFE(hair_cache->final[i].proc_hairs[j]); - } - } - - /* "Normal" legacy hairs */ - GPU_BATCH_DISCARD_SAFE(hair_cache->hairs); - GPU_VERTBUF_DISCARD_SAFE(hair_cache->pos); - GPU_INDEXBUF_DISCARD_SAFE(hair_cache->indices); + /* TODO more granular update tagging. */ + GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_point_buf); + DRW_TEXTURE_FREE_SAFE(hair_cache->point_tex); + + GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_strand_buf); + GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_strand_seg_buf); + DRW_TEXTURE_FREE_SAFE(hair_cache->strand_tex); + DRW_TEXTURE_FREE_SAFE(hair_cache->strand_seg_tex); + + for (int i = 0; i < MAX_MTFACE; ++i) { + GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_uv_buf[i]); + DRW_TEXTURE_FREE_SAFE(hair_cache->uv_tex[i]); + } + for (int i = 0; i < MAX_MCOL; ++i) { + GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_col_buf[i]); + DRW_TEXTURE_FREE_SAFE(hair_cache->col_tex[i]); + } + for (int i = 0; i < MAX_HAIR_SUBDIV; ++i) { + GPU_VERTBUF_DISCARD_SAFE(hair_cache->final[i].proc_buf); + DRW_TEXTURE_FREE_SAFE(hair_cache->final[i].proc_tex); + for (int j = 0; j < MAX_THICKRES; ++j) { + GPU_BATCH_DISCARD_SAFE(hair_cache->final[i].proc_hairs[j]); + } + } + + /* "Normal" legacy hairs */ + GPU_BATCH_DISCARD_SAFE(hair_cache->hairs); + GPU_VERTBUF_DISCARD_SAFE(hair_cache->pos); + GPU_INDEXBUF_DISCARD_SAFE(hair_cache->indices); } static void particle_batch_cache_clear(ParticleSystem *psys) { - ParticleBatchCache *cache = psys->batch_cache; - if (!cache) { - return; - } + ParticleBatchCache *cache = psys->batch_cache; + if (!cache) { + return; + } - particle_batch_cache_clear_point(&cache->point); - particle_batch_cache_clear_hair(&cache->hair); + particle_batch_cache_clear_point(&cache->point); + particle_batch_cache_clear_hair(&cache->hair); - particle_batch_cache_clear_hair(&cache->edit_hair); + particle_batch_cache_clear_hair(&cache->edit_hair); - GPU_BATCH_DISCARD_SAFE(cache->edit_inner_points); - GPU_VERTBUF_DISCARD_SAFE(cache->edit_inner_pos); - GPU_BATCH_DISCARD_SAFE(cache->edit_tip_points); - GPU_VERTBUF_DISCARD_SAFE(cache->edit_tip_pos); + GPU_BATCH_DISCARD_SAFE(cache->edit_inner_points); + GPU_VERTBUF_DISCARD_SAFE(cache->edit_inner_pos); + GPU_BATCH_DISCARD_SAFE(cache->edit_tip_points); + GPU_VERTBUF_DISCARD_SAFE(cache->edit_tip_pos); } void DRW_particle_batch_cache_free(ParticleSystem *psys) { - particle_batch_cache_clear(psys); - MEM_SAFE_FREE(psys->batch_cache); + particle_batch_cache_clear(psys); + MEM_SAFE_FREE(psys->batch_cache); } -static void count_cache_segment_keys( - ParticleCacheKey **pathcache, - const int num_path_cache_keys, - ParticleHairCache *hair_cache) +static void count_cache_segment_keys(ParticleCacheKey **pathcache, + const int num_path_cache_keys, + ParticleHairCache *hair_cache) { - for (int i = 0; i < num_path_cache_keys; i++) { - ParticleCacheKey *path = pathcache[i]; - if (path->segments > 0) { - hair_cache->strands_len++; - hair_cache->elems_len += path->segments + 2; - hair_cache->point_len += path->segments + 1; - } - } + for (int i = 0; i < num_path_cache_keys; i++) { + ParticleCacheKey *path = pathcache[i]; + if (path->segments > 0) { + hair_cache->strands_len++; + hair_cache->elems_len += path->segments + 2; + hair_cache->point_len += path->segments + 1; + } + } } -static void ensure_seg_pt_count( - PTCacheEdit *edit, - ParticleSystem *psys, - ParticleHairCache *hair_cache) +static void ensure_seg_pt_count(PTCacheEdit *edit, + ParticleSystem *psys, + ParticleHairCache *hair_cache) { - if ((hair_cache->pos != NULL && hair_cache->indices != NULL) || - (hair_cache->proc_point_buf != NULL)) - { - return; - } - - hair_cache->strands_len = 0; - hair_cache->elems_len = 0; - hair_cache->point_len = 0; - - if (edit != NULL && edit->pathcache != NULL) { - count_cache_segment_keys(edit->pathcache, edit->totcached, hair_cache); - } - else { - if (psys->pathcache && - (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) - { - count_cache_segment_keys(psys->pathcache, psys->totpart, hair_cache); - } - if (psys->childcache) { - const int child_count = psys->totchild * psys->part->disp / 100; - count_cache_segment_keys(psys->childcache, child_count, hair_cache); - } - } + if ((hair_cache->pos != NULL && hair_cache->indices != NULL) || + (hair_cache->proc_point_buf != NULL)) { + return; + } + + hair_cache->strands_len = 0; + hair_cache->elems_len = 0; + hair_cache->point_len = 0; + + if (edit != NULL && edit->pathcache != NULL) { + count_cache_segment_keys(edit->pathcache, edit->totcached, hair_cache); + } + else { + if (psys->pathcache && (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) { + count_cache_segment_keys(psys->pathcache, psys->totpart, hair_cache); + } + if (psys->childcache) { + const int child_count = psys->totchild * psys->part->disp / 100; + count_cache_segment_keys(psys->childcache, child_count, hair_cache); + } + } } static void particle_pack_mcol(MCol *mcol, ushort r_scol[3]) { - /* Convert to linear ushort and swizzle */ - r_scol[0] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->b]); - r_scol[1] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->g]); - r_scol[2] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->r]); + /* Convert to linear ushort and swizzle */ + r_scol[0] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->b]); + r_scol[1] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->g]); + r_scol[2] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->r]); } /* Used by parent particles and simple children. */ -static void particle_calculate_parent_uvs( - ParticleSystem *psys, - ParticleSystemModifierData *psmd, - const int num_uv_layers, - const int parent_index, - /*const*/ MTFace **mtfaces, - float (*r_uv)[2]) +static void particle_calculate_parent_uvs(ParticleSystem *psys, + ParticleSystemModifierData *psmd, + const int num_uv_layers, + const int parent_index, + /*const*/ MTFace **mtfaces, + float (*r_uv)[2]) { - if (psmd == NULL) { - return; - } - const int emit_from = psmd->psys->part->from; - if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) { - return; - } - ParticleData *particle = &psys->particles[parent_index]; - int num = particle->num_dmcache; - if (num == DMCACHE_NOTFOUND || num == DMCACHE_ISCHILD) { - if (particle->num < psmd->mesh_final->totface) { - num = particle->num; - } - } - if (num != DMCACHE_NOTFOUND && num != DMCACHE_ISCHILD) { - MFace *mface = &psmd->mesh_final->mface[num]; - for (int j = 0; j < num_uv_layers; j++) { - psys_interpolate_uvs( - mtfaces[j] + num, - mface->v4, - particle->fuv, - r_uv[j]); - } - } + if (psmd == NULL) { + return; + } + const int emit_from = psmd->psys->part->from; + if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) { + return; + } + ParticleData *particle = &psys->particles[parent_index]; + int num = particle->num_dmcache; + if (num == DMCACHE_NOTFOUND || num == DMCACHE_ISCHILD) { + if (particle->num < psmd->mesh_final->totface) { + num = particle->num; + } + } + if (num != DMCACHE_NOTFOUND && num != DMCACHE_ISCHILD) { + MFace *mface = &psmd->mesh_final->mface[num]; + for (int j = 0; j < num_uv_layers; j++) { + psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, r_uv[j]); + } + } } -static void particle_calculate_parent_mcol( - ParticleSystem *psys, - ParticleSystemModifierData *psmd, - const int num_uv_layers, - const int parent_index, - /*const*/ MCol **mcols, - MCol *r_mcol) +static void particle_calculate_parent_mcol(ParticleSystem *psys, + ParticleSystemModifierData *psmd, + const int num_uv_layers, + const int parent_index, + /*const*/ MCol **mcols, + MCol *r_mcol) { - if (psmd == NULL) { - return; - } - const int emit_from = psmd->psys->part->from; - if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) { - return; - } - ParticleData *particle = &psys->particles[parent_index]; - int num = particle->num_dmcache; - if (num == DMCACHE_NOTFOUND || num == DMCACHE_ISCHILD) { - if (particle->num < psmd->mesh_final->totface) { - num = particle->num; - } - } - if (num != DMCACHE_NOTFOUND && num != DMCACHE_ISCHILD) { - MFace *mface = &psmd->mesh_final->mface[num]; - for (int j = 0; j < num_uv_layers; j++) { - psys_interpolate_mcol( - mcols[j] + num, - mface->v4, - particle->fuv, - &r_mcol[j]); - } - } + if (psmd == NULL) { + return; + } + const int emit_from = psmd->psys->part->from; + if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) { + return; + } + ParticleData *particle = &psys->particles[parent_index]; + int num = particle->num_dmcache; + if (num == DMCACHE_NOTFOUND || num == DMCACHE_ISCHILD) { + if (particle->num < psmd->mesh_final->totface) { + num = particle->num; + } + } + if (num != DMCACHE_NOTFOUND && num != DMCACHE_ISCHILD) { + MFace *mface = &psmd->mesh_final->mface[num]; + for (int j = 0; j < num_uv_layers; j++) { + psys_interpolate_mcol(mcols[j] + num, mface->v4, particle->fuv, &r_mcol[j]); + } + } } /* Used by interpolated children. */ -static void particle_interpolate_children_uvs( - ParticleSystem *psys, - ParticleSystemModifierData *psmd, - const int num_uv_layers, - const int child_index, - /*const*/ MTFace **mtfaces, - float (*r_uv)[2]) +static void particle_interpolate_children_uvs(ParticleSystem *psys, + ParticleSystemModifierData *psmd, + const int num_uv_layers, + const int child_index, + /*const*/ MTFace **mtfaces, + float (*r_uv)[2]) { - if (psmd == NULL) { - return; - } - const int emit_from = psmd->psys->part->from; - if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) { - return; - } - ChildParticle *particle = &psys->child[child_index]; - int num = particle->num; - if (num != DMCACHE_NOTFOUND) { - MFace *mface = &psmd->mesh_final->mface[num]; - for (int j = 0; j < num_uv_layers; j++) { - psys_interpolate_uvs( - mtfaces[j] + num, - mface->v4, - particle->fuv, - r_uv[j]); - } - } + if (psmd == NULL) { + return; + } + const int emit_from = psmd->psys->part->from; + if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) { + return; + } + ChildParticle *particle = &psys->child[child_index]; + int num = particle->num; + if (num != DMCACHE_NOTFOUND) { + MFace *mface = &psmd->mesh_final->mface[num]; + for (int j = 0; j < num_uv_layers; j++) { + psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, r_uv[j]); + } + } } -static void particle_interpolate_children_mcol( - ParticleSystem *psys, - ParticleSystemModifierData *psmd, - const int num_col_layers, - const int child_index, - /*const*/ MCol **mcols, - MCol *r_mcol) +static void particle_interpolate_children_mcol(ParticleSystem *psys, + ParticleSystemModifierData *psmd, + const int num_col_layers, + const int child_index, + /*const*/ MCol **mcols, + MCol *r_mcol) { - if (psmd == NULL) { - return; - } - const int emit_from = psmd->psys->part->from; - if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) { - return; - } - ChildParticle *particle = &psys->child[child_index]; - int num = particle->num; - if (num != DMCACHE_NOTFOUND) { - MFace *mface = &psmd->mesh_final->mface[num]; - for (int j = 0; j < num_col_layers; j++) { - psys_interpolate_mcol( - mcols[j] + num, - mface->v4, - particle->fuv, - &r_mcol[j]); - } - } + if (psmd == NULL) { + return; + } + const int emit_from = psmd->psys->part->from; + if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) { + return; + } + ChildParticle *particle = &psys->child[child_index]; + int num = particle->num; + if (num != DMCACHE_NOTFOUND) { + MFace *mface = &psmd->mesh_final->mface[num]; + for (int j = 0; j < num_col_layers; j++) { + psys_interpolate_mcol(mcols[j] + num, mface->v4, particle->fuv, &r_mcol[j]); + } + } } -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, - /*const*/ MTFace **mtfaces, - float (**r_parent_uvs)[2], - float (**r_uv)[2]) +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, + /*const*/ MTFace **mtfaces, + float (**r_parent_uvs)[2], + float (**r_uv)[2]) { - if (psmd == NULL) { - return; - } - if (is_simple) { - if (r_parent_uvs[parent_index] != NULL) { - *r_uv = r_parent_uvs[parent_index]; - } - else { - *r_uv = MEM_callocN(sizeof(**r_uv) * num_uv_layers, "Particle UVs"); - } - } - else { - *r_uv = MEM_callocN(sizeof(**r_uv) * num_uv_layers, "Particle UVs"); - } - if (child_index == -1) { - /* Calculate UVs for parent particles. */ - if (is_simple) { - r_parent_uvs[parent_index] = *r_uv; - } - particle_calculate_parent_uvs( - psys, psmd, num_uv_layers, parent_index, mtfaces, *r_uv); - } - else { - /* Calculate UVs for child particles. */ - if (!is_simple) { - particle_interpolate_children_uvs( - psys, psmd, num_uv_layers, child_index, mtfaces, *r_uv); - } - else if (!r_parent_uvs[psys->child[child_index].parent]) { - r_parent_uvs[psys->child[child_index].parent] = *r_uv; - particle_calculate_parent_uvs( - psys, psmd, num_uv_layers, parent_index, mtfaces, *r_uv); - } - } + if (psmd == NULL) { + return; + } + if (is_simple) { + if (r_parent_uvs[parent_index] != NULL) { + *r_uv = r_parent_uvs[parent_index]; + } + else { + *r_uv = MEM_callocN(sizeof(**r_uv) * num_uv_layers, "Particle UVs"); + } + } + else { + *r_uv = MEM_callocN(sizeof(**r_uv) * num_uv_layers, "Particle UVs"); + } + if (child_index == -1) { + /* Calculate UVs for parent particles. */ + if (is_simple) { + r_parent_uvs[parent_index] = *r_uv; + } + particle_calculate_parent_uvs(psys, psmd, num_uv_layers, parent_index, mtfaces, *r_uv); + } + else { + /* Calculate UVs for child particles. */ + if (!is_simple) { + particle_interpolate_children_uvs(psys, psmd, num_uv_layers, child_index, mtfaces, *r_uv); + } + else if (!r_parent_uvs[psys->child[child_index].parent]) { + r_parent_uvs[psys->child[child_index].parent] = *r_uv; + particle_calculate_parent_uvs(psys, psmd, num_uv_layers, parent_index, mtfaces, *r_uv); + } + } } -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, - /*const*/ MCol **mcols, - MCol **r_parent_mcol, - MCol **r_mcol) +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, + /*const*/ MCol **mcols, + MCol **r_parent_mcol, + MCol **r_mcol) { - if (psmd == NULL) { - return; - } - if (is_simple) { - if (r_parent_mcol[parent_index] != NULL) { - *r_mcol = r_parent_mcol[parent_index]; - } - else { - *r_mcol = MEM_callocN(sizeof(**r_mcol) * num_col_layers, "Particle MCol"); - } - } - else { - *r_mcol = MEM_callocN(sizeof(**r_mcol) * num_col_layers, "Particle MCol"); - } - if (child_index == -1) { - /* Calculate MCols for parent particles. */ - if (is_simple) { - r_parent_mcol[parent_index] = *r_mcol; - } - particle_calculate_parent_mcol( - psys, psmd, num_col_layers, parent_index, mcols, *r_mcol); - } - else { - /* Calculate MCols for child particles. */ - if (!is_simple) { - particle_interpolate_children_mcol( - psys, psmd, num_col_layers, child_index, mcols, *r_mcol); - } - else if (!r_parent_mcol[psys->child[child_index].parent]) { - r_parent_mcol[psys->child[child_index].parent] = *r_mcol; - particle_calculate_parent_mcol( - psys, psmd, num_col_layers, parent_index, mcols, *r_mcol); - } - } + if (psmd == NULL) { + return; + } + if (is_simple) { + if (r_parent_mcol[parent_index] != NULL) { + *r_mcol = r_parent_mcol[parent_index]; + } + else { + *r_mcol = MEM_callocN(sizeof(**r_mcol) * num_col_layers, "Particle MCol"); + } + } + else { + *r_mcol = MEM_callocN(sizeof(**r_mcol) * num_col_layers, "Particle MCol"); + } + if (child_index == -1) { + /* Calculate MCols for parent particles. */ + if (is_simple) { + r_parent_mcol[parent_index] = *r_mcol; + } + particle_calculate_parent_mcol(psys, psmd, num_col_layers, parent_index, mcols, *r_mcol); + } + else { + /* Calculate MCols for child particles. */ + if (!is_simple) { + particle_interpolate_children_mcol(psys, psmd, num_col_layers, child_index, mcols, *r_mcol); + } + else if (!r_parent_mcol[psys->child[child_index].parent]) { + r_parent_mcol[psys->child[child_index].parent] = *r_mcol; + particle_calculate_parent_mcol(psys, psmd, num_col_layers, parent_index, mcols, *r_mcol); + } + } } /* Will return last filled index. */ typedef enum ParticleSource { - PARTICLE_SOURCE_PARENT, - PARTICLE_SOURCE_CHILDREN, + PARTICLE_SOURCE_PARENT, + PARTICLE_SOURCE_CHILDREN, } ParticleSource; -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, - /*const*/ MTFace **mtfaces, - /*const*/ 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 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, + /*const*/ MTFace **mtfaces, + /*const*/ 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) { - const bool is_simple = (psys->part->childtype == PART_CHILD_PARTICLES); - const bool is_child = (particle_source == PARTICLE_SOURCE_CHILDREN); - if (is_simple && *r_parent_uvs == NULL) { - /* TODO(sergey): For edit mode it should be edit->totcached. */ - *r_parent_uvs = MEM_callocN( - sizeof(*r_parent_uvs) * psys->totpart, - "Parent particle UVs"); - } - if (is_simple && *r_parent_mcol == NULL) { - *r_parent_mcol = MEM_callocN( - sizeof(*r_parent_mcol) * psys->totpart, - "Parent particle MCol"); - } - int curr_point = start_index; - for (int i = 0; i < num_path_keys; i++) { - ParticleCacheKey *path = path_cache[i]; - if (path->segments <= 0) { - continue; - } - float tangent[3]; - float (*uv)[2] = NULL; - MCol *mcol = NULL; - particle_calculate_mcol( - psys, psmd, - is_simple, num_col_layers, - is_child ? psys->child[i].parent : i, - is_child ? i : -1, - mcols, - *r_parent_mcol, &mcol); - particle_calculate_uvs( - psys, psmd, - is_simple, num_uv_layers, - is_child ? psys->child[i].parent : i, - is_child ? i : -1, - mtfaces, - *r_parent_uvs, &uv); - for (int j = 0; j < path->segments; j++) { - if (j == 0) { - sub_v3_v3v3(tangent, path[j + 1].co, path[j].co); - } - else { - sub_v3_v3v3(tangent, path[j + 1].co, path[j - 1].co); - } - GPU_vertbuf_attr_set(hair_cache->pos, attr_id->pos, curr_point, path[j].co); - GPU_vertbuf_attr_set(hair_cache->pos, attr_id->tan, curr_point, tangent); - GPU_vertbuf_attr_set(hair_cache->pos, attr_id->ind, curr_point, &i); - if (psmd != NULL) { - for (int k = 0; k < num_uv_layers; k++) { - GPU_vertbuf_attr_set( - hair_cache->pos, uv_id[k], curr_point, - (is_simple && is_child) ? - (*r_parent_uvs)[psys->child[i].parent][k] : uv[k]); - } - for (int k = 0; k < num_col_layers; k++) { - /* TODO Put the conversion outside the loop */ - ushort scol[4]; - particle_pack_mcol( - (is_simple && is_child) ? - &(*r_parent_mcol)[psys->child[i].parent][k] : &mcol[k], - scol); - GPU_vertbuf_attr_set(hair_cache->pos, col_id[k], curr_point, scol); - } - } - GPU_indexbuf_add_generic_vert(elb, curr_point); - curr_point++; - } - sub_v3_v3v3(tangent, path[path->segments].co, path[path->segments - 1].co); - - int global_index = i + global_offset; - GPU_vertbuf_attr_set(hair_cache->pos, attr_id->pos, curr_point, path[path->segments].co); - GPU_vertbuf_attr_set(hair_cache->pos, attr_id->tan, curr_point, tangent); - GPU_vertbuf_attr_set(hair_cache->pos, attr_id->ind, curr_point, &global_index); - - if (psmd != NULL) { - for (int k = 0; k < num_uv_layers; k++) { - GPU_vertbuf_attr_set( - hair_cache->pos, uv_id[k], curr_point, - (is_simple && is_child) ? - (*r_parent_uvs)[psys->child[i].parent][k] : uv[k]); - } - for (int k = 0; k < num_col_layers; k++) { - /* TODO Put the conversion outside the loop */ - ushort scol[4]; - particle_pack_mcol( - (is_simple && is_child) ? - &(*r_parent_mcol)[psys->child[i].parent][k] : &mcol[k], - scol); - GPU_vertbuf_attr_set(hair_cache->pos, col_id[k], curr_point, scol); - } - if (!is_simple) { - MEM_freeN(uv); - MEM_freeN(mcol); - } - } - /* Finish the segment and add restart primitive. */ - GPU_indexbuf_add_generic_vert(elb, curr_point); - GPU_indexbuf_add_primitive_restart(elb); - curr_point++; - } - return curr_point; + const bool is_simple = (psys->part->childtype == PART_CHILD_PARTICLES); + const bool is_child = (particle_source == PARTICLE_SOURCE_CHILDREN); + if (is_simple && *r_parent_uvs == NULL) { + /* TODO(sergey): For edit mode it should be edit->totcached. */ + *r_parent_uvs = MEM_callocN(sizeof(*r_parent_uvs) * psys->totpart, "Parent particle UVs"); + } + if (is_simple && *r_parent_mcol == NULL) { + *r_parent_mcol = MEM_callocN(sizeof(*r_parent_mcol) * psys->totpart, "Parent particle MCol"); + } + int curr_point = start_index; + for (int i = 0; i < num_path_keys; i++) { + ParticleCacheKey *path = path_cache[i]; + if (path->segments <= 0) { + continue; + } + float tangent[3]; + float(*uv)[2] = NULL; + MCol *mcol = NULL; + particle_calculate_mcol(psys, + psmd, + is_simple, + num_col_layers, + is_child ? psys->child[i].parent : i, + is_child ? i : -1, + mcols, + *r_parent_mcol, + &mcol); + particle_calculate_uvs(psys, + psmd, + is_simple, + num_uv_layers, + is_child ? psys->child[i].parent : i, + is_child ? i : -1, + mtfaces, + *r_parent_uvs, + &uv); + for (int j = 0; j < path->segments; j++) { + if (j == 0) { + sub_v3_v3v3(tangent, path[j + 1].co, path[j].co); + } + else { + sub_v3_v3v3(tangent, path[j + 1].co, path[j - 1].co); + } + GPU_vertbuf_attr_set(hair_cache->pos, attr_id->pos, curr_point, path[j].co); + GPU_vertbuf_attr_set(hair_cache->pos, attr_id->tan, curr_point, tangent); + GPU_vertbuf_attr_set(hair_cache->pos, attr_id->ind, curr_point, &i); + if (psmd != NULL) { + for (int k = 0; k < num_uv_layers; k++) { + GPU_vertbuf_attr_set( + hair_cache->pos, + uv_id[k], + curr_point, + (is_simple && is_child) ? (*r_parent_uvs)[psys->child[i].parent][k] : uv[k]); + } + for (int k = 0; k < num_col_layers; k++) { + /* TODO Put the conversion outside the loop */ + ushort scol[4]; + particle_pack_mcol( + (is_simple && is_child) ? &(*r_parent_mcol)[psys->child[i].parent][k] : &mcol[k], + scol); + GPU_vertbuf_attr_set(hair_cache->pos, col_id[k], curr_point, scol); + } + } + GPU_indexbuf_add_generic_vert(elb, curr_point); + curr_point++; + } + sub_v3_v3v3(tangent, path[path->segments].co, path[path->segments - 1].co); + + int global_index = i + global_offset; + GPU_vertbuf_attr_set(hair_cache->pos, attr_id->pos, curr_point, path[path->segments].co); + GPU_vertbuf_attr_set(hair_cache->pos, attr_id->tan, curr_point, tangent); + GPU_vertbuf_attr_set(hair_cache->pos, attr_id->ind, curr_point, &global_index); + + if (psmd != NULL) { + for (int k = 0; k < num_uv_layers; k++) { + GPU_vertbuf_attr_set(hair_cache->pos, + uv_id[k], + curr_point, + (is_simple && is_child) ? (*r_parent_uvs)[psys->child[i].parent][k] : + uv[k]); + } + for (int k = 0; k < num_col_layers; k++) { + /* TODO Put the conversion outside the loop */ + ushort scol[4]; + particle_pack_mcol((is_simple && is_child) ? &(*r_parent_mcol)[psys->child[i].parent][k] : + &mcol[k], + scol); + GPU_vertbuf_attr_set(hair_cache->pos, col_id[k], curr_point, scol); + } + if (!is_simple) { + MEM_freeN(uv); + MEM_freeN(mcol); + } + } + /* Finish the segment and add restart primitive. */ + GPU_indexbuf_add_generic_vert(elb, curr_point); + GPU_indexbuf_add_primitive_restart(elb); + curr_point++; + } + return curr_point; } -static void particle_batch_cache_fill_segments_proc_pos( - ParticleCacheKey **path_cache, - const int num_path_keys, - GPUVertBufRaw *attr_step) +static void particle_batch_cache_fill_segments_proc_pos(ParticleCacheKey **path_cache, + const int num_path_keys, + GPUVertBufRaw *attr_step) { - for (int i = 0; i < num_path_keys; i++) { - ParticleCacheKey *path = path_cache[i]; - if (path->segments <= 0) { - continue; - } - float total_len = 0.0f; - float *co_prev = NULL, *seg_data_first; - for (int j = 0; j <= path->segments; j++) { - float *seg_data = (float *)GPU_vertbuf_raw_step(attr_step); - copy_v3_v3(seg_data, path[j].co); - if (co_prev) { - total_len += len_v3v3(co_prev, path[j].co); - } - else { - seg_data_first = seg_data; - } - seg_data[3] = total_len; - co_prev = path[j].co; - } - if (total_len > 0.0f) { - /* Divide by total length to have a [0-1] number. */ - for (int j = 0; j <= path->segments; j++, seg_data_first += 4) { - seg_data_first[3] /= total_len; - } - } - } + for (int i = 0; i < num_path_keys; i++) { + ParticleCacheKey *path = path_cache[i]; + if (path->segments <= 0) { + continue; + } + float total_len = 0.0f; + float *co_prev = NULL, *seg_data_first; + for (int j = 0; j <= path->segments; j++) { + float *seg_data = (float *)GPU_vertbuf_raw_step(attr_step); + copy_v3_v3(seg_data, path[j].co); + if (co_prev) { + total_len += len_v3v3(co_prev, path[j].co); + } + else { + seg_data_first = seg_data; + } + seg_data[3] = total_len; + co_prev = path[j].co; + } + if (total_len > 0.0f) { + /* Divide by total length to have a [0-1] number. */ + for (int j = 0; j <= path->segments; j++, seg_data_first += 4) { + seg_data_first[3] /= total_len; + } + } + } } static float particle_key_select_ratio(const PTCacheEdit *edit, int strand, float t) { - const PTCacheEditPoint *point = &edit->points[strand]; - float edit_key_seg_t = 1.0f / (point->totkey - 1); - if (t == 1.0) { - return (point->keys[point->totkey - 1].flag & PEK_SELECT) ? 1.0f : 0.0; - } - else { - float interp = t / edit_key_seg_t; - int index = (int)interp; - interp -= floorf(interp); /* Time between 2 edit key */ - float s1 = (point->keys[index].flag & PEK_SELECT) ? 1.0f : 0.0; - float s2 = (point->keys[index + 1].flag & PEK_SELECT) ? 1.0f : 0.0; - return s1 + interp * (s2 - s1); - } + const PTCacheEditPoint *point = &edit->points[strand]; + float edit_key_seg_t = 1.0f / (point->totkey - 1); + if (t == 1.0) { + return (point->keys[point->totkey - 1].flag & PEK_SELECT) ? 1.0f : 0.0; + } + else { + float interp = t / edit_key_seg_t; + int index = (int)interp; + interp -= floorf(interp); /* Time between 2 edit key */ + float s1 = (point->keys[index].flag & PEK_SELECT) ? 1.0f : 0.0; + float s2 = (point->keys[index + 1].flag & PEK_SELECT) ? 1.0f : 0.0; + return s1 + interp * (s2 - s1); + } } static float particle_key_weight(const ParticleData *particle, int strand, float t) { - const ParticleData *part = particle + strand; - const HairKey *hkeys = part->hair; - float edit_key_seg_t = 1.0f / (part->totkey - 1); - if (t == 1.0) { - return hkeys[part->totkey - 1].weight; - } - else { - float interp = t / edit_key_seg_t; - int index = (int)interp; - interp -= floorf(interp); /* Time between 2 edit key */ - float s1 = hkeys[index].weight; - float s2 = hkeys[index + 1].weight; - return s1 + interp * (s2 - s1); - } + const ParticleData *part = particle + strand; + const HairKey *hkeys = part->hair; + float edit_key_seg_t = 1.0f / (part->totkey - 1); + if (t == 1.0) { + return hkeys[part->totkey - 1].weight; + } + else { + float interp = t / edit_key_seg_t; + int index = (int)interp; + interp -= floorf(interp); /* Time between 2 edit key */ + float s1 = hkeys[index].weight; + float s2 = hkeys[index + 1].weight; + return s1 + interp * (s2 - s1); + } } static int particle_batch_cache_fill_segments_edit( - const PTCacheEdit *edit, /* NULL for weight data */ - const ParticleData *particle, /* NULL for select data */ - ParticleCacheKey **path_cache, - const int start_index, - const int num_path_keys, - GPUIndexBufBuilder *elb, - GPUVertBufRaw *attr_step) + const PTCacheEdit *edit, /* NULL for weight data */ + const ParticleData *particle, /* NULL for select data */ + ParticleCacheKey **path_cache, + const int start_index, + const int num_path_keys, + GPUIndexBufBuilder *elb, + GPUVertBufRaw *attr_step) { - int curr_point = start_index; - for (int i = 0; i < num_path_keys; i++) { - ParticleCacheKey *path = path_cache[i]; - if (path->segments <= 0) { - continue; - } - for (int j = 0; j <= path->segments; j++) { - EditStrandData *seg_data = (EditStrandData *)GPU_vertbuf_raw_step(attr_step); - copy_v3_v3(seg_data->pos, path[j].co); - float strand_t = (float)(j) / path->segments; - if (particle) { - float weight = particle_key_weight(particle, i, strand_t); - /* NaN or unclamped become 0xFF */ - seg_data->color = (uchar)((weight <= 1.0f) ? 0xFE * weight : 0xFF); - } - else { - float selected = particle_key_select_ratio(edit, i, strand_t); - seg_data->color = (uchar)(0xFF * selected); - } - GPU_indexbuf_add_generic_vert(elb, curr_point); - curr_point++; - } - /* Finish the segment and add restart primitive. */ - GPU_indexbuf_add_primitive_restart(elb); - } - return curr_point; + int curr_point = start_index; + for (int i = 0; i < num_path_keys; i++) { + ParticleCacheKey *path = path_cache[i]; + if (path->segments <= 0) { + continue; + } + for (int j = 0; j <= path->segments; j++) { + EditStrandData *seg_data = (EditStrandData *)GPU_vertbuf_raw_step(attr_step); + copy_v3_v3(seg_data->pos, path[j].co); + float strand_t = (float)(j) / path->segments; + if (particle) { + float weight = particle_key_weight(particle, i, strand_t); + /* NaN or unclamped become 0xFF */ + seg_data->color = (uchar)((weight <= 1.0f) ? 0xFE * weight : 0xFF); + } + else { + float selected = particle_key_select_ratio(edit, i, strand_t); + seg_data->color = (uchar)(0xFF * selected); + } + GPU_indexbuf_add_generic_vert(elb, curr_point); + curr_point++; + } + /* Finish the segment and add restart primitive. */ + GPU_indexbuf_add_primitive_restart(elb); + } + return curr_point; } -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 int particle_batch_cache_fill_segments_indices(ParticleCacheKey **path_cache, + const int start_index, + const int num_path_keys, + const int res, + GPUIndexBufBuilder *elb) { - int curr_point = start_index; - for (int i = 0; i < num_path_keys; i++) { - ParticleCacheKey *path = path_cache[i]; - if (path->segments <= 0) { - continue; - } - for (int k = 0; k < res; k++) { - GPU_indexbuf_add_generic_vert(elb, curr_point++); - } - GPU_indexbuf_add_primitive_restart(elb); - } - return curr_point; + int curr_point = start_index; + for (int i = 0; i < num_path_keys; i++) { + ParticleCacheKey *path = path_cache[i]; + if (path->segments <= 0) { + continue; + } + for (int k = 0; k < res; k++) { + GPU_indexbuf_add_generic_vert(elb, curr_point++); + } + GPU_indexbuf_add_primitive_restart(elb); + } + return curr_point; } -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 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) { - const bool is_simple = (psys->part->childtype == PART_CHILD_PARTICLES); - const bool is_child = (particle_source == PARTICLE_SOURCE_CHILDREN); - if (is_simple && *r_parent_uvs == NULL) { - /* TODO(sergey): For edit mode it should be edit->totcached. */ - *r_parent_uvs = MEM_callocN( - sizeof(*r_parent_uvs) * psys->totpart, - "Parent particle UVs"); - } - if (is_simple && *r_parent_mcol == NULL) { - *r_parent_mcol = MEM_callocN( - sizeof(*r_parent_mcol) * psys->totpart, - "Parent particle MCol"); - } - int curr_point = start_index; - for (int i = 0; i < num_path_keys; i++) { - ParticleCacheKey *path = path_cache[i]; - if (path->segments <= 0) { - continue; - } - - *(uint *)GPU_vertbuf_raw_step(data_step) = curr_point; - *(ushort *)GPU_vertbuf_raw_step(seg_step) = path->segments; - curr_point += path->segments + 1; - - if (psmd != NULL) { - float (*uv)[2] = NULL; - MCol *mcol = NULL; - - particle_calculate_uvs( - psys, psmd, - is_simple, num_uv_layers, - is_child ? psys->child[i].parent : i, - is_child ? i : -1, - mtfaces, - *r_parent_uvs, &uv); - - particle_calculate_mcol( - psys, psmd, - is_simple, num_col_layers, - is_child ? psys->child[i].parent : i, - is_child ? i : -1, - mcols, - *r_parent_mcol, &mcol); - - for (int k = 0; k < num_uv_layers; k++) { - float *t_uv = (float *)GPU_vertbuf_raw_step(uv_step + k); - copy_v2_v2(t_uv, uv[k]); - } - for (int k = 0; k < num_col_layers; k++) { - ushort *scol = (ushort *)GPU_vertbuf_raw_step(col_step + k); - particle_pack_mcol( - (is_simple && is_child) ? - &(*r_parent_mcol)[psys->child[i].parent][k] : &mcol[k], - scol); - } - if (!is_simple) { - MEM_freeN(uv); - MEM_freeN(mcol); - } - } - } - return curr_point; + const bool is_simple = (psys->part->childtype == PART_CHILD_PARTICLES); + const bool is_child = (particle_source == PARTICLE_SOURCE_CHILDREN); + if (is_simple && *r_parent_uvs == NULL) { + /* TODO(sergey): For edit mode it should be edit->totcached. */ + *r_parent_uvs = MEM_callocN(sizeof(*r_parent_uvs) * psys->totpart, "Parent particle UVs"); + } + if (is_simple && *r_parent_mcol == NULL) { + *r_parent_mcol = MEM_callocN(sizeof(*r_parent_mcol) * psys->totpart, "Parent particle MCol"); + } + int curr_point = start_index; + for (int i = 0; i < num_path_keys; i++) { + ParticleCacheKey *path = path_cache[i]; + if (path->segments <= 0) { + continue; + } + + *(uint *)GPU_vertbuf_raw_step(data_step) = curr_point; + *(ushort *)GPU_vertbuf_raw_step(seg_step) = path->segments; + curr_point += path->segments + 1; + + if (psmd != NULL) { + float(*uv)[2] = NULL; + MCol *mcol = NULL; + + particle_calculate_uvs(psys, + psmd, + is_simple, + num_uv_layers, + is_child ? psys->child[i].parent : i, + is_child ? i : -1, + mtfaces, + *r_parent_uvs, + &uv); + + particle_calculate_mcol(psys, + psmd, + is_simple, + num_col_layers, + is_child ? psys->child[i].parent : i, + is_child ? i : -1, + mcols, + *r_parent_mcol, + &mcol); + + for (int k = 0; k < num_uv_layers; k++) { + float *t_uv = (float *)GPU_vertbuf_raw_step(uv_step + k); + copy_v2_v2(t_uv, uv[k]); + } + for (int k = 0; k < num_col_layers; k++) { + ushort *scol = (ushort *)GPU_vertbuf_raw_step(col_step + k); + particle_pack_mcol((is_simple && is_child) ? &(*r_parent_mcol)[psys->child[i].parent][k] : + &mcol[k], + scol); + } + if (!is_simple) { + MEM_freeN(uv); + MEM_freeN(mcol); + } + } + } + return curr_point; } -static void particle_batch_cache_ensure_procedural_final_points( - ParticleHairCache *cache, - int subdiv) +static void particle_batch_cache_ensure_procedural_final_points(ParticleHairCache *cache, + int subdiv) { - /* Same format as point_tex. */ - GPUVertFormat format = { 0 }; - GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + /* Same format as point_tex. */ + GPUVertFormat format = {0}; + GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - cache->final[subdiv].proc_buf = GPU_vertbuf_create_with_format(&format); + cache->final[subdiv].proc_buf = GPU_vertbuf_create_with_format(&format); - /* Create a destination buffer for the transform feedback. Sized appropriately */ - /* Those are points! not line segments. */ - GPU_vertbuf_data_alloc(cache->final[subdiv].proc_buf, cache->final[subdiv].strands_res * cache->strands_len); + /* Create a destination buffer for the transform feedback. Sized appropriately */ + /* Those are points! not line segments. */ + GPU_vertbuf_data_alloc(cache->final[subdiv].proc_buf, + cache->final[subdiv].strands_res * cache->strands_len); - /* Create vbo immediately to bind to texture buffer. */ - GPU_vertbuf_use(cache->final[subdiv].proc_buf); + /* Create vbo immediately to bind to texture buffer. */ + GPU_vertbuf_use(cache->final[subdiv].proc_buf); - cache->final[subdiv].proc_tex = GPU_texture_create_from_vertbuf(cache->final[subdiv].proc_buf); + cache->final[subdiv].proc_tex = GPU_texture_create_from_vertbuf(cache->final[subdiv].proc_buf); } -static void particle_batch_cache_ensure_procedural_strand_data( - PTCacheEdit *edit, - ParticleSystem *psys, - ModifierData *md, - ParticleHairCache *cache) +static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit, + ParticleSystem *psys, + ModifierData *md, + ParticleHairCache *cache) { - int active_uv = 0; - int active_col = 0; - - ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; - - if (psmd != NULL && psmd->mesh_final != NULL) { - if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPUV)) { - cache->num_uv_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPUV); - active_uv = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPUV); - } - if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL)) { - cache->num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPCOL); - active_col = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL); - } - } - - GPUVertBufRaw data_step, seg_step; - GPUVertBufRaw uv_step[MAX_MTFACE]; - GPUVertBufRaw col_step[MAX_MCOL]; - - MTFace *mtfaces[MAX_MTFACE] = {NULL}; - MCol *mcols[MAX_MCOL] = {NULL}; - float (**parent_uvs)[2] = NULL; - MCol **parent_mcol = NULL; - - GPUVertFormat format_data = {0}; - uint data_id = GPU_vertformat_attr_add(&format_data, "data", GPU_COMP_U32, 1, GPU_FETCH_INT); - - GPUVertFormat format_seg = {0}; - uint seg_id = GPU_vertformat_attr_add(&format_seg, "data", GPU_COMP_U16, 1, GPU_FETCH_INT); - - GPUVertFormat format_uv = {0}; - uint uv_id = GPU_vertformat_attr_add(&format_uv, "uv", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - GPUVertFormat format_col = {0}; - uint col_id = GPU_vertformat_attr_add(&format_col, "col", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - - memset(cache->uv_layer_names, 0, sizeof(cache->uv_layer_names)); - memset(cache->col_layer_names, 0, sizeof(cache->col_layer_names)); - - /* Strand Data */ - cache->proc_strand_buf = GPU_vertbuf_create_with_format(&format_data); - GPU_vertbuf_data_alloc(cache->proc_strand_buf, cache->strands_len); - GPU_vertbuf_attr_get_raw_data(cache->proc_strand_buf, data_id, &data_step); - - cache->proc_strand_seg_buf = GPU_vertbuf_create_with_format(&format_seg); - GPU_vertbuf_data_alloc(cache->proc_strand_seg_buf, cache->strands_len); - GPU_vertbuf_attr_get_raw_data(cache->proc_strand_seg_buf, seg_id, &seg_step); - - /* UV layers */ - for (int i = 0; i < cache->num_uv_layers; i++) { - cache->proc_uv_buf[i] = GPU_vertbuf_create_with_format(&format_uv); - GPU_vertbuf_data_alloc(cache->proc_uv_buf[i], cache->strands_len); - GPU_vertbuf_attr_get_raw_data(cache->proc_uv_buf[i], uv_id, &uv_step[i]); - - const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i); - uint hash = BLI_ghashutil_strhash_p(name); - int n = 0; - BLI_snprintf(cache->uv_layer_names[i][n++], MAX_LAYER_NAME_LEN, "u%u", hash); - BLI_snprintf(cache->uv_layer_names[i][n++], MAX_LAYER_NAME_LEN, "a%u", hash); - - if (i == active_uv) { - BLI_strncpy(cache->uv_layer_names[i][n], "u", MAX_LAYER_NAME_LEN); - } - } - /* Vertex colors */ - for (int i = 0; i < cache->num_col_layers; i++) { - cache->proc_col_buf[i] = GPU_vertbuf_create_with_format(&format_col); - GPU_vertbuf_data_alloc(cache->proc_col_buf[i], cache->strands_len); - GPU_vertbuf_attr_get_raw_data(cache->proc_col_buf[i], col_id, &col_step[i]); - - const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPCOL, i); - uint hash = BLI_ghashutil_strhash_p(name); - int n = 0; - BLI_snprintf(cache->col_layer_names[i][n++], MAX_LAYER_NAME_LEN, "c%u", hash); - - /* We only do vcols auto name that are not overridden by uvs */ - if (CustomData_get_named_layer_index(&psmd->mesh_final->ldata, CD_MLOOPUV, name) == -1) { - BLI_snprintf(cache->col_layer_names[i][n++], MAX_LAYER_NAME_LEN, "a%u", hash); - } - - if (i == active_col) { - BLI_strncpy(cache->col_layer_names[i][n], "c", MAX_LAYER_NAME_LEN); - } - } - - if (cache->num_uv_layers || cache->num_col_layers) { - BKE_mesh_tessface_ensure(psmd->mesh_final); - if (cache->num_uv_layers) { - for (int j = 0; j < cache->num_uv_layers; j++) { - mtfaces[j] = (MTFace *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MTFACE, j); - } - } - if (cache->num_col_layers) { - for (int j = 0; j < cache->num_col_layers; j++) { - mcols[j] = (MCol *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MCOL, j); - } - } - } - - if (edit != NULL && edit->pathcache != NULL) { - particle_batch_cache_fill_strands_data( - psys, psmd, edit->pathcache, PARTICLE_SOURCE_PARENT, - 0, edit->totcached, - &data_step, &seg_step, - &parent_uvs, uv_step, (MTFace **)mtfaces, cache->num_uv_layers, - &parent_mcol, col_step, (MCol **)mcols, cache->num_col_layers); - } - else { - int curr_point = 0; - if ((psys->pathcache != NULL) && - (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) - { - curr_point = particle_batch_cache_fill_strands_data( - psys, psmd, psys->pathcache, PARTICLE_SOURCE_PARENT, - 0, psys->totpart, - &data_step, &seg_step, - &parent_uvs, uv_step, (MTFace **)mtfaces, cache->num_uv_layers, - &parent_mcol, col_step, (MCol **)mcols, cache->num_col_layers); - } - if (psys->childcache) { - const int child_count = psys->totchild * psys->part->disp / 100; - curr_point = particle_batch_cache_fill_strands_data( - psys, psmd, psys->childcache, PARTICLE_SOURCE_CHILDREN, - curr_point, child_count, - &data_step, &seg_step, - &parent_uvs, uv_step, (MTFace **)mtfaces, cache->num_uv_layers, - &parent_mcol, col_step, (MCol **)mcols, cache->num_col_layers); - } - } - /* Cleanup. */ - if (parent_uvs != NULL) { - /* TODO(sergey): For edit mode it should be edit->totcached. */ - for (int i = 0; i < psys->totpart; i++) { - MEM_SAFE_FREE(parent_uvs[i]); - } - MEM_freeN(parent_uvs); - } - if (parent_mcol != NULL) { - for (int i = 0; i < psys->totpart; i++) { - MEM_SAFE_FREE(parent_mcol[i]); - } - MEM_freeN(parent_mcol); - } - - /* Create vbo immediately to bind to texture buffer. */ - GPU_vertbuf_use(cache->proc_strand_buf); - cache->strand_tex = GPU_texture_create_from_vertbuf(cache->proc_strand_buf); - - GPU_vertbuf_use(cache->proc_strand_seg_buf); - cache->strand_seg_tex = GPU_texture_create_from_vertbuf(cache->proc_strand_seg_buf); - - for (int i = 0; i < cache->num_uv_layers; i++) { - GPU_vertbuf_use(cache->proc_uv_buf[i]); - cache->uv_tex[i] = GPU_texture_create_from_vertbuf(cache->proc_uv_buf[i]); - } - for (int i = 0; i < cache->num_col_layers; i++) { - GPU_vertbuf_use(cache->proc_col_buf[i]); - cache->col_tex[i] = GPU_texture_create_from_vertbuf(cache->proc_col_buf[i]); - } + int active_uv = 0; + int active_col = 0; + + ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; + + if (psmd != NULL && psmd->mesh_final != NULL) { + if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPUV)) { + cache->num_uv_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPUV); + active_uv = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPUV); + } + if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL)) { + cache->num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPCOL); + active_col = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL); + } + } + + GPUVertBufRaw data_step, seg_step; + GPUVertBufRaw uv_step[MAX_MTFACE]; + GPUVertBufRaw col_step[MAX_MCOL]; + + MTFace *mtfaces[MAX_MTFACE] = {NULL}; + MCol *mcols[MAX_MCOL] = {NULL}; + float(**parent_uvs)[2] = NULL; + MCol **parent_mcol = NULL; + + GPUVertFormat format_data = {0}; + uint data_id = GPU_vertformat_attr_add(&format_data, "data", GPU_COMP_U32, 1, GPU_FETCH_INT); + + GPUVertFormat format_seg = {0}; + uint seg_id = GPU_vertformat_attr_add(&format_seg, "data", GPU_COMP_U16, 1, GPU_FETCH_INT); + + GPUVertFormat format_uv = {0}; + uint uv_id = GPU_vertformat_attr_add(&format_uv, "uv", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + GPUVertFormat format_col = {0}; + uint col_id = GPU_vertformat_attr_add( + &format_col, "col", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + + memset(cache->uv_layer_names, 0, sizeof(cache->uv_layer_names)); + memset(cache->col_layer_names, 0, sizeof(cache->col_layer_names)); + + /* Strand Data */ + cache->proc_strand_buf = GPU_vertbuf_create_with_format(&format_data); + GPU_vertbuf_data_alloc(cache->proc_strand_buf, cache->strands_len); + GPU_vertbuf_attr_get_raw_data(cache->proc_strand_buf, data_id, &data_step); + + cache->proc_strand_seg_buf = GPU_vertbuf_create_with_format(&format_seg); + GPU_vertbuf_data_alloc(cache->proc_strand_seg_buf, cache->strands_len); + GPU_vertbuf_attr_get_raw_data(cache->proc_strand_seg_buf, seg_id, &seg_step); + + /* UV layers */ + for (int i = 0; i < cache->num_uv_layers; i++) { + cache->proc_uv_buf[i] = GPU_vertbuf_create_with_format(&format_uv); + GPU_vertbuf_data_alloc(cache->proc_uv_buf[i], cache->strands_len); + GPU_vertbuf_attr_get_raw_data(cache->proc_uv_buf[i], uv_id, &uv_step[i]); + + const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i); + uint hash = BLI_ghashutil_strhash_p(name); + int n = 0; + BLI_snprintf(cache->uv_layer_names[i][n++], MAX_LAYER_NAME_LEN, "u%u", hash); + BLI_snprintf(cache->uv_layer_names[i][n++], MAX_LAYER_NAME_LEN, "a%u", hash); + + if (i == active_uv) { + BLI_strncpy(cache->uv_layer_names[i][n], "u", MAX_LAYER_NAME_LEN); + } + } + /* Vertex colors */ + for (int i = 0; i < cache->num_col_layers; i++) { + cache->proc_col_buf[i] = GPU_vertbuf_create_with_format(&format_col); + GPU_vertbuf_data_alloc(cache->proc_col_buf[i], cache->strands_len); + GPU_vertbuf_attr_get_raw_data(cache->proc_col_buf[i], col_id, &col_step[i]); + + const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPCOL, i); + uint hash = BLI_ghashutil_strhash_p(name); + int n = 0; + BLI_snprintf(cache->col_layer_names[i][n++], MAX_LAYER_NAME_LEN, "c%u", hash); + + /* We only do vcols auto name that are not overridden by uvs */ + if (CustomData_get_named_layer_index(&psmd->mesh_final->ldata, CD_MLOOPUV, name) == -1) { + BLI_snprintf(cache->col_layer_names[i][n++], MAX_LAYER_NAME_LEN, "a%u", hash); + } + + if (i == active_col) { + BLI_strncpy(cache->col_layer_names[i][n], "c", MAX_LAYER_NAME_LEN); + } + } + + if (cache->num_uv_layers || cache->num_col_layers) { + BKE_mesh_tessface_ensure(psmd->mesh_final); + if (cache->num_uv_layers) { + for (int j = 0; j < cache->num_uv_layers; j++) { + mtfaces[j] = (MTFace *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MTFACE, j); + } + } + if (cache->num_col_layers) { + for (int j = 0; j < cache->num_col_layers; j++) { + mcols[j] = (MCol *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MCOL, j); + } + } + } + + if (edit != NULL && edit->pathcache != NULL) { + particle_batch_cache_fill_strands_data(psys, + psmd, + edit->pathcache, + PARTICLE_SOURCE_PARENT, + 0, + edit->totcached, + &data_step, + &seg_step, + &parent_uvs, + uv_step, + (MTFace **)mtfaces, + cache->num_uv_layers, + &parent_mcol, + col_step, + (MCol **)mcols, + cache->num_col_layers); + } + else { + int curr_point = 0; + if ((psys->pathcache != NULL) && + (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) { + curr_point = particle_batch_cache_fill_strands_data(psys, + psmd, + psys->pathcache, + PARTICLE_SOURCE_PARENT, + 0, + psys->totpart, + &data_step, + &seg_step, + &parent_uvs, + uv_step, + (MTFace **)mtfaces, + cache->num_uv_layers, + &parent_mcol, + col_step, + (MCol **)mcols, + cache->num_col_layers); + } + if (psys->childcache) { + const int child_count = psys->totchild * psys->part->disp / 100; + curr_point = particle_batch_cache_fill_strands_data(psys, + psmd, + psys->childcache, + PARTICLE_SOURCE_CHILDREN, + curr_point, + child_count, + &data_step, + &seg_step, + &parent_uvs, + uv_step, + (MTFace **)mtfaces, + cache->num_uv_layers, + &parent_mcol, + col_step, + (MCol **)mcols, + cache->num_col_layers); + } + } + /* Cleanup. */ + if (parent_uvs != NULL) { + /* TODO(sergey): For edit mode it should be edit->totcached. */ + for (int i = 0; i < psys->totpart; i++) { + MEM_SAFE_FREE(parent_uvs[i]); + } + MEM_freeN(parent_uvs); + } + if (parent_mcol != NULL) { + for (int i = 0; i < psys->totpart; i++) { + MEM_SAFE_FREE(parent_mcol[i]); + } + MEM_freeN(parent_mcol); + } + + /* Create vbo immediately to bind to texture buffer. */ + GPU_vertbuf_use(cache->proc_strand_buf); + cache->strand_tex = GPU_texture_create_from_vertbuf(cache->proc_strand_buf); + + GPU_vertbuf_use(cache->proc_strand_seg_buf); + cache->strand_seg_tex = GPU_texture_create_from_vertbuf(cache->proc_strand_seg_buf); + + for (int i = 0; i < cache->num_uv_layers; i++) { + GPU_vertbuf_use(cache->proc_uv_buf[i]); + cache->uv_tex[i] = GPU_texture_create_from_vertbuf(cache->proc_uv_buf[i]); + } + for (int i = 0; i < cache->num_col_layers; i++) { + GPU_vertbuf_use(cache->proc_col_buf[i]); + cache->col_tex[i] = GPU_texture_create_from_vertbuf(cache->proc_col_buf[i]); + } } -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_procedural_indices(PTCacheEdit *edit, + ParticleSystem *psys, + ParticleHairCache *cache, + int thickness_res, + int subdiv) { - BLI_assert(thickness_res <= MAX_THICKRES); /* Cylinder strip not currently supported. */ - - if (cache->final[subdiv].proc_hairs[thickness_res - 1] != NULL) { - return; - } - - int verts_per_hair = cache->final[subdiv].strands_res * thickness_res; - /* +1 for primitive restart */ - int element_count = (verts_per_hair + 1) * cache->strands_len; - GPUPrimType prim_type = (thickness_res == 1) ? GPU_PRIM_LINE_STRIP : GPU_PRIM_TRI_STRIP; - - static GPUVertFormat format = { 0 }; - GPU_vertformat_clear(&format); - - /* initialize vertex format */ - GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); - - GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(vbo, 1); - - GPUIndexBufBuilder elb; - GPU_indexbuf_init_ex(&elb, prim_type, element_count, element_count, true); - - if (edit != NULL && edit->pathcache != NULL) { - particle_batch_cache_fill_segments_indices( - edit->pathcache, 0, edit->totcached, verts_per_hair, &elb); - } - else { - int curr_point = 0; - if ((psys->pathcache != NULL) && - (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) - { - curr_point = particle_batch_cache_fill_segments_indices( - psys->pathcache, 0, psys->totpart, verts_per_hair, &elb); - } - if (psys->childcache) { - const int child_count = psys->totchild * psys->part->disp / 100; - curr_point = particle_batch_cache_fill_segments_indices( - psys->childcache, curr_point, child_count, verts_per_hair, &elb); - } - } - - cache->final[subdiv].proc_hairs[thickness_res - 1] = GPU_batch_create_ex( - prim_type, - vbo, - GPU_indexbuf_build(&elb), - GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX); + BLI_assert(thickness_res <= MAX_THICKRES); /* Cylinder strip not currently supported. */ + + if (cache->final[subdiv].proc_hairs[thickness_res - 1] != NULL) { + return; + } + + int verts_per_hair = cache->final[subdiv].strands_res * thickness_res; + /* +1 for primitive restart */ + int element_count = (verts_per_hair + 1) * cache->strands_len; + GPUPrimType prim_type = (thickness_res == 1) ? GPU_PRIM_LINE_STRIP : GPU_PRIM_TRI_STRIP; + + static GPUVertFormat format = {0}; + GPU_vertformat_clear(&format); + + /* initialize vertex format */ + GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); + + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(vbo, 1); + + GPUIndexBufBuilder elb; + GPU_indexbuf_init_ex(&elb, prim_type, element_count, element_count, true); + + if (edit != NULL && edit->pathcache != NULL) { + particle_batch_cache_fill_segments_indices( + edit->pathcache, 0, edit->totcached, verts_per_hair, &elb); + } + else { + int curr_point = 0; + if ((psys->pathcache != NULL) && + (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) { + curr_point = particle_batch_cache_fill_segments_indices( + psys->pathcache, 0, psys->totpart, verts_per_hair, &elb); + } + if (psys->childcache) { + const int child_count = psys->totchild * psys->part->disp / 100; + curr_point = particle_batch_cache_fill_segments_indices( + psys->childcache, curr_point, child_count, verts_per_hair, &elb); + } + } + + cache->final[subdiv].proc_hairs[thickness_res - 1] = GPU_batch_create_ex( + prim_type, vbo, GPU_indexbuf_build(&elb), GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX); } -static void particle_batch_cache_ensure_procedural_pos( - PTCacheEdit *edit, - ParticleSystem *psys, - ParticleHairCache *cache) +static void particle_batch_cache_ensure_procedural_pos(PTCacheEdit *edit, + ParticleSystem *psys, + ParticleHairCache *cache) { - if (cache->proc_point_buf != NULL) { - return; - } - - /* initialize vertex format */ - GPUVertFormat format = {0}; - uint pos_id = GPU_vertformat_attr_add(&format, "posTime", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - - cache->proc_point_buf = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(cache->proc_point_buf, cache->point_len); - - GPUVertBufRaw pos_step; - GPU_vertbuf_attr_get_raw_data(cache->proc_point_buf, pos_id, &pos_step); - - if (edit != NULL && edit->pathcache != NULL) { - particle_batch_cache_fill_segments_proc_pos( - edit->pathcache, - edit->totcached, - &pos_step); - } - else { - if ((psys->pathcache != NULL) && - (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) - { - particle_batch_cache_fill_segments_proc_pos( - psys->pathcache, - psys->totpart, - &pos_step); - } - if (psys->childcache) { - const int child_count = psys->totchild * psys->part->disp / 100; - particle_batch_cache_fill_segments_proc_pos( - psys->childcache, - child_count, - &pos_step); - } - } - - /* Create vbo immediately to bind to texture buffer. */ - GPU_vertbuf_use(cache->proc_point_buf); - - cache->point_tex = GPU_texture_create_from_vertbuf(cache->proc_point_buf); + if (cache->proc_point_buf != NULL) { + return; + } + + /* initialize vertex format */ + GPUVertFormat format = {0}; + uint pos_id = GPU_vertformat_attr_add(&format, "posTime", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + + cache->proc_point_buf = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(cache->proc_point_buf, cache->point_len); + + GPUVertBufRaw pos_step; + GPU_vertbuf_attr_get_raw_data(cache->proc_point_buf, pos_id, &pos_step); + + if (edit != NULL && edit->pathcache != NULL) { + particle_batch_cache_fill_segments_proc_pos(edit->pathcache, edit->totcached, &pos_step); + } + else { + if ((psys->pathcache != NULL) && + (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) { + particle_batch_cache_fill_segments_proc_pos(psys->pathcache, psys->totpart, &pos_step); + } + if (psys->childcache) { + const int child_count = psys->totchild * psys->part->disp / 100; + particle_batch_cache_fill_segments_proc_pos(psys->childcache, child_count, &pos_step); + } + } + + /* Create vbo immediately to bind to texture buffer. */ + GPU_vertbuf_use(cache->proc_point_buf); + + cache->point_tex = GPU_texture_create_from_vertbuf(cache->proc_point_buf); } -static void particle_batch_cache_ensure_pos_and_seg( - PTCacheEdit *edit, - ParticleSystem *psys, - ModifierData *md, - ParticleHairCache *hair_cache) +static void particle_batch_cache_ensure_pos_and_seg(PTCacheEdit *edit, + ParticleSystem *psys, + ModifierData *md, + ParticleHairCache *hair_cache) { - if (hair_cache->pos != NULL && hair_cache->indices != NULL) { - return; - } - - int curr_point = 0; - ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; - - GPU_VERTBUF_DISCARD_SAFE(hair_cache->pos); - GPU_INDEXBUF_DISCARD_SAFE(hair_cache->indices); - - static GPUVertFormat format = { 0 }; - HairAttributeID attr_id; - uint *uv_id = NULL; - uint *col_id = NULL; - int num_uv_layers = 0; - int num_col_layers = 0; - int active_uv = 0; - int active_col = 0; - MTFace **mtfaces = NULL; - MCol **mcols = NULL; - float (**parent_uvs)[2] = NULL; - MCol **parent_mcol = NULL; - - if (psmd != NULL) { - if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPUV)) { - num_uv_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPUV); - active_uv = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPUV); - } - if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL)) { - num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPCOL); - active_col = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL); - } - } - - GPU_vertformat_clear(&format); - - /* initialize vertex format */ - attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - attr_id.tan = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - attr_id.ind = GPU_vertformat_attr_add(&format, "ind", GPU_COMP_I32, 1, GPU_FETCH_INT); - - if (psmd) { - uv_id = MEM_mallocN(sizeof(*uv_id) * num_uv_layers, "UV attr format"); - col_id = MEM_mallocN(sizeof(*col_id) * num_col_layers, "Col attr format"); - - for (int i = 0; i < num_uv_layers; i++) { - const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i); - char uuid[32]; - - BLI_snprintf(uuid, sizeof(uuid), "u%u", BLI_ghashutil_strhash_p(name)); - uv_id[i] = GPU_vertformat_attr_add(&format, uuid, GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - if (i == active_uv) { - GPU_vertformat_alias_add(&format, "u"); - } - } - - for (int i = 0; i < num_uv_layers; i++) { - const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i); - char uuid[32]; - - BLI_snprintf(uuid, sizeof(uuid), "c%u", BLI_ghashutil_strhash_p(name)); - col_id[i] = GPU_vertformat_attr_add(&format, uuid, GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - if (i == active_col) { - GPU_vertformat_alias_add(&format, "c"); - } - } - } - - hair_cache->pos = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(hair_cache->pos, hair_cache->point_len); - - GPUIndexBufBuilder elb; - GPU_indexbuf_init_ex( - &elb, - GPU_PRIM_LINE_STRIP, - hair_cache->elems_len, hair_cache->point_len, - true); - - if (num_uv_layers || num_col_layers) { - BKE_mesh_tessface_ensure(psmd->mesh_final); - if (num_uv_layers) { - mtfaces = MEM_mallocN(sizeof(*mtfaces) * num_uv_layers, "Faces UV layers"); - for (int i = 0; i < num_uv_layers; i++) { - mtfaces[i] = (MTFace *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MTFACE, i); - } - } - if (num_col_layers) { - mcols = MEM_mallocN(sizeof(*mcols) * num_col_layers, "Color layers"); - for (int i = 0; i < num_col_layers; i++) { - mcols[i] = (MCol *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MCOL, i); - } - } - } - - if (edit != NULL && edit->pathcache != NULL) { - curr_point = particle_batch_cache_fill_segments( - psys, psmd, edit->pathcache, PARTICLE_SOURCE_PARENT, - 0, 0, edit->totcached, - num_uv_layers, num_col_layers, mtfaces, mcols, uv_id, col_id, &parent_uvs, &parent_mcol, - &elb, &attr_id, hair_cache); - } - else { - if ((psys->pathcache != NULL) && - (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) - { - curr_point = particle_batch_cache_fill_segments( - psys, psmd, psys->pathcache, PARTICLE_SOURCE_PARENT, - 0, 0, psys->totpart, - num_uv_layers, num_col_layers, mtfaces, mcols, uv_id, col_id, &parent_uvs, &parent_mcol, - &elb, &attr_id, hair_cache); - } - if (psys->childcache != NULL) { - const int child_count = psys->totchild * psys->part->disp / 100; - curr_point = particle_batch_cache_fill_segments( - psys, psmd, psys->childcache, PARTICLE_SOURCE_CHILDREN, - psys->totpart, curr_point, child_count, - num_uv_layers, num_col_layers, mtfaces, mcols, uv_id, col_id, &parent_uvs, &parent_mcol, - &elb, &attr_id, hair_cache); - } - } - /* Cleanup. */ - if (parent_uvs != NULL) { - /* TODO(sergey): For edit mode it should be edit->totcached. */ - for (int i = 0; i < psys->totpart; i++) { - MEM_SAFE_FREE(parent_uvs[i]); - } - MEM_freeN(parent_uvs); - } - if (parent_mcol != NULL) { - for (int i = 0; i < psys->totpart; i++) { - MEM_SAFE_FREE(parent_mcol[i]); - } - MEM_freeN(parent_mcol); - } - if (num_uv_layers) { - MEM_freeN(mtfaces); - } - if (num_col_layers) { - MEM_freeN(mcols); - } - if (psmd != NULL) { - MEM_freeN(uv_id); - } - hair_cache->indices = GPU_indexbuf_build(&elb); + if (hair_cache->pos != NULL && hair_cache->indices != NULL) { + return; + } + + int curr_point = 0; + ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; + + GPU_VERTBUF_DISCARD_SAFE(hair_cache->pos); + GPU_INDEXBUF_DISCARD_SAFE(hair_cache->indices); + + static GPUVertFormat format = {0}; + HairAttributeID attr_id; + uint *uv_id = NULL; + uint *col_id = NULL; + int num_uv_layers = 0; + int num_col_layers = 0; + int active_uv = 0; + int active_col = 0; + MTFace **mtfaces = NULL; + MCol **mcols = NULL; + float(**parent_uvs)[2] = NULL; + MCol **parent_mcol = NULL; + + if (psmd != NULL) { + if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPUV)) { + num_uv_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPUV); + active_uv = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPUV); + } + if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL)) { + num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPCOL); + active_col = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL); + } + } + + GPU_vertformat_clear(&format); + + /* initialize vertex format */ + attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + attr_id.tan = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + attr_id.ind = GPU_vertformat_attr_add(&format, "ind", GPU_COMP_I32, 1, GPU_FETCH_INT); + + if (psmd) { + uv_id = MEM_mallocN(sizeof(*uv_id) * num_uv_layers, "UV attr format"); + col_id = MEM_mallocN(sizeof(*col_id) * num_col_layers, "Col attr format"); + + for (int i = 0; i < num_uv_layers; i++) { + const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i); + char uuid[32]; + + BLI_snprintf(uuid, sizeof(uuid), "u%u", BLI_ghashutil_strhash_p(name)); + uv_id[i] = GPU_vertformat_attr_add(&format, uuid, GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + if (i == active_uv) { + GPU_vertformat_alias_add(&format, "u"); + } + } + + for (int i = 0; i < num_uv_layers; i++) { + const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i); + char uuid[32]; + + BLI_snprintf(uuid, sizeof(uuid), "c%u", BLI_ghashutil_strhash_p(name)); + col_id[i] = GPU_vertformat_attr_add(&format, uuid, GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + if (i == active_col) { + GPU_vertformat_alias_add(&format, "c"); + } + } + } + + hair_cache->pos = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(hair_cache->pos, hair_cache->point_len); + + GPUIndexBufBuilder elb; + GPU_indexbuf_init_ex( + &elb, GPU_PRIM_LINE_STRIP, hair_cache->elems_len, hair_cache->point_len, true); + + if (num_uv_layers || num_col_layers) { + BKE_mesh_tessface_ensure(psmd->mesh_final); + if (num_uv_layers) { + mtfaces = MEM_mallocN(sizeof(*mtfaces) * num_uv_layers, "Faces UV layers"); + for (int i = 0; i < num_uv_layers; i++) { + mtfaces[i] = (MTFace *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MTFACE, i); + } + } + if (num_col_layers) { + mcols = MEM_mallocN(sizeof(*mcols) * num_col_layers, "Color layers"); + for (int i = 0; i < num_col_layers; i++) { + mcols[i] = (MCol *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MCOL, i); + } + } + } + + if (edit != NULL && edit->pathcache != NULL) { + curr_point = particle_batch_cache_fill_segments(psys, + psmd, + edit->pathcache, + PARTICLE_SOURCE_PARENT, + 0, + 0, + edit->totcached, + num_uv_layers, + num_col_layers, + mtfaces, + mcols, + uv_id, + col_id, + &parent_uvs, + &parent_mcol, + &elb, + &attr_id, + hair_cache); + } + else { + if ((psys->pathcache != NULL) && + (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT))) { + curr_point = particle_batch_cache_fill_segments(psys, + psmd, + psys->pathcache, + PARTICLE_SOURCE_PARENT, + 0, + 0, + psys->totpart, + num_uv_layers, + num_col_layers, + mtfaces, + mcols, + uv_id, + col_id, + &parent_uvs, + &parent_mcol, + &elb, + &attr_id, + hair_cache); + } + if (psys->childcache != NULL) { + const int child_count = psys->totchild * psys->part->disp / 100; + curr_point = particle_batch_cache_fill_segments(psys, + psmd, + psys->childcache, + PARTICLE_SOURCE_CHILDREN, + psys->totpart, + curr_point, + child_count, + num_uv_layers, + num_col_layers, + mtfaces, + mcols, + uv_id, + col_id, + &parent_uvs, + &parent_mcol, + &elb, + &attr_id, + hair_cache); + } + } + /* Cleanup. */ + if (parent_uvs != NULL) { + /* TODO(sergey): For edit mode it should be edit->totcached. */ + for (int i = 0; i < psys->totpart; i++) { + MEM_SAFE_FREE(parent_uvs[i]); + } + MEM_freeN(parent_uvs); + } + if (parent_mcol != NULL) { + for (int i = 0; i < psys->totpart; i++) { + MEM_SAFE_FREE(parent_mcol[i]); + } + MEM_freeN(parent_mcol); + } + if (num_uv_layers) { + MEM_freeN(mtfaces); + } + if (num_col_layers) { + MEM_freeN(mcols); + } + if (psmd != NULL) { + MEM_freeN(uv_id); + } + hair_cache->indices = GPU_indexbuf_build(&elb); } -static void particle_batch_cache_ensure_pos( - Object *object, - ParticleSystem *psys, - ParticlePointCache *point_cache) +static void particle_batch_cache_ensure_pos(Object *object, + ParticleSystem *psys, + ParticlePointCache *point_cache) { - if (point_cache->pos != NULL) { - return; - } - - static GPUVertFormat format = { 0 }; - static uint pos_id, rot_id, val_id; - int i, curr_point; - ParticleData *pa; - ParticleKey state; - ParticleSimulationData sim = {NULL}; - const DRWContextState *draw_ctx = DRW_context_state_get(); - - sim.depsgraph = draw_ctx->depsgraph; - sim.scene = draw_ctx->scene; - sim.ob = object; - sim.psys = psys; - sim.psmd = psys_get_modifier(object, psys); - sim.psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); - - if (psys->part->phystype == PART_PHYS_KEYED) { - if (psys->flag & PSYS_KEYED) { - psys_count_keyed_targets(&sim); - if (psys->totkeyed == 0) { - return; - } - } - } - - GPU_VERTBUF_DISCARD_SAFE(point_cache->pos); - - if (format.attr_len == 0) { - /* initialize vertex format */ - pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - rot_id = GPU_vertformat_attr_add(&format, "rot", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - val_id = GPU_vertformat_attr_add(&format, "val", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - } - - point_cache->pos = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(point_cache->pos, psys->totpart); - - for (curr_point = 0, i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) { - state.time = DEG_get_ctime(draw_ctx->depsgraph); - if (!psys_get_particle_state(&sim, i, &state, 0)) { - continue; - } - - float val; - - GPU_vertbuf_attr_set(point_cache->pos, pos_id, curr_point, state.co); - GPU_vertbuf_attr_set(point_cache->pos, rot_id, curr_point, state.rot); - - switch (psys->part->draw_col) { - case PART_DRAW_COL_VEL: - val = len_v3(state.vel) / psys->part->color_vec_max; - break; - case PART_DRAW_COL_ACC: - val = len_v3v3( - state.vel, - pa->prev_state.vel) / ((state.time - pa->prev_state.time) * psys->part->color_vec_max); - break; - default: - val = -1.0f; - break; - } - - GPU_vertbuf_attr_set(point_cache->pos, val_id, curr_point, &val); - - curr_point++; - } - - if (curr_point != psys->totpart) { - GPU_vertbuf_data_resize(point_cache->pos, curr_point); - } + if (point_cache->pos != NULL) { + return; + } + + static GPUVertFormat format = {0}; + static uint pos_id, rot_id, val_id; + int i, curr_point; + ParticleData *pa; + ParticleKey state; + ParticleSimulationData sim = {NULL}; + const DRWContextState *draw_ctx = DRW_context_state_get(); + + sim.depsgraph = draw_ctx->depsgraph; + sim.scene = draw_ctx->scene; + sim.ob = object; + sim.psys = psys; + sim.psmd = psys_get_modifier(object, psys); + sim.psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + + if (psys->part->phystype == PART_PHYS_KEYED) { + if (psys->flag & PSYS_KEYED) { + psys_count_keyed_targets(&sim); + if (psys->totkeyed == 0) { + return; + } + } + } + + GPU_VERTBUF_DISCARD_SAFE(point_cache->pos); + + if (format.attr_len == 0) { + /* initialize vertex format */ + pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + rot_id = GPU_vertformat_attr_add(&format, "rot", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + val_id = GPU_vertformat_attr_add(&format, "val", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + } + + point_cache->pos = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(point_cache->pos, psys->totpart); + + for (curr_point = 0, i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) { + state.time = DEG_get_ctime(draw_ctx->depsgraph); + if (!psys_get_particle_state(&sim, i, &state, 0)) { + continue; + } + + float val; + + GPU_vertbuf_attr_set(point_cache->pos, pos_id, curr_point, state.co); + GPU_vertbuf_attr_set(point_cache->pos, rot_id, curr_point, state.rot); + + switch (psys->part->draw_col) { + case PART_DRAW_COL_VEL: + val = len_v3(state.vel) / psys->part->color_vec_max; + break; + case PART_DRAW_COL_ACC: + val = len_v3v3(state.vel, pa->prev_state.vel) / + ((state.time - pa->prev_state.time) * psys->part->color_vec_max); + break; + default: + val = -1.0f; + break; + } + + GPU_vertbuf_attr_set(point_cache->pos, val_id, curr_point, &val); + + curr_point++; + } + + if (curr_point != psys->totpart) { + GPU_vertbuf_data_resize(point_cache->pos, curr_point); + } } -static void drw_particle_update_ptcache_edit( - Object *object_eval, - ParticleSystem *psys, - PTCacheEdit *edit) +static void drw_particle_update_ptcache_edit(Object *object_eval, + ParticleSystem *psys, + PTCacheEdit *edit) { - if (edit->psys == NULL) { - return; - } - /* NOTE: Get flag from particle system coming from drawing object. - * this is where depsgraph will be setting flags to. - */ - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene_orig = (Scene *)DEG_get_original_id(&draw_ctx->scene->id); - Object *object_orig = DEG_get_original_object(object_eval); - if (psys->flag & PSYS_HAIR_UPDATED) { - PE_update_object(draw_ctx->depsgraph, scene_orig, object_orig, 0); - psys->flag &= ~PSYS_HAIR_UPDATED; - } - if (edit->pathcache == NULL) { - Depsgraph *depsgraph = draw_ctx->depsgraph; - psys_cache_edit_paths( - depsgraph, - scene_orig, object_orig, - edit, - DEG_get_ctime(depsgraph), - DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); - } + if (edit->psys == NULL) { + return; + } + /* NOTE: Get flag from particle system coming from drawing object. + * this is where depsgraph will be setting flags to. + */ + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene_orig = (Scene *)DEG_get_original_id(&draw_ctx->scene->id); + Object *object_orig = DEG_get_original_object(object_eval); + if (psys->flag & PSYS_HAIR_UPDATED) { + PE_update_object(draw_ctx->depsgraph, scene_orig, object_orig, 0); + psys->flag &= ~PSYS_HAIR_UPDATED; + } + if (edit->pathcache == NULL) { + Depsgraph *depsgraph = draw_ctx->depsgraph; + psys_cache_edit_paths(depsgraph, + scene_orig, + object_orig, + edit, + DEG_get_ctime(depsgraph), + DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); + } } -static void drw_particle_update_ptcache( - Object *object_eval, - ParticleSystem *psys) +static void drw_particle_update_ptcache(Object *object_eval, ParticleSystem *psys) { - if ((object_eval->mode & OB_MODE_PARTICLE_EDIT) == 0) { - return; - } - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene_orig = (Scene *)DEG_get_original_id(&draw_ctx->scene->id); - Object *object_orig = DEG_get_original_object(object_eval); - PTCacheEdit *edit = PE_create_current( - draw_ctx->depsgraph, scene_orig, object_orig); - if (edit != NULL) { - drw_particle_update_ptcache_edit(object_eval, psys, edit); - } + if ((object_eval->mode & OB_MODE_PARTICLE_EDIT) == 0) { + return; + } + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene_orig = (Scene *)DEG_get_original_id(&draw_ctx->scene->id); + Object *object_orig = DEG_get_original_object(object_eval); + PTCacheEdit *edit = PE_create_current(draw_ctx->depsgraph, scene_orig, object_orig); + if (edit != NULL) { + drw_particle_update_ptcache_edit(object_eval, psys, edit); + } } typedef struct ParticleDrawSource { - Object *object; - ParticleSystem *psys; - ModifierData *md; - PTCacheEdit *edit; + Object *object; + ParticleSystem *psys; + ModifierData *md; + PTCacheEdit *edit; } ParticleDrawSource; -static void drw_particle_get_hair_source( - Object *object, - ParticleSystem *psys, - ModifierData *md, - PTCacheEdit *edit, - ParticleDrawSource *r_draw_source) +static void drw_particle_get_hair_source(Object *object, + ParticleSystem *psys, + ModifierData *md, + PTCacheEdit *edit, + ParticleDrawSource *r_draw_source) { - r_draw_source->object = object; - r_draw_source->psys = psys; - r_draw_source->md = md; - r_draw_source->edit = edit; - if ((object->mode & OB_MODE_PARTICLE_EDIT) != 0) { - r_draw_source->object = DEG_get_original_object(object); - r_draw_source->psys = psys_orig_get(psys); - } + r_draw_source->object = object; + r_draw_source->psys = psys; + r_draw_source->md = md; + r_draw_source->edit = edit; + if ((object->mode & OB_MODE_PARTICLE_EDIT) != 0) { + r_draw_source->object = DEG_get_original_object(object); + r_draw_source->psys = psys_orig_get(psys); + } } -GPUBatch *DRW_particles_batch_cache_get_hair( - Object *object, - ParticleSystem *psys, - ModifierData *md) +GPUBatch *DRW_particles_batch_cache_get_hair(Object *object, + ParticleSystem *psys, + ModifierData *md) { - ParticleBatchCache *cache = particle_batch_cache_get(psys); - if (cache->hair.hairs == NULL) { - drw_particle_update_ptcache(object, psys); - ParticleDrawSource source; - drw_particle_get_hair_source(object, psys, md, NULL, &source); - ensure_seg_pt_count(source.edit, source.psys, &cache->hair); - particle_batch_cache_ensure_pos_and_seg(source.edit, source.psys, source.md, &cache->hair); - cache->hair.hairs = GPU_batch_create( - GPU_PRIM_LINE_STRIP, - cache->hair.pos, - cache->hair.indices); - } - return cache->hair.hairs; + ParticleBatchCache *cache = particle_batch_cache_get(psys); + if (cache->hair.hairs == NULL) { + drw_particle_update_ptcache(object, psys); + ParticleDrawSource source; + drw_particle_get_hair_source(object, psys, md, NULL, &source); + ensure_seg_pt_count(source.edit, source.psys, &cache->hair); + particle_batch_cache_ensure_pos_and_seg(source.edit, source.psys, source.md, &cache->hair); + cache->hair.hairs = GPU_batch_create( + GPU_PRIM_LINE_STRIP, cache->hair.pos, cache->hair.indices); + } + return cache->hair.hairs; } GPUBatch *DRW_particles_batch_cache_get_dots(Object *object, ParticleSystem *psys) { - ParticleBatchCache *cache = particle_batch_cache_get(psys); + ParticleBatchCache *cache = particle_batch_cache_get(psys); - if (cache->point.points == NULL) { - particle_batch_cache_ensure_pos(object, psys, &cache->point); - cache->point.points = GPU_batch_create(GPU_PRIM_POINTS, cache->point.pos, NULL); - } + if (cache->point.points == NULL) { + particle_batch_cache_ensure_pos(object, psys, &cache->point); + cache->point.points = GPU_batch_create(GPU_PRIM_POINTS, cache->point.pos, NULL); + } - return cache->point.points; + return cache->point.points; } -static void particle_batch_cache_ensure_edit_pos_and_seg( - PTCacheEdit *edit, - ParticleSystem *psys, - ModifierData *UNUSED(md), - ParticleHairCache *hair_cache, - bool use_weight) +static void particle_batch_cache_ensure_edit_pos_and_seg(PTCacheEdit *edit, + ParticleSystem *psys, + ModifierData *UNUSED(md), + ParticleHairCache *hair_cache, + bool use_weight) { - if (hair_cache->pos != NULL && hair_cache->indices != NULL) { - return; - } - - ParticleData *particle = (use_weight) ? psys->particles : NULL; - - GPU_VERTBUF_DISCARD_SAFE(hair_cache->pos); - GPU_INDEXBUF_DISCARD_SAFE(hair_cache->indices); - - GPUVertBufRaw data_step; - GPUIndexBufBuilder elb; - uint pos_id, color_id; - GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id); - - hair_cache->pos = GPU_vertbuf_create_with_format(edit_point_format); - GPU_vertbuf_data_alloc(hair_cache->pos, hair_cache->point_len); - GPU_vertbuf_attr_get_raw_data(hair_cache->pos, pos_id, &data_step); - - GPU_indexbuf_init_ex( - &elb, - GPU_PRIM_LINE_STRIP, - hair_cache->elems_len, hair_cache->point_len, - true); - - if (edit != NULL && edit->pathcache != NULL) { - particle_batch_cache_fill_segments_edit( - edit, particle, edit->pathcache, - 0, edit->totcached, - &elb, &data_step); - } - else { - BLI_assert(!"Hairs are not in edit mode!"); - } - hair_cache->indices = GPU_indexbuf_build(&elb); + if (hair_cache->pos != NULL && hair_cache->indices != NULL) { + return; + } + + ParticleData *particle = (use_weight) ? psys->particles : NULL; + + GPU_VERTBUF_DISCARD_SAFE(hair_cache->pos); + GPU_INDEXBUF_DISCARD_SAFE(hair_cache->indices); + + GPUVertBufRaw data_step; + GPUIndexBufBuilder elb; + uint pos_id, color_id; + GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id); + + hair_cache->pos = GPU_vertbuf_create_with_format(edit_point_format); + GPU_vertbuf_data_alloc(hair_cache->pos, hair_cache->point_len); + GPU_vertbuf_attr_get_raw_data(hair_cache->pos, pos_id, &data_step); + + GPU_indexbuf_init_ex( + &elb, GPU_PRIM_LINE_STRIP, hair_cache->elems_len, hair_cache->point_len, true); + + if (edit != NULL && edit->pathcache != NULL) { + particle_batch_cache_fill_segments_edit( + edit, particle, edit->pathcache, 0, edit->totcached, &elb, &data_step); + } + else { + BLI_assert(!"Hairs are not in edit mode!"); + } + hair_cache->indices = GPU_indexbuf_build(&elb); } -GPUBatch *DRW_particles_batch_cache_get_edit_strands( - Object *object, - ParticleSystem *psys, - PTCacheEdit *edit, - bool use_weight) +GPUBatch *DRW_particles_batch_cache_get_edit_strands(Object *object, + ParticleSystem *psys, + PTCacheEdit *edit, + bool use_weight) { - ParticleBatchCache *cache = particle_batch_cache_get(psys); - if (cache->edit_is_weight != use_weight) { - GPU_VERTBUF_DISCARD_SAFE(cache->edit_hair.pos); - GPU_BATCH_DISCARD_SAFE(cache->edit_hair.hairs); - } - if (cache->edit_hair.hairs != NULL) { - return cache->edit_hair.hairs; - } - drw_particle_update_ptcache_edit(object, psys, edit); - ensure_seg_pt_count(edit, psys, &cache->edit_hair); - particle_batch_cache_ensure_edit_pos_and_seg(edit, psys, NULL, &cache->edit_hair, use_weight); - cache->edit_hair.hairs = GPU_batch_create( - GPU_PRIM_LINE_STRIP, - cache->edit_hair.pos, - cache->edit_hair.indices); - cache->edit_is_weight = use_weight; - return cache->edit_hair.hairs; + ParticleBatchCache *cache = particle_batch_cache_get(psys); + if (cache->edit_is_weight != use_weight) { + GPU_VERTBUF_DISCARD_SAFE(cache->edit_hair.pos); + GPU_BATCH_DISCARD_SAFE(cache->edit_hair.hairs); + } + if (cache->edit_hair.hairs != NULL) { + return cache->edit_hair.hairs; + } + drw_particle_update_ptcache_edit(object, psys, edit); + ensure_seg_pt_count(edit, psys, &cache->edit_hair); + particle_batch_cache_ensure_edit_pos_and_seg(edit, psys, NULL, &cache->edit_hair, use_weight); + cache->edit_hair.hairs = GPU_batch_create( + GPU_PRIM_LINE_STRIP, cache->edit_hair.pos, cache->edit_hair.indices); + cache->edit_is_weight = use_weight; + return cache->edit_hair.hairs; } -static void ensure_edit_inner_points_count( - const PTCacheEdit *edit, - ParticleBatchCache *cache) +static void ensure_edit_inner_points_count(const PTCacheEdit *edit, ParticleBatchCache *cache) { - if (cache->edit_inner_pos != NULL) { - return; - } - cache->edit_inner_point_len = 0; - for (int point_index = 0; point_index < edit->totpoint; point_index++) { - const PTCacheEditPoint *point = &edit->points[point_index]; - BLI_assert(point->totkey >= 1); - cache->edit_inner_point_len += (point->totkey - 1); - } + if (cache->edit_inner_pos != NULL) { + return; + } + cache->edit_inner_point_len = 0; + for (int point_index = 0; point_index < edit->totpoint; point_index++) { + const PTCacheEditPoint *point = &edit->points[point_index]; + BLI_assert(point->totkey >= 1); + cache->edit_inner_point_len += (point->totkey - 1); + } } -static void particle_batch_cache_ensure_edit_inner_pos( - PTCacheEdit *edit, - ParticleBatchCache *cache) +static void particle_batch_cache_ensure_edit_inner_pos(PTCacheEdit *edit, + ParticleBatchCache *cache) { - if (cache->edit_inner_pos != NULL) { - return; - } - - uint pos_id, color_id; - GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id); - - cache->edit_inner_pos = GPU_vertbuf_create_with_format(edit_point_format); - GPU_vertbuf_data_alloc(cache->edit_inner_pos, cache->edit_inner_point_len); - - int global_key_index = 0; - for (int point_index = 0; point_index < edit->totpoint; point_index++) { - const PTCacheEditPoint *point = &edit->points[point_index]; - for (int key_index = 0; key_index < point->totkey - 1; key_index++) { - PTCacheEditKey *key = &point->keys[key_index]; - uchar color = (key->flag & PEK_SELECT) ? 0xFF : 0x00; - GPU_vertbuf_attr_set(cache->edit_inner_pos, pos_id, global_key_index, key->world_co); - GPU_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, &color); - global_key_index++; - } - } + if (cache->edit_inner_pos != NULL) { + return; + } + + uint pos_id, color_id; + GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id); + + cache->edit_inner_pos = GPU_vertbuf_create_with_format(edit_point_format); + GPU_vertbuf_data_alloc(cache->edit_inner_pos, cache->edit_inner_point_len); + + int global_key_index = 0; + for (int point_index = 0; point_index < edit->totpoint; point_index++) { + const PTCacheEditPoint *point = &edit->points[point_index]; + for (int key_index = 0; key_index < point->totkey - 1; key_index++) { + PTCacheEditKey *key = &point->keys[key_index]; + uchar color = (key->flag & PEK_SELECT) ? 0xFF : 0x00; + GPU_vertbuf_attr_set(cache->edit_inner_pos, pos_id, global_key_index, key->world_co); + GPU_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, &color); + global_key_index++; + } + } } -GPUBatch *DRW_particles_batch_cache_get_edit_inner_points( - Object *object, - ParticleSystem *psys, - PTCacheEdit *edit) +GPUBatch *DRW_particles_batch_cache_get_edit_inner_points(Object *object, + ParticleSystem *psys, + PTCacheEdit *edit) { - ParticleBatchCache *cache = particle_batch_cache_get(psys); - if (cache->edit_inner_points != NULL) { - return cache->edit_inner_points; - } - drw_particle_update_ptcache_edit(object, psys, edit); - ensure_edit_inner_points_count(edit, cache); - particle_batch_cache_ensure_edit_inner_pos(edit, cache); - cache->edit_inner_points = GPU_batch_create( - GPU_PRIM_POINTS, - cache->edit_inner_pos, - NULL); - return cache->edit_inner_points; + ParticleBatchCache *cache = particle_batch_cache_get(psys); + if (cache->edit_inner_points != NULL) { + return cache->edit_inner_points; + } + drw_particle_update_ptcache_edit(object, psys, edit); + ensure_edit_inner_points_count(edit, cache); + particle_batch_cache_ensure_edit_inner_pos(edit, cache); + cache->edit_inner_points = GPU_batch_create(GPU_PRIM_POINTS, cache->edit_inner_pos, NULL); + return cache->edit_inner_points; } -static void ensure_edit_tip_points_count( - const PTCacheEdit *edit, - ParticleBatchCache *cache) +static void ensure_edit_tip_points_count(const PTCacheEdit *edit, ParticleBatchCache *cache) { - if (cache->edit_tip_pos != NULL) { - return; - } - cache->edit_tip_point_len = edit->totpoint; + if (cache->edit_tip_pos != NULL) { + return; + } + cache->edit_tip_point_len = edit->totpoint; } -static void particle_batch_cache_ensure_edit_tip_pos( - PTCacheEdit *edit, - ParticleBatchCache *cache) +static void particle_batch_cache_ensure_edit_tip_pos(PTCacheEdit *edit, ParticleBatchCache *cache) { - if (cache->edit_tip_pos != NULL) { - return; - } - - uint pos_id, color_id; - GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id); - - cache->edit_tip_pos = GPU_vertbuf_create_with_format(edit_point_format); - GPU_vertbuf_data_alloc(cache->edit_tip_pos, cache->edit_tip_point_len); - - for (int point_index = 0; point_index < edit->totpoint; point_index++) { - const PTCacheEditPoint *point = &edit->points[point_index]; - PTCacheEditKey *key = &point->keys[point->totkey - 1]; - uchar color = (key->flag & PEK_SELECT) ? 0xFF : 0x00; - GPU_vertbuf_attr_set(cache->edit_tip_pos, pos_id, point_index, key->world_co); - GPU_vertbuf_attr_set(cache->edit_tip_pos, color_id, point_index, &color); - } + if (cache->edit_tip_pos != NULL) { + return; + } + + uint pos_id, color_id; + GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id); + + cache->edit_tip_pos = GPU_vertbuf_create_with_format(edit_point_format); + GPU_vertbuf_data_alloc(cache->edit_tip_pos, cache->edit_tip_point_len); + + for (int point_index = 0; point_index < edit->totpoint; point_index++) { + const PTCacheEditPoint *point = &edit->points[point_index]; + PTCacheEditKey *key = &point->keys[point->totkey - 1]; + uchar color = (key->flag & PEK_SELECT) ? 0xFF : 0x00; + GPU_vertbuf_attr_set(cache->edit_tip_pos, pos_id, point_index, key->world_co); + GPU_vertbuf_attr_set(cache->edit_tip_pos, color_id, point_index, &color); + } } -GPUBatch *DRW_particles_batch_cache_get_edit_tip_points( - Object *object, - ParticleSystem *psys, - PTCacheEdit *edit) +GPUBatch *DRW_particles_batch_cache_get_edit_tip_points(Object *object, + ParticleSystem *psys, + PTCacheEdit *edit) { - ParticleBatchCache *cache = particle_batch_cache_get(psys); - if (cache->edit_tip_points != NULL) { - return cache->edit_tip_points; - } - drw_particle_update_ptcache_edit(object, psys, edit); - ensure_edit_tip_points_count(edit, cache); - particle_batch_cache_ensure_edit_tip_pos(edit, cache); - cache->edit_tip_points = GPU_batch_create( - GPU_PRIM_POINTS, - cache->edit_tip_pos, - NULL); - return cache->edit_tip_points; + ParticleBatchCache *cache = particle_batch_cache_get(psys); + if (cache->edit_tip_points != NULL) { + return cache->edit_tip_points; + } + drw_particle_update_ptcache_edit(object, psys, edit); + ensure_edit_tip_points_count(edit, cache); + particle_batch_cache_ensure_edit_tip_pos(edit, cache); + cache->edit_tip_points = GPU_batch_create(GPU_PRIM_POINTS, cache->edit_tip_pos, NULL); + return cache->edit_tip_points; } /* Ensure all textures and buffers needed for GPU accelerated drawing. */ -bool particles_ensure_procedural_data( - Object *object, - ParticleSystem *psys, - ModifierData *md, - ParticleHairCache **r_hair_cache, - int subdiv, - int thickness_res) +bool particles_ensure_procedural_data(Object *object, + ParticleSystem *psys, + ModifierData *md, + ParticleHairCache **r_hair_cache, + int subdiv, + int thickness_res) { - bool need_ft_update = false; - - drw_particle_update_ptcache(object, psys); - - ParticleDrawSource source; - drw_particle_get_hair_source(object, psys, md, NULL, &source); - - ParticleSettings *part = source.psys->part; - ParticleBatchCache *cache = particle_batch_cache_get(source.psys); - *r_hair_cache = &cache->hair; - - (*r_hair_cache)->final[subdiv].strands_res = 1 << (part->draw_step + subdiv); - - /* Refreshed on combing and simulation. */ - if ((*r_hair_cache)->proc_point_buf == NULL) { - ensure_seg_pt_count(source.edit, source.psys, &cache->hair); - particle_batch_cache_ensure_procedural_pos(source.edit, source.psys, &cache->hair); - need_ft_update = true; - } - - /* Refreshed if active layer or custom data changes. */ - if ((*r_hair_cache)->strand_tex == NULL) { - particle_batch_cache_ensure_procedural_strand_data(source.edit, source.psys, source.md, &cache->hair); - } - - /* Refreshed only on subdiv count change. */ - if ((*r_hair_cache)->final[subdiv].proc_buf == NULL) { - particle_batch_cache_ensure_procedural_final_points(&cache->hair, subdiv); - need_ft_update = true; - } - if ((*r_hair_cache)->final[subdiv].proc_hairs[thickness_res - 1] == NULL) { - particle_batch_cache_ensure_procedural_indices(source.edit, source.psys, &cache->hair, thickness_res, subdiv); - } - - return need_ft_update; + bool need_ft_update = false; + + drw_particle_update_ptcache(object, psys); + + ParticleDrawSource source; + drw_particle_get_hair_source(object, psys, md, NULL, &source); + + ParticleSettings *part = source.psys->part; + ParticleBatchCache *cache = particle_batch_cache_get(source.psys); + *r_hair_cache = &cache->hair; + + (*r_hair_cache)->final[subdiv].strands_res = 1 << (part->draw_step + subdiv); + + /* Refreshed on combing and simulation. */ + if ((*r_hair_cache)->proc_point_buf == NULL) { + ensure_seg_pt_count(source.edit, source.psys, &cache->hair); + particle_batch_cache_ensure_procedural_pos(source.edit, source.psys, &cache->hair); + need_ft_update = true; + } + + /* Refreshed if active layer or custom data changes. */ + if ((*r_hair_cache)->strand_tex == NULL) { + particle_batch_cache_ensure_procedural_strand_data( + source.edit, source.psys, source.md, &cache->hair); + } + + /* Refreshed only on subdiv count change. */ + if ((*r_hair_cache)->final[subdiv].proc_buf == NULL) { + particle_batch_cache_ensure_procedural_final_points(&cache->hair, subdiv); + need_ft_update = true; + } + if ((*r_hair_cache)->final[subdiv].proc_hairs[thickness_res - 1] == NULL) { + particle_batch_cache_ensure_procedural_indices( + source.edit, source.psys, &cache->hair, thickness_res, subdiv); + } + + return need_ft_update; } |