diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-04-08 10:28:52 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-04-13 15:38:59 +0300 |
commit | 7b9fb3259157cea2df5e7b461d04f55cfa380031 (patch) | |
tree | a54e7d066283aeae384beb2ae99cc9a0e158bec5 /source/blender/blenkernel | |
parent | a1e2415ed51e2da97e3b182f18f462345a02ce14 (diff) |
Python API: remove preview/render resolution settings from API functions.
For correct results these must have been set already when the depsgraph was
created and evaluated, so all dependencies have appropriate resolutions too.
For particle we no longer backup and restore the viewport particles to avoid
overwriting them during render, as copy-on-write solves this for us. Even
without COW particles seem to work ok.
This also removes the particle simplification options based on camera. This
was never used much and only available in Blender Internal.
Differential Revision: https://developer.blender.org/D3148
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_mesh.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_particle.h | 40 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh.c | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object_dupli.c | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle.c | 235 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle_distribute.c | 279 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle_system.c | 50 |
8 files changed, 71 insertions, 543 deletions
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 19caf30a280..79d72206903 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -141,7 +141,7 @@ float (*BKE_mesh_vertexCos_get(const struct Mesh *me, int *r_numVerts))[3]; void BKE_mesh_split_faces(struct Mesh *mesh, bool free_loop_normals); struct Mesh *BKE_mesh_new_from_object(const struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *sce, struct Object *ob, - int apply_modifiers, int settings, int calc_tessface, int calc_undeformed); + int apply_modifiers, int calc_tessface, int calc_undeformed); /* vertex level transformations & checks (no derived mesh) */ diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 886ccb9113a..8cd76097401 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -49,6 +49,7 @@ struct ParticleSettings; struct Main; struct Object; struct Scene; +struct Depsgraph; struct DerivedMesh; struct ModifierData; struct MTFace; @@ -147,7 +148,7 @@ typedef struct ParticleThreadContext { float *jit, *jitoff, *weight; float maxweight; - int *index, *skip, jitlevel; + int *index, jitlevel; int cfrom, distr; @@ -289,8 +290,8 @@ BLI_INLINE void psys_frand_vec(ParticleSystem *psys, unsigned int seed, float ve int count_particles(struct ParticleSystem *psys); int count_particles_mod(struct ParticleSystem *psys, int totgr, int cur); -int psys_get_child_number(struct Scene *scene, struct ParticleSystem *psys); -int psys_get_tot_child(struct Scene *scene, struct ParticleSystem *psys); +int psys_get_child_number(struct Scene *scene, struct ParticleSystem *psys, const bool use_render_params); +int psys_get_tot_child(struct Scene *scene, struct ParticleSystem *psys, const bool use_render_params); struct ParticleSystem *psys_get_current(struct Object *ob); /* for rna */ @@ -301,7 +302,7 @@ void psys_set_current_num(Object *ob, int index); struct LatticeDeformData *psys_create_lattice_deform_data(struct ParticleSimulationData *sim); -bool psys_in_edit_mode(struct ViewLayer *view_layer, struct ParticleSystem *psys); +bool psys_in_edit_mode(struct Depsgraph *depsgraph, struct ParticleSystem *psys); bool psys_check_enabled(struct Object *ob, struct ParticleSystem *psys, const bool use_render_params); bool psys_check_edited(struct ParticleSystem *psys); @@ -313,8 +314,6 @@ void BKE_particlesettings_free(struct ParticleSettings *part); void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit); void psys_free(struct Object *ob, struct ParticleSystem *psys); -void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy, int timeoffset); -void psys_render_restore(struct Object *ob, struct ParticleSystem *psys); bool psys_render_simplify_params(struct ParticleSystem *psys, struct ChildParticle *cpa, float *params); void psys_interpolate_uvs(const struct MTFace *tface, int quad, const float w[4], float uvco[2]); @@ -441,34 +440,7 @@ int psys_particle_dm_face_lookup(struct DerivedMesh *dm_final, struct DerivedMes void reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, float dtime, float cfra); -float psys_get_current_display_percentage(struct ParticleSystem *psys); - -typedef struct ParticleRenderElem { - int curchild, totchild, reduce; - float lambda, t, scalemin, scalemax; -} ParticleRenderElem; - -typedef struct ParticleRenderData { - ChildParticle *child; - ParticleCacheKey **pathcache; - ParticleCacheKey **childcache; - ListBase pathcachebufs, childcachebufs; - int totchild, totcached, totchildcache; - struct DerivedMesh *dm; - int totdmvert, totdmedge, totdmface; - - float mat[4][4]; - float viewmat[4][4], winmat[4][4]; - int winx, winy; - - int do_simplify; - int timeoffset; - ParticleRenderElem *elems; - - /* ORIGINDEX */ - const int *index_mf_to_mpoly; - const int *index_mp_to_orig; -} ParticleRenderData; +float psys_get_current_display_percentage(struct ParticleSystem *psys, const bool use_render_params); /* psys_reset */ #define PSYS_RESET_ALL 1 diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 8c88430aa10..af92422f4c3 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -66,6 +66,7 @@ #include "BKE_editmesh.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" /* Define for cases when you want extra validation of mesh * after certain modifications. @@ -2428,12 +2429,12 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals) /* settings: 1 - preview, 2 - render */ Mesh *BKE_mesh_new_from_object( const EvaluationContext *eval_ctx, Main *bmain, Scene *sce, Object *ob, - int apply_modifiers, int settings, int calc_tessface, int calc_undeformed) + int apply_modifiers, int calc_tessface, int calc_undeformed) { Mesh *tmpmesh; Curve *tmpcu = NULL, *copycu; int i; - const bool render = (settings == eModifierMode_Render); + const bool render = (DEG_get_mode(eval_ctx->depsgraph) == DAG_EVAL_RENDER); const bool cage = !apply_modifiers; bool do_mat_id_data_us = true; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 98fcd478b07..67769c9ae3b 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1038,7 +1038,6 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys, const int f BLI_listbase_clear(&psysn->pathcachebufs); BLI_listbase_clear(&psysn->childcachebufs); - psysn->renderdata = NULL; /* XXX Never copy caches here? */ psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, flag & ~LIB_ID_COPY_CACHES); diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 0db77432d53..1b976fef166 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -881,7 +881,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem BLI_srandom((unsigned int)(31415926 + psys->seed)); - if ((psys->renderdata || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) { + if ((for_render || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) { ParticleSimulationData sim = {NULL}; sim.eval_ctx = ctx->eval_ctx; sim.scene = scene; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 3e9c525b92d..1917e370aa9 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -87,6 +87,7 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_query.h" #include "RE_render_ext.h" @@ -251,7 +252,7 @@ struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData { struct LatticeDeformData *lattice_deform_data = NULL; - if (psys_in_edit_mode(sim->eval_ctx->view_layer, sim->psys) == 0) { + if (psys_in_edit_mode(sim->eval_ctx->depsgraph, sim->psys) == 0) { Object *lattice = NULL; ModifierData *md = (ModifierData *)psys_get_modifier(sim->ob, sim->psys); int mode = G.is_rendering ? eModifierMode_Render : eModifierMode_Realtime; @@ -288,13 +289,16 @@ void psys_enable_all(Object *ob) psys->flag &= ~PSYS_DISABLED; } -bool psys_in_edit_mode(ViewLayer *view_layer, ParticleSystem *psys) +bool psys_in_edit_mode(Depsgraph *depsgraph, ParticleSystem *psys) { + ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph); + const bool use_render_params = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); + return (view_layer->basact && (view_layer->basact->object->mode & OB_MODE_PARTICLE_EDIT) && psys == psys_get_current((view_layer->basact)->object) && (psys->edit || psys->pointcache->edit) && - !psys->renderdata); + !use_render_params); } bool psys_check_enabled(Object *ob, ParticleSystem *psys, const bool use_render_params) @@ -305,7 +309,7 @@ bool psys_check_enabled(Object *ob, ParticleSystem *psys, const bool use_render_ return 0; psmd = psys_get_modifier(ob, psys); - if (psys->renderdata || use_render_params) { + if (use_render_params) { if (!(psmd->modifier.mode & eModifierMode_Render)) return 0; } @@ -622,204 +626,6 @@ void psys_free(Object *ob, ParticleSystem *psys) } /************************************************/ -/* Rendering */ -/************************************************/ -/* these functions move away particle data and bring it back after - * rendering, to make different render settings possible without - * removing the previous data. this should be solved properly once */ - -void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy, int timeoffset) -{ - ParticleRenderData *data; - ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); - - if (psys->renderdata) - return; - - data = MEM_callocN(sizeof(ParticleRenderData), "ParticleRenderData"); - - data->child = psys->child; - data->totchild = psys->totchild; - data->pathcache = psys->pathcache; - data->pathcachebufs.first = psys->pathcachebufs.first; - data->pathcachebufs.last = psys->pathcachebufs.last; - data->totcached = psys->totcached; - data->childcache = psys->childcache; - data->childcachebufs.first = psys->childcachebufs.first; - data->childcachebufs.last = psys->childcachebufs.last; - data->totchildcache = psys->totchildcache; - - if (psmd->dm_final) { - data->dm = CDDM_copy_with_tessface(psmd->dm_final); - } - data->totdmvert = psmd->totdmvert; - data->totdmedge = psmd->totdmedge; - data->totdmface = psmd->totdmface; - - psys->child = NULL; - psys->pathcache = NULL; - psys->childcache = NULL; - psys->totchild = psys->totcached = psys->totchildcache = 0; - BLI_listbase_clear(&psys->pathcachebufs); - BLI_listbase_clear(&psys->childcachebufs); - - copy_m4_m4(data->winmat, winmat); - mul_m4_m4m4(data->viewmat, viewmat, ob->obmat); - mul_m4_m4m4(data->mat, winmat, data->viewmat); - data->winx = winx; - data->winy = winy; - - data->timeoffset = timeoffset; - - psys->renderdata = data; - - /* Hair can and has to be recalculated if everything isn't displayed. */ - if (psys->part->disp != 100 && ELEM(psys->part->type, PART_HAIR, PART_FLUID)) { - psys->recalc |= PSYS_RECALC_RESET; - } -} - -void psys_render_restore(Object *ob, ParticleSystem *psys) -{ - ParticleRenderData *data; - ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); - float render_disp = psys_get_current_display_percentage(psys); - float disp; - - data = psys->renderdata; - if (!data) - return; - - if (data->elems) - MEM_freeN(data->elems); - - if (psmd->dm_final) { - psmd->dm_final->needsFree = 1; - psmd->dm_final->release(psmd->dm_final); - } - if (psmd->dm_deformed) { - psmd->dm_deformed->needsFree = 1; - psmd->dm_deformed->release(psmd->dm_deformed); - psmd->dm_deformed = NULL; - } - - psys_free_path_cache(psys, NULL); - - if (psys->child) { - MEM_freeN(psys->child); - psys->child = 0; - psys->totchild = 0; - } - - psys->child = data->child; - psys->totchild = data->totchild; - psys->pathcache = data->pathcache; - psys->pathcachebufs.first = data->pathcachebufs.first; - psys->pathcachebufs.last = data->pathcachebufs.last; - psys->totcached = data->totcached; - psys->childcache = data->childcache; - psys->childcachebufs.first = data->childcachebufs.first; - psys->childcachebufs.last = data->childcachebufs.last; - psys->totchildcache = data->totchildcache; - - psmd->dm_final = data->dm; - psmd->totdmvert = data->totdmvert; - psmd->totdmedge = data->totdmedge; - psmd->totdmface = data->totdmface; - psmd->flag &= ~eParticleSystemFlag_psys_updated; - - if (psmd->dm_final) { - if (!psmd->dm_final->deformedOnly) { - if (ob->derivedDeform) { - psmd->dm_deformed = CDDM_copy(ob->derivedDeform); - } - else { - psmd->dm_deformed = CDDM_from_mesh((Mesh *)ob->data); - } - DM_ensure_tessface(psmd->dm_deformed); - } - psys_calc_dmcache(ob, psmd->dm_final, psmd->dm_deformed, psys); - } - - MEM_freeN(data); - psys->renderdata = NULL; - - /* restore particle display percentage */ - disp = psys_get_current_display_percentage(psys); - - if (disp != render_disp) { - /* Hair can and has to be recalculated if everything isn't displayed. */ - if (ELEM(psys->part->type, PART_HAIR, PART_FLUID)) { - psys->recalc |= PSYS_RECALC_RESET; - } - else { - PARTICLE_P; - - LOOP_PARTICLES { - if (psys_frand(psys, p) > disp) - pa->flag |= PARS_NO_DISP; - else - pa->flag &= ~PARS_NO_DISP; - } - } - } -} - -bool psys_render_simplify_params(ParticleSystem *psys, ChildParticle *cpa, float *params) -{ - ParticleRenderData *data; - ParticleRenderElem *elem; - float x, w, scale, alpha, lambda, t, scalemin, scalemax; - int b; - - if (!(psys->renderdata && (psys->part->simplify_flag & PART_SIMPLIFY_ENABLE))) - return false; - - data = psys->renderdata; - if (!data->do_simplify) - return false; - b = (data->index_mf_to_mpoly) ? DM_origindex_mface_mpoly(data->index_mf_to_mpoly, data->index_mp_to_orig, cpa->num) : cpa->num; - if (b == ORIGINDEX_NONE) { - return false; - } - - elem = &data->elems[b]; - - lambda = elem->lambda; - t = elem->t; - scalemin = elem->scalemin; - scalemax = elem->scalemax; - - if (!elem->reduce) { - scale = scalemin; - alpha = 1.0f; - } - else { - x = (elem->curchild + 0.5f) / elem->totchild; - if (x < lambda - t) { - scale = scalemax; - alpha = 1.0f; - } - else if (x >= lambda + t) { - scale = scalemin; - alpha = 0.0f; - } - else { - w = (lambda + t - x) / (2.0f * t); - scale = scalemin + (scalemax - scalemin) * w; - alpha = w; - } - } - - params[0] = scale; - params[1] = alpha; - - elem->curchild++; - - return 1; -} - -/************************************************/ /* Interpolation */ /************************************************/ static float interpolate_particle_value(float v1, float v2, float v3, float v4, const float w[4], int four) @@ -2050,7 +1856,7 @@ void psys_find_parents(ParticleSimulationData *sim, const bool use_render_params int from = PART_FROM_FACE; totparent = (int)(totchild * part->parents * 0.3f); - if ((sim->psys->renderdata || use_render_params) && part->child_nbr && part->ren_child_nbr) + if (use_render_params && part->child_nbr && part->ren_child_nbr) totparent *= (float)part->child_nbr / (float)part->ren_child_nbr; /* hard limit, workaround for it being ignored above */ @@ -2094,10 +1900,10 @@ static bool psys_thread_context_init_path( psys_thread_context_init(ctx, sim); /*---start figuring out what is actually wanted---*/ - if (psys_in_edit_mode(sim->eval_ctx->view_layer, psys)) { + if (psys_in_edit_mode(sim->eval_ctx->depsgraph, psys)) { ParticleEditSettings *pset = &scene->toolsettings->particle; - if ((psys->renderdata == 0 && use_render_params == 0) && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0) + if ((use_render_params == 0) && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0) totchild = 0; segments = 1 << pset->draw_step; @@ -2106,14 +1912,14 @@ static bool psys_thread_context_init_path( if (totchild && part->childtype == PART_CHILD_FACES) { totparent = (int)(totchild * part->parents * 0.3f); - if ((psys->renderdata || use_render_params) && part->child_nbr && part->ren_child_nbr) + if (use_render_params && part->child_nbr && part->ren_child_nbr) totparent *= (float)part->child_nbr / (float)part->ren_child_nbr; /* part->parents could still be 0 so we can't test with totparent */ between = 1; } - if (psys->renderdata || use_render_params) + if (use_render_params) segments = 1 << part->ren_step; else { totchild = (int)((float)totchild * (float)part->disp / 100.0f); @@ -2191,7 +1997,7 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp ParticleSystem *psys = ctx->sim.psys; ParticleSettings *part = psys->part; ParticleCacheKey **cache = psys->childcache; - ParticleCacheKey **pcache = psys_in_edit_mode(ctx->sim.eval_ctx->view_layer, psys) && psys->edit ? psys->edit->pathcache : psys->pathcache; + ParticleCacheKey **pcache = psys_in_edit_mode(ctx->sim.eval_ctx->depsgraph, psys) && psys->edit ? psys->edit->pathcache : psys->pathcache; ParticleCacheKey *child, *key[4]; ParticleTexture ptex; float *cpa_fuv = 0, *par_rot = 0, rot[4]; @@ -2603,7 +2409,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re float prev_tangent[3] = {0.0f, 0.0f, 0.0f}, hairmat[4][4]; float rotmat[3][3]; int k; - int segments = (int)pow(2.0, (double)((psys->renderdata || use_render_params) ? part->ren_step : part->draw_step)); + int segments = (int)pow(2.0, (double)((use_render_params) ? part->ren_step : part->draw_step)); int totpart = psys->totpart; float length, vec[3]; float *vg_effector = NULL; @@ -2615,8 +2421,8 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re return; #if 0 /* TODO(mai): something is very wrong with these conditionals, they dont make sense and the cache isnt updating */ - if (psys_in_edit_mode(sim->eval_ctx->view_layer, psys)) - if (psys->renderdata == 0 && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0) + if (psys_in_edit_mode(sim->eval_ctx->depsgraph, psys)) + if ((psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0) return; #endif @@ -3322,11 +3128,6 @@ static void default_particle_settings(ParticleSettings *part) part->color_vec_max = 1.f; part->draw_col = PART_DRAW_COL_MAT; - part->simplify_refsize = 1920; - part->simplify_rate = 1.0f; - part->simplify_transition = 0.1f; - part->simplify_viewport = 0.8; - if (!part->effector_weights) part->effector_weights = BKE_add_effector_weights(NULL); @@ -3830,7 +3631,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE); /* pind.dm disabled in editmode means we don't get effectors taken into * account when subdividing for instance */ - pind.dm = psys_in_edit_mode(sim->eval_ctx->view_layer, psys) ? NULL : psys->hair_out_dm; + pind.dm = psys_in_edit_mode(sim->eval_ctx->depsgraph, psys) ? NULL : psys->hair_out_dm; init_particle_interpolation(sim->ob, psys, pa, &pind); do_particle_interpolation(psys, p, pa, t, &pind, state); diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index e9eacfe1eb5..c261b0dc22c 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -57,7 +57,7 @@ #include "BKE_object.h" #include "BKE_particle.h" -static int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot); +#include "DEG_depsgraph_query.h" static void alloc_child_particles(ParticleSystem *psys, int tot) { @@ -80,12 +80,12 @@ static void alloc_child_particles(ParticleSystem *psys, int tot) } } -static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, DerivedMesh *deformdm, ParticleSystem *psys) +static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, DerivedMesh *deformdm, ParticleSystem *psys, const bool use_render_params) { ChildParticle *cpa = NULL; int i, p; - int child_nbr= psys_get_child_number(scene, psys); - int totpart= psys_get_tot_child(scene, psys); + int child_nbr= psys_get_child_number(scene, psys, use_render_params); + int totpart= psys_get_tot_child(scene, psys, use_render_params); alloc_child_particles(psys, totpart); @@ -738,16 +738,10 @@ static void exec_distribute_child(TaskPool * __restrict UNUSED(pool), void *task /* RNG skipping at the beginning */ cpa = psys->child; for (p = 0; p < task->begin; ++p, ++cpa) { - if (task->ctx->skip) /* simplification skip */ - BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->ctx->skip[p]); - BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP); } for (; p < task->end; ++p, ++cpa) { - if (task->ctx->skip) /* simplification skip */ - BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->ctx->skip[p]); - distribute_children_exec(task, cpa, p); } } @@ -774,11 +768,15 @@ static int distribute_compare_orig_index(const void *p1, const void *p2, void *u return 1; } -static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from) +static void distribute_invalid(ParticleSimulationData *sim, int from) { + Scene *scene = sim->scene; + ParticleSystem *psys = sim->psys; + const bool use_render_params = (DEG_get_mode(sim->eval_ctx->depsgraph) == DAG_EVAL_RENDER); + if (from == PART_FROM_CHILD) { ChildParticle *cpa; - int p, totchild = psys_get_tot_child(scene, psys); + int p, totchild = psys_get_tot_child(scene, psys, use_render_params); if (psys->child && totchild) { for (p=0,cpa=psys->child; p<totchild; p++,cpa++) { @@ -841,13 +839,15 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti */ psys_thread_context_init(ctx, sim); + + const bool use_render_params = (DEG_get_mode(sim->eval_ctx->depsgraph) == DAG_EVAL_RENDER); /* First handle special cases */ if (from == PART_FROM_CHILD) { /* Simple children */ if (part->childtype != PART_CHILD_FACES) { BLI_srandom(31415926 + psys->seed + psys->child_seed); - distribute_simple_children(scene, ob, finaldm, sim->psmd->dm_deformed, psys); + distribute_simple_children(scene, ob, finaldm, sim->psmd->dm_deformed, psys, use_render_params); return 0; } } @@ -895,7 +895,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti BLI_kdtree_balance(tree); - totpart = psys_get_tot_child(scene, psys); + totpart = psys_get_tot_child(scene, psys, use_render_params); cfrom = from = PART_FROM_FACE; } else { @@ -938,7 +938,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti totelem = (from == PART_FROM_VERT) ? dm->getNumVerts(dm) : dm->getNumTessFaces(dm); if (totelem == 0) { - distribute_invalid(scene, psys, children ? PART_FROM_CHILD : 0); + distribute_invalid(sim, children ? PART_FROM_CHILD : 0); if (G.debug & G_DEBUG) fprintf(stderr,"Particle distribution error: Nothing to emit from!\n"); @@ -1082,7 +1082,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti totmapped = i_mapped; /* Finally assign elements to particles */ - if ((part->flag & PART_TRAND) || (part->simplify_flag & PART_SIMPLIFY_ENABLE)) { + if (part->flag & PART_TRAND) { for (p = 0; p < totpart; p++) { /* In theory element_sum[totmapped - 1] should be 1.0, * but due to float errors this is not necessarily always true, so scale pos accordingly. */ @@ -1176,7 +1176,6 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti ctx->tpars= tpars; if (children) { - totpart= psys_render_simplify_distribution(ctx, totpart); alloc_child_particles(psys, totpart); } @@ -1235,7 +1234,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from) /* ready for future use, to emit particles without geometry */ static void distribute_particles_on_shape(ParticleSimulationData *sim, int UNUSED(from)) { - distribute_invalid(sim->scene, sim->psys, 0); + distribute_invalid(sim, 0); fprintf(stderr,"Shape emission not yet possible!\n"); } @@ -1255,250 +1254,8 @@ void distribute_particles(ParticleSimulationData *sim, int from) distribute_particles_on_shape(sim, from); if (distr_error) { - distribute_invalid(sim->scene, sim->psys, from); + distribute_invalid(sim, from); fprintf(stderr,"Particle distribution error!\n"); } } - -/* ======== Simplify ======== */ - -static float psys_render_viewport_falloff(double rate, float dist, float width) -{ - return pow(rate, dist / width); -} - -static float psys_render_projected_area(ParticleSystem *psys, const float center[3], float area, double vprate, float *viewport) -{ - ParticleRenderData *data = psys->renderdata; - float co[4], view[3], ortho1[3], ortho2[3], w, dx, dy, radius; - - /* transform to view space */ - copy_v3_v3(co, center); - co[3] = 1.0f; - mul_m4_v4(data->viewmat, co); - - /* compute two vectors orthogonal to view vector */ - normalize_v3_v3(view, co); - ortho_basis_v3v3_v3(ortho1, ortho2, view); - - /* compute on screen minification */ - w = co[2] * data->winmat[2][3] + data->winmat[3][3]; - dx = data->winx * ortho2[0] * data->winmat[0][0]; - dy = data->winy * ortho2[1] * data->winmat[1][1]; - w = sqrtf(dx * dx + dy * dy) / w; - - /* w squared because we are working with area */ - area = area * w * w; - - /* viewport of the screen test */ - - /* project point on screen */ - mul_m4_v4(data->winmat, co); - if (co[3] != 0.0f) { - co[0] = 0.5f * data->winx * (1.0f + co[0] / co[3]); - co[1] = 0.5f * data->winy * (1.0f + co[1] / co[3]); - } - - /* screen space radius */ - radius = sqrtf(area / (float)M_PI); - - /* make smaller using fallof once over screen edge */ - *viewport = 1.0f; - - if (co[0] + radius < 0.0f) - *viewport *= psys_render_viewport_falloff(vprate, -(co[0] + radius), data->winx); - else if (co[0] - radius > data->winx) - *viewport *= psys_render_viewport_falloff(vprate, (co[0] - radius) - data->winx, data->winx); - - if (co[1] + radius < 0.0f) - *viewport *= psys_render_viewport_falloff(vprate, -(co[1] + radius), data->winy); - else if (co[1] - radius > data->winy) - *viewport *= psys_render_viewport_falloff(vprate, (co[1] - radius) - data->winy, data->winy); - - return area; -} - -/* BMESH_TODO, for orig face data, we need to use MPoly */ -static int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) -{ - DerivedMesh *dm = ctx->dm; - Mesh *me = (Mesh *)(ctx->sim.ob->data); - MFace *mf, *mface; - MVert *mvert; - ParticleRenderData *data; - ParticleRenderElem *elems, *elem; - ParticleSettings *part = ctx->sim.psys->part; - float *facearea, (*facecenter)[3], size[3], fac, powrate, scaleclamp; - float co1[3], co2[3], co3[3], co4[3], lambda, arearatio, t, area, viewport; - double vprate; - int *facetotvert; - int a, b, totorigface, totface, newtot, skipped; - - /* double lookup */ - const int *index_mf_to_mpoly; - const int *index_mp_to_orig; - - if (part->ren_as != PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND)) - return tot; - if (!ctx->sim.psys->renderdata) - return tot; - - data = ctx->sim.psys->renderdata; - if (data->timeoffset) - return 0; - if (!(part->simplify_flag & PART_SIMPLIFY_ENABLE)) - return tot; - - mvert = dm->getVertArray(dm); - mface = dm->getTessFaceArray(dm); - totface = dm->getNumTessFaces(dm); - totorigface = me->totpoly; - - if (totface == 0 || totorigface == 0) - return tot; - - index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); - index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - if (index_mf_to_mpoly == NULL) { - index_mp_to_orig = NULL; - } - - facearea = MEM_callocN(sizeof(float) * totorigface, "SimplifyFaceArea"); - facecenter = MEM_callocN(sizeof(float[3]) * totorigface, "SimplifyFaceCenter"); - facetotvert = MEM_callocN(sizeof(int) * totorigface, "SimplifyFaceArea"); - elems = MEM_callocN(sizeof(ParticleRenderElem) * totorigface, "SimplifyFaceElem"); - - if (data->elems) - MEM_freeN(data->elems); - - data->do_simplify = true; - data->elems = elems; - data->index_mf_to_mpoly = index_mf_to_mpoly; - data->index_mp_to_orig = index_mp_to_orig; - - /* compute number of children per original face */ - for (a = 0; a < tot; a++) { - b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a]; - if (b != ORIGINDEX_NONE) { - elems[b].totchild++; - } - } - - /* compute areas and centers of original faces */ - for (mf = mface, a = 0; a < totface; a++, mf++) { - b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a; - - if (b != ORIGINDEX_NONE) { - copy_v3_v3(co1, mvert[mf->v1].co); - copy_v3_v3(co2, mvert[mf->v2].co); - copy_v3_v3(co3, mvert[mf->v3].co); - - add_v3_v3(facecenter[b], co1); - add_v3_v3(facecenter[b], co2); - add_v3_v3(facecenter[b], co3); - - if (mf->v4) { - copy_v3_v3(co4, mvert[mf->v4].co); - add_v3_v3(facecenter[b], co4); - facearea[b] += area_quad_v3(co1, co2, co3, co4); - facetotvert[b] += 4; - } - else { - facearea[b] += area_tri_v3(co1, co2, co3); - facetotvert[b] += 3; - } - } - } - - for (a = 0; a < totorigface; a++) - if (facetotvert[a] > 0) - mul_v3_fl(facecenter[a], 1.0f / facetotvert[a]); - - /* for conversion from BU area / pixel area to reference screen size */ - BKE_mesh_texspace_get(me, 0, 0, size); - fac = ((size[0] + size[1] + size[2]) / 3.0f) / part->simplify_refsize; - fac = fac * fac; - - powrate = log(0.5f) / log(part->simplify_rate * 0.5f); - if (part->simplify_flag & PART_SIMPLIFY_VIEWPORT) - vprate = pow(1.0f - part->simplify_viewport, 5.0); - else - vprate = 1.0; - - /* set simplification parameters per original face */ - for (a = 0, elem = elems; a < totorigface; a++, elem++) { - area = psys_render_projected_area(ctx->sim.psys, facecenter[a], facearea[a], vprate, &viewport); - arearatio = fac * area / facearea[a]; - - if ((arearatio < 1.0f || viewport < 1.0f) && elem->totchild) { - /* lambda is percentage of elements to keep */ - lambda = (arearatio < 1.0f) ? powf(arearatio, powrate) : 1.0f; - lambda *= viewport; - - lambda = MAX2(lambda, 1.0f / elem->totchild); - - /* compute transition region */ - t = part->simplify_transition; - elem->t = (lambda - t < 0.0f) ? lambda : (lambda + t > 1.0f) ? 1.0f - lambda : t; - elem->reduce = 1; - - /* scale at end and beginning of the transition region */ - elem->scalemax = (lambda + t < 1.0f) ? 1.0f / lambda : 1.0f / (1.0f - elem->t * elem->t / t); - elem->scalemin = (lambda + t < 1.0f) ? 0.0f : elem->scalemax * (1.0f - elem->t / t); - - elem->scalemin = sqrtf(elem->scalemin); - elem->scalemax = sqrtf(elem->scalemax); - - /* clamp scaling */ - scaleclamp = (float)min_ii(elem->totchild, 10); - elem->scalemin = MIN2(scaleclamp, elem->scalemin); - elem->scalemax = MIN2(scaleclamp, elem->scalemax); - - /* extend lambda to include transition */ - lambda = lambda + elem->t; - if (lambda > 1.0f) - lambda = 1.0f; - } - else { - lambda = arearatio; - - elem->scalemax = 1.0f; //sqrt(lambda); - elem->scalemin = 1.0f; //sqrt(lambda); - elem->reduce = 0; - } - - elem->lambda = lambda; - elem->scalemin = sqrtf(elem->scalemin); - elem->scalemax = sqrtf(elem->scalemax); - elem->curchild = 0; - } - - MEM_freeN(facearea); - MEM_freeN(facecenter); - MEM_freeN(facetotvert); - - /* move indices and set random number skipping */ - ctx->skip = MEM_callocN(sizeof(int) * tot, "SimplificationSkip"); - - skipped = 0; - for (a = 0, newtot = 0; a < tot; a++) { - b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a]; - - if (b != ORIGINDEX_NONE) { - if (elems[b].curchild++ < ceil(elems[b].lambda * elems[b].totchild)) { - ctx->index[newtot] = ctx->index[a]; - ctx->skip[newtot] = skipped; - skipped = 0; - newtot++; - } - else skipped++; - } - else skipped++; - } - - for (a = 0, elem = elems; a < totorigface; a++, elem++) - elem->curchild = 0; - - return newtot; -} diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 2b00e52246f..ffe6617d561 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -90,11 +90,11 @@ #include "BKE_bvhutils.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "PIL_time.h" #include "RE_shader_ext.h" -#include "DEG_depsgraph.h" /* fluid sim particle import */ #ifdef WITH_MOD_FLUID @@ -122,11 +122,11 @@ static int particles_are_dynamic(ParticleSystem *psys) return ELEM(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID); } -float psys_get_current_display_percentage(ParticleSystem *psys) +float psys_get_current_display_percentage(ParticleSystem *psys, const bool use_render_params) { ParticleSettings *part=psys->part; - if ((psys->renderdata && !particles_are_dynamic(psys)) || /* non-dynamic particles can be rendered fully */ + if ((use_render_params && !particles_are_dynamic(psys)) || /* non-dynamic particles can be rendered fully */ (part->child_nbr && part->childtype) || /* display percentage applies to children */ (psys->pointcache->flag & PTCACHE_BAKING)) /* baking is always done with full amount */ { @@ -286,24 +286,24 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart) } } -int psys_get_child_number(Scene *scene, ParticleSystem *psys) +int psys_get_child_number(Scene *scene, ParticleSystem *psys, const bool use_render_params) { int nbr; if (!psys->part->childtype) return 0; - if (psys->renderdata) + if (use_render_params) nbr= psys->part->ren_child_nbr; else nbr= psys->part->child_nbr; - return get_render_child_particle_number(&scene->r, nbr, psys->renderdata != NULL); + return get_render_child_particle_number(&scene->r, nbr, use_render_params); } -int psys_get_tot_child(Scene *scene, ParticleSystem *psys) +int psys_get_tot_child(Scene *scene, ParticleSystem *psys, const bool use_render_params) { - return psys->totpart*psys_get_child_number(scene, psys); + return psys->totpart*psys_get_child_number(scene, psys, use_render_params); } /************************************************/ @@ -512,7 +512,6 @@ void psys_thread_context_free(ParticleThreadContext *ctx) if (ctx->jitoff) MEM_freeN(ctx->jitoff); if (ctx->weight) MEM_freeN(ctx->weight); if (ctx->index) MEM_freeN(ctx->index); - if (ctx->skip) MEM_freeN(ctx->skip); if (ctx->seams) MEM_freeN(ctx->seams); //if (ctx->vertpart) MEM_freeN(ctx->vertpart); BLI_kdtree_free(ctx->tree); @@ -2908,7 +2907,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons #endif int distr=0, alloc=0, skip=0; - if ((psys->part->childtype && psys->totchild != psys_get_tot_child(sim->scene, psys)) || psys->recalc&PSYS_RECALC_RESET) + if ((psys->part->childtype && psys->totchild != psys_get_tot_child(sim->scene, psys, use_render_params)) || psys->recalc&PSYS_RECALC_RESET) alloc=1; if (alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (sim->ob && sim->ob->mode & OB_MODE_WEIGHT_PAINT))) @@ -2918,7 +2917,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons if (alloc) realloc_particles(sim, sim->psys->totpart); - if (psys_get_tot_child(sim->scene, psys)) { + if (psys_get_tot_child(sim->scene, psys, use_render_params)) { /* don't generate children while computing the hair keys */ if (!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) { distribute_particles(sim, PART_FROM_CHILD); @@ -2935,14 +2934,14 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons skip = 1; /* only hair, keyed and baked stuff can have paths */ else if (part->ren_as != PART_DRAW_PATH && !(part->type==PART_HAIR && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR))) skip = 1; /* particle visualization must be set as path */ - else if (!psys->renderdata) { + else { if (part->draw_as != PART_DRAW_REND) skip = 1; /* draw visualization */ else if (psys->pointcache->flag & PTCACHE_BAKING) skip = 1; /* no need to cache paths while baking dynamics */ #if 0 /* TODO(mai): something is very wrong with these conditionals, they dont make sense and the cache isnt updating */ - else if (psys_in_edit_mode(sim->eval_ctx->view_layer, psys)) { + else if (psys_in_edit_mode(sim->eval_ctx->depsgraph, psys)) { if ((pset->flag & PE_DRAW_PART)==0) skip = 1; else if (part->childtype==0 && (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED)==0) @@ -3224,7 +3223,7 @@ static void hair_step(ParticleSimulationData *sim, float cfra, const bool use_re ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; PARTICLE_P; - float disp = psys_get_current_display_percentage(psys); + float disp = psys_get_current_display_percentage(psys, use_render_params); LOOP_PARTICLES { pa->size = part->size; @@ -3740,13 +3739,13 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) free_collider_cache(&sim->colliders); BLI_rng_free(rng); } -static void update_children(ParticleSimulationData *sim) +static void update_children(ParticleSimulationData *sim, const bool use_render_params) { if ((sim->psys->part->type == PART_HAIR) && (sim->psys->flag & PSYS_HAIR_DONE)==0) /* don't generate children while growing hair - waste of time */ psys_free_children(sim->psys); else if (sim->psys->part->childtype) { - if (sim->psys->totchild != psys_get_tot_child(sim->scene, sim->psys)) + if (sim->psys->totchild != psys_get_tot_child(sim->scene, sim->psys, use_render_params)) distribute_particles(sim, PART_FROM_CHILD); else { /* Children are up to date, nothing to do. */ @@ -3756,7 +3755,7 @@ static void update_children(ParticleSimulationData *sim) psys_free_children(sim->psys); } /* updates cached particles' alive & other flags etc..*/ -static void cached_step(ParticleSimulationData *sim, float cfra) +static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_render_params) { ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; @@ -3766,7 +3765,7 @@ static void cached_step(ParticleSimulationData *sim, float cfra) psys_update_effectors(sim); - disp= psys_get_current_display_percentage(psys); + disp= psys_get_current_display_percentage(psys, use_render_params); LOOP_PARTICLES { psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra); @@ -3988,8 +3987,8 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_ int cache_result = BKE_ptcache_read(pid, cache_cfra, true); if (ELEM(cache_result, PTCACHE_READ_EXACT, PTCACHE_READ_INTERPOLATED)) { - cached_step(sim, cfra); - update_children(sim); + cached_step(sim, cfra, use_render_params); + update_children(sim, use_render_params); psys_update_path_cache(sim, cfra, use_render_params); BKE_ptcache_validate(cache, (int)cache_cfra); @@ -4006,7 +4005,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_ } else if (cache_result == PTCACHE_READ_OLD) { psys->cfra = (float)cache->simframe; - cached_step(sim, psys->cfra); + cached_step(sim, psys->cfra, use_render_params); } /* if on second frame, write cache for first frame */ @@ -4018,7 +4017,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_ /* 3. do dynamics */ /* set particles to be not calculated TODO: can't work with pointcache */ - disp= psys_get_current_display_percentage(psys); + disp= psys_get_current_display_percentage(psys, use_render_params); LOOP_PARTICLES { if (psys_frand(psys, p) > disp) @@ -4074,7 +4073,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_ BKE_ptcache_write(pid, (int)cache_cfra); } - update_children(sim); + update_children(sim, use_render_params); /* cleanup */ if (psys->lattice_deform_data) { @@ -4317,7 +4316,7 @@ void particle_system_update(const struct EvaluationContext *eval_ctx, Scene *sce case PART_PHYS_KEYED: { PARTICLE_P; - float disp = psys_get_current_display_percentage(psys); + float disp = psys_get_current_display_percentage(psys, use_render_params); bool free_unexisting = false; /* Particles without dynamics haven't been reset yet because they don't use pointcache */ @@ -4379,8 +4378,7 @@ void particle_system_update(const struct EvaluationContext *eval_ctx, Scene *sce psys->recalc = 0; /* save matrix for duplicators, at rendertime the actual dupliobject's matrix is used so don't update! */ - if (psys->renderdata==0) - invert_m4_m4(psys->imat, ob->obmat); + invert_m4_m4(psys->imat, ob->obmat); BKE_particle_batch_cache_dirty(psys, BKE_PARTICLE_BATCH_DIRTY_ALL); } |