Hair editing: Use original object's particles for drawing

This allows to rely on brush to update children positions,
and avoid tag of object. Makes it way faster to comb with
children enabled.
This commit is contained in:
Sergey Sharybin 2018-06-15 17:22:31 +02:00
parent 5ac7068c5f
commit ca2be6912d
2 changed files with 46 additions and 22 deletions

View File

@ -45,6 +45,7 @@
#include "DNA_customdata_types.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
@ -1309,17 +1310,45 @@ static void drw_particle_update_ptcache(
}
}
typedef struct ParticleDrawSource {
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)
{
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);
if (md != NULL) {
r_draw_source->md = modifiers_findByName(r_draw_source->object, md->name);
}
}
}
Gwn_Batch *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);
ensure_seg_pt_count(NULL, psys, &cache->hair);
particle_batch_cache_ensure_pos_and_seg(NULL, psys, md, &cache->hair);
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 = GWN_batch_create(
GWN_PRIM_LINE_STRIP,
cache->hair.pos,
@ -1515,7 +1544,7 @@ Gwn_Batch *DRW_particles_batch_cache_get_edit_tip_points(
/* Ensure all textures and buffers needed for GPU accelerated drawing. */
bool particles_ensure_procedural_data(
Object *UNUSED(object),
Object *object,
ParticleSystem *psys,
ModifierData *md,
ParticleHairCache **r_hair_cache,
@ -1524,22 +1553,27 @@ bool particles_ensure_procedural_data(
{
bool need_ft_update = false;
ParticleSettings *part = psys->part;
ParticleBatchCache *cache = particle_batch_cache_get(psys);
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(NULL, psys, &cache->hair);
particle_batch_cache_ensure_procedural_pos(NULL, psys, &cache->hair);
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(NULL, psys, md, &cache->hair);
particle_batch_cache_ensure_procedural_strand_data(source.edit, source.psys, source.md, &cache->hair);
}
/* Refreshed only on subdiv count change. */
@ -1548,7 +1582,7 @@ bool particles_ensure_procedural_data(
need_ft_update = true;
}
if ((*r_hair_cache)->final[subdiv].proc_hairs[thickness_res - 1] == NULL) {
particle_batch_cache_ensure_procedural_indices(NULL, psys, &cache->hair, thickness_res, subdiv);
particle_batch_cache_ensure_procedural_indices(source.edit, source.psys, &cache->hair, thickness_res, subdiv);
}

View File

@ -4232,12 +4232,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
if (edit->psys) {
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
BKE_particle_batch_cache_dirty(edit->psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
if (pset->flag & PE_DRAW_PART) {
DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
}
else {
DEG_id_tag_update(&ob->id, DEG_TAG_SELECT_UPDATE);
}
DEG_id_tag_update(&ob->id, DEG_TAG_SELECT_UPDATE);
}
else {
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
@ -4505,12 +4500,7 @@ static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op))
if (edit->psys) {
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
BKE_particle_batch_cache_dirty(edit->psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
if (pset->flag & PE_DRAW_PART) {
DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
}
else {
DEG_id_tag_update(&ob->id, DEG_TAG_SELECT_UPDATE);
}
DEG_id_tag_update(&ob->id, DEG_TAG_SELECT_UPDATE);
}
else {
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);