From e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 17 Apr 2019 06:17:24 +0200 Subject: ClangFormat: apply to source, most of intern Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat --- .../blenkernel/intern/particle_distribute.c | 2266 ++++++++++---------- 1 file changed, 1161 insertions(+), 1105 deletions(-) (limited to 'source/blender/blenkernel/intern/particle_distribute.c') diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index fc8292531dc..facfc318426 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -50,375 +50,395 @@ static void alloc_child_particles(ParticleSystem *psys, int tot) { - if (psys->child) { - /* only re-allocate if we have to */ - if (psys->part->childtype && psys->totchild == tot) { - memset(psys->child, 0, tot*sizeof(ChildParticle)); - return; - } - - MEM_freeN(psys->child); - psys->child=NULL; - psys->totchild=0; - } - - if (psys->part->childtype) { - psys->totchild= tot; - if (psys->totchild) - psys->child= MEM_callocN(psys->totchild*sizeof(ChildParticle), "child_particles"); - } + if (psys->child) { + /* only re-allocate if we have to */ + if (psys->part->childtype && psys->totchild == tot) { + memset(psys->child, 0, tot * sizeof(ChildParticle)); + return; + } + + MEM_freeN(psys->child); + psys->child = NULL; + psys->totchild = 0; + } + + if (psys->part->childtype) { + psys->totchild = tot; + if (psys->totchild) + psys->child = MEM_callocN(psys->totchild * sizeof(ChildParticle), "child_particles"); + } } -static void distribute_simple_children(Scene *scene, Object *ob, Mesh *final_mesh, Mesh *deform_mesh, ParticleSystem *psys, const bool use_render_params) +static void distribute_simple_children(Scene *scene, + Object *ob, + Mesh *final_mesh, + Mesh *deform_mesh, + ParticleSystem *psys, + const bool use_render_params) { - ChildParticle *cpa = NULL; - int i, p; - int child_nbr= psys_get_child_number(scene, psys, use_render_params); - int totpart= psys_get_tot_child(scene, psys, use_render_params); - RNG *rng = BLI_rng_new_srandom(31415926 + psys->seed + psys->child_seed); - - alloc_child_particles(psys, totpart); - - cpa = psys->child; - for (i=0; itotpart; p++,cpa++) { - float length=2.0; - cpa->parent=p; - - /* create even spherical distribution inside unit sphere */ - while (length>=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); - } - - cpa->num=-1; - } - } - /* dmcache must be updated for parent particles if children from faces is used */ - psys_calc_dmcache(ob, final_mesh, deform_mesh, psys); - - BLI_rng_free(rng); + ChildParticle *cpa = NULL; + int i, p; + int child_nbr = psys_get_child_number(scene, psys, use_render_params); + int totpart = psys_get_tot_child(scene, psys, use_render_params); + RNG *rng = BLI_rng_new_srandom(31415926 + psys->seed + psys->child_seed); + + alloc_child_particles(psys, totpart); + + cpa = psys->child; + for (i = 0; i < child_nbr; i++) { + for (p = 0; p < psys->totpart; p++, cpa++) { + float length = 2.0; + cpa->parent = p; + + /* create even spherical distribution inside unit sphere */ + while (length >= 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); + } + + cpa->num = -1; + } + } + /* dmcache must be updated for parent particles if children from faces is used */ + psys_calc_dmcache(ob, final_mesh, deform_mesh, psys); + + BLI_rng_free(rng); } static void distribute_grid(Mesh *mesh, ParticleSystem *psys) { - ParticleData *pa=NULL; - float min[3], max[3], delta[3], d; - MVert *mv, *mvert = mesh->mvert; - int totvert=mesh->totvert, from=psys->part->from; - int i, j, k, p, res=psys->part->grid_res, size[3], axis; - - /* find bounding box of dm */ - if (totvert > 0) { - mv=mvert; - copy_v3_v3(min, mv->co); - copy_v3_v3(max, mv->co); - mv++; - for (i = 1; i < totvert; i++, mv++) { - minmax_v3v3_v3(min, max, mv->co); - } - } - else { - zero_v3(min); - zero_v3(max); - } - - sub_v3_v3v3(delta, max, min); - - /* determine major axis */ - axis = axis_dominant_v3_single(delta); - - d = delta[axis]/(float)res; - - size[axis] = res; - size[(axis+1)%3] = (int)ceil(delta[(axis+1)%3]/d); - size[(axis+2)%3] = (int)ceil(delta[(axis+2)%3]/d); - - /* float errors grrr.. */ - size[(axis+1)%3] = MIN2(size[(axis+1)%3],res); - size[(axis+2)%3] = MIN2(size[(axis+2)%3],res); - - size[0] = MAX2(size[0], 1); - size[1] = MAX2(size[1], 1); - size[2] = MAX2(size[2], 1); - - /* no full offset for flat/thin objects */ - min[0]+= d < delta[0] ? d/2.f : delta[0]/2.f; - min[1]+= d < delta[1] ? d/2.f : delta[1]/2.f; - min[2]+= d < delta[2] ? d/2.f : delta[2]/2.f; - - for (i=0,p=0,pa=psys->particles; ifuv[0] = min[0] + (float)i*d; - pa->fuv[1] = min[1] + (float)j*d; - pa->fuv[2] = min[2] + (float)k*d; - pa->flag |= PARS_UNEXIST; - pa->hair_index = 0; /* abused in volume calculation */ - } - } - } - - /* enable particles near verts/edges/faces/inside surface */ - if (from==PART_FROM_VERT) { - float vec[3]; - - pa=psys->particles; - - min[0] -= d/2.0f; - min[1] -= d/2.0f; - min[2] -= d/2.0f; - - for (i=0,mv=mvert; ico,min); - vec[0]/=delta[0]; - vec[1]/=delta[1]; - vec[2]/=delta[2]; - pa[((int)(vec[0] * (size[0] - 1)) * res + - (int)(vec[1] * (size[1] - 1))) * res + - (int)(vec[2] * (size[2] - 1))].flag &= ~PARS_UNEXIST; - } - } - else if (ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) { - float co1[3], co2[3]; - - MFace *mface= NULL, *mface_array; - float v1[3], v2[3], v3[3], v4[4], lambda; - int a, a1, a2, a0mul, a1mul, a2mul, totface; - int amax= from==PART_FROM_FACE ? 3 : 1; - - totface = mesh->totface; - mface = mface_array = mesh->mface; - - for (a=0; aparticles + a1*a1mul + a2*a2mul; - copy_v3_v3(co1, pa->fuv); - co1[a] -= d < delta[a] ? d/2.f : delta[a]/2.f; - copy_v3_v3(co2, co1); - co2[a] += delta[a] + 0.001f*d; - co1[a] -= 0.001f*d; - - struct IsectRayPrecalc isect_precalc; - float ray_direction[3]; - sub_v3_v3v3(ray_direction, co2, co1); - isect_ray_tri_watertight_v3_precalc(&isect_precalc, ray_direction); - - /* lets intersect the faces */ - for (i=0; iv1].co); - copy_v3_v3(v2, mvert[mface->v2].co); - copy_v3_v3(v3, mvert[mface->v3].co); - - bool intersects_tri = isect_ray_tri_watertight_v3(co1, - &isect_precalc, - v1, v2, v3, - &lambda, NULL); - 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++; - } - - if (mface->v4 && (!intersects_tri || from==PART_FROM_VOLUME)) { - copy_v3_v3(v4, mvert[mface->v4].co); - - if (isect_ray_tri_watertight_v3( - co1, - &isect_precalc, - v1, v3, v4, - &lambda, NULL)) - { - if (from==PART_FROM_FACE) - (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST; - else - (pa+(int)(lambda*size[a])*a0mul)->hair_index++; - } - } - } - - if (from==PART_FROM_VOLUME) { - int in=pa->hair_index%2; - if (in) pa->hair_index++; - for (i=0; ihair_index%2) - (pa+i*a0mul)->flag &= ~PARS_UNEXIST; - /* odd intersections == in->out / out->in */ - /* even intersections -> in stays same */ - in=(in + (pa+i*a0mul)->hair_index) % 2; - } - } - } - } - } - } - - if (psys->part->flag & PART_GRID_HEXAGONAL) { - for (i=0,p=0,pa=psys->particles; ifuv[0] += d/2.f; - - if (k%2) { - pa->fuv[0] += d/2.f; - pa->fuv[1] += d/2.f; - } - } - } - } - } - - if (psys->part->flag & PART_GRID_INVERT) { - for (i=0; iparticles + res*(i*res + j); - for (k=0; kflag ^= PARS_UNEXIST; - } - } - } - } - - if (psys->part->grid_rand > 0.f) { - float rfac = d * psys->part->grid_rand; - for (p=0,pa=psys->particles; ptotpart; p++,pa++) { - if (pa->flag & PARS_UNEXIST) - continue; - - pa->fuv[0] += rfac * (psys_frand(psys, p + 31) - 0.5f); - pa->fuv[1] += rfac * (psys_frand(psys, p + 32) - 0.5f); - pa->fuv[2] += rfac * (psys_frand(psys, p + 33) - 0.5f); - } - } + ParticleData *pa = NULL; + float min[3], max[3], delta[3], d; + MVert *mv, *mvert = mesh->mvert; + int totvert = mesh->totvert, from = psys->part->from; + int i, j, k, p, res = psys->part->grid_res, size[3], axis; + + /* find bounding box of dm */ + if (totvert > 0) { + mv = mvert; + copy_v3_v3(min, mv->co); + copy_v3_v3(max, mv->co); + mv++; + for (i = 1; i < totvert; i++, mv++) { + minmax_v3v3_v3(min, max, mv->co); + } + } + else { + zero_v3(min); + zero_v3(max); + } + + sub_v3_v3v3(delta, max, min); + + /* determine major axis */ + axis = axis_dominant_v3_single(delta); + + d = delta[axis] / (float)res; + + size[axis] = res; + size[(axis + 1) % 3] = (int)ceil(delta[(axis + 1) % 3] / d); + size[(axis + 2) % 3] = (int)ceil(delta[(axis + 2) % 3] / d); + + /* float errors grrr.. */ + size[(axis + 1) % 3] = MIN2(size[(axis + 1) % 3], res); + size[(axis + 2) % 3] = MIN2(size[(axis + 2) % 3], res); + + size[0] = MAX2(size[0], 1); + size[1] = MAX2(size[1], 1); + size[2] = MAX2(size[2], 1); + + /* no full offset for flat/thin objects */ + min[0] += d < delta[0] ? d / 2.f : delta[0] / 2.f; + min[1] += d < delta[1] ? d / 2.f : delta[1] / 2.f; + min[2] += d < delta[2] ? d / 2.f : delta[2] / 2.f; + + for (i = 0, p = 0, pa = psys->particles; i < res; i++) { + for (j = 0; j < res; j++) { + for (k = 0; k < res; k++, p++, pa++) { + pa->fuv[0] = min[0] + (float)i * d; + pa->fuv[1] = min[1] + (float)j * d; + pa->fuv[2] = min[2] + (float)k * d; + pa->flag |= PARS_UNEXIST; + pa->hair_index = 0; /* abused in volume calculation */ + } + } + } + + /* enable particles near verts/edges/faces/inside surface */ + if (from == PART_FROM_VERT) { + float vec[3]; + + pa = psys->particles; + + min[0] -= d / 2.0f; + min[1] -= d / 2.0f; + min[2] -= d / 2.0f; + + for (i = 0, mv = mvert; i < totvert; i++, mv++) { + sub_v3_v3v3(vec, mv->co, min); + vec[0] /= delta[0]; + vec[1] /= delta[1]; + vec[2] /= delta[2]; + pa[((int)(vec[0] * (size[0] - 1)) * res + (int)(vec[1] * (size[1] - 1))) * res + + (int)(vec[2] * (size[2] - 1))] + .flag &= ~PARS_UNEXIST; + } + } + else if (ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) { + float co1[3], co2[3]; + + MFace *mface = NULL, *mface_array; + float v1[3], v2[3], v3[3], v4[4], lambda; + int a, a1, a2, a0mul, a1mul, a2mul, totface; + int amax = from == PART_FROM_FACE ? 3 : 1; + + totface = mesh->totface; + mface = mface_array = mesh->mface; + + for (a = 0; a < amax; a++) { + if (a == 0) { + a0mul = res * res; + a1mul = res; + a2mul = 1; + } + else if (a == 1) { + a0mul = res; + a1mul = 1; + a2mul = res * res; + } + else { + a0mul = 1; + a1mul = res * res; + a2mul = res; + } + + for (a1 = 0; a1 < size[(a + 1) % 3]; a1++) { + for (a2 = 0; a2 < size[(a + 2) % 3]; a2++) { + mface = mface_array; + + pa = psys->particles + a1 * a1mul + a2 * a2mul; + copy_v3_v3(co1, pa->fuv); + co1[a] -= d < delta[a] ? d / 2.f : delta[a] / 2.f; + copy_v3_v3(co2, co1); + co2[a] += delta[a] + 0.001f * d; + co1[a] -= 0.001f * d; + + struct IsectRayPrecalc isect_precalc; + float ray_direction[3]; + sub_v3_v3v3(ray_direction, co2, co1); + isect_ray_tri_watertight_v3_precalc(&isect_precalc, ray_direction); + + /* lets intersect the faces */ + for (i = 0; i < totface; i++, mface++) { + copy_v3_v3(v1, mvert[mface->v1].co); + copy_v3_v3(v2, mvert[mface->v2].co); + copy_v3_v3(v3, mvert[mface->v3].co); + + bool intersects_tri = isect_ray_tri_watertight_v3( + co1, &isect_precalc, v1, v2, v3, &lambda, NULL); + 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++; + } + + if (mface->v4 && (!intersects_tri || from == PART_FROM_VOLUME)) { + copy_v3_v3(v4, mvert[mface->v4].co); + + if (isect_ray_tri_watertight_v3(co1, &isect_precalc, v1, v3, v4, &lambda, NULL)) { + if (from == PART_FROM_FACE) + (pa + (int)(lambda * size[a]) * a0mul)->flag &= ~PARS_UNEXIST; + else + (pa + (int)(lambda * size[a]) * a0mul)->hair_index++; + } + } + } + + if (from == PART_FROM_VOLUME) { + int in = pa->hair_index % 2; + if (in) + pa->hair_index++; + for (i = 0; i < size[0]; i++) { + if (in || (pa + i * a0mul)->hair_index % 2) + (pa + i * a0mul)->flag &= ~PARS_UNEXIST; + /* odd intersections == in->out / out->in */ + /* even intersections -> in stays same */ + in = (in + (pa + i * a0mul)->hair_index) % 2; + } + } + } + } + } + } + + if (psys->part->flag & PART_GRID_HEXAGONAL) { + for (i = 0, p = 0, pa = psys->particles; i < res; i++) { + for (j = 0; j < res; j++) { + for (k = 0; k < res; k++, p++, pa++) { + if (j % 2) + pa->fuv[0] += d / 2.f; + + if (k % 2) { + pa->fuv[0] += d / 2.f; + pa->fuv[1] += d / 2.f; + } + } + } + } + } + + if (psys->part->flag & PART_GRID_INVERT) { + for (i = 0; i < size[0]; i++) { + for (j = 0; j < size[1]; j++) { + pa = psys->particles + res * (i * res + j); + for (k = 0; k < size[2]; k++, pa++) { + pa->flag ^= PARS_UNEXIST; + } + } + } + } + + if (psys->part->grid_rand > 0.f) { + float rfac = d * psys->part->grid_rand; + for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) { + if (pa->flag & PARS_UNEXIST) + continue; + + pa->fuv[0] += rfac * (psys_frand(psys, p + 31) - 0.5f); + pa->fuv[1] += rfac * (psys_frand(psys, p + 32) - 0.5f); + pa->fuv[2] += rfac * (psys_frand(psys, p + 33) - 0.5f); + } + } } /* modified copy from rayshade.c */ static void hammersley_create(float *out, int n, int seed, float amount) { - RNG *rng; + RNG *rng; - double offs[2], t; + double offs[2], t; - rng = BLI_rng_new(31415926 + n + seed); - offs[0] = BLI_rng_get_double(rng) + (double)amount; - offs[1] = BLI_rng_get_double(rng) + (double)amount; - BLI_rng_free(rng); + rng = BLI_rng_new(31415926 + n + seed); + offs[0] = BLI_rng_get_double(rng) + (double)amount; + offs[1] = BLI_rng_get_double(rng) + (double)amount; + BLI_rng_free(rng); - for (int k = 0; k < n; k++) { - BLI_hammersley_1d(k, &t); + for (int k = 0; k < n; k++) { + BLI_hammersley_1d(k, &t); - out[2*k + 0] = fmod((double)k/(double)n + offs[0], 1.0); - out[2*k + 1] = fmod(t + offs[1], 1.0); - } + out[2 * k + 0] = fmod((double)k / (double)n + offs[0], 1.0); + out[2 * k + 1] = fmod(t + offs[1], 1.0); + } } /* almost exact copy of BLI_jitter_init */ static void init_mv_jit(float *jit, int num, int seed2, float amount) { - RNG *rng; - float *jit2, x, rad1, rad2, rad3; - int i, num2; + RNG *rng; + float *jit2, x, rad1, rad2, rad3; + int i, num2; - if (num==0) return; + if (num == 0) + return; - rad1= (float)(1.0f/sqrtf((float)num)); - rad2= (float)(1.0f/((float)num)); - rad3= (float)sqrtf((float)num)/((float)num); + rad1 = (float)(1.0f / sqrtf((float)num)); + rad2 = (float)(1.0f / ((float)num)); + rad3 = (float)sqrtf((float)num) / ((float)num); - rng = BLI_rng_new(31415926 + num + seed2); - x= 0; - num2 = 2 * num; - for (i=0; i 1.0f) - v= 1.0f-v; - else - u= 1.0f-u; - } - - vert[0][0] = 0.0f; vert[0][1] = 0.0f; vert[0][2] = 0.0f; - vert[1][0] = 1.0f; vert[1][1] = 0.0f; vert[1][2] = 0.0f; - vert[2][0] = 1.0f; vert[2][1] = 1.0f; vert[2][2] = 0.0f; - - co[0] = u; - co[1] = v; - co[2] = 0.0f; - - if (quad) { - vert[3][0] = 0.0f; vert[3][1] = 1.0f; vert[3][2] = 0.0f; - interp_weights_poly_v3( w,vert, 4, co); - } - else { - interp_weights_poly_v3( w,vert, 3, co); - w[3] = 0.0f; - } + float vert[4][3], co[3]; + + if (!quad) { + if (u + v > 1.0f) + v = 1.0f - v; + else + u = 1.0f - u; + } + + vert[0][0] = 0.0f; + vert[0][1] = 0.0f; + vert[0][2] = 0.0f; + vert[1][0] = 1.0f; + vert[1][1] = 0.0f; + vert[1][2] = 0.0f; + vert[2][0] = 1.0f; + vert[2][1] = 1.0f; + vert[2][2] = 0.0f; + + co[0] = u; + co[1] = v; + co[2] = 0.0f; + + if (quad) { + vert[3][0] = 0.0f; + vert[3][1] = 1.0f; + vert[3][2] = 0.0f; + interp_weights_poly_v3(w, vert, 4, co); + } + else { + interp_weights_poly_v3(w, vert, 3, co); + w[3] = 0.0f; + } } /* Find the index in "sum" array before "value" is crossed. */ static int distribute_binary_search(float *sum, int n, float value) { - int mid, low = 0, high = n - 1; + int mid, low = 0, high = n - 1; - if (high == low) - return low; + if (high == low) + return low; - if (sum[low] >= value) - return low; + if (sum[low] >= value) + return low; - if (sum[high - 1] < value) - return high; + if (sum[high - 1] < value) + return high; - while (low < high) { - mid = (low + high) / 2; + while (low < high) { + mid = (low + high) / 2; - if ((sum[mid] >= value) && (sum[mid - 1] < value)) - return mid; + if ((sum[mid] >= value) && (sum[mid - 1] < value)) + return mid; - if (sum[mid] > value) { - high = mid - 1; - } - else { - low = mid + 1; - } - } + if (sum[mid] > value) { + high = mid - 1; + } + else { + low = mid + 1; + } + } - return low; + return low; } /* the max number if calls to rng_* funcs within psys_thread_distribute_particle @@ -429,848 +449,884 @@ static int distribute_binary_search(float *sum, int n, float value) #define ONLY_WORKING_WITH_PA_VERTS 0 static void distribute_from_verts_exec(ParticleTask *thread, ParticleData *pa, int p) { - ParticleThreadContext *ctx= thread->ctx; - MFace *mface; + ParticleThreadContext *ctx = thread->ctx; + MFace *mface; - mface = ctx->mesh->mface; + mface = ctx->mesh->mface; - int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */ + int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */ - /* TODO_PARTICLE - use original index */ - pa->num = ctx->index[p]; + /* TODO_PARTICLE - use original index */ + pa->num = ctx->index[p]; - zero_v4(pa->fuv); + zero_v4(pa->fuv); - if (pa->num != DMCACHE_NOTFOUND && pa->num < ctx->mesh->totvert) { + if (pa->num != DMCACHE_NOTFOUND && pa->num < ctx->mesh->totvert) { - /* This finds the first face to contain the emitting vertex, - * this is not ideal, but is mostly fine as UV seams generally - * map to equal-colored parts of a texture */ - for (int i = 0; i < ctx->mesh->totface; i++, mface++) { - if (ELEM(pa->num, mface->v1, mface->v2, mface->v3, mface->v4)) { - unsigned int *vert = &mface->v1; + /* This finds the first face to contain the emitting vertex, + * this is not ideal, but is mostly fine as UV seams generally + * map to equal-colored parts of a texture */ + for (int i = 0; i < ctx->mesh->totface; i++, mface++) { + if (ELEM(pa->num, mface->v1, mface->v2, mface->v3, mface->v4)) { + unsigned int *vert = &mface->v1; - for (int j = 0; j < 4; j++, vert++) { - if (*vert == pa->num) { - pa->fuv[j] = 1.0f; - break; - } - } + for (int j = 0; j < 4; j++, vert++) { + if (*vert == pa->num) { + pa->fuv[j] = 1.0f; + break; + } + } - break; - } - } - } + break; + } + } + } #if ONLY_WORKING_WITH_PA_VERTS - if (ctx->tree) { - KDTreeNearest_3d ptn[3]; - int w, maxw; - - psys_particle_on_dm(ctx->mesh,from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0,orco1,0); - BKE_mesh_orco_verts_transform(ob->data, &orco1, 1, 1); - maxw = BLI_kdtree_3d_find_nearest_n(ctx->tree,orco1,ptn,3); - - for (w=0; wverts[w]=ptn->num; - } - } + if (ctx->tree) { + KDTreeNearest_3d ptn[3]; + int w, maxw; + + psys_particle_on_dm( + ctx->mesh, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, orco1, 0); + BKE_mesh_orco_verts_transform(ob->data, &orco1, 1, 1); + maxw = BLI_kdtree_3d_find_nearest_n(ctx->tree, orco1, ptn, 3); + + for (w = 0; w < maxw; w++) { + pa->verts[w] = ptn->num; + } + } #endif - BLI_assert(rng_skip_tot >= 0); /* should never be below zero */ - if (rng_skip_tot > 0) { - BLI_rng_skip(thread->rng, rng_skip_tot); - } + BLI_assert(rng_skip_tot >= 0); /* should never be below zero */ + if (rng_skip_tot > 0) { + BLI_rng_skip(thread->rng, rng_skip_tot); + } } -static void distribute_from_faces_exec(ParticleTask *thread, ParticleData *pa, int p) { - ParticleThreadContext *ctx= thread->ctx; - Mesh *mesh = ctx->mesh; - float randu, randv; - int distr= ctx->distr; - int i; - int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */ - - MFace *mface; - - pa->num = i = ctx->index[p]; - mface = &mesh->mface[i]; - - switch (distr) { - case PART_DISTR_JIT: - if (ctx->jitlevel == 1) { - if (mface->v4) - psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv); - else - psys_uv_to_w(1.0f / 3.0f, 1.0f / 3.0f, mface->v4, pa->fuv); - } - else { - float offset = fmod(ctx->jitoff[i] + (float)p, (float)ctx->jitlevel); - if (!isnan(offset)) { - psys_uv_to_w(ctx->jit[2*(int)offset], ctx->jit[2*(int)offset+1], mface->v4, pa->fuv); - } - } - break; - case PART_DISTR_RAND: - randu= BLI_rng_get_float(thread->rng); - randv= BLI_rng_get_float(thread->rng); - rng_skip_tot -= 2; - - psys_uv_to_w(randu, randv, mface->v4, pa->fuv); - break; - } - pa->foffset= 0.0f; - - BLI_assert(rng_skip_tot >= 0); /* should never be below zero */ - if (rng_skip_tot > 0) { - BLI_rng_skip(thread->rng, rng_skip_tot); - } +static void distribute_from_faces_exec(ParticleTask *thread, ParticleData *pa, int p) +{ + ParticleThreadContext *ctx = thread->ctx; + Mesh *mesh = ctx->mesh; + float randu, randv; + int distr = ctx->distr; + int i; + int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */ + + MFace *mface; + + pa->num = i = ctx->index[p]; + mface = &mesh->mface[i]; + + switch (distr) { + case PART_DISTR_JIT: + if (ctx->jitlevel == 1) { + if (mface->v4) + psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv); + else + psys_uv_to_w(1.0f / 3.0f, 1.0f / 3.0f, mface->v4, pa->fuv); + } + else { + float offset = fmod(ctx->jitoff[i] + (float)p, (float)ctx->jitlevel); + if (!isnan(offset)) { + psys_uv_to_w( + ctx->jit[2 * (int)offset], ctx->jit[2 * (int)offset + 1], mface->v4, pa->fuv); + } + } + break; + case PART_DISTR_RAND: + randu = BLI_rng_get_float(thread->rng); + randv = BLI_rng_get_float(thread->rng); + rng_skip_tot -= 2; + + psys_uv_to_w(randu, randv, mface->v4, pa->fuv); + break; + } + pa->foffset = 0.0f; + + BLI_assert(rng_skip_tot >= 0); /* should never be below zero */ + if (rng_skip_tot > 0) { + BLI_rng_skip(thread->rng, rng_skip_tot); + } } -static void distribute_from_volume_exec(ParticleTask *thread, ParticleData *pa, int p) { - ParticleThreadContext *ctx= thread->ctx; - Mesh *mesh = ctx->mesh; - float *v1, *v2, *v3, *v4, nor[3], co[3]; - float cur_d, min_d, randu, randv; - int distr= ctx->distr; - int i, intersect, tot; - int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */ - - MFace *mface; - MVert *mvert = mesh->mvert; - - pa->num = i = ctx->index[p]; - mface = &mesh->mface[i]; - - switch (distr) { - case PART_DISTR_JIT: - if (ctx->jitlevel == 1) { - if (mface->v4) - psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv); - else - psys_uv_to_w(1.0f / 3.0f, 1.0f / 3.0f, mface->v4, pa->fuv); - } - else { - float offset = fmod(ctx->jitoff[i] + (float)p, (float)ctx->jitlevel); - if (!isnan(offset)) { - psys_uv_to_w(ctx->jit[2*(int)offset], ctx->jit[2*(int)offset+1], mface->v4, pa->fuv); - } - } - break; - case PART_DISTR_RAND: - randu= BLI_rng_get_float(thread->rng); - randv= BLI_rng_get_float(thread->rng); - rng_skip_tot -= 2; - - psys_uv_to_w(randu, randv, mface->v4, pa->fuv); - break; - } - pa->foffset= 0.0f; - - /* experimental */ - tot = mesh->totface; - - psys_interpolate_face(mvert,mface,0,0,pa->fuv,co,nor,0,0,0); - - normalize_v3(nor); - negate_v3(nor); - - min_d=FLT_MAX; - intersect=0; - - for (i=0, mface=mesh->mface; inum) continue; - - v1=mvert[mface->v1].co; - v2=mvert[mface->v2].co; - v3=mvert[mface->v3].co; - - if (isect_ray_tri_v3(co, nor, v2, v3, v1, &cur_d, NULL)) { - if (cur_dfoffset=cur_d*0.5f; /* to the middle of volume */ - intersect=1; - } - } - if (mface->v4) { - v4=mvert[mface->v4].co; - - if (isect_ray_tri_v3(co, nor, v4, v1, v3, &cur_d, NULL)) { - if (cur_dfoffset=cur_d*0.5f; /* to the middle of volume */ - intersect=1; - } - } - } - } - if (intersect==0) - pa->foffset=0.0; - else { - switch (distr) { - case PART_DISTR_JIT: - pa->foffset *= ctx->jit[p % (2 * ctx->jitlevel)]; - break; - case PART_DISTR_RAND: - pa->foffset *= BLI_rng_get_float(thread->rng); - rng_skip_tot--; - break; - } - } - - BLI_assert(rng_skip_tot >= 0); /* should never be below zero */ - if (rng_skip_tot > 0) { - BLI_rng_skip(thread->rng, rng_skip_tot); - } +static void distribute_from_volume_exec(ParticleTask *thread, ParticleData *pa, int p) +{ + ParticleThreadContext *ctx = thread->ctx; + Mesh *mesh = ctx->mesh; + float *v1, *v2, *v3, *v4, nor[3], co[3]; + float cur_d, min_d, randu, randv; + int distr = ctx->distr; + int i, intersect, tot; + int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */ + + MFace *mface; + MVert *mvert = mesh->mvert; + + pa->num = i = ctx->index[p]; + mface = &mesh->mface[i]; + + switch (distr) { + case PART_DISTR_JIT: + if (ctx->jitlevel == 1) { + if (mface->v4) + psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv); + else + psys_uv_to_w(1.0f / 3.0f, 1.0f / 3.0f, mface->v4, pa->fuv); + } + else { + float offset = fmod(ctx->jitoff[i] + (float)p, (float)ctx->jitlevel); + if (!isnan(offset)) { + psys_uv_to_w( + ctx->jit[2 * (int)offset], ctx->jit[2 * (int)offset + 1], mface->v4, pa->fuv); + } + } + break; + case PART_DISTR_RAND: + randu = BLI_rng_get_float(thread->rng); + randv = BLI_rng_get_float(thread->rng); + rng_skip_tot -= 2; + + psys_uv_to_w(randu, randv, mface->v4, pa->fuv); + break; + } + pa->foffset = 0.0f; + + /* experimental */ + tot = mesh->totface; + + psys_interpolate_face(mvert, mface, 0, 0, pa->fuv, co, nor, 0, 0, 0); + + normalize_v3(nor); + negate_v3(nor); + + min_d = FLT_MAX; + intersect = 0; + + for (i = 0, mface = mesh->mface; i < tot; i++, mface++) { + if (i == pa->num) + continue; + + v1 = mvert[mface->v1].co; + v2 = mvert[mface->v2].co; + v3 = mvert[mface->v3].co; + + if (isect_ray_tri_v3(co, nor, v2, v3, v1, &cur_d, NULL)) { + if (cur_d < min_d) { + min_d = cur_d; + pa->foffset = cur_d * 0.5f; /* to the middle of volume */ + intersect = 1; + } + } + if (mface->v4) { + v4 = mvert[mface->v4].co; + + if (isect_ray_tri_v3(co, nor, v4, v1, v3, &cur_d, NULL)) { + if (cur_d < min_d) { + min_d = cur_d; + pa->foffset = cur_d * 0.5f; /* to the middle of volume */ + intersect = 1; + } + } + } + } + if (intersect == 0) + pa->foffset = 0.0; + else { + switch (distr) { + case PART_DISTR_JIT: + pa->foffset *= ctx->jit[p % (2 * ctx->jitlevel)]; + break; + case PART_DISTR_RAND: + pa->foffset *= BLI_rng_get_float(thread->rng); + rng_skip_tot--; + break; + } + } + + BLI_assert(rng_skip_tot >= 0); /* should never be below zero */ + if (rng_skip_tot > 0) { + BLI_rng_skip(thread->rng, rng_skip_tot); + } } -static void distribute_children_exec(ParticleTask *thread, ChildParticle *cpa, int p) { - ParticleThreadContext *ctx= thread->ctx; - Object *ob= ctx->sim.ob; - Mesh *mesh = ctx->mesh; - float orco1[3], co1[3], nor1[3]; - float randu, randv; - int cfrom= ctx->cfrom; - int i; - int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */ - - MFace *mf; - - if (ctx->index[p] < 0) { - cpa->num=0; - cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]=0.0f; - cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0; - return; - } - - mf = &mesh->mface[ctx->index[p]]; - - randu= BLI_rng_get_float(thread->rng); - randv= BLI_rng_get_float(thread->rng); - rng_skip_tot -= 2; - - psys_uv_to_w(randu, randv, mf->v4, cpa->fuv); - - cpa->num = ctx->index[p]; - - if (ctx->tree) { - KDTreeNearest_3d ptn[10]; - int w,maxw;//, do_seams; - float maxd /*, mind,dd */, totw= 0.0f; - int parent[10]; - float pweight[10]; - - psys_particle_on_dm(mesh,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,NULL,NULL,orco1); - BKE_mesh_orco_verts_transform(ob->data, &orco1, 1, 1); - maxw = BLI_kdtree_3d_find_nearest_n(ctx->tree,orco1,ptn,3); - - maxd=ptn[maxw-1].dist; - /* mind=ptn[0].dist; */ /* UNUSED */ - - /* the weights here could be done better */ - for (w=0; w=0) { - cpa->pa[i]=parent[w]; - cpa->w[i]=pweight[w]; - totw+=pweight[w]; - i++; - } - } - for (;i<4; i++) { - cpa->pa[i]=-1; - cpa->w[i]=0.0f; - } - - if (totw > 0.0f) { - for (w = 0; w < 4; w++) { - cpa->w[w] /= totw; - } - } - - cpa->parent=cpa->pa[0]; - } - - if (rng_skip_tot > 0) /* should never be below zero */ - BLI_rng_skip(thread->rng, rng_skip_tot); +static void distribute_children_exec(ParticleTask *thread, ChildParticle *cpa, int p) +{ + ParticleThreadContext *ctx = thread->ctx; + Object *ob = ctx->sim.ob; + Mesh *mesh = ctx->mesh; + float orco1[3], co1[3], nor1[3]; + float randu, randv; + int cfrom = ctx->cfrom; + int i; + int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */ + + MFace *mf; + + if (ctx->index[p] < 0) { + cpa->num = 0; + cpa->fuv[0] = cpa->fuv[1] = cpa->fuv[2] = cpa->fuv[3] = 0.0f; + cpa->pa[0] = cpa->pa[1] = cpa->pa[2] = cpa->pa[3] = 0; + return; + } + + mf = &mesh->mface[ctx->index[p]]; + + randu = BLI_rng_get_float(thread->rng); + randv = BLI_rng_get_float(thread->rng); + rng_skip_tot -= 2; + + psys_uv_to_w(randu, randv, mf->v4, cpa->fuv); + + cpa->num = ctx->index[p]; + + if (ctx->tree) { + KDTreeNearest_3d ptn[10]; + int w, maxw; //, do_seams; + float maxd /*, mind,dd */, totw = 0.0f; + int parent[10]; + float pweight[10]; + + psys_particle_on_dm(mesh, + cfrom, + cpa->num, + DMCACHE_ISCHILD, + cpa->fuv, + cpa->foffset, + co1, + nor1, + NULL, + NULL, + orco1); + BKE_mesh_orco_verts_transform(ob->data, &orco1, 1, 1); + maxw = BLI_kdtree_3d_find_nearest_n(ctx->tree, orco1, ptn, 3); + + maxd = ptn[maxw - 1].dist; + /* mind=ptn[0].dist; */ /* UNUSED */ + + /* the weights here could be done better */ + for (w = 0; w < maxw; w++) { + parent[w] = ptn[w].index; + pweight[w] = (float)pow(2.0, (double)(-6.0f * ptn[w].dist / maxd)); + } + for (; w < 10; w++) { + parent[w] = -1; + pweight[w] = 0.0f; + } + + for (w = 0, i = 0; w < maxw && i < 4; w++) { + if (parent[w] >= 0) { + cpa->pa[i] = parent[w]; + cpa->w[i] = pweight[w]; + totw += pweight[w]; + i++; + } + } + for (; i < 4; i++) { + cpa->pa[i] = -1; + cpa->w[i] = 0.0f; + } + + if (totw > 0.0f) { + for (w = 0; w < 4; w++) { + cpa->w[w] /= totw; + } + } + + cpa->parent = cpa->pa[0]; + } + + if (rng_skip_tot > 0) /* should never be below zero */ + BLI_rng_skip(thread->rng, rng_skip_tot); } -static void exec_distribute_parent(TaskPool * __restrict 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; - ParticleData *pa; - int p; - - BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->begin); - - pa= psys->particles + task->begin; - switch (psys->part->from) { - case PART_FROM_FACE: - for (p = task->begin; p < task->end; ++p, ++pa) - distribute_from_faces_exec(task, pa, p); - break; - case PART_FROM_VOLUME: - for (p = task->begin; p < task->end; ++p, ++pa) - distribute_from_volume_exec(task, pa, p); - break; - case PART_FROM_VERT: - for (p = task->begin; p < task->end; ++p, ++pa) - distribute_from_verts_exec(task, pa, p); - break; - } + ParticleTask *task = taskdata; + ParticleSystem *psys = task->ctx->sim.psys; + ParticleData *pa; + int p; + + BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->begin); + + pa = psys->particles + task->begin; + switch (psys->part->from) { + case PART_FROM_FACE: + for (p = task->begin; p < task->end; ++p, ++pa) + distribute_from_faces_exec(task, pa, p); + break; + case PART_FROM_VOLUME: + for (p = task->begin; p < task->end; ++p, ++pa) + distribute_from_volume_exec(task, pa, p); + break; + case PART_FROM_VERT: + for (p = task->begin; p < task->end; ++p, ++pa) + distribute_from_verts_exec(task, pa, p); + break; + } } -static void exec_distribute_child(TaskPool * __restrict 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; - ChildParticle *cpa; - int p; - - /* RNG skipping at the beginning */ - cpa = psys->child; - for (p = 0; p < task->begin; ++p, ++cpa) { - BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP); - } - - for (; p < task->end; ++p, ++cpa) { - distribute_children_exec(task, cpa, p); - } + ParticleTask *task = taskdata; + ParticleSystem *psys = task->ctx->sim.psys; + ChildParticle *cpa; + int p; + + /* RNG skipping at the beginning */ + cpa = psys->child; + for (p = 0; p < task->begin; ++p, ++cpa) { + BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP); + } + + for (; p < task->end; ++p, ++cpa) { + distribute_children_exec(task, cpa, p); + } } static int distribute_compare_orig_index(const void *p1, const void *p2, void *user_data) { - int *orig_index = (int *) user_data; - int index1 = orig_index[*(const int *)p1]; - int index2 = orig_index[*(const int *)p2]; - - if (index1 < index2) - return -1; - else if (index1 == index2) { - /* this pointer comparison appears to make qsort stable for glibc, - * and apparently on solaris too, makes the renders reproducible */ - if (p1 < p2) - return -1; - else if (p1 == p2) - return 0; - else - return 1; - } - else - return 1; + int *orig_index = (int *)user_data; + int index1 = orig_index[*(const int *)p1]; + int index2 = orig_index[*(const int *)p2]; + + if (index1 < index2) + return -1; + else if (index1 == index2) { + /* this pointer comparison appears to make qsort stable for glibc, + * and apparently on solaris too, makes the renders reproducible */ + if (p1 < p2) + return -1; + else if (p1 == p2) + return 0; + else + return 1; + } + else + return 1; } 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->depsgraph) == DAG_EVAL_RENDER); - - if (from == PART_FROM_CHILD) { - ChildParticle *cpa; - int p, totchild = psys_get_tot_child(scene, psys, use_render_params); - - if (psys->child && totchild) { - for (p=0,cpa=psys->child; pfuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3] = 0.0; - cpa->foffset= 0.0f; - cpa->parent=0; - cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0; - cpa->num= -1; - } - } - } - else { - PARTICLE_P; - LOOP_PARTICLES { - pa->fuv[0] = pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0; - pa->foffset= 0.0f; - pa->num= -1; - } - } + Scene *scene = sim->scene; + ParticleSystem *psys = sim->psys; + const bool use_render_params = (DEG_get_mode(sim->depsgraph) == DAG_EVAL_RENDER); + + if (from == PART_FROM_CHILD) { + ChildParticle *cpa; + 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++) { + cpa->fuv[0] = cpa->fuv[1] = cpa->fuv[2] = cpa->fuv[3] = 0.0; + cpa->foffset = 0.0f; + cpa->parent = 0; + cpa->pa[0] = cpa->pa[1] = cpa->pa[2] = cpa->pa[3] = 0; + cpa->num = -1; + } + } + } + else { + PARTICLE_P; + LOOP_PARTICLES + { + pa->fuv[0] = pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0; + pa->foffset = 0.0f; + pa->num = -1; + } + } } /* Creates a distribution of coordinates on a Mesh */ -static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, ParticleSimulationData *sim, int from) +static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, + ParticleSimulationData *sim, + int from) { - Scene *scene = sim->scene; - Mesh *final_mesh = sim->psmd->mesh_final; - Object *ob = sim->ob; - ParticleSystem *psys= sim->psys; - ParticleData *pa=0, *tpars= 0; - ParticleSettings *part; - ParticleSeam *seams= 0; - KDTree_3d *tree=0; - Mesh *mesh = NULL; - float *jit= NULL; - int i, p=0; - int cfrom=0; - int totelem=0, totpart, *particle_element=0, children=0, totseam=0; - int jitlevel= 1, distr; - float *element_weight=NULL,*jitter_offset=NULL, *vweight=NULL; - float cur, maxweight=0.0, tweight, totweight, inv_totweight, co[3], nor[3], orco[3]; - RNG *rng = NULL; - - if (ELEM(NULL, ob, psys, psys->part)) - return 0; - - part=psys->part; - totpart=psys->totpart; - if (totpart==0) - return 0; - - if (!final_mesh->runtime.deformed_only && !CustomData_get_layer(&final_mesh->fdata, CD_ORIGINDEX)) { - printf("Can't create particles with the current modifier stack, disable destructive modifiers\n"); -// XXX error("Can't paint with the current modifier stack, disable destructive modifiers"); - 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); - - const bool use_render_params = (DEG_get_mode(sim->depsgraph) == DAG_EVAL_RENDER); - - /* First handle special cases */ - if (from == PART_FROM_CHILD) { - /* Simple children */ - if (part->childtype != PART_CHILD_FACES) { - distribute_simple_children(scene, ob, final_mesh, sim->psmd->mesh_original, psys, use_render_params); - return 0; - } - } - else { - /* Grid distribution */ - if (part->distr==PART_DISTR_GRID && from != PART_FROM_VERT) { - if (psys->part->use_modifier_stack) { - mesh = final_mesh; - } - else { - BKE_id_copy_ex(NULL, ob->data, (ID **)&mesh, LIB_ID_COPY_LOCALIZE); - } - BKE_mesh_tessface_ensure(mesh); - - distribute_grid(mesh,psys); - - if (mesh != final_mesh) { - BKE_id_free(NULL, mesh); - } - - return 0; - } - } - - /* Create trees and original coordinates if needed */ - if (from == PART_FROM_CHILD) { - distr = PART_DISTR_RAND; - rng = BLI_rng_new_srandom(31415926 + psys->seed + psys->child_seed); - mesh= final_mesh; - - /* BMESH ONLY */ - BKE_mesh_tessface_ensure(mesh); - - children=1; - - tree=BLI_kdtree_3d_new(totpart); - - for (p=0,pa=psys->particles; pfrom,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,orco); - BKE_mesh_orco_verts_transform(ob->data, &orco, 1, 1); - BLI_kdtree_3d_insert(tree, p, orco); - } - - BLI_kdtree_3d_balance(tree); - - totpart = psys_get_tot_child(scene, psys, use_render_params); - cfrom = from = PART_FROM_FACE; - } - else { - distr = part->distr; - - rng = BLI_rng_new_srandom(31415926 + psys->seed); - - if (psys->part->use_modifier_stack) - mesh = final_mesh; - else - BKE_id_copy_ex(NULL, ob->data, (ID **)&mesh, LIB_ID_COPY_LOCALIZE); - - BKE_mesh_tessface_ensure(mesh); - - /* we need orco for consistent distributions */ - if (!CustomData_has_layer(&mesh->vdata, CD_ORCO)) { - /* Orcos are stored in normalized 0..1 range by convention. */ - float (*orcodata)[3] = BKE_mesh_orco_verts_get(ob); - BKE_mesh_orco_verts_transform(mesh, orcodata, mesh->totvert, false); - CustomData_add_layer(&mesh->vdata, CD_ORCO, CD_ASSIGN, orcodata, mesh->totvert); - } - - if (from == PART_FROM_VERT) { - MVert *mv = mesh->mvert; - float (*orcodata)[3] = CustomData_get_layer(&mesh->vdata, CD_ORCO); - int totvert = mesh->totvert; - - tree=BLI_kdtree_3d_new(totvert); - - for (p=0; pdata, &co, 1, 1); - } - else - copy_v3_v3(co,mv[p].co); - BLI_kdtree_3d_insert(tree, p, co); - } - - BLI_kdtree_3d_balance(tree); - } - } - - /* Get total number of emission elements and allocate needed arrays */ - totelem = (from == PART_FROM_VERT) ? mesh->totvert : mesh->totface; - - if (totelem == 0) { - distribute_invalid(sim, children ? PART_FROM_CHILD : 0); - - if (G.debug & G_DEBUG) - fprintf(stderr,"Particle distribution error: Nothing to emit from!\n"); - - if (mesh != final_mesh) BKE_id_free(NULL, mesh); - - BLI_kdtree_3d_free(tree); - BLI_rng_free(rng); - - return 0; - } - - element_weight = MEM_callocN(sizeof(float) * totelem, "particle_distribution_weights"); - particle_element = MEM_callocN(sizeof(int) * totpart, "particle_distribution_indexes"); - jitter_offset = MEM_callocN(sizeof(float) * totelem, "particle_distribution_jitoff"); - - /* Calculate weights from face areas */ - if ((part->flag & PART_EDISTR || children) && from != PART_FROM_VERT) { - MVert *v1, *v2, *v3, *v4; - float totarea=0.f, co1[3], co2[3], co3[3], co4[3]; - float (*orcodata)[3]; - - orcodata = CustomData_get_layer(&mesh->vdata, CD_ORCO); - - for (i=0; imface[i]; - - if (orcodata) { - /* Transform orcos from normalized 0..1 to object space. */ - copy_v3_v3(co1, orcodata[mf->v1]); - copy_v3_v3(co2, orcodata[mf->v2]); - copy_v3_v3(co3, orcodata[mf->v3]); - BKE_mesh_orco_verts_transform(ob->data, &co1, 1, 1); - BKE_mesh_orco_verts_transform(ob->data, &co2, 1, 1); - BKE_mesh_orco_verts_transform(ob->data, &co3, 1, 1); - if (mf->v4) { - copy_v3_v3(co4, orcodata[mf->v4]); - BKE_mesh_orco_verts_transform(ob->data, &co4, 1, 1); - } - } - else { - v1 = &mesh->mvert[mf->v1]; - v2 = &mesh->mvert[mf->v2]; - v3 = &mesh->mvert[mf->v3]; - copy_v3_v3(co1, v1->co); - copy_v3_v3(co2, v2->co); - copy_v3_v3(co3, v3->co); - if (mf->v4) { - v4 = &mesh->mvert[mf->v4]; - copy_v3_v3(co4, v4->co); - } - } - - cur = mf->v4 ? area_quad_v3(co1, co2, co3, co4) : area_tri_v3(co1, co2, co3); - - if (cur > maxweight) - maxweight = cur; - - element_weight[i] = cur; - totarea += cur; - } - - for (i=0; imface[i]; - tweight = vweight[mf->v1] + vweight[mf->v2] + vweight[mf->v3]; - - if (mf->v4) { - tweight += vweight[mf->v4]; - tweight /= 4.0f; - } - else { - tweight /= 3.0f; - } - - element_weight[i]*=tweight; - } - } - MEM_freeN(vweight); - } - - /* Calculate total weight of all elements */ - int totmapped = 0; - totweight = 0.0f; - for (i = 0; i < totelem; i++) { - if (element_weight[i] > 0.0f) { - totmapped++; - totweight += element_weight[i]; - } - } - - if (totmapped == 0) { - /* We are not allowed to distribute particles anywhere... */ - if (mesh != final_mesh) { - BKE_id_free(NULL, mesh); - } - BLI_kdtree_3d_free(tree); - BLI_rng_free(rng); - MEM_freeN(element_weight); - MEM_freeN(particle_element); - MEM_freeN(jitter_offset); - return 0; - } - - inv_totweight = 1.0f / totweight; - - /* Calculate cumulative weights. - * We remove all null-weighted elements from element_sum, and create a new mapping - * 'activ'_elem_index -> orig_elem_index. - * This simplifies greatly the filtering of zero-weighted items - and can be much more efficient - * especially in random case (reducing a lot the size of binary-searched array)... - */ - float *element_sum = MEM_mallocN(sizeof(*element_sum) * totmapped, __func__); - int *element_map = MEM_mallocN(sizeof(*element_map) * totmapped, __func__); - int i_mapped = 0; - - for (i = 0; i < totelem && element_weight[i] == 0.0f; i++); - element_sum[i_mapped] = element_weight[i] * inv_totweight; - element_map[i_mapped] = i; - i_mapped++; - for (i++; i < totelem; i++) { - if (element_weight[i] > 0.0f) { - element_sum[i_mapped] = element_sum[i_mapped - 1] + element_weight[i] * inv_totweight; - /* Skip elements which weight is so small that it does not affect the sum. */ - if (element_sum[i_mapped] > element_sum[i_mapped - 1]) { - element_map[i_mapped] = i; - i_mapped++; - } - } - } - totmapped = i_mapped; - - /* Finally assign elements to particles */ - 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. */ - const float pos = BLI_rng_get_float(rng) * element_sum[totmapped - 1]; - const int eidx = distribute_binary_search(element_sum, totmapped, pos); - particle_element[p] = element_map[eidx]; - BLI_assert(pos <= element_sum[eidx]); - BLI_assert(eidx ? (pos > element_sum[eidx - 1]) : (pos >= 0.0f)); - jitter_offset[particle_element[p]] = pos; - } - } - else { - double step, pos; - - 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 impression in element_sum. - * Note: moved face and volume distribution to this as well (instead of starting at zero), - * for the same reasons, see T52682. */ - pos = (totpart < totmapped) ? 0.5 / (double)totmapped : step * 0.5; /* We choose the smaller step. */ - - for (i = 0, p = 0; p < totpart; p++, pos += step) { - for ( ; (i < totmapped - 1) && (pos > (double)element_sum[i]); i++); - - particle_element[p] = element_map[i]; - - jitter_offset[particle_element[p]] = pos; - } - } - - MEM_freeN(element_sum); - MEM_freeN(element_map); - - /* For hair, sort by origindex (allows optimization's in rendering), */ - /* however with virtual parents the children need to be in random order. */ - if (part->type == PART_HAIR && !(part->childtype==PART_CHILD_FACES && part->parents != 0.0f)) { - int *orig_index = NULL; - - if (from == PART_FROM_VERT) { - if (mesh->totvert) - orig_index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX); - } - else { - if (mesh->totface) - orig_index = CustomData_get_layer(&mesh->fdata, CD_ORIGINDEX); - } - - if (orig_index) { - BLI_qsort_r(particle_element, totpart, sizeof(int), distribute_compare_orig_index, orig_index); - } - } - - /* Create jittering if needed */ - if (distr==PART_DISTR_JIT && ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) { - jitlevel= part->userjit; - - if (jitlevel == 0) { - jitlevel= totpart/totelem; - if (part->flag & PART_EDISTR) jitlevel*= 2; /* looks better in general, not very scientific */ - if (jitlevel<3) jitlevel= 3; - } - - jit= MEM_callocN((2+ jitlevel*2)*sizeof(float), "jit"); - - /* for small amounts of particles we use regular jitter since it looks - * a bit better, for larger amounts we switch to hammersley sequence - * because it is much faster */ - if (jitlevel < 25) - init_mv_jit(jit, jitlevel, psys->seed, part->jitfac); - else - hammersley_create(jit, jitlevel+1, psys->seed, part->jitfac); - BLI_array_randomize(jit, 2*sizeof(float), jitlevel, psys->seed); /* for custom jit or even distribution */ - } - - /* Setup things for threaded distribution */ - ctx->tree= tree; - ctx->seams= seams; - ctx->totseam= totseam; - ctx->sim.psys= psys; - ctx->index= particle_element; - ctx->jit= jit; - ctx->jitlevel= jitlevel; - ctx->jitoff= jitter_offset; - ctx->weight= element_weight; - ctx->maxweight= maxweight; - ctx->cfrom= cfrom; - ctx->distr= distr; - ctx->mesh= mesh; - ctx->tpars= tpars; - - if (children) { - alloc_child_particles(psys, totpart); - } - - BLI_rng_free(rng); - - return 1; + Scene *scene = sim->scene; + Mesh *final_mesh = sim->psmd->mesh_final; + Object *ob = sim->ob; + ParticleSystem *psys = sim->psys; + ParticleData *pa = 0, *tpars = 0; + ParticleSettings *part; + ParticleSeam *seams = 0; + KDTree_3d *tree = 0; + Mesh *mesh = NULL; + float *jit = NULL; + int i, p = 0; + int cfrom = 0; + int totelem = 0, totpart, *particle_element = 0, children = 0, totseam = 0; + int jitlevel = 1, distr; + float *element_weight = NULL, *jitter_offset = NULL, *vweight = NULL; + float cur, maxweight = 0.0, tweight, totweight, inv_totweight, co[3], nor[3], orco[3]; + RNG *rng = NULL; + + if (ELEM(NULL, ob, psys, psys->part)) + return 0; + + part = psys->part; + totpart = psys->totpart; + if (totpart == 0) + return 0; + + if (!final_mesh->runtime.deformed_only && + !CustomData_get_layer(&final_mesh->fdata, CD_ORIGINDEX)) { + printf( + "Can't create particles with the current modifier stack, disable destructive modifiers\n"); + // XXX error("Can't paint with the current modifier stack, disable destructive modifiers"); + 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); + + const bool use_render_params = (DEG_get_mode(sim->depsgraph) == DAG_EVAL_RENDER); + + /* First handle special cases */ + if (from == PART_FROM_CHILD) { + /* Simple children */ + if (part->childtype != PART_CHILD_FACES) { + distribute_simple_children( + scene, ob, final_mesh, sim->psmd->mesh_original, psys, use_render_params); + return 0; + } + } + else { + /* Grid distribution */ + if (part->distr == PART_DISTR_GRID && from != PART_FROM_VERT) { + if (psys->part->use_modifier_stack) { + mesh = final_mesh; + } + else { + BKE_id_copy_ex(NULL, ob->data, (ID **)&mesh, LIB_ID_COPY_LOCALIZE); + } + BKE_mesh_tessface_ensure(mesh); + + distribute_grid(mesh, psys); + + if (mesh != final_mesh) { + BKE_id_free(NULL, mesh); + } + + return 0; + } + } + + /* Create trees and original coordinates if needed */ + if (from == PART_FROM_CHILD) { + distr = PART_DISTR_RAND; + rng = BLI_rng_new_srandom(31415926 + psys->seed + psys->child_seed); + mesh = final_mesh; + + /* BMESH ONLY */ + BKE_mesh_tessface_ensure(mesh); + + children = 1; + + tree = BLI_kdtree_3d_new(totpart); + + for (p = 0, pa = psys->particles; p < totpart; p++, pa++) { + psys_particle_on_dm( + mesh, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co, nor, 0, 0, orco); + BKE_mesh_orco_verts_transform(ob->data, &orco, 1, 1); + BLI_kdtree_3d_insert(tree, p, orco); + } + + BLI_kdtree_3d_balance(tree); + + totpart = psys_get_tot_child(scene, psys, use_render_params); + cfrom = from = PART_FROM_FACE; + } + else { + distr = part->distr; + + rng = BLI_rng_new_srandom(31415926 + psys->seed); + + if (psys->part->use_modifier_stack) + mesh = final_mesh; + else + BKE_id_copy_ex(NULL, ob->data, (ID **)&mesh, LIB_ID_COPY_LOCALIZE); + + BKE_mesh_tessface_ensure(mesh); + + /* we need orco for consistent distributions */ + if (!CustomData_has_layer(&mesh->vdata, CD_ORCO)) { + /* Orcos are stored in normalized 0..1 range by convention. */ + float(*orcodata)[3] = BKE_mesh_orco_verts_get(ob); + BKE_mesh_orco_verts_transform(mesh, orcodata, mesh->totvert, false); + CustomData_add_layer(&mesh->vdata, CD_ORCO, CD_ASSIGN, orcodata, mesh->totvert); + } + + if (from == PART_FROM_VERT) { + MVert *mv = mesh->mvert; + float(*orcodata)[3] = CustomData_get_layer(&mesh->vdata, CD_ORCO); + int totvert = mesh->totvert; + + tree = BLI_kdtree_3d_new(totvert); + + for (p = 0; p < totvert; p++) { + if (orcodata) { + copy_v3_v3(co, orcodata[p]); + BKE_mesh_orco_verts_transform(ob->data, &co, 1, 1); + } + else + copy_v3_v3(co, mv[p].co); + BLI_kdtree_3d_insert(tree, p, co); + } + + BLI_kdtree_3d_balance(tree); + } + } + + /* Get total number of emission elements and allocate needed arrays */ + totelem = (from == PART_FROM_VERT) ? mesh->totvert : mesh->totface; + + if (totelem == 0) { + distribute_invalid(sim, children ? PART_FROM_CHILD : 0); + + if (G.debug & G_DEBUG) + fprintf(stderr, "Particle distribution error: Nothing to emit from!\n"); + + if (mesh != final_mesh) + BKE_id_free(NULL, mesh); + + BLI_kdtree_3d_free(tree); + BLI_rng_free(rng); + + return 0; + } + + element_weight = MEM_callocN(sizeof(float) * totelem, "particle_distribution_weights"); + particle_element = MEM_callocN(sizeof(int) * totpart, "particle_distribution_indexes"); + jitter_offset = MEM_callocN(sizeof(float) * totelem, "particle_distribution_jitoff"); + + /* Calculate weights from face areas */ + if ((part->flag & PART_EDISTR || children) && from != PART_FROM_VERT) { + MVert *v1, *v2, *v3, *v4; + float totarea = 0.f, co1[3], co2[3], co3[3], co4[3]; + float(*orcodata)[3]; + + orcodata = CustomData_get_layer(&mesh->vdata, CD_ORCO); + + for (i = 0; i < totelem; i++) { + MFace *mf = &mesh->mface[i]; + + if (orcodata) { + /* Transform orcos from normalized 0..1 to object space. */ + copy_v3_v3(co1, orcodata[mf->v1]); + copy_v3_v3(co2, orcodata[mf->v2]); + copy_v3_v3(co3, orcodata[mf->v3]); + BKE_mesh_orco_verts_transform(ob->data, &co1, 1, 1); + BKE_mesh_orco_verts_transform(ob->data, &co2, 1, 1); + BKE_mesh_orco_verts_transform(ob->data, &co3, 1, 1); + if (mf->v4) { + copy_v3_v3(co4, orcodata[mf->v4]); + BKE_mesh_orco_verts_transform(ob->data, &co4, 1, 1); + } + } + else { + v1 = &mesh->mvert[mf->v1]; + v2 = &mesh->mvert[mf->v2]; + v3 = &mesh->mvert[mf->v3]; + copy_v3_v3(co1, v1->co); + copy_v3_v3(co2, v2->co); + copy_v3_v3(co3, v3->co); + if (mf->v4) { + v4 = &mesh->mvert[mf->v4]; + copy_v3_v3(co4, v4->co); + } + } + + cur = mf->v4 ? area_quad_v3(co1, co2, co3, co4) : area_tri_v3(co1, co2, co3); + + if (cur > maxweight) + maxweight = cur; + + element_weight[i] = cur; + totarea += cur; + } + + for (i = 0; i < totelem; i++) + element_weight[i] /= totarea; + + maxweight /= totarea; + } + else { + float min = 1.0f / (float)(MIN2(totelem, totpart)); + for (i = 0; i < totelem; i++) + element_weight[i] = min; + maxweight = min; + } + + /* Calculate weights from vgroup */ + vweight = psys_cache_vgroup(mesh, psys, PSYS_VG_DENSITY); + + if (vweight) { + if (from == PART_FROM_VERT) { + for (i = 0; i < totelem; i++) + element_weight[i] *= vweight[i]; + } + else { /* PART_FROM_FACE / PART_FROM_VOLUME */ + for (i = 0; i < totelem; i++) { + MFace *mf = &mesh->mface[i]; + tweight = vweight[mf->v1] + vweight[mf->v2] + vweight[mf->v3]; + + if (mf->v4) { + tweight += vweight[mf->v4]; + tweight /= 4.0f; + } + else { + tweight /= 3.0f; + } + + element_weight[i] *= tweight; + } + } + MEM_freeN(vweight); + } + + /* Calculate total weight of all elements */ + int totmapped = 0; + totweight = 0.0f; + for (i = 0; i < totelem; i++) { + if (element_weight[i] > 0.0f) { + totmapped++; + totweight += element_weight[i]; + } + } + + if (totmapped == 0) { + /* We are not allowed to distribute particles anywhere... */ + if (mesh != final_mesh) { + BKE_id_free(NULL, mesh); + } + BLI_kdtree_3d_free(tree); + BLI_rng_free(rng); + MEM_freeN(element_weight); + MEM_freeN(particle_element); + MEM_freeN(jitter_offset); + return 0; + } + + inv_totweight = 1.0f / totweight; + + /* Calculate cumulative weights. + * We remove all null-weighted elements from element_sum, and create a new mapping + * 'activ'_elem_index -> orig_elem_index. + * This simplifies greatly the filtering of zero-weighted items - and can be much more efficient + * especially in random case (reducing a lot the size of binary-searched array)... + */ + float *element_sum = MEM_mallocN(sizeof(*element_sum) * totmapped, __func__); + int *element_map = MEM_mallocN(sizeof(*element_map) * totmapped, __func__); + int i_mapped = 0; + + for (i = 0; i < totelem && element_weight[i] == 0.0f; i++) + ; + element_sum[i_mapped] = element_weight[i] * inv_totweight; + element_map[i_mapped] = i; + i_mapped++; + for (i++; i < totelem; i++) { + if (element_weight[i] > 0.0f) { + element_sum[i_mapped] = element_sum[i_mapped - 1] + element_weight[i] * inv_totweight; + /* Skip elements which weight is so small that it does not affect the sum. */ + if (element_sum[i_mapped] > element_sum[i_mapped - 1]) { + element_map[i_mapped] = i; + i_mapped++; + } + } + } + totmapped = i_mapped; + + /* Finally assign elements to particles */ + 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. */ + const float pos = BLI_rng_get_float(rng) * element_sum[totmapped - 1]; + const int eidx = distribute_binary_search(element_sum, totmapped, pos); + particle_element[p] = element_map[eidx]; + BLI_assert(pos <= element_sum[eidx]); + BLI_assert(eidx ? (pos > element_sum[eidx - 1]) : (pos >= 0.0f)); + jitter_offset[particle_element[p]] = pos; + } + } + else { + double step, pos; + + 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 impression in element_sum. + * Note: moved face and volume distribution to this as well (instead of starting at zero), + * for the same reasons, see T52682. */ + pos = (totpart < totmapped) ? 0.5 / (double)totmapped : + step * 0.5; /* We choose the smaller step. */ + + for (i = 0, p = 0; p < totpart; p++, pos += step) { + for (; (i < totmapped - 1) && (pos > (double)element_sum[i]); i++) + ; + + particle_element[p] = element_map[i]; + + jitter_offset[particle_element[p]] = pos; + } + } + + MEM_freeN(element_sum); + MEM_freeN(element_map); + + /* For hair, sort by origindex (allows optimization's in rendering), */ + /* however with virtual parents the children need to be in random order. */ + if (part->type == PART_HAIR && !(part->childtype == PART_CHILD_FACES && part->parents != 0.0f)) { + int *orig_index = NULL; + + if (from == PART_FROM_VERT) { + if (mesh->totvert) + orig_index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX); + } + else { + if (mesh->totface) + orig_index = CustomData_get_layer(&mesh->fdata, CD_ORIGINDEX); + } + + if (orig_index) { + BLI_qsort_r( + particle_element, totpart, sizeof(int), distribute_compare_orig_index, orig_index); + } + } + + /* Create jittering if needed */ + if (distr == PART_DISTR_JIT && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) { + jitlevel = part->userjit; + + if (jitlevel == 0) { + jitlevel = totpart / totelem; + if (part->flag & PART_EDISTR) + jitlevel *= 2; /* looks better in general, not very scientific */ + if (jitlevel < 3) + jitlevel = 3; + } + + jit = MEM_callocN((2 + jitlevel * 2) * sizeof(float), "jit"); + + /* for small amounts of particles we use regular jitter since it looks + * a bit better, for larger amounts we switch to hammersley sequence + * because it is much faster */ + if (jitlevel < 25) + init_mv_jit(jit, jitlevel, psys->seed, part->jitfac); + else + hammersley_create(jit, jitlevel + 1, psys->seed, part->jitfac); + BLI_array_randomize( + jit, 2 * sizeof(float), jitlevel, psys->seed); /* for custom jit or even distribution */ + } + + /* Setup things for threaded distribution */ + ctx->tree = tree; + ctx->seams = seams; + ctx->totseam = totseam; + ctx->sim.psys = psys; + ctx->index = particle_element; + ctx->jit = jit; + ctx->jitlevel = jitlevel; + ctx->jitoff = jitter_offset; + ctx->weight = element_weight; + ctx->maxweight = maxweight; + ctx->cfrom = cfrom; + ctx->distr = distr; + ctx->mesh = mesh; + ctx->tpars = tpars; + + if (children) { + alloc_child_particles(psys, totpart); + } + + BLI_rng_free(rng); + + return 1; } static void psys_task_init_distribute(ParticleTask *task, ParticleSimulationData *sim) { - /* init random number generator */ - int seed = 31415926 + sim->psys->seed; + /* init random number generator */ + int seed = 31415926 + sim->psys->seed; - task->rng = BLI_rng_new(seed); + task->rng = BLI_rng_new(seed); } static void distribute_particles_on_dm(ParticleSimulationData *sim, int from) { - TaskScheduler *task_scheduler; - TaskPool *task_pool; - ParticleThreadContext ctx; - ParticleTask *tasks; - Mesh *final_mesh = sim->psmd->mesh_final; - int i, totpart, numtasks; + TaskScheduler *task_scheduler; + TaskPool *task_pool; + ParticleThreadContext ctx; + ParticleTask *tasks; + Mesh *final_mesh = sim->psmd->mesh_final; + int i, totpart, numtasks; - /* create a task pool for distribution tasks */ - if (!psys_thread_context_init_distribute(&ctx, sim, from)) - return; + /* create a task pool for distribution tasks */ + if (!psys_thread_context_init_distribute(&ctx, sim, from)) + return; - task_scheduler = BLI_task_scheduler_get(); - task_pool = BLI_task_pool_create(task_scheduler, &ctx); + task_scheduler = BLI_task_scheduler_get(); + task_pool = BLI_task_pool_create(task_scheduler, &ctx); - totpart = (from == PART_FROM_CHILD ? sim->psys->totchild : sim->psys->totpart); - psys_tasks_create(&ctx, 0, totpart, &tasks, &numtasks); - for (i = 0; i < numtasks; ++i) { - ParticleTask *task = &tasks[i]; + totpart = (from == PART_FROM_CHILD ? sim->psys->totchild : sim->psys->totpart); + psys_tasks_create(&ctx, 0, totpart, &tasks, &numtasks); + for (i = 0; i < numtasks; ++i) { + ParticleTask *task = &tasks[i]; - psys_task_init_distribute(task, sim); - if (from == PART_FROM_CHILD) - BLI_task_pool_push(task_pool, exec_distribute_child, task, false, TASK_PRIORITY_LOW); - else - BLI_task_pool_push(task_pool, exec_distribute_parent, task, false, TASK_PRIORITY_LOW); - } - BLI_task_pool_work_and_wait(task_pool); + psys_task_init_distribute(task, sim); + if (from == PART_FROM_CHILD) + BLI_task_pool_push(task_pool, exec_distribute_child, task, false, TASK_PRIORITY_LOW); + else + BLI_task_pool_push(task_pool, exec_distribute_parent, task, false, TASK_PRIORITY_LOW); + } + BLI_task_pool_work_and_wait(task_pool); - BLI_task_pool_free(task_pool); + BLI_task_pool_free(task_pool); - psys_calc_dmcache(sim->ob, final_mesh, sim->psmd->mesh_original, sim->psys); + psys_calc_dmcache(sim->ob, final_mesh, sim->psmd->mesh_original, sim->psys); - if (ctx.mesh != final_mesh) - BKE_id_free(NULL, ctx.mesh); + if (ctx.mesh != final_mesh) + BKE_id_free(NULL, ctx.mesh); - psys_tasks_free(tasks, numtasks); + psys_tasks_free(tasks, numtasks); - psys_thread_context_free(&ctx); + psys_thread_context_free(&ctx); } /* ready for future use, to emit particles without geometry */ static void distribute_particles_on_shape(ParticleSimulationData *sim, int UNUSED(from)) { - distribute_invalid(sim, 0); + distribute_invalid(sim, 0); - fprintf(stderr,"Shape emission not yet possible!\n"); + fprintf(stderr, "Shape emission not yet possible!\n"); } void distribute_particles(ParticleSimulationData *sim, int from) { - PARTICLE_PSMD; - int distr_error=0; - - if (psmd) { - if (psmd->mesh_final) - distribute_particles_on_dm(sim, from); - else - distr_error=1; - } - else - distribute_particles_on_shape(sim, from); - - if (distr_error) { - distribute_invalid(sim, from); - - fprintf(stderr,"Particle distribution error!\n"); - } + PARTICLE_PSMD; + int distr_error = 0; + + if (psmd) { + if (psmd->mesh_final) + distribute_particles_on_dm(sim, from); + else + distr_error = 1; + } + else + distribute_particles_on_shape(sim, from); + + if (distr_error) { + distribute_invalid(sim, from); + + fprintf(stderr, "Particle distribution error!\n"); + } } -- cgit v1.2.3