diff options
Diffstat (limited to 'source/blender/draw/intern/draw_cache_impl_particles.c')
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_particles.c | 172 |
1 files changed, 119 insertions, 53 deletions
diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c index 263aaa1ffdf..46ce115c382 100644 --- a/source/blender/draw/intern/draw_cache_impl_particles.c +++ b/source/blender/draw/intern/draw_cache_impl_particles.c @@ -80,6 +80,9 @@ typedef struct ParticleBatchCache { /* Control points when in edit mode. */ ParticleHairCache edit_hair; + GPUVertBuf *edit_pos; + GPUBatch *edit_strands; + GPUVertBuf *edit_inner_pos; GPUBatch *edit_inner_points; int edit_inner_point_len; @@ -100,6 +103,25 @@ typedef struct HairAttributeID { uint ind; } HairAttributeID; +typedef struct EditStrandData { + 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 bool particle_batch_cache_valid(ParticleSystem *psys) { ParticleBatchCache *cache = psys->batch_cache; @@ -653,6 +675,52 @@ static void particle_batch_cache_fill_segments_proc_pos( } } +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); + } +} + +static int particle_batch_cache_fill_segments_edit( + const PTCacheEdit *edit, + 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; + 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, @@ -1366,6 +1434,46 @@ GPUBatch *DRW_particles_batch_cache_get_dots(Object *object, ParticleSystem *psy return cache->point.points; } +static void particle_batch_cache_ensure_edit_pos_and_seg( + PTCacheEdit *edit, + ParticleSystem *UNUSED(psys), + ModifierData *UNUSED(md), + ParticleHairCache *hair_cache) +{ + if (hair_cache->pos != NULL && hair_cache->indices != NULL) { + return; + } + + 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, 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, @@ -1377,7 +1485,7 @@ GPUBatch *DRW_particles_batch_cache_get_edit_strands( } drw_particle_update_ptcache_edit(object, psys, edit); ensure_seg_pt_count(edit, psys, &cache->edit_hair); - particle_batch_cache_ensure_pos_and_seg(edit, psys, NULL, &cache->edit_hair); + particle_batch_cache_ensure_edit_pos_and_seg(edit, psys, NULL, &cache->edit_hair); cache->edit_hair.hairs = GPU_batch_create( GPU_PRIM_LINE_STRIP, cache->edit_hair.pos, @@ -1400,17 +1508,6 @@ static void ensure_edit_inner_points_count( } } -static void edit_colors_get( - PTCacheEdit *edit, - float selected_color[4], - float normal_color[4]) -{ - rgb_uchar_to_float(selected_color, edit->sel_col); - rgb_uchar_to_float(normal_color, edit->nosel_col); - selected_color[3] = 1.0f; - normal_color[3] = 1.0f; -} - static void particle_batch_cache_ensure_edit_inner_pos( PTCacheEdit *edit, ParticleBatchCache *cache) @@ -1419,35 +1516,20 @@ static void particle_batch_cache_ensure_edit_inner_pos( return; } - static GPUVertFormat format = { 0 }; - static uint pos_id, color_id; - - GPU_VERTBUF_DISCARD_SAFE(cache->edit_inner_pos); - - if (format.attr_len == 0) { - /* initialize vertex format */ - pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - } + 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(&format); + 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); - float selected_color[4], normal_color[4]; - edit_colors_get(edit, selected_color, normal_color); - 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); - if (key->flag & PEK_SELECT) { - GPU_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, selected_color); - } - else { - GPU_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, normal_color); - } + GPU_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, &color); global_key_index++; } } @@ -1490,33 +1572,18 @@ static void particle_batch_cache_ensure_edit_tip_pos( return; } - static GPUVertFormat format = { 0 }; - static uint pos_id, color_id; + uint pos_id, color_id; + GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id); - GPU_VERTBUF_DISCARD_SAFE(cache->edit_tip_pos); - - if (format.attr_len == 0) { - /* initialize vertex format */ - pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - color_id = GPU_vertformat_attr_add(&format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - } - - cache->edit_tip_pos = GPU_vertbuf_create_with_format(&format); + 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); - float selected_color[4], normal_color[4]; - edit_colors_get(edit, selected_color, normal_color); - 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); - if (key->flag & PEK_SELECT) { - GPU_vertbuf_attr_set(cache->edit_tip_pos, color_id, point_index, selected_color); - } - else { - GPU_vertbuf_attr_set(cache->edit_tip_pos, color_id, point_index, normal_color); - } + GPU_vertbuf_attr_set(cache->edit_tip_pos, color_id, point_index, &color); } } @@ -1582,6 +1649,5 @@ bool particles_ensure_procedural_data( particle_batch_cache_ensure_procedural_indices(source.edit, source.psys, &cache->hair, thickness_res, subdiv); } - return need_ft_update; } |