Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/particle_distribute.c')
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c89
1 files changed, 60 insertions, 29 deletions
diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
index 87bc355894d..9185c0964b9 100644
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ b/source/blender/blenkernel/intern/particle_distribute.c
@@ -79,7 +79,7 @@ static void alloc_child_particles(ParticleSystem *psys, int tot)
}
}
-static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, ParticleSystem *psys)
+static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, DerivedMesh *deformdm, ParticleSystem *psys)
{
ChildParticle *cpa = NULL;
int i, p;
@@ -106,7 +106,7 @@ static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *fi
}
}
/* dmcache must be updated for parent particles if children from faces is used */
- psys_calc_dmcache(ob, finaldm, psys);
+ psys_calc_dmcache(ob, finaldm, deformdm, psys);
}
static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
{
@@ -220,16 +220,18 @@ static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
copy_v3_v3(v2, mvert[mface->v2].co);
copy_v3_v3(v3, mvert[mface->v3].co);
- if (isect_axial_line_tri_v3(a, co1, co2, v2, v3, v1, &lambda)) {
+ bool intersects_tri = isect_axial_line_segment_tri_v3(a, co1, co2, v2, v3, v1, &lambda);
+ if (intersects_tri) {
if (from==PART_FROM_FACE)
(pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST;
else /* store number of intersections */
(pa+(int)(lambda*size[a])*a0mul)->hair_index++;
}
- else if (mface->v4) {
+
+ if (mface->v4 && (!intersects_tri || from==PART_FROM_VOLUME)) {
copy_v3_v3(v4, mvert[mface->v4].co);
- if (isect_axial_line_tri_v3(a, co1, co2, v4, v1, v3, &lambda)) {
+ if (isect_axial_line_segment_tri_v3(a, co1, co2, v4, v1, v3, &lambda)) {
if (from==PART_FROM_FACE)
(pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST;
else
@@ -660,7 +662,7 @@ static void distribute_children_exec(ParticleTask *thread, ChildParticle *cpa, i
BLI_rng_skip(thread->rng, rng_skip_tot);
}
-static void exec_distribute_parent(TaskPool *UNUSED(pool), void *taskdata, int UNUSED(threadid))
+static void exec_distribute_parent(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
{
ParticleTask *task = taskdata;
ParticleSystem *psys= task->ctx->sim.psys;
@@ -686,7 +688,7 @@ static void exec_distribute_parent(TaskPool *UNUSED(pool), void *taskdata, int U
}
}
-static void exec_distribute_child(TaskPool *UNUSED(pool), void *taskdata, int UNUSED(threadid))
+static void exec_distribute_child(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
{
ParticleTask *task = taskdata;
ParticleSystem *psys = task->ctx->sim.psys;
@@ -763,7 +765,7 @@ static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from)
static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, ParticleSimulationData *sim, int from)
{
Scene *scene = sim->scene;
- DerivedMesh *finaldm = sim->psmd->dm;
+ DerivedMesh *finaldm = sim->psmd->dm_final;
Object *ob = sim->ob;
ParticleSystem *psys= sim->psys;
ParticleData *pa=0, *tpars= 0;
@@ -793,6 +795,11 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
return 0;
}
+ /* XXX This distribution code is totally broken in case from == PART_FROM_CHILD, it's always using finaldm
+ * even if use_modifier_stack is unset... But making things consistent here break all existing edited
+ * hair systems, so better wait for complete rewrite.
+ */
+
psys_thread_context_init(ctx, sim);
/* First handle special cases */
@@ -800,7 +807,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
/* Simple children */
if (part->childtype != PART_CHILD_FACES) {
BLI_srandom(31415926 + psys->seed + psys->child_seed);
- distribute_simple_children(scene, ob, finaldm, psys);
+ distribute_simple_children(scene, ob, finaldm, sim->psmd->dm_deformed, psys);
return 0;
}
}
@@ -808,10 +815,21 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
/* Grid distribution */
if (part->distr==PART_DISTR_GRID && from != PART_FROM_VERT) {
BLI_srandom(31415926 + psys->seed);
- dm= CDDM_from_mesh((Mesh*)ob->data);
+
+ if (psys->part->use_modifier_stack) {
+ dm = finaldm;
+ }
+ else {
+ dm = CDDM_from_mesh((Mesh*)ob->data);
+ }
DM_ensure_tessface(dm);
+
distribute_grid(dm,psys);
- dm->release(dm);
+
+ if (dm != finaldm) {
+ dm->release(dm);
+ }
+
return 0;
}
}
@@ -897,7 +915,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
element_weight = MEM_callocN(sizeof(float)*totelem, "particle_distribution_weights");
particle_element= MEM_callocN(sizeof(int)*totpart, "particle_distribution_indexes");
- element_sum = MEM_callocN(sizeof(float)*(totelem+1), "particle_distribution_sum");
+ element_sum = MEM_mallocN(sizeof(*element_sum) * totelem, "particle_distribution_sum");
jitter_offset = MEM_callocN(sizeof(float)*totelem, "particle_distribution_jitoff");
/* Calculate weights from face areas */
@@ -992,9 +1010,10 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
inv_totweight = (totweight > 0.f ? 1.f/totweight : 0.f);
/* Calculate cumulative weights */
- element_sum[0] = 0.0f;
- for (i=0; i<totelem; i++)
- element_sum[i+1] = element_sum[i] + element_weight[i] * inv_totweight;
+ element_sum[0] = element_weight[0] * inv_totweight;
+ for (i = 1; i < totelem; i++) {
+ element_sum[i] = element_sum[i - 1] + element_weight[i] * inv_totweight;
+ }
/* Finally assign elements to particles */
if ((part->flag&PART_TRAND) || (part->simplify_flag&PART_SIMPLIFY_ENABLE)) {
@@ -1002,7 +1021,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
for (p=0; p<totpart; p++) {
/* In theory element_sum[totelem] should be 1.0, but due to float errors this is not necessarily always true, so scale pos accordingly. */
- pos= BLI_frand() * element_sum[totelem];
+ pos= BLI_frand() * element_sum[totelem - 1];
particle_element[p] = distribute_binary_search(element_sum, totelem, pos);
particle_element[p] = MIN2(totelem-1, particle_element[p]);
jitter_offset[particle_element[p]] = pos;
@@ -1011,22 +1030,34 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
else {
double step, pos;
- step= (totpart < 2) ? 0.5 : 1.0/(double)totpart;
- pos= 1e-6; /* tiny offset to avoid zero weight face */
- i= 0;
+ step = (totpart < 2) ? 0.5 : 1.0 / (double)totpart;
+ /* This is to address tricky issues with vertex-emitting when user tries (and expects) exact 1-1 vert/part
+ * distribution (see T47983 and its two example files). It allows us to consider pos as
+ * 'midpoint between v and v+1' (or 'p and p+1', depending whether we have more vertices than particles or not),
+ * and avoid stumbling over float imprecisions in element_sum. */
+ if (from == PART_FROM_VERT) {
+ pos = (totpart < totelem) ? 0.5 / (double)totelem : step * 0.5; /* We choose the smaller step. */
+ }
+ else {
+ pos = 0.0;
+ }
- for (p=0; p<totpart; p++, pos+=step) {
- while ((i < totelem) && (pos > (double)element_sum[i + 1]))
- i++;
+ /* Avoid initial zero-weight items. */
+ for (i = 0; (element_sum[i] == 0.0) && (i < totelem - 1); i++);
- particle_element[p] = MIN2(totelem-1, i);
+ for (p = 0; p < totpart; p++, pos += step) {
+ for ( ; (pos > (double)element_sum[i]) && (i < totelem - 1); i++);
- /* avoid zero weight face */
- if (p == totpart-1 && element_weight[particle_element[p]] == 0.0f)
- particle_element[p] = particle_element[p-1];
+ particle_element[p] = i;
jitter_offset[particle_element[p]] = pos;
}
+
+ /* Avoid final zero weight items. */
+ BLI_assert(p == totpart);
+ if (element_weight[particle_element[--p]] == 0.0f) {
+ particle_element[p] = particle_element[p - 1];
+ }
}
MEM_freeN(element_sum);
@@ -1110,7 +1141,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
TaskPool *task_pool;
ParticleThreadContext ctx;
ParticleTask *tasks;
- DerivedMesh *finaldm = sim->psmd->dm;
+ DerivedMesh *finaldm = sim->psmd->dm_final;
int i, totpart, numtasks;
/* create a task pool for distribution tasks */
@@ -1135,7 +1166,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
BLI_task_pool_free(task_pool);
- psys_calc_dmcache(sim->ob, finaldm, sim->psys);
+ psys_calc_dmcache(sim->ob, finaldm, sim->psmd->dm_deformed, sim->psys);
if (ctx.dm != finaldm)
ctx.dm->release(ctx.dm);
@@ -1159,7 +1190,7 @@ void distribute_particles(ParticleSimulationData *sim, int from)
int distr_error=0;
if (psmd) {
- if (psmd->dm)
+ if (psmd->dm_final)
distribute_particles_on_dm(sim, from);
else
distr_error=1;