Blender V5.0
particle_distribute.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2007 by Janne Karhu. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10#include <cstring>
11
12#include "MEM_guardedalloc.h"
13
14#include "BLI_jitter_2d.h"
15#include "BLI_kdtree.h"
16#include "BLI_math_geom.h"
17#include "BLI_rand.h"
18#include "BLI_sort.h"
19#include "BLI_task.h"
20#include "BLI_utildefines.h"
21
22#include "DNA_mesh_types.h"
23#include "DNA_meshdata_types.h"
24#include "DNA_modifier_types.h"
25#include "DNA_particle_types.h"
26
27#include "BKE_customdata.hh"
28#include "BKE_global.hh"
29#include "BKE_lib_id.hh"
30#include "BKE_mesh.hh"
32#include "BKE_particle.h"
33
35
36static void alloc_child_particles(ParticleSystem *psys, int tot)
37{
38 if (psys->child) {
39 /* only re-allocate if we have to */
40 if (psys->part->childtype && psys->totchild == tot) {
41 std::fill_n(psys->child, tot, ChildParticle{});
42 return;
43 }
44
45 MEM_freeN(psys->child);
46 psys->child = nullptr;
47 psys->totchild = 0;
48 }
49
50 if (psys->part->childtype) {
51 psys->totchild = tot;
52 if (psys->totchild) {
53 psys->child = MEM_calloc_arrayN<ChildParticle>(psys->totchild, "child_particles");
54 }
55 }
56}
57
59 Object *ob,
60 Mesh *final_mesh,
61 Mesh *deform_mesh,
62 ParticleSystem *psys,
63 const bool use_render_params)
64{
65 ChildParticle *cpa = nullptr;
66 int i, p;
67 const int child_num = psys_get_child_number(scene, psys, use_render_params);
68 const int totpart = psys_get_tot_child(scene, psys, use_render_params);
69 RNG *rng = BLI_rng_new_srandom(31415926 + psys->seed + psys->child_seed);
70
71 alloc_child_particles(psys, totpart);
72
73 cpa = psys->child;
74 for (i = 0; i < child_num; i++) {
75 for (p = 0; p < psys->totpart; p++, cpa++) {
76 float length = 2.0;
77 cpa->parent = p;
78
79 /* create even spherical distribution inside unit sphere */
80 while (length >= 1.0f) {
81 cpa->fuv[0] = 2.0f * BLI_rng_get_float(rng) - 1.0f;
82 cpa->fuv[1] = 2.0f * BLI_rng_get_float(rng) - 1.0f;
83 cpa->fuv[2] = 2.0f * BLI_rng_get_float(rng) - 1.0f;
84 length = len_v3(cpa->fuv);
85 }
86
87 cpa->num = -1;
88 }
89 }
90 /* dmcache must be updated for parent particles if children from faces is used */
91 psys_calc_dmcache(ob, final_mesh, deform_mesh, psys);
92
93 BLI_rng_free(rng);
94}
95static void distribute_grid(Mesh *mesh, ParticleSystem *psys)
96{
97 ParticleData *pa = nullptr;
98 float min[3], max[3], delta[3], d;
99 const blender::Span<blender::float3> positions = mesh->vert_positions();
100 int totvert = mesh->verts_num, from = psys->part->from;
101 int i, j, k, p, res = psys->part->grid_res, size[3], axis;
102
103 /* find bounding box of dm */
104 if (totvert > 0) {
106 for (i = 1; i < totvert; i++) {
107 minmax_v3v3_v3(min, max, positions[i]);
108 }
109 }
110 else {
111 zero_v3(min);
112 zero_v3(max);
113 }
114
115 sub_v3_v3v3(delta, max, min);
116
117 /* determine major axis */
118 axis = axis_dominant_v3_single(delta);
119
120 d = delta[axis] / float(res);
121
122 size[axis] = res;
123 size[(axis + 1) % 3] = int(ceil(delta[(axis + 1) % 3] / d));
124 size[(axis + 2) % 3] = int(ceil(delta[(axis + 2) % 3] / d));
125
126 /* float errors grrr. */
127 size[(axis + 1) % 3] = std::min(size[(axis + 1) % 3], res);
128 size[(axis + 2) % 3] = std::min(size[(axis + 2) % 3], res);
129
130 size[0] = std::max(size[0], 1);
131 size[1] = std::max(size[1], 1);
132 size[2] = std::max(size[2], 1);
133
134 /* no full offset for flat/thin objects */
135 min[0] += d < delta[0] ? d / 2.0f : delta[0] / 2.0f;
136 min[1] += d < delta[1] ? d / 2.0f : delta[1] / 2.0f;
137 min[2] += d < delta[2] ? d / 2.0f : delta[2] / 2.0f;
138
139 for (i = 0, p = 0, pa = psys->particles; i < res; i++) {
140 for (j = 0; j < res; j++) {
141 for (k = 0; k < res; k++, p++, pa++) {
142 pa->fuv[0] = min[0] + float(i) * d;
143 pa->fuv[1] = min[1] + float(j) * d;
144 pa->fuv[2] = min[2] + float(k) * d;
145 pa->flag |= PARS_UNEXIST;
146 pa->hair_index = 0; /* abused in volume calculation */
147 }
148 }
149 }
150
151 /* enable particles near verts/edges/faces/inside surface */
152 if (from == PART_FROM_VERT) {
153 float vec[3];
154
155 pa = psys->particles;
156
157 min[0] -= d / 2.0f;
158 min[1] -= d / 2.0f;
159 min[2] -= d / 2.0f;
160
161 for (i = 0; i < totvert; i++) {
162 sub_v3_v3v3(vec, positions[i], min);
163 vec[0] /= delta[0];
164 vec[1] /= delta[1];
165 vec[2] /= delta[2];
166 pa[(int(vec[0] * (size[0] - 1)) * res + int(vec[1] * (size[1] - 1))) * res +
167 int(vec[2] * (size[2] - 1))]
169 }
170 }
171 else if (ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
172 float co1[3], co2[3];
173
174 MFace *mface = nullptr, *mface_array;
175 float v1[3], v2[3], v3[3], v4[4], lambda;
176 int a, a1, a2, a0mul, a1mul, a2mul, totface;
177 int amax = from == PART_FROM_FACE ? 3 : 1;
178
179 totface = mesh->totface_legacy;
180 mface = mface_array = static_cast<MFace *>(
182
183 for (a = 0; a < amax; a++) {
184 if (a == 0) {
185 a0mul = res * res;
186 a1mul = res;
187 a2mul = 1;
188 }
189 else if (a == 1) {
190 a0mul = res;
191 a1mul = 1;
192 a2mul = res * res;
193 }
194 else {
195 a0mul = 1;
196 a1mul = res * res;
197 a2mul = res;
198 }
199
200 for (a1 = 0; a1 < size[(a + 1) % 3]; a1++) {
201 for (a2 = 0; a2 < size[(a + 2) % 3]; a2++) {
202 mface = mface_array;
203
204 pa = psys->particles + a1 * a1mul + a2 * a2mul;
205 copy_v3_v3(co1, pa->fuv);
206 co1[a] -= d < delta[a] ? d / 2.0f : delta[a] / 2.0f;
207 copy_v3_v3(co2, co1);
208 co2[a] += delta[a] + 0.001f * d;
209 co1[a] -= 0.001f * d;
210
211 IsectRayPrecalc isect_precalc;
212 float ray_direction[3];
213 sub_v3_v3v3(ray_direction, co2, co1);
214 isect_ray_tri_watertight_v3_precalc(&isect_precalc, ray_direction);
215
216 /* lets intersect the faces */
217 for (i = 0; i < totface; i++, mface++) {
218 ParticleData *pa1 = nullptr, *pa2 = nullptr;
219
220 copy_v3_v3(v1, positions[mface->v1]);
221 copy_v3_v3(v2, positions[mface->v2]);
222 copy_v3_v3(v3, positions[mface->v3]);
223
224 bool intersects_tri = isect_ray_tri_watertight_v3(
225 co1, &isect_precalc, v1, v2, v3, &lambda, nullptr);
226 if (intersects_tri) {
227 pa1 = (pa + int(lambda * size[a]) * a0mul);
228 }
229
230 if (mface->v4 && (!intersects_tri || from == PART_FROM_VOLUME)) {
231 copy_v3_v3(v4, positions[mface->v4]);
232
233 if (isect_ray_tri_watertight_v3(co1, &isect_precalc, v1, v3, v4, &lambda, nullptr)) {
234 pa2 = (pa + int(lambda * size[a]) * a0mul);
235 }
236 }
237
238 if (pa1) {
239 if (from == PART_FROM_FACE) {
240 pa1->flag &= ~PARS_UNEXIST;
241 }
242 else { /* store number of intersections */
243 pa1->hair_index++;
244 }
245 }
246
247 if (pa2 && pa2 != pa1) {
248 if (from == PART_FROM_FACE) {
249 pa2->flag &= ~PARS_UNEXIST;
250 }
251 else { /* store number of intersections */
252 pa2->hair_index++;
253 }
254 }
255 }
256
257 if (from == PART_FROM_VOLUME) {
258 int in = pa->hair_index % 2;
259 if (in) {
260 pa->hair_index++;
261 }
262 for (i = 0; i < size[0]; i++) {
263 if (in || (pa + i * a0mul)->hair_index % 2) {
264 (pa + i * a0mul)->flag &= ~PARS_UNEXIST;
265 }
266 /* odd intersections == in->out / out->in */
267 /* even intersections -> in stays same */
268 in = (in + (pa + i * a0mul)->hair_index) % 2;
269 }
270 }
271 }
272 }
273 }
274 }
275
276 if (psys->part->flag & PART_GRID_HEXAGONAL) {
277 for (i = 0, p = 0, pa = psys->particles; i < res; i++) {
278 for (j = 0; j < res; j++) {
279 for (k = 0; k < res; k++, p++, pa++) {
280 if (j % 2) {
281 pa->fuv[0] += d / 2.0f;
282 }
283
284 if (k % 2) {
285 pa->fuv[0] += d / 2.0f;
286 pa->fuv[1] += d / 2.0f;
287 }
288 }
289 }
290 }
291 }
292
293 if (psys->part->flag & PART_GRID_INVERT) {
294 for (i = 0; i < size[0]; i++) {
295 for (j = 0; j < size[1]; j++) {
296 pa = psys->particles + res * (i * res + j);
297 for (k = 0; k < size[2]; k++, pa++) {
298 pa->flag ^= PARS_UNEXIST;
299 }
300 }
301 }
302 }
303
304 if (psys->part->grid_rand > 0.0f) {
305 float rfac = d * psys->part->grid_rand;
306 for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++) {
307 if (pa->flag & PARS_UNEXIST) {
308 continue;
309 }
310
311 pa->fuv[0] += rfac * (psys_frand(psys, p + 31) - 0.5f);
312 pa->fuv[1] += rfac * (psys_frand(psys, p + 32) - 0.5f);
313 pa->fuv[2] += rfac * (psys_frand(psys, p + 33) - 0.5f);
314 }
315 }
316}
317
318static void hammersley_create(float *out, int n, int seed, float amount)
319{
320 /* This code is originally from a modified copy from `rayshade.c`
321 * (a file that's no longer included). */
322 RNG *rng;
323
324 double ofs[2], t;
325
326 rng = BLI_rng_new(31415926 + n + seed);
327 ofs[0] = BLI_rng_get_double(rng) + double(amount);
328 ofs[1] = BLI_rng_get_double(rng) + double(amount);
329 BLI_rng_free(rng);
330
331 for (int k = 0; k < n; k++) {
332 BLI_hammersley_1d(k, &t);
333
334 out[2 * k + 0] = fmod(double(k) / double(n) + ofs[0], 1.0);
335 out[2 * k + 1] = fmod(t + ofs[1], 1.0);
336 }
337}
338
339/* almost exact copy of BLI_jitter_init */
340static void init_mv_jit(float *jit, int num, int seed2, float amount)
341{
342 RNG *rng;
343 float *jit2, x, rad1, rad2, rad3;
344 int i, num2;
345
346 if (num == 0) {
347 return;
348 }
349
350 rad1 = (1.0f / sqrtf(float(num)));
351 rad2 = (1.0f / float(num));
352 rad3 = (sqrtf(float(num)) / float(num));
353
354 rng = BLI_rng_new(31415926 + num + seed2);
355 x = 0;
356 num2 = 2 * num;
357 for (i = 0; i < num2; i += 2) {
358
359 jit[i] = x + amount * rad1 * (0.5f - BLI_rng_get_float(rng));
360 jit[i + 1] = i / (2.0f * num) + amount * rad1 * (0.5f - BLI_rng_get_float(rng));
361
362 jit[i] -= floor(jit[i]);
363 jit[i + 1] -= floor(jit[i + 1]);
364
365 x += rad3;
366 x -= floor(x);
367 }
368
369 /* FIXME: The `+ 3` number of items does not seem to be required? */
370 jit2 = MEM_malloc_arrayN<float>(3 + 2 * size_t(num), "initjit");
371
372 for (i = 0; i < 4; i++) {
373 BLI_jitterate1((float (*)[2])jit, (float (*)[2])jit2, num, rad1);
374 BLI_jitterate1((float (*)[2])jit, (float (*)[2])jit2, num, rad1);
375 BLI_jitterate2((float (*)[2])jit, (float (*)[2])jit2, num, rad2);
376 }
377 MEM_freeN(jit2);
378 BLI_rng_free(rng);
379}
380
381static void psys_uv_to_w(float u, float v, int quad, float *w)
382{
383 float vert[4][3], co[3];
384
385 if (!quad) {
386 if (u + v > 1.0f) {
387 v = 1.0f - v;
388 }
389 else {
390 u = 1.0f - u;
391 }
392 }
393
394 vert[0][0] = 0.0f;
395 vert[0][1] = 0.0f;
396 vert[0][2] = 0.0f;
397 vert[1][0] = 1.0f;
398 vert[1][1] = 0.0f;
399 vert[1][2] = 0.0f;
400 vert[2][0] = 1.0f;
401 vert[2][1] = 1.0f;
402 vert[2][2] = 0.0f;
403
404 co[0] = u;
405 co[1] = v;
406 co[2] = 0.0f;
407
408 if (quad) {
409 vert[3][0] = 0.0f;
410 vert[3][1] = 1.0f;
411 vert[3][2] = 0.0f;
412 interp_weights_poly_v3(w, vert, 4, co);
413 }
414 else {
415 interp_weights_poly_v3(w, vert, 3, co);
416 w[3] = 0.0f;
417 }
418}
419
420/* Find the index in "sum" array before "value" is crossed. */
421static int distribute_binary_search(const float *sum, int n, float value)
422{
423 int mid, low = 0, high = n - 1;
424
425 if (high == low) {
426 return low;
427 }
428
429 if (sum[low] >= value) {
430 return low;
431 }
432
433 if (sum[high - 1] < value) {
434 return high;
435 }
436
437 while (low < high) {
438 mid = (low + high) / 2;
439
440 if ((sum[mid] >= value) && (sum[mid - 1] < value)) {
441 return mid;
442 }
443
444 if (sum[mid] > value) {
445 high = mid - 1;
446 }
447 else {
448 low = mid + 1;
449 }
450 }
451
452 return low;
453}
454
455/* the max number if calls to rng_* functions within psys_thread_distribute_particle
456 * be sure to keep up to date if this changes */
457#define PSYS_RND_DIST_SKIP 3
458
459/* NOTE: this function must be thread safe, for `from == PART_FROM_CHILD`. */
460#define ONLY_WORKING_WITH_PA_VERTS 0
462{
463 ParticleThreadContext *ctx = thread->ctx;
464 MFace *mface;
465
466 mface = static_cast<MFace *>(CustomData_get_layer_for_write(
468
469 int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls won't need skipping */
470
471 /* TODO_PARTICLE - use original index */
472 pa->num = ctx->index[p];
473
474 zero_v4(pa->fuv);
475
476 if (pa->num != DMCACHE_NOTFOUND && pa->num < ctx->mesh->verts_num) {
477
478 /* This finds the first face to contain the emitting vertex,
479 * this is not ideal, but is mostly fine as UV seams generally
480 * map to equal-colored parts of a texture */
481 for (int i = 0; i < ctx->mesh->totface_legacy; i++, mface++) {
482 if (ELEM(pa->num, mface->v1, mface->v2, mface->v3, mface->v4)) {
483 uint *vert = &mface->v1;
484
485 for (int j = 0; j < 4; j++, vert++) {
486 if (*vert == pa->num) {
487 pa->fuv[j] = 1.0f;
488 break;
489 }
490 }
491
492 break;
493 }
494 }
495 }
496
497#if ONLY_WORKING_WITH_PA_VERTS
498 if (ctx->tree) {
499 KDTreeNearest_3d ptn[3];
500 int w, maxw;
501
503 ctx->mesh, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, orco1, 0);
504 BKE_mesh_orco_verts_transform(ob->data, &orco1, 1, true);
505 maxw = BLI_kdtree_3d_find_nearest_n(ctx->tree, orco1, ptn, 3);
506
507 for (w = 0; w < maxw; w++) {
508 pa->verts[w] = ptn->num;
509 }
510 }
511#endif
512
513 BLI_assert(rng_skip_tot >= 0); /* should never be below zero */
514 if (rng_skip_tot > 0) {
515 BLI_rng_skip(thread->rng, rng_skip_tot);
516 }
517}
518
520{
521 ParticleThreadContext *ctx = thread->ctx;
522 Mesh *mesh = ctx->mesh;
523 float randu, randv;
524 int distr = ctx->distr;
525 int i;
526 int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls won't need skipping */
527
529 &mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy);
530 MFace *mface;
531
532 pa->num = i = ctx->index[p];
533 mface = &mfaces[i];
534
535 switch (distr) {
536 case PART_DISTR_JIT:
537 if (ctx->jitlevel == 1) {
538 if (mface->v4) {
539 psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv);
540 }
541 else {
542 psys_uv_to_w(1.0f / 3.0f, 1.0f / 3.0f, mface->v4, pa->fuv);
543 }
544 }
545 else {
546 float offset = fmod(ctx->jitoff[i] + float(p), float(ctx->jitlevel));
547 if (!isnan(offset)) {
549 ctx->jit[2 * int(offset)], ctx->jit[2 * int(offset) + 1], mface->v4, pa->fuv);
550 }
551 }
552 break;
553 case PART_DISTR_RAND:
554 randu = BLI_rng_get_float(thread->rng);
555 randv = BLI_rng_get_float(thread->rng);
556 rng_skip_tot -= 2;
557
558 psys_uv_to_w(randu, randv, mface->v4, pa->fuv);
559 break;
560 }
561 pa->foffset = 0.0f;
562
563 BLI_assert(rng_skip_tot >= 0); /* should never be below zero */
564 if (rng_skip_tot > 0) {
565 BLI_rng_skip(thread->rng, rng_skip_tot);
566 }
567}
568
570{
571 ParticleThreadContext *ctx = thread->ctx;
572 Mesh *mesh = ctx->mesh;
573 const float *v1, *v2, *v3, *v4;
574 float nor[3], co[3];
575 float cur_d, min_d, randu, randv;
576 int distr = ctx->distr;
577 int i, intersect, tot;
578 int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls won't need skipping */
579
580 MFace *mface;
581 const blender::Span<blender::float3> positions = mesh->vert_positions();
582
583 pa->num = i = ctx->index[p];
585 &mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy);
586 mface = &mfaces[i];
587
588 switch (distr) {
589 case PART_DISTR_JIT:
590 if (ctx->jitlevel == 1) {
591 if (mface->v4) {
592 psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv);
593 }
594 else {
595 psys_uv_to_w(1.0f / 3.0f, 1.0f / 3.0f, mface->v4, pa->fuv);
596 }
597 }
598 else {
599 float offset = fmod(ctx->jitoff[i] + float(p), float(ctx->jitlevel));
600 if (!isnan(offset)) {
602 ctx->jit[2 * int(offset)], ctx->jit[2 * int(offset) + 1], mface->v4, pa->fuv);
603 }
604 }
605 break;
606 case PART_DISTR_RAND:
607 randu = BLI_rng_get_float(thread->rng);
608 randv = BLI_rng_get_float(thread->rng);
609 rng_skip_tot -= 2;
610
611 psys_uv_to_w(randu, randv, mface->v4, pa->fuv);
612 break;
613 }
614 pa->foffset = 0.0f;
615
616 /* experimental */
617 tot = mesh->totface_legacy;
618
620 reinterpret_cast<const float (*)[3]>(positions.data()),
621 reinterpret_cast<const float (*)[3]>(mesh->vert_normals().data()),
622 mface,
623 nullptr,
624 nullptr,
625 pa->fuv,
626 co,
627 nor,
628 nullptr,
629 nullptr,
630 nullptr);
631
633 negate_v3(nor);
634
635 min_d = FLT_MAX;
636 intersect = 0;
637 mface = static_cast<MFace *>(
639 for (i = 0; i < tot; i++, mface++) {
640 if (i == pa->num) {
641 continue;
642 }
643
644 v1 = positions[mface->v1];
645 v2 = positions[mface->v2];
646 v3 = positions[mface->v3];
647
648 if (isect_ray_tri_v3(co, nor, v2, v3, v1, &cur_d, nullptr)) {
649 if (cur_d < min_d) {
650 min_d = cur_d;
651 pa->foffset = cur_d * 0.5f; /* to the middle of volume */
652 intersect = 1;
653 }
654 }
655 if (mface->v4) {
656 v4 = positions[mface->v4];
657
658 if (isect_ray_tri_v3(co, nor, v4, v1, v3, &cur_d, nullptr)) {
659 if (cur_d < min_d) {
660 min_d = cur_d;
661 pa->foffset = cur_d * 0.5f; /* to the middle of volume */
662 intersect = 1;
663 }
664 }
665 }
666 }
667 if (intersect == 0) {
668 pa->foffset = 0.0;
669 }
670 else {
671 switch (distr) {
672 case PART_DISTR_JIT:
673 pa->foffset *= ctx->jit[p % (2 * ctx->jitlevel)];
674 break;
675 case PART_DISTR_RAND:
676 pa->foffset *= BLI_rng_get_float(thread->rng);
677 rng_skip_tot--;
678 break;
679 }
680 }
681
682 BLI_assert(rng_skip_tot >= 0); /* should never be below zero */
683 if (rng_skip_tot > 0) {
684 BLI_rng_skip(thread->rng, rng_skip_tot);
685 }
686}
687
689{
690 ParticleThreadContext *ctx = thread->ctx;
691 Object *ob = ctx->sim.ob;
692 Mesh *mesh = ctx->mesh;
693 float orco1[3], co1[3], nor1[3];
694 float randu, randv;
695 int cfrom = ctx->cfrom;
696 int i;
697 int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls won't need skipping */
698
699 MFace *mf;
700
701 if (ctx->index[p] < 0) {
702 cpa->num = 0;
703 cpa->fuv[0] = cpa->fuv[1] = cpa->fuv[2] = cpa->fuv[3] = 0.0f;
704 cpa->pa[0] = cpa->pa[1] = cpa->pa[2] = cpa->pa[3] = 0;
705 return;
706 }
707
709 &mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy);
710 mf = &mfaces[ctx->index[p]];
711
712 randu = BLI_rng_get_float(thread->rng);
713 randv = BLI_rng_get_float(thread->rng);
714 rng_skip_tot -= 2;
715
716 psys_uv_to_w(randu, randv, mf->v4, cpa->fuv);
717
718 cpa->num = ctx->index[p];
719
720 if (ctx->tree) {
721 KDTreeNearest_3d ptn[10];
722 int w, maxw; //, do_seams;
723 float maxd /*, mind,dd */, totw = 0.0f;
724 int parent[10];
725 float pweight[10];
726
728 cfrom,
729 cpa->num,
731 cpa->fuv,
732 cpa->foffset,
733 co1,
734 nor1,
735 nullptr,
736 nullptr,
737 orco1);
738 BKE_mesh_orco_verts_transform(static_cast<Mesh *>(ob->data), &orco1, 1, true);
739 maxw = BLI_kdtree_3d_find_nearest_n(ctx->tree, orco1, ptn, 3);
740
741 maxd = ptn[maxw - 1].dist;
742 // mind=ptn[0].dist; /* UNUSED */
743
744 /* the weights here could be done better */
745 for (w = 0; w < maxw; w++) {
746 parent[w] = ptn[w].index;
747 pweight[w] = float(pow(2.0, double(-6.0f * ptn[w].dist / maxd)));
748 }
749 for (; w < 10; w++) {
750 parent[w] = -1;
751 pweight[w] = 0.0f;
752 }
753
754 for (w = 0, i = 0; w < maxw && i < 4; w++) {
755 if (parent[w] >= 0) {
756 cpa->pa[i] = parent[w];
757 cpa->w[i] = pweight[w];
758 totw += pweight[w];
759 i++;
760 }
761 }
762 for (; i < 4; i++) {
763 cpa->pa[i] = -1;
764 cpa->w[i] = 0.0f;
765 }
766
767 if (totw > 0.0f) {
768 for (w = 0; w < 4; w++) {
769 cpa->w[w] /= totw;
770 }
771 }
772
773 cpa->parent = cpa->pa[0];
774 }
775
776 if (rng_skip_tot > 0) { /* should never be below zero */
777 BLI_rng_skip(thread->rng, rng_skip_tot);
778 }
779}
780
781static void exec_distribute_parent(TaskPool *__restrict /*pool*/, void *taskdata)
782{
783 ParticleTask *task = static_cast<ParticleTask *>(taskdata);
784 ParticleSystem *psys = task->ctx->sim.psys;
785 ParticleData *pa;
786 int p;
787
789
790 pa = psys->particles + task->begin;
791 switch (psys->part->from) {
792 case PART_FROM_FACE:
793 for (p = task->begin; p < task->end; p++, pa++) {
794 distribute_from_faces_exec(task, pa, p);
795 }
796 break;
797 case PART_FROM_VOLUME:
798 for (p = task->begin; p < task->end; p++, pa++) {
799 distribute_from_volume_exec(task, pa, p);
800 }
801 break;
802 case PART_FROM_VERT:
803 for (p = task->begin; p < task->end; p++, pa++) {
804 distribute_from_verts_exec(task, pa, p);
805 }
806 break;
807 }
808}
809
810static void exec_distribute_child(TaskPool *__restrict /*pool*/, void *taskdata)
811{
812 ParticleTask *task = static_cast<ParticleTask *>(taskdata);
813 ParticleSystem *psys = task->ctx->sim.psys;
814 ChildParticle *cpa;
815 int p;
816
817 /* RNG skipping at the beginning */
818 cpa = psys->child;
819 for (p = 0; p < task->begin; p++, cpa++) {
821 }
822
823 for (; p < task->end; p++, cpa++) {
824 distribute_children_exec(task, cpa, p);
825 }
826}
827
828static int distribute_compare_orig_index(const void *p1, const void *p2, void *user_data)
829{
830 const int *orig_index = (const int *)user_data;
831 int index1 = orig_index[*(const int *)p1];
832 int index2 = orig_index[*(const int *)p2];
833
834 if (index1 < index2) {
835 return -1;
836 }
837 if (index1 == index2) {
838 /* This pointer comparison appears to make #qsort stable for GLIBC,
839 * and apparently on SOLARIS too, makes the renders reproducible. */
840 if (p1 < p2) {
841 return -1;
842 }
843 if (p1 == p2) {
844 return 0;
845 }
846
847 return 1;
848 }
849
850 return 1;
851}
852
854{
855 Scene *scene = sim->scene;
856 ParticleSystem *psys = sim->psys;
857 const bool use_render_params = (DEG_get_mode(sim->depsgraph) == DAG_EVAL_RENDER);
858
859 if (from == PART_FROM_CHILD) {
860 ChildParticle *cpa;
861 int p, totchild = psys_get_tot_child(scene, psys, use_render_params);
862
863 if (psys->child && totchild) {
864 for (p = 0, cpa = psys->child; p < totchild; p++, cpa++) {
865 cpa->fuv[0] = cpa->fuv[1] = cpa->fuv[2] = cpa->fuv[3] = 0.0;
866 cpa->foffset = 0.0f;
867 cpa->parent = 0;
868 cpa->pa[0] = cpa->pa[1] = cpa->pa[2] = cpa->pa[3] = 0;
869 cpa->num = -1;
870 }
871 }
872 }
873 else {
876 {
877 pa->fuv[0] = pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0;
878 pa->foffset = 0.0f;
879 pa->num = -1;
880 }
881 }
882}
883
884/* Creates a distribution of coordinates on a Mesh */
887 int from)
888{
889 Scene *scene = sim->scene;
890 Mesh *final_mesh = sim->psmd->mesh_final;
891 Object *ob = sim->ob;
892 ParticleSystem *psys = sim->psys;
893 ParticleData *pa = nullptr, *tpars = nullptr;
894 ParticleSettings *part;
895 ParticleSeam *seams = nullptr;
896 KDTree_3d *tree = nullptr;
897 Mesh *mesh = nullptr;
898 float *jit = nullptr;
899 int i, p = 0;
900 int cfrom = 0;
901 int totelem = 0, totpart, *particle_element = nullptr, children = 0, totseam = 0;
902 int jitlevel = 1, distr;
903 float *element_weight = nullptr, *jitter_offset = nullptr, *vweight = nullptr;
904 float cur, maxweight = 0.0, tweight, totweight, inv_totweight, co[3], nor[3], orco[3];
905 RNG *rng = nullptr;
906
907 if (ELEM(nullptr, ob, psys, psys->part)) {
908 return 0;
909 }
910
911 part = psys->part;
912 totpart = psys->totpart;
913 if (totpart == 0) {
914 return 0;
915 }
916
917 if (!final_mesh->runtime->deformed_only &&
919 {
920 printf(
921 "Can't create particles with the current modifier stack, disable destructive modifiers\n");
922 // XXX error("Can't paint with the current modifier stack, disable destructive modifiers");
923 return 0;
924 }
925
926 /* XXX This distribution code is totally broken in case from == PART_FROM_CHILD,
927 * it's always using `final_mesh` even if use_modifier_stack is unset...
928 * But making things consistent here break all existing edited
929 * hair systems, so better wait for complete rewrite. */
930
931 psys_thread_context_init(ctx, sim);
932
933 const bool use_render_params = (DEG_get_mode(sim->depsgraph) == DAG_EVAL_RENDER);
934
935 /* First handle special cases */
936 if (from == PART_FROM_CHILD) {
937 /* Simple children */
938 if (part->childtype != PART_CHILD_FACES) {
940 scene, ob, final_mesh, sim->psmd->mesh_original, psys, use_render_params);
941 return 0;
942 }
943 }
944 else {
945 /* Grid distribution */
946 if (part->distr == PART_DISTR_GRID && from != PART_FROM_VERT) {
947 if (psys->part->use_modifier_stack) {
948 mesh = final_mesh;
949 }
950 else {
951 mesh = (Mesh *)BKE_id_copy_ex(
952 nullptr, static_cast<const ID *>(ob->data), nullptr, LIB_ID_COPY_LOCALIZE);
953 }
955
956 distribute_grid(mesh, psys);
957
958 if (mesh != final_mesh) {
959 BKE_id_free(nullptr, mesh);
960 }
961
962 return 0;
963 }
964 }
965
966 /* After this #BKE_mesh_orco_verts_transform can be used safely from multiple threads. */
967 BKE_mesh_texspace_ensure(final_mesh);
968
969 /* Create trees and original coordinates if needed */
970 if (from == PART_FROM_CHILD) {
971 distr = PART_DISTR_RAND;
972 rng = BLI_rng_new_srandom(31415926 + psys->seed + psys->child_seed);
973 mesh = final_mesh;
974
975 /* BMESH ONLY */
977
978 children = 1;
979
980 tree = BLI_kdtree_3d_new(totpart);
981
982 for (p = 0, pa = psys->particles; p < totpart; p++, pa++) {
984 part->from,
985 pa->num,
986 pa->num_dmcache,
987 pa->fuv,
988 pa->foffset,
989 co,
990 nor,
991 nullptr,
992 nullptr,
993 orco);
994 BKE_mesh_orco_verts_transform(static_cast<Mesh *>(ob->data), &orco, 1, true);
995 BLI_kdtree_3d_insert(tree, p, orco);
996 }
997
998 BLI_kdtree_3d_balance(tree);
999
1000 totpart = psys_get_tot_child(scene, psys, use_render_params);
1001 cfrom = from = PART_FROM_FACE;
1002 }
1003 else {
1004 distr = part->distr;
1005
1006 rng = BLI_rng_new_srandom(31415926 + psys->seed);
1007
1008 if (psys->part->use_modifier_stack) {
1009 mesh = final_mesh;
1010 }
1011 else {
1012 mesh = (Mesh *)BKE_id_copy_ex(
1013 nullptr, static_cast<const ID *>(ob->data), nullptr, LIB_ID_COPY_LOCALIZE);
1014 }
1015
1017
1018 /* we need orco for consistent distributions */
1019 BKE_mesh_orco_ensure(ob, mesh);
1020
1021 if (from == PART_FROM_VERT) {
1022 const blender::Span<blender::float3> positions = mesh->vert_positions();
1023 const float (*orcodata)[3] = static_cast<const float (*)[3]>(
1025 int totvert = mesh->verts_num;
1026
1027 tree = BLI_kdtree_3d_new(totvert);
1028
1029 for (p = 0; p < totvert; p++) {
1030 if (orcodata) {
1031 copy_v3_v3(co, orcodata[p]);
1032 BKE_mesh_orco_verts_transform(static_cast<Mesh *>(ob->data), &co, 1, true);
1033 }
1034 else {
1035 copy_v3_v3(co, positions[p]);
1036 }
1037 BLI_kdtree_3d_insert(tree, p, co);
1038 }
1039
1040 BLI_kdtree_3d_balance(tree);
1041 }
1042 }
1043
1044 /* Get total number of emission elements and allocate needed arrays */
1045 totelem = (from == PART_FROM_VERT) ? mesh->verts_num : mesh->totface_legacy;
1046
1047 if (totelem == 0) {
1048 distribute_invalid(sim, children ? PART_FROM_CHILD : 0);
1049
1050 if (G.debug & G_DEBUG) {
1051 fprintf(stderr, "Particle distribution error: Nothing to emit from!\n");
1052 }
1053
1054 if (mesh != final_mesh) {
1055 BKE_id_free(nullptr, mesh);
1056 }
1057
1058 BLI_kdtree_3d_free(tree);
1059 BLI_rng_free(rng);
1060
1061 return 0;
1062 }
1063
1064 element_weight = MEM_calloc_arrayN<float>(totelem, "particle_distribution_weights");
1065 particle_element = MEM_calloc_arrayN<int>(totpart, "particle_distribution_indexes");
1066 jitter_offset = MEM_calloc_arrayN<float>(totelem, "particle_distribution_jitoff");
1067
1068 /* Calculate weights from face areas */
1069 if ((part->flag & PART_EDISTR || children) && from != PART_FROM_VERT) {
1070 float totarea = 0.0f, co1[3], co2[3], co3[3], co4[3];
1071 const float (*orcodata)[3];
1072
1073 orcodata = static_cast<const float (*)[3]>(CustomData_get_layer(&mesh->vert_data, CD_ORCO));
1074
1076 &mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy);
1077 for (i = 0; i < totelem; i++) {
1078 MFace *mf = &mfaces[i];
1079
1080 if (orcodata) {
1081 /* Transform orcos from normalized 0..1 to object space. */
1082 copy_v3_v3(co1, orcodata[mf->v1]);
1083 copy_v3_v3(co2, orcodata[mf->v2]);
1084 copy_v3_v3(co3, orcodata[mf->v3]);
1085 BKE_mesh_orco_verts_transform(static_cast<Mesh *>(ob->data), &co1, 1, true);
1086 BKE_mesh_orco_verts_transform(static_cast<Mesh *>(ob->data), &co2, 1, true);
1087 BKE_mesh_orco_verts_transform(static_cast<Mesh *>(ob->data), &co3, 1, true);
1088 if (mf->v4) {
1089 copy_v3_v3(co4, orcodata[mf->v4]);
1090 BKE_mesh_orco_verts_transform(static_cast<Mesh *>(ob->data), &co4, 1, true);
1091 }
1092 }
1093 else {
1094 blender::MutableSpan<blender::float3> positions = mesh->vert_positions_for_write();
1095 copy_v3_v3(co1, positions[mf->v1]);
1096 copy_v3_v3(co2, positions[mf->v2]);
1097 copy_v3_v3(co3, positions[mf->v3]);
1098 if (mf->v4) {
1099 copy_v3_v3(co4, positions[mf->v4]);
1100 }
1101 }
1102
1103 cur = mf->v4 ? area_quad_v3(co1, co2, co3, co4) : area_tri_v3(co1, co2, co3);
1104
1105 maxweight = std::max(cur, maxweight);
1106
1107 element_weight[i] = cur;
1108 totarea += cur;
1109 }
1110
1111 for (i = 0; i < totelem; i++) {
1112 element_weight[i] /= totarea;
1113 }
1114
1115 maxweight /= totarea;
1116 }
1117 else {
1118 float min = 1.0f / float(std::min(totelem, totpart));
1119 for (i = 0; i < totelem; i++) {
1120 element_weight[i] = min;
1121 }
1122 maxweight = min;
1123 }
1124
1125 /* Calculate weights from vgroup */
1126 vweight = psys_cache_vgroup(mesh, psys, PSYS_VG_DENSITY);
1127
1128 if (vweight) {
1129 if (from == PART_FROM_VERT) {
1130 for (i = 0; i < totelem; i++) {
1131 element_weight[i] *= vweight[i];
1132 }
1133 }
1134 else { /* PART_FROM_FACE / PART_FROM_VOLUME */
1136 &mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy);
1137 for (i = 0; i < totelem; i++) {
1138 MFace *mf = &mfaces[i];
1139 tweight = vweight[mf->v1] + vweight[mf->v2] + vweight[mf->v3];
1140
1141 if (mf->v4) {
1142 tweight += vweight[mf->v4];
1143 tweight /= 4.0f;
1144 }
1145 else {
1146 tweight /= 3.0f;
1147 }
1148
1149 element_weight[i] *= tweight;
1150 }
1151 }
1152 MEM_freeN(vweight);
1153 }
1154
1155 /* Calculate total weight of all elements */
1156 int totmapped = 0;
1157 totweight = 0.0f;
1158 for (i = 0; i < totelem; i++) {
1159 if (element_weight[i] > 0.0f) {
1160 totmapped++;
1161 totweight += element_weight[i];
1162 }
1163 }
1164
1165 if (totmapped == 0) {
1166 /* We are not allowed to distribute particles anywhere... */
1167 if (mesh != final_mesh) {
1168 BKE_id_free(nullptr, mesh);
1169 }
1170 BLI_kdtree_3d_free(tree);
1171 BLI_rng_free(rng);
1172 MEM_freeN(element_weight);
1173 MEM_freeN(particle_element);
1174 MEM_freeN(jitter_offset);
1175 return 0;
1176 }
1177
1178 inv_totweight = 1.0f / totweight;
1179
1180 /* Calculate cumulative weights.
1181 * We remove all null-weighted elements from element_sum, and create a new mapping
1182 * 'activ'_elem_index -> orig_elem_index.
1183 * This simplifies greatly the filtering of zero-weighted items - and can be much more efficient
1184 * especially in random case (reducing a lot the size of binary-searched array)...
1185 */
1186 float *element_sum = MEM_malloc_arrayN<float>(size_t(totmapped), __func__);
1187 int *element_map = MEM_malloc_arrayN<int>(size_t(totmapped), __func__);
1188 int i_mapped = 0;
1189
1190 for (i = 0; i < totelem && element_weight[i] == 0.0f; i++) {
1191 /* pass */
1192 }
1193 element_sum[i_mapped] = element_weight[i] * inv_totweight;
1194 element_map[i_mapped] = i;
1195 i_mapped++;
1196 for (i++; i < totelem; i++) {
1197 if (element_weight[i] > 0.0f) {
1198 element_sum[i_mapped] = element_sum[i_mapped - 1] + element_weight[i] * inv_totweight;
1199 /* Skip elements which weight is so small that it does not affect the sum. */
1200 if (element_sum[i_mapped] > element_sum[i_mapped - 1]) {
1201 element_map[i_mapped] = i;
1202 i_mapped++;
1203 }
1204 }
1205 }
1206 totmapped = i_mapped;
1207
1208 /* Finally assign elements to particles */
1209 if (part->flag & PART_TRAND) {
1210 for (p = 0; p < totpart; p++) {
1211 /* In theory element_sum[totmapped - 1] should be 1.0,
1212 * but due to float errors this is not necessarily always true, so scale pos accordingly. */
1213 const float pos = BLI_rng_get_float(rng) * element_sum[totmapped - 1];
1214 const int eidx = distribute_binary_search(element_sum, totmapped, pos);
1215 particle_element[p] = element_map[eidx];
1216 BLI_assert(pos <= element_sum[eidx]);
1217 BLI_assert(eidx ? (pos > element_sum[eidx - 1]) : (pos >= 0.0f));
1218 jitter_offset[particle_element[p]] = pos;
1219 }
1220 }
1221 else {
1222 double step, pos;
1223
1224 step = (totpart < 2) ? 0.5 : 1.0 / double(totpart);
1225 /* This is to address tricky issues with vertex-emitting when user tries
1226 * (and expects) exact 1-1 vert/part distribution (see #47983 and its two example files).
1227 * It allows us to consider pos as 'midpoint between v and v+1'
1228 * (or 'p and p+1', depending whether we have more vertices than particles or not),
1229 * and avoid stumbling over float impression in element_sum.
1230 * NOTE: moved face and volume distribution to this as well (instead of starting at zero),
1231 * for the same reasons, see #52682. */
1232 pos = (totpart < totmapped) ? 0.5 / double(totmapped) :
1233 step * 0.5; /* We choose the smaller step. */
1234
1235 for (i = 0, p = 0; p < totpart; p++, pos += step) {
1236 for (; (i < totmapped - 1) && (pos > double(element_sum[i])); i++) {
1237 /* pass */
1238 }
1239
1240 particle_element[p] = element_map[i];
1241
1242 jitter_offset[particle_element[p]] = pos;
1243 }
1244 }
1245
1246 MEM_freeN(element_sum);
1247 MEM_freeN(element_map);
1248
1249 /* For hair, sort by #CD_ORIGINDEX (allows optimization's in rendering),
1250 * however with virtual parents the children need to be in random order. */
1251 if (part->type == PART_HAIR && !(part->childtype == PART_CHILD_FACES && part->parents != 0.0f)) {
1252 const int *orig_index = nullptr;
1253
1254 if (from == PART_FROM_VERT) {
1255 if (mesh->verts_num) {
1256 orig_index = static_cast<const int *>(
1258 }
1259 }
1260 else {
1261 if (mesh->totface_legacy) {
1262 orig_index = static_cast<const int *>(
1264 }
1265 }
1266
1267 if (orig_index) {
1268 BLI_qsort_r(particle_element,
1269 totpart,
1270 sizeof(int),
1272 (void *)orig_index);
1273 }
1274 }
1275
1276 /* Create jittering if needed */
1277 if (distr == PART_DISTR_JIT && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
1278 jitlevel = part->userjit;
1279
1280 if (jitlevel == 0) {
1281 jitlevel = totpart / totelem;
1282 if (part->flag & PART_EDISTR) {
1283 jitlevel *= 2; /* looks better in general, not very scientific */
1284 }
1285 jitlevel = std::max(jitlevel, 3);
1286 }
1287
1288 jit = MEM_calloc_arrayN<float>(2 + size_t(jitlevel * 2), "jit");
1289
1290 /* for small amounts of particles we use regular jitter since it looks
1291 * a bit better, for larger amounts we switch to hammersley sequence
1292 * because it is much faster */
1293 if (jitlevel < 25) {
1294 init_mv_jit(jit, jitlevel, psys->seed, part->jitfac);
1295 }
1296 else {
1297 hammersley_create(jit, jitlevel + 1, psys->seed, part->jitfac);
1298 }
1300 jit, sizeof(float[2]), jitlevel, psys->seed); /* for custom jit or even distribution */
1301 }
1302
1303 /* Setup things for threaded distribution */
1304 ctx->tree = tree;
1305 ctx->seams = seams;
1306 ctx->totseam = totseam;
1307 ctx->sim.psys = psys;
1308 ctx->index = particle_element;
1309 ctx->jit = jit;
1310 ctx->jitlevel = jitlevel;
1311 ctx->jitoff = jitter_offset;
1312 ctx->weight = element_weight;
1313 ctx->maxweight = maxweight;
1314 ctx->cfrom = cfrom;
1315 ctx->distr = distr;
1316 ctx->mesh = mesh;
1317 ctx->tpars = tpars;
1318
1319 if (children) {
1320 alloc_child_particles(psys, totpart);
1321 }
1322
1323 BLI_rng_free(rng);
1324
1325 return 1;
1326}
1327
1329{
1330 /* init random number generator */
1331 int seed = 31415926 + sim->psys->seed;
1332
1333 task->rng = BLI_rng_new(seed);
1334}
1335
1337{
1339 Mesh *final_mesh = sim->psmd->mesh_final;
1340
1341 /* create a task pool for distribution tasks */
1342 if (!psys_thread_context_init_distribute(&ctx, sim, from)) {
1343 return;
1344 }
1345
1347
1348 const int totpart = (from == PART_FROM_CHILD ? sim->psys->totchild : sim->psys->totpart);
1349 blender::Vector<ParticleTask> tasks = psys_tasks_create(&ctx, 0, totpart);
1350 for (ParticleTask &task : tasks) {
1351 psys_task_init_distribute(&task, sim);
1352 if (from == PART_FROM_CHILD) {
1353 BLI_task_pool_push(task_pool, exec_distribute_child, &task, false, nullptr);
1354 }
1355 else {
1356 BLI_task_pool_push(task_pool, exec_distribute_parent, &task, false, nullptr);
1357 }
1358 }
1360
1362
1363 psys_calc_dmcache(sim->ob, final_mesh, sim->psmd->mesh_original, sim->psys);
1364
1365 if (ctx.mesh != final_mesh) {
1366 BKE_id_free(nullptr, ctx.mesh);
1367 }
1368
1369 psys_tasks_free(tasks);
1370
1372}
1373
1374/* ready for future use, to emit particles without geometry */
1376{
1377 distribute_invalid(sim, 0);
1378
1379 fprintf(stderr, "Shape emission not yet possible!\n");
1380}
1381
1383{
1385 int distr_error = 0;
1386
1387 if (psmd) {
1388 if (psmd->mesh_final) {
1389 distribute_particles_on_dm(sim, from);
1390 }
1391 else {
1392 distr_error = 1;
1393 }
1394 }
1395 else {
1397 }
1398
1399 if (distr_error) {
1400 distribute_invalid(sim, from);
1401
1402 fprintf(stderr, "Particle distribution error!\n");
1403 }
1404}
CustomData interface, see also DNA_customdata_types.h.
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
void * CustomData_get_layer_for_write(CustomData *data, eCustomDataType type, int totelem)
@ G_DEBUG
void BKE_id_free(Main *bmain, void *idv)
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:777
@ LIB_ID_COPY_LOCALIZE
void BKE_mesh_orco_verts_transform(Mesh *mesh, blender::MutableSpan< blender::float3 > orco, bool invert)
void BKE_mesh_orco_ensure(Object *ob, Mesh *mesh)
void BKE_mesh_texspace_ensure(Mesh *mesh)
void BKE_mesh_tessface_ensure(Mesh *mesh)
int psys_get_child_number(struct Scene *scene, struct ParticleSystem *psys, bool use_render_params)
void psys_thread_context_init(struct ParticleThreadContext *ctx, struct ParticleSimulationData *sim)
void psys_calc_dmcache(struct Object *ob, struct Mesh *mesh_final, struct Mesh *mesh_original, struct ParticleSystem *psys)
#define DMCACHE_NOTFOUND
float * psys_cache_vgroup(struct Mesh *mesh, struct ParticleSystem *psys, int vgroup)
Definition particle.cc:2579
void psys_thread_context_free(struct ParticleThreadContext *ctx)
int psys_get_tot_child(struct Scene *scene, struct ParticleSystem *psys, bool use_render_params)
void psys_particle_on_dm(struct Mesh *mesh_final, int from, int index, int index_dmcache, const float fw[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3], float orco[3])
Definition particle.cc:2021
void psys_interpolate_face(struct Mesh *mesh, const float(*vert_positions)[3], const float(*vert_normals)[3], const struct MFace *mface, struct MTFace *tface, const float(*orcodata)[3], float w[4], float vec[3], float nor[3], float utan[3], float vtan[3], float orco[3])
#define LOOP_PARTICLES
blender::Vector< ParticleTask > psys_tasks_create(struct ParticleThreadContext *ctx, int startpart, int endpart)
#define DMCACHE_ISCHILD
#define PARTICLE_PSMD
void psys_tasks_free(blender::Vector< ParticleTask > &tasks)
#define PARTICLE_P
BLI_INLINE float psys_frand(ParticleSystem *psys, unsigned int seed)
#define BLI_assert(a)
Definition BLI_assert.h:46
void BLI_jitterate1(float(*jit1)[2], float(*jit2)[2], int num, float radius1)
Definition jitter_2d.cc:19
void BLI_jitterate2(float(*jit1)[2], float(*jit2)[2], int num, float radius2)
Definition jitter_2d.cc:77
A KD-tree for nearest neighbor search.
void isect_ray_tri_watertight_v3_precalc(struct IsectRayPrecalc *isect_precalc, const float ray_direction[3])
bool isect_ray_tri_v3(const float ray_origin[3], const float ray_direction[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2])
MINLINE int axis_dominant_v3_single(const float vec[3])
float area_tri_v3(const float v1[3], const float v2[3], const float v3[3])
Definition math_geom.cc:100
bool isect_ray_tri_watertight_v3(const float ray_origin[3], const struct IsectRayPrecalc *isect_precalc, const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2])
float area_quad_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition math_geom.cc:85
void interp_weights_poly_v3(float w[], float v[][3], int n, const float co[3])
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3(float r[3])
MINLINE void zero_v4(float r[4])
MINLINE void zero_v3(float r[3])
MINLINE float normalize_v3(float n[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
ATTR_WARN_UNUSED_RESULT const size_t num
Random number functions.
struct RNG * BLI_rng_new(unsigned int seed)
Definition rand.cc:39
void BLI_rng_free(struct RNG *rng) ATTR_NONNULL(1)
Definition rand.cc:53
void BLI_hammersley_1d(unsigned int n, double *r)
Definition rand.cc:281
struct RNG * BLI_rng_new_srandom(unsigned int seed)
Definition rand.cc:46
double BLI_rng_get_double(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition rand.cc:83
void void void BLI_rng_skip(struct RNG *rng, int n) ATTR_NONNULL(1)
Definition rand.cc:141
float BLI_rng_get_float(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition rand.cc:88
void BLI_array_randomize(void *data, unsigned int elem_size, unsigned int elem_num, unsigned int seed)
Definition rand.cc:156
void BLI_qsort_r(void *a, size_t n, size_t es, BLI_sort_cmp_t cmp, void *thunk)
Definition sort.cc:77
unsigned int uint
@ TASK_PRIORITY_HIGH
Definition BLI_task.h:53
void BLI_task_pool_work_and_wait(TaskPool *pool)
Definition task_pool.cc:535
TaskPool * BLI_task_pool_create(void *userdata, eTaskPriority priority)
Definition task_pool.cc:484
void BLI_task_pool_free(TaskPool *pool)
Definition task_pool.cc:521
void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata)
Definition task_pool.cc:526
#define INIT_MINMAX(min, max)
#define ELEM(...)
@ DAG_EVAL_RENDER
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
@ PART_DISTR_GRID
@ PART_DISTR_RAND
@ PART_DISTR_JIT
@ PART_EDISTR
@ PART_GRID_HEXAGONAL
@ PART_GRID_INVERT
@ PART_TRAND
@ PART_HAIR
@ PARS_UNEXIST
@ PART_CHILD_FACES
@ PSYS_VG_DENSITY
@ PART_FROM_VOLUME
@ PART_FROM_CHILD
@ PART_FROM_VERT
@ PART_FROM_FACE
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
__forceinline BoundBox intersect(const BoundBox &a, const BoundBox &b)
Definition boundbox.h:184
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
static T sum(const btAlignedObjectArray< T > &items)
static unsigned long seed
Definition btSoftBody.h:39
constexpr const T * data() const
Definition BLI_span.hh:215
nullptr float
TaskPool * task_pool
KDTree_3d * tree
uint pos
blender::gpu::Batch * quad
uint nor
#define in
#define out
#define printf(...)
#define isnan
#define pow
#define floor
#define ceil
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
float length(VecOp< float, D >) RET
#define jit
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
ccl_device_inline float2 fmod(const float2 a, const float b)
#define G(x, y, z)
static void init_mv_jit(float *jit, int num, int seed2, float amount)
static void distribute_children_exec(ParticleTask *thread, ChildParticle *cpa, int p)
static void distribute_particles_on_shape(ParticleSimulationData *sim, int)
#define PSYS_RND_DIST_SKIP
static void exec_distribute_child(TaskPool *__restrict, void *taskdata)
static void psys_task_init_distribute(ParticleTask *task, ParticleSimulationData *sim)
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_from_verts_exec(ParticleTask *thread, ParticleData *pa, int p)
static void distribute_invalid(ParticleSimulationData *sim, int from)
static void distribute_from_volume_exec(ParticleTask *thread, ParticleData *pa, int p)
static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
static void distribute_from_faces_exec(ParticleTask *thread, ParticleData *pa, int p)
static void distribute_grid(Mesh *mesh, ParticleSystem *psys)
void distribute_particles(ParticleSimulationData *sim, int from)
static int distribute_binary_search(const float *sum, int n, float value)
static void exec_distribute_parent(TaskPool *__restrict, void *taskdata)
static void psys_uv_to_w(float u, float v, int quad, float *w)
static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, ParticleSimulationData *sim, int from)
static void hammersley_create(float *out, int n, int seed, float amount)
static void alloc_child_particles(ParticleSystem *psys, int tot)
static int distribute_compare_orig_index(const void *p1, const void *p2, void *user_data)
#define sqrtf
#define min(a, b)
Definition sort.cc:36
#define FLT_MAX
Definition stdcycles.h:14
Definition DNA_ID.h:414
unsigned int v2
unsigned int v1
unsigned int v4
unsigned int v3
MeshRuntimeHandle * runtime
CustomData vert_data
CustomData fdata_legacy
int totface_legacy
int verts_num
struct Depsgraph * depsgraph
struct ParticleSystemModifierData * psmd
struct Scene * scene
struct ParticleSystem * psys
struct Object * ob
ChildParticle * child
ParticleData * particles
ParticleSettings * part
ParticleThreadContext * ctx
struct RNG * rng
struct ParticleData * tpars
struct ParticleSeam * seams
struct ParticleSimulationData sim
struct KDTree_3d * tree
Definition rand.cc:33
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
uint8_t flag
Definition wm_window.cc:145