Blender V4.3
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
9#include <cstring>
10
11#include "MEM_guardedalloc.h"
12
13#include "BLI_jitter_2d.h"
14#include "BLI_kdtree.h"
15#include "BLI_math_geom.h"
16#include "BLI_rand.h"
17#include "BLI_sort.h"
18#include "BLI_task.h"
19#include "BLI_utildefines.h"
20
21#include "DNA_mesh_types.h"
22#include "DNA_meshdata_types.h"
23#include "DNA_modifier_types.h"
24#include "DNA_particle_types.h"
25
26#include "BKE_customdata.hh"
27#include "BKE_global.hh"
28#include "BKE_lib_id.hh"
29#include "BKE_mesh.hh"
31#include "BKE_particle.h"
32
34
35static void alloc_child_particles(ParticleSystem *psys, int tot)
36{
37 if (psys->child) {
38 /* only re-allocate if we have to */
39 if (psys->part->childtype && psys->totchild == tot) {
40 memset(psys->child, 0, tot * sizeof(ChildParticle));
41 return;
42 }
43
44 MEM_freeN(psys->child);
45 psys->child = nullptr;
46 psys->totchild = 0;
47 }
48
49 if (psys->part->childtype) {
50 psys->totchild = tot;
51 if (psys->totchild) {
52 psys->child = static_cast<ChildParticle *>(
53 MEM_callocN(psys->totchild * sizeof(ChildParticle), "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) {
105 INIT_MINMAX(min, max);
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))]
168 .flag &= ~PARS_UNEXIST;
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 *>(
181 CustomData_get_layer_for_write(&mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy));
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 = float(1.0f / sqrtf(float(num)));
351 rad2 = float(1.0f / float(num));
352 rad3 = float(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] -= float(floor(jit[i]));
363 jit[i + 1] -= float(floor(jit[i + 1]));
364
365 x += rad3;
366 x -= float(floor(x));
367 }
368
369 jit2 = static_cast<float *>(MEM_mallocN(12 + sizeof(float[2]) * num, "initjit"));
370
371 for (i = 0; i < 4; i++) {
372 BLI_jitterate1((float(*)[2])jit, (float(*)[2])jit2, num, rad1);
373 BLI_jitterate1((float(*)[2])jit, (float(*)[2])jit2, num, rad1);
374 BLI_jitterate2((float(*)[2])jit, (float(*)[2])jit2, num, rad2);
375 }
376 MEM_freeN(jit2);
377 BLI_rng_free(rng);
378}
379
380static void psys_uv_to_w(float u, float v, int quad, float *w)
381{
382 float vert[4][3], co[3];
383
384 if (!quad) {
385 if (u + v > 1.0f) {
386 v = 1.0f - v;
387 }
388 else {
389 u = 1.0f - u;
390 }
391 }
392
393 vert[0][0] = 0.0f;
394 vert[0][1] = 0.0f;
395 vert[0][2] = 0.0f;
396 vert[1][0] = 1.0f;
397 vert[1][1] = 0.0f;
398 vert[1][2] = 0.0f;
399 vert[2][0] = 1.0f;
400 vert[2][1] = 1.0f;
401 vert[2][2] = 0.0f;
402
403 co[0] = u;
404 co[1] = v;
405 co[2] = 0.0f;
406
407 if (quad) {
408 vert[3][0] = 0.0f;
409 vert[3][1] = 1.0f;
410 vert[3][2] = 0.0f;
411 interp_weights_poly_v3(w, vert, 4, co);
412 }
413 else {
414 interp_weights_poly_v3(w, vert, 3, co);
415 w[3] = 0.0f;
416 }
417}
418
419/* Find the index in "sum" array before "value" is crossed. */
420static int distribute_binary_search(const float *sum, int n, float value)
421{
422 int mid, low = 0, high = n - 1;
423
424 if (high == low) {
425 return low;
426 }
427
428 if (sum[low] >= value) {
429 return low;
430 }
431
432 if (sum[high - 1] < value) {
433 return high;
434 }
435
436 while (low < high) {
437 mid = (low + high) / 2;
438
439 if ((sum[mid] >= value) && (sum[mid - 1] < value)) {
440 return mid;
441 }
442
443 if (sum[mid] > value) {
444 high = mid - 1;
445 }
446 else {
447 low = mid + 1;
448 }
449 }
450
451 return low;
452}
453
454/* the max number if calls to rng_* functions within psys_thread_distribute_particle
455 * be sure to keep up to date if this changes */
456#define PSYS_RND_DIST_SKIP 3
457
458/* NOTE: this function must be thread safe, for `from == PART_FROM_CHILD`. */
459#define ONLY_WORKING_WITH_PA_VERTS 0
461{
462 ParticleThreadContext *ctx = thread->ctx;
463 MFace *mface;
464
465 mface = static_cast<MFace *>(CustomData_get_layer_for_write(
467
468 int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls won't need skipping */
469
470 /* TODO_PARTICLE - use original index */
471 pa->num = ctx->index[p];
472
473 zero_v4(pa->fuv);
474
475 if (pa->num != DMCACHE_NOTFOUND && pa->num < ctx->mesh->verts_num) {
476
477 /* This finds the first face to contain the emitting vertex,
478 * this is not ideal, but is mostly fine as UV seams generally
479 * map to equal-colored parts of a texture */
480 for (int i = 0; i < ctx->mesh->totface_legacy; i++, mface++) {
481 if (ELEM(pa->num, mface->v1, mface->v2, mface->v3, mface->v4)) {
482 uint *vert = &mface->v1;
483
484 for (int j = 0; j < 4; j++, vert++) {
485 if (*vert == pa->num) {
486 pa->fuv[j] = 1.0f;
487 break;
488 }
489 }
490
491 break;
492 }
493 }
494 }
495
496#if ONLY_WORKING_WITH_PA_VERTS
497 if (ctx->tree) {
498 KDTreeNearest_3d ptn[3];
499 int w, maxw;
500
502 ctx->mesh, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, orco1, 0);
503 BKE_mesh_orco_verts_transform(ob->data, &orco1, 1, true);
504 maxw = BLI_kdtree_3d_find_nearest_n(ctx->tree, orco1, ptn, 3);
505
506 for (w = 0; w < maxw; w++) {
507 pa->verts[w] = ptn->num;
508 }
509 }
510#endif
511
512 BLI_assert(rng_skip_tot >= 0); /* should never be below zero */
513 if (rng_skip_tot > 0) {
514 BLI_rng_skip(thread->rng, rng_skip_tot);
515 }
516}
517
519{
520 ParticleThreadContext *ctx = thread->ctx;
521 Mesh *mesh = ctx->mesh;
522 float randu, randv;
523 int distr = ctx->distr;
524 int i;
525 int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls won't need skipping */
526
528 &mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy);
529 MFace *mface;
530
531 pa->num = i = ctx->index[p];
532 mface = &mfaces[i];
533
534 switch (distr) {
535 case PART_DISTR_JIT:
536 if (ctx->jitlevel == 1) {
537 if (mface->v4) {
538 psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv);
539 }
540 else {
541 psys_uv_to_w(1.0f / 3.0f, 1.0f / 3.0f, mface->v4, pa->fuv);
542 }
543 }
544 else {
545 float offset = fmod(ctx->jitoff[i] + float(p), float(ctx->jitlevel));
546 if (!isnan(offset)) {
548 ctx->jit[2 * int(offset)], ctx->jit[2 * int(offset) + 1], mface->v4, pa->fuv);
549 }
550 }
551 break;
552 case PART_DISTR_RAND:
553 randu = BLI_rng_get_float(thread->rng);
554 randv = BLI_rng_get_float(thread->rng);
555 rng_skip_tot -= 2;
556
557 psys_uv_to_w(randu, randv, mface->v4, pa->fuv);
558 break;
559 }
560 pa->foffset = 0.0f;
561
562 BLI_assert(rng_skip_tot >= 0); /* should never be below zero */
563 if (rng_skip_tot > 0) {
564 BLI_rng_skip(thread->rng, rng_skip_tot);
565 }
566}
567
569{
570 ParticleThreadContext *ctx = thread->ctx;
571 Mesh *mesh = ctx->mesh;
572 const float *v1, *v2, *v3, *v4;
573 float nor[3], co[3];
574 float cur_d, min_d, randu, randv;
575 int distr = ctx->distr;
576 int i, intersect, tot;
577 int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls won't need skipping */
578
579 MFace *mface;
580 const blender::Span<blender::float3> positions = mesh->vert_positions();
581
582 pa->num = i = ctx->index[p];
584 &mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy);
585 mface = &mfaces[i];
586
587 switch (distr) {
588 case PART_DISTR_JIT:
589 if (ctx->jitlevel == 1) {
590 if (mface->v4) {
591 psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv);
592 }
593 else {
594 psys_uv_to_w(1.0f / 3.0f, 1.0f / 3.0f, mface->v4, pa->fuv);
595 }
596 }
597 else {
598 float offset = fmod(ctx->jitoff[i] + float(p), float(ctx->jitlevel));
599 if (!isnan(offset)) {
601 ctx->jit[2 * int(offset)], ctx->jit[2 * int(offset) + 1], mface->v4, pa->fuv);
602 }
603 }
604 break;
605 case PART_DISTR_RAND:
606 randu = BLI_rng_get_float(thread->rng);
607 randv = BLI_rng_get_float(thread->rng);
608 rng_skip_tot -= 2;
609
610 psys_uv_to_w(randu, randv, mface->v4, pa->fuv);
611 break;
612 }
613 pa->foffset = 0.0f;
614
615 /* experimental */
616 tot = mesh->totface_legacy;
617
619 reinterpret_cast<const float(*)[3]>(positions.data()),
620 reinterpret_cast<const float(*)[3]>(mesh->vert_normals().data()),
621 mface,
622 nullptr,
623 nullptr,
624 pa->fuv,
625 co,
626 nor,
627 nullptr,
628 nullptr,
629 nullptr);
630
632 negate_v3(nor);
633
634 min_d = FLT_MAX;
635 intersect = 0;
636 mface = static_cast<MFace *>(
637 CustomData_get_layer_for_write(&mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy));
638 for (i = 0; i < tot; i++, mface++) {
639 if (i == pa->num) {
640 continue;
641 }
642
643 v1 = positions[mface->v1];
644 v2 = positions[mface->v2];
645 v3 = positions[mface->v3];
646
647 if (isect_ray_tri_v3(co, nor, v2, v3, v1, &cur_d, nullptr)) {
648 if (cur_d < min_d) {
649 min_d = cur_d;
650 pa->foffset = cur_d * 0.5f; /* to the middle of volume */
651 intersect = 1;
652 }
653 }
654 if (mface->v4) {
655 v4 = positions[mface->v4];
656
657 if (isect_ray_tri_v3(co, nor, v4, v1, v3, &cur_d, nullptr)) {
658 if (cur_d < min_d) {
659 min_d = cur_d;
660 pa->foffset = cur_d * 0.5f; /* to the middle of volume */
661 intersect = 1;
662 }
663 }
664 }
665 }
666 if (intersect == 0) {
667 pa->foffset = 0.0;
668 }
669 else {
670 switch (distr) {
671 case PART_DISTR_JIT:
672 pa->foffset *= ctx->jit[p % (2 * ctx->jitlevel)];
673 break;
674 case PART_DISTR_RAND:
675 pa->foffset *= BLI_rng_get_float(thread->rng);
676 rng_skip_tot--;
677 break;
678 }
679 }
680
681 BLI_assert(rng_skip_tot >= 0); /* should never be below zero */
682 if (rng_skip_tot > 0) {
683 BLI_rng_skip(thread->rng, rng_skip_tot);
684 }
685}
686
688{
689 ParticleThreadContext *ctx = thread->ctx;
690 Object *ob = ctx->sim.ob;
691 Mesh *mesh = ctx->mesh;
692 float orco1[3], co1[3], nor1[3];
693 float randu, randv;
694 int cfrom = ctx->cfrom;
695 int i;
696 int rng_skip_tot = PSYS_RND_DIST_SKIP; /* count how many rng_* calls won't need skipping */
697
698 MFace *mf;
699
700 if (ctx->index[p] < 0) {
701 cpa->num = 0;
702 cpa->fuv[0] = cpa->fuv[1] = cpa->fuv[2] = cpa->fuv[3] = 0.0f;
703 cpa->pa[0] = cpa->pa[1] = cpa->pa[2] = cpa->pa[3] = 0;
704 return;
705 }
706
708 &mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy);
709 mf = &mfaces[ctx->index[p]];
710
711 randu = BLI_rng_get_float(thread->rng);
712 randv = BLI_rng_get_float(thread->rng);
713 rng_skip_tot -= 2;
714
715 psys_uv_to_w(randu, randv, mf->v4, cpa->fuv);
716
717 cpa->num = ctx->index[p];
718
719 if (ctx->tree) {
720 KDTreeNearest_3d ptn[10];
721 int w, maxw; //, do_seams;
722 float maxd /*, mind,dd */, totw = 0.0f;
723 int parent[10];
724 float pweight[10];
725
727 cfrom,
728 cpa->num,
730 cpa->fuv,
731 cpa->foffset,
732 co1,
733 nor1,
734 nullptr,
735 nullptr,
736 orco1);
737 BKE_mesh_orco_verts_transform(static_cast<Mesh *>(ob->data), &orco1, 1, true);
738 maxw = BLI_kdtree_3d_find_nearest_n(ctx->tree, orco1, ptn, 3);
739
740 maxd = ptn[maxw - 1].dist;
741 // mind=ptn[0].dist; /* UNUSED */
742
743 /* the weights here could be done better */
744 for (w = 0; w < maxw; w++) {
745 parent[w] = ptn[w].index;
746 pweight[w] = float(pow(2.0, double(-6.0f * ptn[w].dist / maxd)));
747 }
748 for (; w < 10; w++) {
749 parent[w] = -1;
750 pweight[w] = 0.0f;
751 }
752
753 for (w = 0, i = 0; w < maxw && i < 4; w++) {
754 if (parent[w] >= 0) {
755 cpa->pa[i] = parent[w];
756 cpa->w[i] = pweight[w];
757 totw += pweight[w];
758 i++;
759 }
760 }
761 for (; i < 4; i++) {
762 cpa->pa[i] = -1;
763 cpa->w[i] = 0.0f;
764 }
765
766 if (totw > 0.0f) {
767 for (w = 0; w < 4; w++) {
768 cpa->w[w] /= totw;
769 }
770 }
771
772 cpa->parent = cpa->pa[0];
773 }
774
775 if (rng_skip_tot > 0) { /* should never be below zero */
776 BLI_rng_skip(thread->rng, rng_skip_tot);
777 }
778}
779
780static void exec_distribute_parent(TaskPool *__restrict /*pool*/, void *taskdata)
781{
782 ParticleTask *task = static_cast<ParticleTask *>(taskdata);
783 ParticleSystem *psys = task->ctx->sim.psys;
784 ParticleData *pa;
785 int p;
786
787 BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->begin);
788
789 pa = psys->particles + task->begin;
790 switch (psys->part->from) {
791 case PART_FROM_FACE:
792 for (p = task->begin; p < task->end; p++, pa++) {
793 distribute_from_faces_exec(task, pa, p);
794 }
795 break;
796 case PART_FROM_VOLUME:
797 for (p = task->begin; p < task->end; p++, pa++) {
798 distribute_from_volume_exec(task, pa, p);
799 }
800 break;
801 case PART_FROM_VERT:
802 for (p = task->begin; p < task->end; p++, pa++) {
803 distribute_from_verts_exec(task, pa, p);
804 }
805 break;
806 }
807}
808
809static void exec_distribute_child(TaskPool *__restrict /*pool*/, void *taskdata)
810{
811 ParticleTask *task = static_cast<ParticleTask *>(taskdata);
812 ParticleSystem *psys = task->ctx->sim.psys;
813 ChildParticle *cpa;
814 int p;
815
816 /* RNG skipping at the beginning */
817 cpa = psys->child;
818 for (p = 0; p < task->begin; p++, cpa++) {
820 }
821
822 for (; p < task->end; p++, cpa++) {
823 distribute_children_exec(task, cpa, p);
824 }
825}
826
827static int distribute_compare_orig_index(const void *p1, const void *p2, void *user_data)
828{
829 const int *orig_index = (const int *)user_data;
830 int index1 = orig_index[*(const int *)p1];
831 int index2 = orig_index[*(const int *)p2];
832
833 if (index1 < index2) {
834 return -1;
835 }
836 if (index1 == index2) {
837 /* This pointer comparison appears to make #qsort stable for GLIBC,
838 * and apparently on SOLARIS too, makes the renders reproducible. */
839 if (p1 < p2) {
840 return -1;
841 }
842 if (p1 == p2) {
843 return 0;
844 }
845
846 return 1;
847 }
848
849 return 1;
850}
851
853{
854 Scene *scene = sim->scene;
855 ParticleSystem *psys = sim->psys;
856 const bool use_render_params = (DEG_get_mode(sim->depsgraph) == DAG_EVAL_RENDER);
857
858 if (from == PART_FROM_CHILD) {
859 ChildParticle *cpa;
860 int p, totchild = psys_get_tot_child(scene, psys, use_render_params);
861
862 if (psys->child && totchild) {
863 for (p = 0, cpa = psys->child; p < totchild; p++, cpa++) {
864 cpa->fuv[0] = cpa->fuv[1] = cpa->fuv[2] = cpa->fuv[3] = 0.0;
865 cpa->foffset = 0.0f;
866 cpa->parent = 0;
867 cpa->pa[0] = cpa->pa[1] = cpa->pa[2] = cpa->pa[3] = 0;
868 cpa->num = -1;
869 }
870 }
871 }
872 else {
875 {
876 pa->fuv[0] = pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0;
877 pa->foffset = 0.0f;
878 pa->num = -1;
879 }
880 }
881}
882
883/* Creates a distribution of coordinates on a Mesh */
886 int from)
887{
888 Scene *scene = sim->scene;
889 Mesh *final_mesh = sim->psmd->mesh_final;
890 Object *ob = sim->ob;
891 ParticleSystem *psys = sim->psys;
892 ParticleData *pa = nullptr, *tpars = nullptr;
893 ParticleSettings *part;
894 ParticleSeam *seams = nullptr;
895 KDTree_3d *tree = nullptr;
896 Mesh *mesh = nullptr;
897 float *jit = nullptr;
898 int i, p = 0;
899 int cfrom = 0;
900 int totelem = 0, totpart, *particle_element = nullptr, children = 0, totseam = 0;
901 int jitlevel = 1, distr;
902 float *element_weight = nullptr, *jitter_offset = nullptr, *vweight = nullptr;
903 float cur, maxweight = 0.0, tweight, totweight, inv_totweight, co[3], nor[3], orco[3];
904 RNG *rng = nullptr;
905
906 if (ELEM(nullptr, ob, psys, psys->part)) {
907 return 0;
908 }
909
910 part = psys->part;
911 totpart = psys->totpart;
912 if (totpart == 0) {
913 return 0;
914 }
915
916 if (!final_mesh->runtime->deformed_only &&
918 {
919 printf(
920 "Can't create particles with the current modifier stack, disable destructive modifiers\n");
921 // XXX error("Can't paint with the current modifier stack, disable destructive modifiers");
922 return 0;
923 }
924
925 /* XXX This distribution code is totally broken in case from == PART_FROM_CHILD,
926 * it's always using `final_mesh` even if use_modifier_stack is unset...
927 * But making things consistent here break all existing edited
928 * hair systems, so better wait for complete rewrite. */
929
930 psys_thread_context_init(ctx, sim);
931
932 const bool use_render_params = (DEG_get_mode(sim->depsgraph) == DAG_EVAL_RENDER);
933
934 /* First handle special cases */
935 if (from == PART_FROM_CHILD) {
936 /* Simple children */
937 if (part->childtype != PART_CHILD_FACES) {
939 scene, ob, final_mesh, sim->psmd->mesh_original, psys, use_render_params);
940 return 0;
941 }
942 }
943 else {
944 /* Grid distribution */
945 if (part->distr == PART_DISTR_GRID && from != PART_FROM_VERT) {
946 if (psys->part->use_modifier_stack) {
947 mesh = final_mesh;
948 }
949 else {
950 mesh = (Mesh *)BKE_id_copy_ex(
951 nullptr, static_cast<const ID *>(ob->data), nullptr, LIB_ID_COPY_LOCALIZE);
952 }
954
955 distribute_grid(mesh, psys);
956
957 if (mesh != final_mesh) {
958 BKE_id_free(nullptr, mesh);
959 }
960
961 return 0;
962 }
963 }
964
965 /* After this #BKE_mesh_orco_verts_transform can be used safely from multiple threads. */
966 BKE_mesh_texspace_ensure(final_mesh);
967
968 /* Create trees and original coordinates if needed */
969 if (from == PART_FROM_CHILD) {
970 distr = PART_DISTR_RAND;
971 rng = BLI_rng_new_srandom(31415926 + psys->seed + psys->child_seed);
972 mesh = final_mesh;
973
974 /* BMESH ONLY */
976
977 children = 1;
978
979 tree = BLI_kdtree_3d_new(totpart);
980
981 for (p = 0, pa = psys->particles; p < totpart; p++, pa++) {
983 part->from,
984 pa->num,
985 pa->num_dmcache,
986 pa->fuv,
987 pa->foffset,
988 co,
989 nor,
990 nullptr,
991 nullptr,
992 orco);
993 BKE_mesh_orco_verts_transform(static_cast<Mesh *>(ob->data), &orco, 1, true);
994 BLI_kdtree_3d_insert(tree, p, orco);
995 }
996
997 BLI_kdtree_3d_balance(tree);
998
999 totpart = psys_get_tot_child(scene, psys, use_render_params);
1000 cfrom = from = PART_FROM_FACE;
1001 }
1002 else {
1003 distr = part->distr;
1004
1005 rng = BLI_rng_new_srandom(31415926 + psys->seed);
1006
1007 if (psys->part->use_modifier_stack) {
1008 mesh = final_mesh;
1009 }
1010 else {
1011 mesh = (Mesh *)BKE_id_copy_ex(
1012 nullptr, static_cast<const ID *>(ob->data), nullptr, LIB_ID_COPY_LOCALIZE);
1013 }
1014
1016
1017 /* we need orco for consistent distributions */
1018 BKE_mesh_orco_ensure(ob, mesh);
1019
1020 if (from == PART_FROM_VERT) {
1021 const blender::Span<blender::float3> positions = mesh->vert_positions();
1022 const float(*orcodata)[3] = static_cast<const float(*)[3]>(
1023 CustomData_get_layer(&mesh->vert_data, CD_ORCO));
1024 int totvert = mesh->verts_num;
1025
1026 tree = BLI_kdtree_3d_new(totvert);
1027
1028 for (p = 0; p < totvert; p++) {
1029 if (orcodata) {
1030 copy_v3_v3(co, orcodata[p]);
1031 BKE_mesh_orco_verts_transform(static_cast<Mesh *>(ob->data), &co, 1, true);
1032 }
1033 else {
1034 copy_v3_v3(co, positions[p]);
1035 }
1036 BLI_kdtree_3d_insert(tree, p, co);
1037 }
1038
1039 BLI_kdtree_3d_balance(tree);
1040 }
1041 }
1042
1043 /* Get total number of emission elements and allocate needed arrays */
1044 totelem = (from == PART_FROM_VERT) ? mesh->verts_num : mesh->totface_legacy;
1045
1046 if (totelem == 0) {
1047 distribute_invalid(sim, children ? PART_FROM_CHILD : 0);
1048
1049 if (G.debug & G_DEBUG) {
1050 fprintf(stderr, "Particle distribution error: Nothing to emit from!\n");
1051 }
1052
1053 if (mesh != final_mesh) {
1054 BKE_id_free(nullptr, mesh);
1055 }
1056
1057 BLI_kdtree_3d_free(tree);
1058 BLI_rng_free(rng);
1059
1060 return 0;
1061 }
1062
1063 element_weight = static_cast<float *>(
1064 MEM_callocN(sizeof(float) * totelem, "particle_distribution_weights"));
1065 particle_element = static_cast<int *>(
1066 MEM_callocN(sizeof(int) * totpart, "particle_distribution_indexes"));
1067 jitter_offset = static_cast<float *>(
1068 MEM_callocN(sizeof(float) * totelem, "particle_distribution_jitoff"));
1069
1070 /* Calculate weights from face areas */
1071 if ((part->flag & PART_EDISTR || children) && from != PART_FROM_VERT) {
1072 float totarea = 0.0f, co1[3], co2[3], co3[3], co4[3];
1073 const float(*orcodata)[3];
1074
1075 orcodata = static_cast<const float(*)[3]>(CustomData_get_layer(&mesh->vert_data, CD_ORCO));
1076
1078 &mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy);
1079 for (i = 0; i < totelem; i++) {
1080 MFace *mf = &mfaces[i];
1081
1082 if (orcodata) {
1083 /* Transform orcos from normalized 0..1 to object space. */
1084 copy_v3_v3(co1, orcodata[mf->v1]);
1085 copy_v3_v3(co2, orcodata[mf->v2]);
1086 copy_v3_v3(co3, orcodata[mf->v3]);
1087 BKE_mesh_orco_verts_transform(static_cast<Mesh *>(ob->data), &co1, 1, true);
1088 BKE_mesh_orco_verts_transform(static_cast<Mesh *>(ob->data), &co2, 1, true);
1089 BKE_mesh_orco_verts_transform(static_cast<Mesh *>(ob->data), &co3, 1, true);
1090 if (mf->v4) {
1091 copy_v3_v3(co4, orcodata[mf->v4]);
1092 BKE_mesh_orco_verts_transform(static_cast<Mesh *>(ob->data), &co4, 1, true);
1093 }
1094 }
1095 else {
1096 blender::MutableSpan<blender::float3> positions = mesh->vert_positions_for_write();
1097 copy_v3_v3(co1, positions[mf->v1]);
1098 copy_v3_v3(co2, positions[mf->v2]);
1099 copy_v3_v3(co3, positions[mf->v3]);
1100 if (mf->v4) {
1101 copy_v3_v3(co4, positions[mf->v4]);
1102 }
1103 }
1104
1105 cur = mf->v4 ? area_quad_v3(co1, co2, co3, co4) : area_tri_v3(co1, co2, co3);
1106
1107 if (cur > maxweight) {
1108 maxweight = cur;
1109 }
1110
1111 element_weight[i] = cur;
1112 totarea += cur;
1113 }
1114
1115 for (i = 0; i < totelem; i++) {
1116 element_weight[i] /= totarea;
1117 }
1118
1119 maxweight /= totarea;
1120 }
1121 else {
1122 float min = 1.0f / float(std::min(totelem, totpart));
1123 for (i = 0; i < totelem; i++) {
1124 element_weight[i] = min;
1125 }
1126 maxweight = min;
1127 }
1128
1129 /* Calculate weights from vgroup */
1130 vweight = psys_cache_vgroup(mesh, psys, PSYS_VG_DENSITY);
1131
1132 if (vweight) {
1133 if (from == PART_FROM_VERT) {
1134 for (i = 0; i < totelem; i++) {
1135 element_weight[i] *= vweight[i];
1136 }
1137 }
1138 else { /* PART_FROM_FACE / PART_FROM_VOLUME */
1140 &mesh->fdata_legacy, CD_MFACE, mesh->totface_legacy);
1141 for (i = 0; i < totelem; i++) {
1142 MFace *mf = &mfaces[i];
1143 tweight = vweight[mf->v1] + vweight[mf->v2] + vweight[mf->v3];
1144
1145 if (mf->v4) {
1146 tweight += vweight[mf->v4];
1147 tweight /= 4.0f;
1148 }
1149 else {
1150 tweight /= 3.0f;
1151 }
1152
1153 element_weight[i] *= tweight;
1154 }
1155 }
1156 MEM_freeN(vweight);
1157 }
1158
1159 /* Calculate total weight of all elements */
1160 int totmapped = 0;
1161 totweight = 0.0f;
1162 for (i = 0; i < totelem; i++) {
1163 if (element_weight[i] > 0.0f) {
1164 totmapped++;
1165 totweight += element_weight[i];
1166 }
1167 }
1168
1169 if (totmapped == 0) {
1170 /* We are not allowed to distribute particles anywhere... */
1171 if (mesh != final_mesh) {
1172 BKE_id_free(nullptr, mesh);
1173 }
1174 BLI_kdtree_3d_free(tree);
1175 BLI_rng_free(rng);
1176 MEM_freeN(element_weight);
1177 MEM_freeN(particle_element);
1178 MEM_freeN(jitter_offset);
1179 return 0;
1180 }
1181
1182 inv_totweight = 1.0f / totweight;
1183
1184 /* Calculate cumulative weights.
1185 * We remove all null-weighted elements from element_sum, and create a new mapping
1186 * 'activ'_elem_index -> orig_elem_index.
1187 * This simplifies greatly the filtering of zero-weighted items - and can be much more efficient
1188 * especially in random case (reducing a lot the size of binary-searched array)...
1189 */
1190 float *element_sum = static_cast<float *>(
1191 MEM_mallocN(sizeof(*element_sum) * totmapped, __func__));
1192 int *element_map = static_cast<int *>(MEM_mallocN(sizeof(*element_map) * totmapped, __func__));
1193 int i_mapped = 0;
1194
1195 for (i = 0; i < totelem && element_weight[i] == 0.0f; i++) {
1196 /* pass */
1197 }
1198 element_sum[i_mapped] = element_weight[i] * inv_totweight;
1199 element_map[i_mapped] = i;
1200 i_mapped++;
1201 for (i++; i < totelem; i++) {
1202 if (element_weight[i] > 0.0f) {
1203 element_sum[i_mapped] = element_sum[i_mapped - 1] + element_weight[i] * inv_totweight;
1204 /* Skip elements which weight is so small that it does not affect the sum. */
1205 if (element_sum[i_mapped] > element_sum[i_mapped - 1]) {
1206 element_map[i_mapped] = i;
1207 i_mapped++;
1208 }
1209 }
1210 }
1211 totmapped = i_mapped;
1212
1213 /* Finally assign elements to particles */
1214 if (part->flag & PART_TRAND) {
1215 for (p = 0; p < totpart; p++) {
1216 /* In theory element_sum[totmapped - 1] should be 1.0,
1217 * but due to float errors this is not necessarily always true, so scale pos accordingly. */
1218 const float pos = BLI_rng_get_float(rng) * element_sum[totmapped - 1];
1219 const int eidx = distribute_binary_search(element_sum, totmapped, pos);
1220 particle_element[p] = element_map[eidx];
1221 BLI_assert(pos <= element_sum[eidx]);
1222 BLI_assert(eidx ? (pos > element_sum[eidx - 1]) : (pos >= 0.0f));
1223 jitter_offset[particle_element[p]] = pos;
1224 }
1225 }
1226 else {
1227 double step, pos;
1228
1229 step = (totpart < 2) ? 0.5 : 1.0 / double(totpart);
1230 /* This is to address tricky issues with vertex-emitting when user tries
1231 * (and expects) exact 1-1 vert/part distribution (see #47983 and its two example files).
1232 * It allows us to consider pos as 'midpoint between v and v+1'
1233 * (or 'p and p+1', depending whether we have more vertices than particles or not),
1234 * and avoid stumbling over float impression in element_sum.
1235 * NOTE: moved face and volume distribution to this as well (instead of starting at zero),
1236 * for the same reasons, see #52682. */
1237 pos = (totpart < totmapped) ? 0.5 / double(totmapped) :
1238 step * 0.5; /* We choose the smaller step. */
1239
1240 for (i = 0, p = 0; p < totpart; p++, pos += step) {
1241 for (; (i < totmapped - 1) && (pos > double(element_sum[i])); i++) {
1242 /* pass */
1243 }
1244
1245 particle_element[p] = element_map[i];
1246
1247 jitter_offset[particle_element[p]] = pos;
1248 }
1249 }
1250
1251 MEM_freeN(element_sum);
1252 MEM_freeN(element_map);
1253
1254 /* For hair, sort by #CD_ORIGINDEX (allows optimization's in rendering),
1255 * however with virtual parents the children need to be in random order. */
1256 if (part->type == PART_HAIR && !(part->childtype == PART_CHILD_FACES && part->parents != 0.0f)) {
1257 const int *orig_index = nullptr;
1258
1259 if (from == PART_FROM_VERT) {
1260 if (mesh->verts_num) {
1261 orig_index = static_cast<const int *>(
1262 CustomData_get_layer(&mesh->vert_data, CD_ORIGINDEX));
1263 }
1264 }
1265 else {
1266 if (mesh->totface_legacy) {
1267 orig_index = static_cast<const int *>(
1268 CustomData_get_layer(&mesh->fdata_legacy, CD_ORIGINDEX));
1269 }
1270 }
1271
1272 if (orig_index) {
1273 BLI_qsort_r(particle_element,
1274 totpart,
1275 sizeof(int),
1277 (void *)orig_index);
1278 }
1279 }
1280
1281 /* Create jittering if needed */
1282 if (distr == PART_DISTR_JIT && ELEM(from, PART_FROM_FACE, PART_FROM_VOLUME)) {
1283 jitlevel = part->userjit;
1284
1285 if (jitlevel == 0) {
1286 jitlevel = totpart / totelem;
1287 if (part->flag & PART_EDISTR) {
1288 jitlevel *= 2; /* looks better in general, not very scientific */
1289 }
1290 if (jitlevel < 3) {
1291 jitlevel = 3;
1292 }
1293 }
1294
1295 jit = static_cast<float *>(MEM_callocN((2 + jitlevel * 2) * sizeof(float), "jit"));
1296
1297 /* for small amounts of particles we use regular jitter since it looks
1298 * a bit better, for larger amounts we switch to hammersley sequence
1299 * because it is much faster */
1300 if (jitlevel < 25) {
1301 init_mv_jit(jit, jitlevel, psys->seed, part->jitfac);
1302 }
1303 else {
1304 hammersley_create(jit, jitlevel + 1, psys->seed, part->jitfac);
1305 }
1307 jit, sizeof(float[2]), jitlevel, psys->seed); /* for custom jit or even distribution */
1308 }
1309
1310 /* Setup things for threaded distribution */
1311 ctx->tree = tree;
1312 ctx->seams = seams;
1313 ctx->totseam = totseam;
1314 ctx->sim.psys = psys;
1315 ctx->index = particle_element;
1316 ctx->jit = jit;
1317 ctx->jitlevel = jitlevel;
1318 ctx->jitoff = jitter_offset;
1319 ctx->weight = element_weight;
1320 ctx->maxweight = maxweight;
1321 ctx->cfrom = cfrom;
1322 ctx->distr = distr;
1323 ctx->mesh = mesh;
1324 ctx->tpars = tpars;
1325
1326 if (children) {
1327 alloc_child_particles(psys, totpart);
1328 }
1329
1330 BLI_rng_free(rng);
1331
1332 return 1;
1333}
1334
1336{
1337 /* init random number generator */
1338 int seed = 31415926 + sim->psys->seed;
1339
1340 task->rng = BLI_rng_new(seed);
1341}
1342
1344{
1347 ParticleTask *tasks;
1348 Mesh *final_mesh = sim->psmd->mesh_final;
1349 int i, totpart, numtasks;
1350
1351 /* create a task pool for distribution tasks */
1352 if (!psys_thread_context_init_distribute(&ctx, sim, from)) {
1353 return;
1354 }
1355
1357
1358 totpart = (from == PART_FROM_CHILD ? sim->psys->totchild : sim->psys->totpart);
1359 psys_tasks_create(&ctx, 0, totpart, &tasks, &numtasks);
1360 for (i = 0; i < numtasks; i++) {
1361 ParticleTask *task = &tasks[i];
1362
1363 psys_task_init_distribute(task, sim);
1364 if (from == PART_FROM_CHILD) {
1365 BLI_task_pool_push(task_pool, exec_distribute_child, task, false, nullptr);
1366 }
1367 else {
1368 BLI_task_pool_push(task_pool, exec_distribute_parent, task, false, nullptr);
1369 }
1370 }
1372
1374
1375 psys_calc_dmcache(sim->ob, final_mesh, sim->psmd->mesh_original, sim->psys);
1376
1377 if (ctx.mesh != final_mesh) {
1378 BKE_id_free(nullptr, ctx.mesh);
1379 }
1380
1381 psys_tasks_free(tasks, numtasks);
1382
1384}
1385
1386/* ready for future use, to emit particles without geometry */
1388{
1389 distribute_invalid(sim, 0);
1390
1391 fprintf(stderr, "Shape emission not yet possible!\n");
1392}
1393
1395{
1397 int distr_error = 0;
1398
1399 if (psmd) {
1400 if (psmd->mesh_final) {
1401 distribute_particles_on_dm(sim, from);
1402 }
1403 else {
1404 distr_error = 1;
1405 }
1406 }
1407 else {
1409 }
1410
1411 if (distr_error) {
1412 distribute_invalid(sim, from);
1413
1414 fprintf(stderr, "Particle distribution error!\n");
1415 }
1416}
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
@ LIB_ID_COPY_LOCALIZE
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:760
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
void psys_tasks_free(struct ParticleTask *tasks, int numtasks)
float * psys_cache_vgroup(struct Mesh *mesh, struct ParticleSystem *psys, int vgroup)
Definition particle.cc:2575
void psys_tasks_create(struct ParticleThreadContext *ctx, int startpart, int endpart, struct ParticleTask **r_tasks, int *r_numtasks)
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:2017
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
#define DMCACHE_ISCHILD
#define PARTICLE_PSMD
#define PARTICLE_P
BLI_INLINE float psys_frand(ParticleSystem *psys, unsigned int seed)
#define BLI_assert(a)
Definition BLI_assert.h:50
void BLI_jitterate1(float(*jit1)[2], float(*jit2)[2], int num, float radius1)
Definition jitter_2d.c:19
void BLI_jitterate2(float(*jit1)[2], float(*jit2)[2], int num, float radius2)
Definition jitter_2d.c: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:98
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:83
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
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:58
void BLI_hammersley_1d(unsigned int n, double *r)
Definition rand.cc:350
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:88
void void void BLI_rng_skip(struct RNG *rng, int n) ATTR_NONNULL(1)
Definition rand.cc:162
float BLI_rng_get_float(struct RNG *rng) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition rand.cc:93
void BLI_array_randomize(void *data, unsigned int elem_size, unsigned int elem_num, unsigned int seed)
Definition rand.cc:188
void BLI_qsort_r(void *a, size_t n, size_t es, BLI_sort_cmp_t cmp, void *thunk)
Definition sort.c:76
unsigned int uint
@ TASK_PRIORITY_HIGH
Definition BLI_task.h:57
void BLI_task_pool_work_and_wait(TaskPool *pool)
Definition task_pool.cc:471
TaskPool * BLI_task_pool_create(void *userdata, eTaskPriority priority)
Definition task_pool.cc:394
void BLI_task_pool_free(TaskPool *pool)
Definition task_pool.cc:431
void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata)
Definition task_pool.cc:450
#define INIT_MINMAX(min, max)
#define ELEM(...)
typedef double(DMatrix)[4][4]
@ DAG_EVAL_RENDER
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
@ PART_FROM_VOLUME
@ PART_FROM_CHILD
@ PART_FROM_VERT
@ PART_FROM_FACE
@ PART_EDISTR
@ PART_GRID_HEXAGONAL
@ PART_GRID_INVERT
@ PART_TRAND
@ PART_HAIR
@ PARS_UNEXIST
@ PSYS_VG_DENSITY
@ PART_CHILD_FACES
@ PART_DISTR_GRID
@ PART_DISTR_RAND
@ PART_DISTR_JIT
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:178
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
pow(value.r - subtrahend, 2.0)") .do_static_compilation(true)
#define printf
#define sqrtf(x)
TaskPool * task_pool
KDTree_3d * tree
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
blender::gpu::Batch * quad
#define jit
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
ccl_device_inline float2 fmod(const float2 a, const float b)
ccl_device_inline float2 floor(const float2 a)
ccl_device_inline float3 ceil(const float3 a)
#define G(x, y, z)
Frequency::GEOMETRY nor[]
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 min(a, b)
Definition sort.c:32
#define FLT_MAX
Definition stdcycles.h:14
Definition DNA_ID.h:413
unsigned int v2
unsigned int v1
unsigned int v4
unsigned int v3
MeshRuntimeHandle * runtime
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
struct ParticleData * tpars
struct ParticleSeam * seams
struct ParticleSimulationData sim
struct KDTree_3d * tree
Definition rand.cc:33
uint8_t flag
Definition wm_window.cc:138