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:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2013-04-16 03:12:40 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2013-04-16 03:12:40 +0400
commitafb4b65167165613f177a531bd3d4dcb3649c1c6 (patch)
tree32e1446b5fc3ce8ec00fa0e8b9e0fcb2eedda127 /source/blender/blenkernel/intern
parent638b084f824bc345468bc8e02422b5da65a641a7 (diff)
Random number generator: replace a bunch of usage of the global random number
generator with a local one. It's not thread safe and will not give repeatable results, so in most cases it should not be used. Also fixes #34992 where the noise texture of a displacement modifier was not properly random in opengl animation render, because the seed got reset to a fixed value by an unrelated function while for final render it changed each frame.
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r--source/blender/blenkernel/intern/anim.c23
-rw-r--r--source/blender/blenkernel/intern/boids.c26
-rw-r--r--source/blender/blenkernel/intern/effect.c1
-rw-r--r--source/blender/blenkernel/intern/ocean.c21
-rw-r--r--source/blender/blenkernel/intern/particle.c13
-rw-r--r--source/blender/blenkernel/intern/particle_system.c47
-rw-r--r--source/blender/blenkernel/intern/smoke.c3
7 files changed, 83 insertions, 51 deletions
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 6fa33e8d3c5..1f54da402ab 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -1263,6 +1263,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
ChildParticle *cpa = NULL;
ParticleKey state;
ParticleCacheKey *cache;
+ RNG *rng = NULL;
float ctime, pa_time, scale = 1.0f;
float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size = 0.0;
float (*obmat)[4], (*oldobmat)[4];
@@ -1293,14 +1294,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
totpart = psys->totpart;
totchild = psys->totchild;
- BLI_srandom(31415926 + psys->seed);
-
if ((psys->renderdata || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
ParticleSimulationData sim = {NULL};
- sim.scene = scene;
- sim.ob = par;
- sim.psys = psys;
- sim.psmd = psys_get_modifier(par, psys);
+
/* make sure emitter imat is in global coordinates instead of render view coordinates */
invert_m4_m4(par->imat, par->obmat);
@@ -1332,6 +1328,12 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
psys_check_group_weights(part);
+ sim.scene = scene;
+ sim.ob = par;
+ sim.psys = psys;
+ sim.psmd = psys_get_modifier(par, psys);
+ sim.rng = BLI_rng_new(0);
+
psys->lattice = psys_get_lattice(&sim);
/* gather list of objects or single object */
@@ -1378,6 +1380,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
obcopy = *ob;
}
+ rng = BLI_rng_new_srandom(31415926 + psys->seed);
+
if (totchild == 0 || part->draw & PART_DRAW_PARENT)
a = 0;
else
@@ -1417,7 +1421,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
/* for groups, pick the object based on settings */
if (part->draw & PART_DRAW_RAND_GR)
- b = BLI_rand() % totgroup;
+ b = BLI_rng_get_int(rng) % totgroup;
else
b = a % totgroup;
@@ -1561,6 +1565,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
}
else
*ob = obcopy;
+
+ BLI_rng_free(sim.rng);
}
/* clean up */
@@ -1573,6 +1579,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
end_latt_deform(psys->lattice);
psys->lattice = NULL;
}
+
+ if (rng)
+ BLI_rng_free(rng);
}
static Object *find_family_object(Object **obar, char *family, char ch)
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
index b6f1b88c912..dfffb7c795e 100644
--- a/source/blender/blenkernel/intern/boids.c
+++ b/source/blender/blenkernel/intern/boids.c
@@ -234,9 +234,9 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *
if (dot_v3v3(col.pce.nor, pa->prev_state.ave) < -0.99f) {
/* don't know why, but uneven range [0.0, 1.0] */
/* works much better than even [-1.0, 1.0] */
- bbd->wanted_co[0] = BLI_frand();
- bbd->wanted_co[1] = BLI_frand();
- bbd->wanted_co[2] = BLI_frand();
+ bbd->wanted_co[0] = BLI_rng_get_float(bbd->rng);
+ bbd->wanted_co[1] = BLI_rng_get_float(bbd->rng);
+ bbd->wanted_co[2] = BLI_rng_get_float(bbd->rng);
}
else {
copy_v3_v3(bbd->wanted_co, col.pce.nor);
@@ -558,9 +558,9 @@ static int rule_average_speed(BoidRule *rule, BoidBrainData *bbd, BoidValues *va
if (asbr->wander > 0.0f) {
/* abuse pa->r_ave for wandering */
- bpa->wander[0] += asbr->wander * (-1.0f + 2.0f * BLI_frand());
- bpa->wander[1] += asbr->wander * (-1.0f + 2.0f * BLI_frand());
- bpa->wander[2] += asbr->wander * (-1.0f + 2.0f * BLI_frand());
+ bpa->wander[0] += asbr->wander * (-1.0f + 2.0f * BLI_rng_get_float(bbd->rng));
+ bpa->wander[1] += asbr->wander * (-1.0f + 2.0f * BLI_rng_get_float(bbd->rng));
+ bpa->wander[2] += asbr->wander * (-1.0f + 2.0f * BLI_rng_get_float(bbd->rng));
normalize_v3(bpa->wander);
@@ -586,9 +586,9 @@ static int rule_average_speed(BoidRule *rule, BoidBrainData *bbd, BoidValues *va
/* may happen at birth */
if (dot_v2v2(bbd->wanted_co, bbd->wanted_co)==0.0f) {
- bbd->wanted_co[0] = 2.0f*(0.5f - BLI_frand());
- bbd->wanted_co[1] = 2.0f*(0.5f - BLI_frand());
- bbd->wanted_co[2] = 2.0f*(0.5f - BLI_frand());
+ bbd->wanted_co[0] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
+ bbd->wanted_co[1] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
+ bbd->wanted_co[2] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
}
/* leveling */
@@ -663,7 +663,7 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti
/* attack if in range */
if (closest_dist <= bbd->part->boids->range + pa->size + enemy_pa->size) {
- float damage = BLI_frand();
+ float damage = BLI_rng_get_float(bbd->rng);
float enemy_dir[3];
normalize_v3_v3(enemy_dir, bbd->wanted_co);
@@ -1164,9 +1164,9 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
/* choose random direction to turn if wanted velocity */
/* is directly behind regardless of z-coordinate */
if (dot_v2v2(old_dir2, wanted_dir2) < -0.99f) {
- wanted_dir[0] = 2.0f*(0.5f - BLI_frand());
- wanted_dir[1] = 2.0f*(0.5f - BLI_frand());
- wanted_dir[2] = 2.0f*(0.5f - BLI_frand());
+ wanted_dir[0] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
+ wanted_dir[1] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
+ wanted_dir[2] = 2.0f*(0.5f - BLI_rng_get_float(bbd->rng));
normalize_v3(wanted_dir);
}
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 9e8693e957e..3fbbc484169 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -619,6 +619,7 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin
sim.scene= eff->scene;
sim.ob= eff->ob;
sim.psys= eff->psys;
+ sim.rng= NULL;
/* TODO: time from actual previous calculated frame (step might not be 1) */
state.time = cfra - 1.0f;
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index 695ac7da792..94dbe7b87c2 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -144,12 +144,12 @@ typedef struct Ocean {
-static float nextfr(float min, float max)
+static float nextfr(RNG *rng, float min, float max)
{
- return BLI_frand() * (min - max) + max;
+ return BLI_rng_get_float(rng) * (min - max) + max;
}
-static float gaussRand(void)
+static float gaussRand(RNG *rng)
{
/* Note: to avoid numerical problems with very small numbers, we make these variables singe-precision floats,
* but later we call the double-precision log() and sqrt() functions instead of logf() and sqrtf().
@@ -765,6 +765,7 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V,
float alignment, float depth, float time, short do_height_field, short do_chop, short do_normals,
short do_jacobian, int seed)
{
+ RNG *rng;
int i, j, ii;
BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE);
@@ -825,12 +826,12 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V,
o->_k[i * (1 + o->_N / 2) + j] = sqrt(o->_kx[i] * o->_kx[i] + o->_kz[j] * o->_kz[j]);
/*srand(seed);*/
- BLI_srand(seed);
+ rng = BLI_rng_new(seed);
for (i = 0; i < o->_M; ++i) {
for (j = 0; j < o->_N; ++j) {
- float r1 = gaussRand();
- float r2 = gaussRand();
+ float r1 = gaussRand(rng);
+ float r2 = gaussRand(rng);
fftw_complex r1r2;
init_complex(r1r2, r1, r2);
@@ -890,6 +891,7 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V,
set_height_normalize_factor(o);
+ BLI_rng_free(rng);
}
void BKE_free_ocean_data(struct Ocean *oc)
@@ -1188,13 +1190,14 @@ void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(v
int res_x = och->resolution_x;
int res_y = och->resolution_y;
char string[FILE_MAX];
+ //RNG *rng;
if (!o) return;
if (o->_do_jacobian) prev_foam = MEM_callocN(res_x * res_y * sizeof(float), "previous frame foam bake data");
else prev_foam = NULL;
- BLI_srand(0);
+ //rng = BLI_rng_new(0);
/* setup image format */
imf.imtype = R_IMF_IMTYPE_OPENEXR;
@@ -1232,7 +1235,7 @@ void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(v
pr = prev_foam[res_x * y + x];
}
- /* r = BLI_frand(); */ /* UNUSED */ /* randomly reduce foam */
+ /* r = BLI_rng_get_float(rng); */ /* UNUSED */ /* randomly reduce foam */
/* pr = pr * och->foam_fade; */ /* overall fade */
@@ -1311,10 +1314,12 @@ void BKE_bake_ocean(struct Ocean *o, struct OceanCache *och, void (*update_cb)(v
if (cancel) {
if (prev_foam) MEM_freeN(prev_foam);
+ //BLI_rng_free(rng);
return;
}
}
+ //BLI_rng_free(rng);
if (prev_foam) MEM_freeN(prev_foam);
och->baked = 1;
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 4e78ab52499..b0ef6715382 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -264,11 +264,12 @@ static void psys_create_frand(ParticleSystem *psys)
{
int i;
float *rand = psys->frand = MEM_callocN(PSYS_FRAND_COUNT * sizeof(float), "particle randoms");
-
- BLI_srandom(psys->seed);
+ RNG *rng = BLI_rng_new_srandom(psys->seed);
for (i = 0; i < 1024; i++, rand++)
- *rand = BLI_frand();
+ *rand = BLI_rng_get_float(rng);
+
+ BLI_rng_free(rng);
}
int psys_check_enabled(Object *ob, ParticleSystem *psys)
{
@@ -3302,8 +3303,11 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
sim.ob = ob;
sim.psys = psys;
sim.psmd = psys_get_modifier(ob, psys);
+ sim.rng = BLI_rng_new(0);
psys_cache_child_paths(&sim, cfra, 1);
+
+ BLI_rng_free(sim.rng);
}
/* clear recalc flag if set here */
@@ -4660,6 +4664,7 @@ void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
sim.ob = ob;
sim.psys = psys;
sim.psmd = psys_get_modifier(ob, psys);
+ sim.rng = BLI_rng_new(0);
psys->lattice = psys_get_lattice(&sim);
@@ -4687,4 +4692,6 @@ void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
/* protect the applied shape */
psys->flag |= PSYS_EDITED;
}
+
+ BLI_rng_free(sim.rng);
}
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 5124cb1da26..f131e7297ed 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -423,7 +423,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
}
}
-static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, ParticleSystem *psys)
+static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, ParticleSystem *psys, RNG *rng)
{
ChildParticle *cpa = NULL;
int i, p;
@@ -440,9 +440,9 @@ static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *fi
/* create even spherical distribution inside unit sphere */
while (length>=1.0f) {
- cpa->fuv[0]=2.0f*BLI_frand()-1.0f;
- cpa->fuv[1]=2.0f*BLI_frand()-1.0f;
- cpa->fuv[2]=2.0f*BLI_frand()-1.0f;
+ cpa->fuv[0]=2.0f*BLI_rng_get_float(rng)-1.0f;
+ cpa->fuv[1]=2.0f*BLI_rng_get_float(rng)-1.0f;
+ cpa->fuv[2]=2.0f*BLI_rng_get_float(rng)-1.0f;
length=len_v3(cpa->fuv);
}
@@ -872,7 +872,7 @@ static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, Ch
pa->foffset *= ctx->jit[p % (2 * ctx->jitlevel)];
break;
case PART_DISTR_RAND:
- pa->foffset *= BLI_frand();
+ pa->foffset *= BLI_rng_get_float(ctx->sim.rng);
break;
}
}
@@ -1065,15 +1065,15 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D
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, psys);
+ BLI_rng_srandom(ctx->sim.rng, 31415926 + psys->seed + psys->child_seed);
+ distribute_simple_children(scene, ob, finaldm, psys, ctx->sim.rng);
return 0;
}
}
else {
/* Grid distribution */
if (part->distr==PART_DISTR_GRID && from != PART_FROM_VERT) {
- BLI_srandom(31415926 + psys->seed);
+ BLI_rng_srandom(ctx->sim.rng, 31415926 + psys->seed);
dm= CDDM_from_mesh((Mesh*)ob->data, ob);
DM_ensure_tessface(dm);
distribute_grid(dm,psys);
@@ -1085,7 +1085,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D
/* Create trees and original coordinates if needed */
if (from == PART_FROM_CHILD) {
distr=PART_DISTR_RAND;
- BLI_srandom(31415926 + psys->seed + psys->child_seed);
+ BLI_rng_srandom(ctx->sim.rng, 31415926 + psys->seed + psys->child_seed);
dm= finaldm;
/* BMESH ONLY */
@@ -1108,7 +1108,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D
}
else {
distr = part->distr;
- BLI_srandom(31415926 + psys->seed);
+ BLI_rng_srandom(ctx->sim.rng, 31415926 + psys->seed);
dm= CDDM_from_mesh((Mesh*)ob->data, ob);
@@ -1264,7 +1264,7 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D
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_rng_get_float(ctx->sim.rng) * element_sum[totelem];
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;
@@ -2916,9 +2916,9 @@ static void basic_force_cb(void *efdata_v, ParticleKey *state, float *force, flo
/* brownian force */
if (part->brownfac != 0.0f) {
- force[0] += (BLI_frand()-0.5f) * part->brownfac;
- force[1] += (BLI_frand()-0.5f) * part->brownfac;
- force[2] += (BLI_frand()-0.5f) * part->brownfac;
+ force[0] += (BLI_rng_get_float(sim->rng)-0.5f) * part->brownfac;
+ force[1] += (BLI_rng_get_float(sim->rng)-0.5f) * part->brownfac;
+ force[2] += (BLI_rng_get_float(sim->rng)-0.5f) * part->brownfac;
}
if (part->flag & PART_ROT_DYN && epoint.ave)
@@ -3497,7 +3497,7 @@ static int collision_detect(ParticleData *pa, ParticleCollision *col, BVHTreeRay
return hit->index >= 0;
}
-static int collision_response(ParticleData *pa, ParticleCollision *col, BVHTreeRayHit *hit, int kill, int dynamic_rotation)
+static int collision_response(ParticleData *pa, ParticleCollision *col, BVHTreeRayHit *hit, int kill, int dynamic_rotation, RNG *rng)
{
ParticleCollisionElement *pce = &col->pce;
PartDeflect *pd = col->hit->pd;
@@ -3506,7 +3506,7 @@ static int collision_response(ParticleData *pa, ParticleCollision *col, BVHTreeR
float f = col->f + x * (1.0f - col->f); /* time factor of collision between timestep */
float dt1 = (f - col->f) * col->total_time; /* time since previous collision (in seconds) */
float dt2 = (1.0f - f) * col->total_time; /* time left after collision (in seconds) */
- int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0; /* did particle pass through the collision surface? */
+ int through = (BLI_rng_get_float(rng) < pd->pdef_perm) ? 1 : 0; /* did particle pass through the collision surface? */
/* calculate exact collision location */
interp_v3_v3v3(co, col->co1, col->co2, x);
@@ -3531,8 +3531,8 @@ static int collision_response(ParticleData *pa, ParticleCollision *col, BVHTreeR
float v0_tan[3];/* tangential component of v0 */
float vc_tan[3];/* tangential component of collision surface velocity */
float v0_dot, vc_dot;
- float damp = pd->pdef_damp + pd->pdef_rdamp * 2 * (BLI_frand() - 0.5f);
- float frict = pd->pdef_frict + pd->pdef_rfrict * 2 * (BLI_frand() - 0.5f);
+ float damp = pd->pdef_damp + pd->pdef_rdamp * 2 * (BLI_rng_get_float(rng) - 0.5f);
+ float frict = pd->pdef_frict + pd->pdef_rfrict * 2 * (BLI_rng_get_float(rng) - 0.5f);
float distance, nor[3], dot;
CLAMP(damp,0.0f, 1.0f);
@@ -3740,7 +3740,7 @@ static void collision_check(ParticleSimulationData *sim, int p, float dfra, floa
if (collision_count == COLLISION_MAX_COLLISIONS)
collision_fail(pa, &col);
- else if (collision_response(pa, &col, &hit, part->flag & PART_DIE_ON_COL, part->flag & PART_ROT_DYN)==0)
+ else if (collision_response(pa, &col, &hit, part->flag & PART_DIE_ON_COL, part->flag & PART_ROT_DYN, sim->rng)==0)
return;
}
else
@@ -4100,6 +4100,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
{
ParticleSystem *psys = sim->psys;
ParticleSettings *part=psys->part;
+ RNG *rng;
BoidBrainData bbd;
ParticleTexture ptex;
PARTICLE_P;
@@ -4126,7 +4127,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
return;
}
- BLI_srandom(31415926 + (int)cfra + psys->seed);
+ rng = BLI_rng_new_srandom(31415926 + (int)cfra + psys->seed);
psys_update_effectors(sim);
@@ -4143,6 +4144,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
bbd.cfra = cfra;
bbd.dfra = dfra;
bbd.timestep = timestep;
+ bbd.rng = rng;
psys_update_particle_tree(psys, cfra);
@@ -4326,6 +4328,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
}
free_collider_cache(&sim->colliders);
+ BLI_rng_free(rng);
}
static void update_children(ParticleSimulationData *sim)
{
@@ -4822,6 +4825,8 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
if (!sim.psmd->dm)
return;
+ sim.rng = BLI_rng_new(0);
+
if (part->from != PART_FROM_VERT) {
DM_ensure_tessface(sim.psmd->dm);
}
@@ -4962,5 +4967,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
/* 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);
+
+ BLI_rng_free(sim.rng);
}
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index 6b8f0348e16..ba6e8fe0a3a 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -969,6 +969,7 @@ static void emit_from_particles(Object *flow_ob, SmokeDomainSettings *sds, Smoke
sim.scene = scene;
sim.ob = flow_ob;
sim.psys = psys;
+ sim.rng = BLI_rng_new(sim.rng);
if (psys->part->type == PART_HAIR)
{
@@ -1055,6 +1056,8 @@ static void emit_from_particles(Object *flow_ob, SmokeDomainSettings *sds, Smoke
MEM_freeN(particle_pos);
if (particle_vel)
MEM_freeN(particle_vel);
+
+ BLI_rng_free(sim.rng);
}
}