Blender V4.5
texture_pointdensity.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cmath>
10#include <cstdio>
11#include <cstdlib>
12
13#include "MEM_guardedalloc.h"
14
15#include "BLI_color.hh"
16#include "BLI_kdopbvh.hh"
17#include "BLI_listbase.h"
18#include "BLI_math_color.h"
19#include "BLI_math_matrix.h"
20#include "BLI_math_vector.h"
21#include "BLI_noise.h"
22#include "BLI_task.h"
23#include "BLI_utildefines.h"
24
25#include "DNA_meshdata_types.h"
26#include "DNA_object_types.h"
27#include "DNA_particle_types.h"
28#include "DNA_texture_types.h"
29
30#include "BKE_attribute.hh"
31#include "BKE_colorband.hh"
32#include "BKE_colortools.hh"
33#include "BKE_customdata.hh"
34#include "BKE_deform.hh"
35#include "BKE_mesh.hh"
36#include "BKE_object.hh"
37#include "BKE_particle.h"
38#include "BKE_scene.hh"
39
40#include "DEG_depsgraph.hh"
42
43#include "RE_texture.h"
44
46
47enum {
51};
52
54{
55 int pd_bitflag = 0;
56
57 if (pd->source == TEX_PD_PSYS) {
60 {
61 pd_bitflag |= POINT_DATA_VEL;
62 }
65 {
66 pd_bitflag |= POINT_DATA_LIFE;
67 }
68 }
69 else if (pd->source == TEX_PD_OBJECT) {
70 if (ELEM(pd->ob_color_source,
74 {
75 pd_bitflag |= POINT_DATA_COLOR;
76 }
77 }
78
79 return pd_bitflag;
80}
81
83 float **r_data_velocity,
84 float **r_data_life,
85 float **r_data_color)
86{
87 const int data_used = point_data_used(pd);
88 const int totpoint = pd->totpoints;
89 float *data = pd->point_data;
90 int offset = 0;
91
92 if (data_used & POINT_DATA_VEL) {
93 if (r_data_velocity) {
94 *r_data_velocity = data + offset;
95 }
96 offset += 3 * totpoint;
97 }
98 else {
99 if (r_data_velocity) {
100 *r_data_velocity = nullptr;
101 }
102 }
103
104 if (data_used & POINT_DATA_LIFE) {
105 if (r_data_life) {
106 *r_data_life = data + offset;
107 }
108 offset += totpoint;
109 }
110 else {
111 if (r_data_life) {
112 *r_data_life = nullptr;
113 }
114 }
115
116 if (data_used & POINT_DATA_COLOR) {
117 if (r_data_color) {
118 *r_data_color = data + offset;
119 }
120 offset += 3 * totpoint;
121 }
122 else {
123 if (r_data_color) {
124 *r_data_color = nullptr;
125 }
126 }
127}
128
129/* additional data stored alongside the point density BVH,
130 * accessible by point index number to retrieve other information
131 * such as particle velocity or lifetime */
133{
134 const int totpoints = pd->totpoints;
135 int data_used = point_data_used(pd);
136 int data_size = 0;
137
138 if (data_used & POINT_DATA_VEL) {
139 /* store 3 channels of velocity data */
140 data_size += 3;
141 }
142 if (data_used & POINT_DATA_LIFE) {
143 /* store 1 channel of lifetime data */
144 data_size += 1;
145 }
146 if (data_used & POINT_DATA_COLOR) {
147 /* store 3 channels of RGB data */
148 data_size += 3;
149 }
150
151 if (data_size) {
152 pd->point_data = MEM_calloc_arrayN<float>(size_t(data_size) * size_t(totpoints),
153 "particle point data");
154 }
155}
156
158 Depsgraph *depsgraph, Scene *scene, PointDensity *pd, Object *ob, ParticleSystem *psys)
159{
161 ParticleCacheKey *cache;
162 ParticleSimulationData sim = {nullptr};
163 ParticleData *pa = nullptr;
164 float cfra = BKE_scene_ctime_get(scene);
165 int i;
166 // int childexists = 0; /* UNUSED */
167 int total_particles;
168 int data_used;
169 float *data_vel, *data_life;
170 float partco[3];
171 const bool use_render_params = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
172
173 data_used = point_data_used(pd);
174
175 if (!psys_check_enabled(ob, psys, use_render_params)) {
176 return;
177 }
178
179 sim.depsgraph = depsgraph;
180 sim.scene = scene;
181 sim.ob = ob;
182 sim.psys = psys;
183 sim.psmd = psys_get_modifier(ob, psys);
184
185 /* in case ob->world_to_object isn't up-to-date */
186 invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
187
188 total_particles = psys->totpart + psys->totchild;
189 psys_sim_data_init(&sim);
190
191 pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6);
192 pd->totpoints = total_particles;
194 point_data_pointers(pd, &data_vel, &data_life, nullptr);
195
196#if 0 /* UNUSED */
197 if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT)) {
198 childexists = 1;
199 }
200#endif
201
202 for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) {
203
204 if (psys->part->type == PART_HAIR) {
205 /* hair particles */
206 if (i < psys->totpart && psys->pathcache) {
207 cache = psys->pathcache[i];
208 }
209 else if (i >= psys->totpart && psys->childcache) {
210 cache = psys->childcache[i - psys->totpart];
211 }
212 else {
213 continue;
214 }
215
216 cache += cache->segments; /* use endpoint */
217
218 copy_v3_v3(state.co, cache->co);
219 zero_v3(state.vel);
220 state.time = 0.0f;
221 }
222 else {
223 /* emitter particles */
224 state.time = cfra;
225
226 if (!psys_get_particle_state(&sim, i, &state, false)) {
227 continue;
228 }
229
230 if (data_used & POINT_DATA_LIFE) {
231 if (i < psys->totpart) {
232 state.time = (cfra - pa->time) / pa->lifetime;
233 }
234 else {
235 ChildParticle *cpa = (psys->child + i) - psys->totpart;
236 float pa_birthtime, pa_dietime;
237
238 state.time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
239 }
240 }
241 }
242
243 copy_v3_v3(partco, state.co);
244
246 mul_m4_v3(ob->world_to_object().ptr(), partco);
247 }
248 else if (pd->psys_cache_space == TEX_PD_OBJECTLOC) {
249 sub_v3_v3(partco, ob->loc);
250 }
251 else {
252 /* TEX_PD_WORLDSPACE */
253 }
254
255 BLI_bvhtree_insert(static_cast<BVHTree *>(pd->point_tree), i, partco, 1);
256
257 if (data_vel) {
258 data_vel[i * 3 + 0] = state.vel[0];
259 data_vel[i * 3 + 1] = state.vel[1];
260 data_vel[i * 3 + 2] = state.vel[2];
261 }
262 if (data_life) {
263 data_life[i] = state.time;
264 }
265 }
266
267 BLI_bvhtree_balance(static_cast<BVHTree *>(pd->point_tree));
268
269 psys_sim_data_free(&sim);
270}
271
273 Object * /*ob*/,
274 Mesh *mesh,
275 float *data_color)
276{
277 using namespace blender;
278 const blender::Span<int> corner_verts = mesh->corner_verts();
279 const int totloop = mesh->corners_num;
280 int i;
281
282 BLI_assert(data_color);
283
284 const bke::AttributeAccessor attributes = mesh->attributes();
285 const StringRef name = attributes.contains(pd->vertex_attribute_name) ?
288
289 const VArray mcol = *attributes.lookup<ColorGeometry4b>(name, bke::AttrDomain::Corner);
290 if (!mcol) {
291 return;
292 }
293
294 /* Stores the number of MLoops using the same vertex, so we can normalize colors. */
295 int *mcorners = MEM_calloc_arrayN<int>(pd->totpoints, "point density corner count");
296
297 for (i = 0; i < totloop; i++) {
298 int v = corner_verts[i];
299
300 if (mcorners[v] == 0) {
301 rgb_uchar_to_float(&data_color[v * 3], mcol[i]);
302 }
303 else {
304 float col[3];
305 rgb_uchar_to_float(col, mcol[i]);
306 add_v3_v3(&data_color[v * 3], col);
307 }
308
309 ++mcorners[v];
310 }
311
312 /* Normalize colors by averaging over mcorners.
313 * All the corners share the same vertex, ie. occupy the same point in space.
314 */
315 for (i = 0; i < pd->totpoints; i++) {
316 if (mcorners[i] > 0) {
317 mul_v3_fl(&data_color[i * 3], 1.0f / mcorners[i]);
318 }
319 }
320
321 MEM_freeN(mcorners);
322}
323
325 Object *ob,
326 Mesh *mesh,
327 float *data_color)
328{
329 const int totvert = mesh->verts_num;
330 int mdef_index;
331 int i;
332
333 BLI_assert(data_color);
334
335 const MDeformVert *mdef = static_cast<const MDeformVert *>(
337 if (!mdef) {
338 return;
339 }
340 mdef_index = BKE_id_defgroup_name_index(&mesh->id, pd->vertex_attribute_name);
341 if (mdef_index < 0) {
342 mdef_index = BKE_object_defgroup_active_index_get(ob) - 1;
343 }
344 if (mdef_index < 0) {
345 return;
346 }
347
348 const MDeformVert *dv;
349 for (i = 0, dv = mdef; i < totvert; i++, dv++, data_color += 3) {
350 MDeformWeight *dw;
351 int j;
352
353 for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) {
354 if (dw->def_nr == mdef_index) {
355 copy_v3_fl(data_color, dw->weight);
356 break;
357 }
358 }
359 }
360}
361
362static void pointdensity_cache_vertex_normal(Mesh *mesh, float *data_color)
363{
364 BLI_assert(data_color);
365 const blender::Span<blender::float3> normals = mesh->vert_normals();
366 memcpy(data_color, normals.data(), sizeof(float[3]) * mesh->verts_num);
367}
368
370{
371 float *data_color;
372 int i;
373 Mesh *mesh = static_cast<Mesh *>(ob->data);
374
375#if 0 /* UNUSED */
378 switch (pd->ob_color_source) {
381 break;
383 mask.vmask |= CD_MASK_MDEFORMVERT;
384 break;
385 }
386#endif
387
388 const blender::Span<blender::float3> positions = mesh->vert_positions(); /* local object space */
389 pd->totpoints = mesh->verts_num;
390 if (pd->totpoints == 0) {
391 return;
392 }
393
394 pd->point_tree = BLI_bvhtree_new(pd->totpoints, 0.0, 4, 6);
396 point_data_pointers(pd, nullptr, nullptr, &data_color);
397
398 for (i = 0; i < pd->totpoints; i++) {
399 float co[3];
400
401 copy_v3_v3(co, positions[i]);
402
403 switch (pd->ob_cache_space) {
405 break;
406 case TEX_PD_OBJECTLOC:
407 mul_m4_v3(ob->object_to_world().ptr(), co);
408 sub_v3_v3(co, ob->loc);
409 break;
411 default:
412 mul_m4_v3(ob->object_to_world().ptr(), co);
413 break;
414 }
415
416 BLI_bvhtree_insert(static_cast<BVHTree *>(pd->point_tree), i, co, 1);
417 }
418
419 switch (pd->ob_color_source) {
421 pointdensity_cache_vertex_color(pd, ob, mesh, data_color);
422 break;
424 pointdensity_cache_vertex_weight(pd, ob, mesh, data_color);
425 break;
427 pointdensity_cache_vertex_normal(mesh, data_color);
428 break;
429 }
430
431 BLI_bvhtree_balance(static_cast<BVHTree *>(pd->point_tree));
432}
433
434static void cache_pointdensity(Depsgraph *depsgraph, Scene *scene, PointDensity *pd)
435{
436 if (pd == nullptr) {
437 return;
438 }
439
440 if (pd->point_tree) {
441 BLI_bvhtree_free(static_cast<BVHTree *>(pd->point_tree));
442 pd->point_tree = nullptr;
443 }
444
445 if (pd->source == TEX_PD_PSYS) {
446 Object *ob = pd->object;
447 ParticleSystem *psys;
448
449 if (!ob || !pd->psys) {
450 return;
451 }
452
453 psys = static_cast<ParticleSystem *>(BLI_findlink(&ob->particlesystem, pd->psys - 1));
454 if (!psys) {
455 return;
456 }
457
458 pointdensity_cache_psys(depsgraph, scene, pd, ob, psys);
459 }
460 else if (pd->source == TEX_PD_OBJECT) {
461 Object *ob = pd->object;
462 if (ob && ob->type == OB_MESH) {
464 }
465 }
466}
467
469{
470 if (pd == nullptr) {
471 return;
472 }
473
474 if (pd->point_tree) {
475 BLI_bvhtree_free(static_cast<BVHTree *>(pd->point_tree));
476 pd->point_tree = nullptr;
477 }
478
480 pd->totpoints = 0;
481}
482
498
499static float density_falloff(PointDensityRangeData *pdr, int index, float squared_dist)
500{
501 const float dist = (pdr->squared_radius - squared_dist) / pdr->squared_radius * 0.5f;
502 float density = 0.0f;
503
504 switch (pdr->falloff_type) {
506 density = dist;
507 break;
509 density = 3.0f * dist * dist - 2.0f * dist * dist * dist;
510 break;
512 density = pow(dist, pdr->softness);
513 break;
515 density = pdr->squared_radius;
516 break;
518 density = sqrtf(dist);
519 break;
521 if (pdr->point_data_life) {
522 density = dist * std::min(pdr->point_data_life[index], 1.0f);
523 }
524 else {
525 density = dist;
526 }
527 break;
529 if (pdr->point_data_velocity) {
530 density = dist * len_v3(&pdr->point_data_velocity[index * 3]) * pdr->velscale;
531 }
532 else {
533 density = dist;
534 }
535 break;
536 }
537
538 if (pdr->density_curve && dist != 0.0f) {
540 density = BKE_curvemapping_evaluateF(pdr->density_curve, 0, density / dist) * dist;
541 }
542
543 return density;
544}
545
546static void accum_density(void *userdata, int index, const float co[3], float squared_dist)
547{
549 float density = 0.0f;
550
551 UNUSED_VARS(co);
552
553 if (pdr->point_data_velocity) {
554 pdr->vec[0] += pdr->point_data_velocity[index * 3 + 0]; // * density;
555 pdr->vec[1] += pdr->point_data_velocity[index * 3 + 1]; // * density;
556 pdr->vec[2] += pdr->point_data_velocity[index * 3 + 2]; // * density;
557 }
558 if (pdr->point_data_life) {
559 *pdr->age += pdr->point_data_life[index]; // * density;
560 }
561 if (pdr->point_data_color) {
562 add_v3_v3(pdr->col, &pdr->point_data_color[index * 3]); // * density;
563 }
564
565 density = density_falloff(pdr, index, squared_dist);
566
567 *pdr->density += density;
568}
569
572 float *density,
573 float *vec,
574 float *age,
575 float *col,
576 CurveMapping *density_curve,
577 float velscale)
578{
579 pdr->squared_radius = pd->radius * pd->radius;
580 pdr->density = density;
581 pdr->falloff_type = pd->falloff_type;
582 pdr->vec = vec;
583 pdr->age = age;
584 pdr->col = col;
585 pdr->softness = pd->falloff_softness;
589 pdr->density_curve = density_curve;
590 pdr->velscale = velscale;
591}
592
594 const float texvec[3],
595 TexResult *texres,
596 float r_vec[3],
597 float *r_age,
598 float r_col[3])
599{
600 int retval = TEX_INT;
602 float density = 0.0f, age = 0.0f;
603 float vec[3] = {0.0f, 0.0f, 0.0f}, col[3] = {0.0f, 0.0f, 0.0f}, co[3];
604 float turb, noise_fac;
605 int num = 0;
606
607 texres->tin = 0.0f;
608
610 &pdr,
611 &density,
612 vec,
613 &age,
614 col,
615 (pd->flag & TEX_PD_FALLOFF_CURVE ? pd->falloff_curve : nullptr),
616 pd->falloff_speed_scale * 0.001f);
617 noise_fac = pd->noise_fac * 0.5f; /* better default */
618
619 copy_v3_v3(co, texvec);
620
621 if (point_data_used(pd)) {
622 /* does a BVH lookup to find accumulated density and additional point data *
623 * stores particle velocity vector in 'vec', and particle lifetime in 'time' */
625 static_cast<const BVHTree *>(pd->point_tree), co, pd->radius, accum_density, &pdr);
626 if (num > 0) {
627 age /= num;
628 mul_v3_fl(vec, 1.0f / num);
629 mul_v3_fl(col, 1.0f / num);
630 }
631
632 /* reset */
633 density = 0.0f;
634 zero_v3(vec);
635 zero_v3(col);
636 }
637
638 if (pd->flag & TEX_PD_TURBULENCE) {
640 texvec[0] + vec[0],
641 texvec[1] + vec[1],
642 texvec[2] + vec[2],
643 pd->noise_depth,
644 false,
645 pd->noise_basis);
646
647 turb -= 0.5f; /* re-center 0.0-1.0 range around 0 to prevent offsetting result */
648
649 /* now we have an offset coordinate to use for the density lookup */
650 co[0] = texvec[0] + noise_fac * turb;
651 co[1] = texvec[1] + noise_fac * turb;
652 co[2] = texvec[2] + noise_fac * turb;
653 }
654
655 /* BVH query with the potentially perturbed coordinates */
657 static_cast<const BVHTree *>(pd->point_tree), co, pd->radius, accum_density, &pdr);
658 if (num > 0) {
659 age /= num;
660 mul_v3_fl(vec, 1.0f / num);
661 mul_v3_fl(col, 1.0f / num);
662 }
663
664 texres->tin = density;
665 if (r_age != nullptr) {
666 *r_age = age;
667 }
668 if (r_vec != nullptr) {
669 copy_v3_v3(r_vec, vec);
670 }
671 if (r_col != nullptr) {
672 copy_v3_v3(r_col, col);
673 }
674
675 return retval;
676}
677
679 PointDensity *pd, TexResult *texres, float age, const float vec[3], const float col[3])
680{
681 copy_v4_fl(texres->trgba, 1.0f);
682
683 if (pd->source == TEX_PD_PSYS) {
684 float rgba[4];
685
686 switch (pd->color_source) {
688 if (pd->coba) {
689 if (BKE_colorband_evaluate(pd->coba, age, rgba)) {
690 texres->talpha = true;
691 copy_v3_v3(texres->trgba, rgba);
692 texres->tin *= rgba[3];
693 texres->trgba[3] = texres->tin;
694 }
695 }
696 break;
698 float speed = len_v3(vec) * pd->speed_scale;
699
700 if (pd->coba) {
701 if (BKE_colorband_evaluate(pd->coba, speed, rgba)) {
702 texres->talpha = true;
703 copy_v3_v3(texres->trgba, rgba);
704 texres->tin *= rgba[3];
705 texres->trgba[3] = texres->tin;
706 }
707 }
708 break;
709 }
711 texres->talpha = true;
712 mul_v3_v3fl(texres->trgba, vec, pd->speed_scale);
713 texres->trgba[3] = texres->tin;
714 break;
716 default:
717 break;
718 }
719 }
720 else {
721 float rgba[4];
722
723 switch (pd->ob_color_source) {
725 texres->talpha = true;
726 copy_v3_v3(texres->trgba, col);
727 texres->trgba[3] = texres->tin;
728 break;
730 texres->talpha = true;
731 if (pd->coba && BKE_colorband_evaluate(pd->coba, col[0], rgba)) {
732 copy_v3_v3(texres->trgba, rgba);
733 texres->tin *= rgba[3];
734 }
735 else {
736 copy_v3_v3(texres->trgba, col);
737 }
738 texres->trgba[3] = texres->tin;
739 break;
741 texres->talpha = true;
742 copy_v3_v3(texres->trgba, col);
743 texres->trgba[3] = texres->tin;
744 break;
746 default:
747 break;
748 }
749 }
750}
751
752static void sample_dummy_point_density(int resolution, float *values)
753{
754 memset(values, 0, sizeof(float[4]) * resolution * resolution * resolution);
755}
756
757static void particle_system_minmax(Depsgraph *depsgraph,
758 Scene *scene,
759 Object *object,
760 ParticleSystem *psys,
761 float radius,
762 float min[3],
763 float max[3])
764{
765 const float size[3] = {radius, radius, radius};
766 const float cfra = BKE_scene_ctime_get(scene);
767 ParticleSettings *part = psys->part;
768 ParticleSimulationData sim = {nullptr};
769 ParticleData *pa = nullptr;
770 int i;
771 int total_particles;
772 float mat[4][4], imat[4][4];
773
775 if (part->type == PART_HAIR) {
776 /* TODO(sergey): Not supported currently. */
777 return;
778 }
779
780 unit_m4(mat);
781
782 sim.depsgraph = depsgraph;
783 sim.scene = scene;
784 sim.ob = object;
785 sim.psys = psys;
786 sim.psmd = psys_get_modifier(object, psys);
787
788 invert_m4_m4(imat, object->object_to_world().ptr());
789 total_particles = psys->totpart + psys->totchild;
790 psys_sim_data_init(&sim);
791
792 for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) {
793 float co_object[3], co_min[3], co_max[3];
795 state.time = cfra;
796 if (!psys_get_particle_state(&sim, i, &state, false)) {
797 continue;
798 }
799 mul_v3_m4v3(co_object, imat, state.co);
800 sub_v3_v3v3(co_min, co_object, size);
801 add_v3_v3v3(co_max, co_object, size);
802 minmax_v3v3_v3(min, max, co_min);
803 minmax_v3v3_v3(min, max, co_max);
804 }
805
806 psys_sim_data_free(&sim);
807}
808
810{
812
813 /* Same matrices/resolution as dupli_render_particle_set(). */
814 std::scoped_lock lock(sample_mutex);
815 cache_pointdensity(depsgraph, scene, pd);
816}
817
819 PointDensity *pd,
820 float r_min[3],
821 float r_max[3])
822{
823 using namespace blender;
825 Object *object = pd->object;
826 if (object == nullptr) {
827 zero_v3(r_min);
828 zero_v3(r_max);
829 return;
830 }
831 if (pd->source == TEX_PD_PSYS) {
832 ParticleSystem *psys;
833
834 if (pd->psys == 0) {
835 zero_v3(r_min);
836 zero_v3(r_max);
837 return;
838 }
839 psys = static_cast<ParticleSystem *>(BLI_findlink(&object->particlesystem, pd->psys - 1));
840 if (psys == nullptr) {
841 zero_v3(r_min);
842 zero_v3(r_max);
843 return;
844 }
845
846 particle_system_minmax(depsgraph, scene, object, psys, pd->radius, r_min, r_max);
847 }
848 else {
849 const float radius[3] = {pd->radius, pd->radius, pd->radius};
850 if (const std::optional<Bounds<float3>> bb = BKE_object_boundbox_get(object)) {
851 copy_v3_v3(r_min, bb->min);
852 copy_v3_v3(r_max, bb->max);
853 /* Adjust texture space to include density points on the boundaries. */
854 sub_v3_v3(r_min, radius);
855 add_v3_v3(r_max, radius);
856 }
857 else {
858 zero_v3(r_min);
859 zero_v3(r_max);
860 }
861 }
862}
863
870
871static void point_density_sample_func(void *__restrict data_v,
872 const int iter,
873 const TaskParallelTLS *__restrict /*tls*/)
874{
876
877 const int resolution = data->resolution;
878 const int resolution2 = resolution * resolution;
879 const float *min = data->min, *dim = data->dim;
880 PointDensity *pd = data->pd;
881 float *values = data->values;
882
883 if (!pd || !pd->point_tree) {
884 return;
885 }
886
887 size_t z = size_t(iter);
888 for (size_t y = 0; y < resolution; y++) {
889 for (size_t x = 0; x < resolution; x++) {
890 size_t index = z * resolution2 + y * resolution + x;
891 float texvec[3];
892 float age, vec[3], col[3];
893 TexResult texres;
894
895 copy_v3_v3(texvec, min);
896 texvec[0] += dim[0] * float(x) / float(resolution);
897 texvec[1] += dim[1] * float(y) / float(resolution);
898 texvec[2] += dim[2] * float(z) / float(resolution);
899
900 pointdensity(pd, texvec, &texres, vec, &age, col);
901 pointdensity_color(pd, &texres, age, vec, col);
902
903 copy_v3_v3(&values[index * 4 + 0], texres.trgba);
904 values[index * 4 + 3] = texres.tin;
905 }
906 }
907}
908
910 PointDensity *pd,
911 const int resolution,
912 float *values)
913{
914 Object *object = pd->object;
915 float min[3], max[3], dim[3];
916
917 /* TODO(sergey): Implement some sort of assert() that point density
918 * was cached already.
919 */
920
921 if (object == nullptr) {
922 sample_dummy_point_density(resolution, values);
923 return;
924 }
925
926 {
927 std::scoped_lock lock(sample_mutex);
929 }
930 sub_v3_v3v3(dim, max, min);
931 if (dim[0] <= 0.0f || dim[1] <= 0.0f || dim[2] <= 0.0f) {
932 sample_dummy_point_density(resolution, values);
933 return;
934 }
935
937 data.pd = pd;
938 data.resolution = resolution;
939 data.min = min;
940 data.dim = dim;
941 data.values = values;
942 TaskParallelSettings settings;
944 settings.use_threading = (resolution > 32);
945 BLI_task_parallel_range(0, resolution, &data, point_density_sample_func, &settings);
946
948}
949
954
bool BKE_colorband_evaluate(const ColorBand *coba, float in, float out[4])
Definition colorband.cc:395
float BKE_curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value)
void BKE_curvemapping_init(CurveMapping *cumap)
CustomData interface, see also DNA_customdata_types.h.
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
const CustomData_MeshMasks CD_MASK_BAREMESH
support for deformation groups and hooks.
int BKE_object_defgroup_active_index_get(const Object *ob)
Definition deform.cc:596
int BKE_id_defgroup_name_index(const ID *id, blender::StringRef name)
Definition deform.cc:538
General operations, lookup, etc. for blender objects.
std::optional< blender::Bounds< blender::float3 > > BKE_object_boundbox_get(const Object *ob)
struct ParticleSystemModifierData * psys_get_modifier(struct Object *ob, struct ParticleSystem *psys)
Definition particle.cc:2153
bool psys_check_enabled(struct Object *ob, struct ParticleSystem *psys, bool use_render_params)
Definition particle.cc:709
float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *birthtime, float *dietime)
Definition particle.cc:4469
void psys_sim_data_free(struct ParticleSimulationData *sim)
Definition particle.cc:632
void psys_sim_data_init(struct ParticleSimulationData *sim)
Definition particle.cc:591
bool psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, bool always)
Definition particle.cc:4877
float BKE_scene_ctime_get(const Scene *scene)
Definition scene.cc:2367
#define BLI_assert(a)
Definition BLI_assert.h:46
BVHTree * BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
void BLI_bvhtree_balance(BVHTree *tree)
void BLI_bvhtree_free(BVHTree *tree)
void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
int BLI_bvhtree_range_query(const BVHTree *tree, const float co[3], float radius, BVHTree_RangeQuery callback, void *userdata)
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
void rgb_uchar_to_float(float r_col[3], const unsigned char col_ub[3])
void mul_m4_v3(const float M[4][4], float r[3])
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void unit_m4(float m[4][4])
void minmax_v3v3_v3(float min[3], float max[3], const float vec[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void zero_v3(float r[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE void copy_v4_fl(float r[4], float f)
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
ATTR_WARN_UNUSED_RESULT const size_t num
float BLI_noise_generic_turbulence(float noisesize, float x, float y, float z, int oct, bool hard, int noisebasis)
Definition noise_c.cc:1210
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition task_range.cc:99
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition BLI_task.h:221
#define INIT_MINMAX(min, max)
#define UNUSED_VARS(...)
#define ELEM(...)
@ DAG_EVAL_RENDER
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
@ CD_MDEFORMVERT
Object is a sort of wrapper for general info.
@ OB_MESH
@ PART_DRAW_PARENT
@ PART_HAIR
@ TEX_PD_OBJECT
@ TEX_PD_PSYS
@ TEX_INT
@ TEX_PD_COLOR_VERTWEIGHT
@ TEX_PD_COLOR_VERTNOR
@ TEX_PD_COLOR_VERTCOL
@ TEX_PD_COLOR_PARTAGE
@ TEX_PD_COLOR_CONSTANT
@ TEX_PD_COLOR_PARTVEL
@ TEX_PD_COLOR_PARTSPEED
@ TEX_PD_FALLOFF_PARTICLE_VEL
@ TEX_PD_FALLOFF_PARTICLE_AGE
@ TEX_PD_FALLOFF_ROOT
@ TEX_PD_FALLOFF_STD
@ TEX_PD_FALLOFF_SMOOTH
@ TEX_PD_FALLOFF_SOFT
@ TEX_PD_FALLOFF_CONSTANT
@ TEX_PD_OBJECTSPACE
@ TEX_PD_OBJECTLOC
@ TEX_PD_WORLDSPACE
@ TEX_PD_FALLOFF_CURVE
@ TEX_PD_TURBULENCE
Read Guarded memory(de)allocation.
volatile int lock
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
AttributeSet attributes
bool contains(StringRef attribute_id) const
GAttributeReader lookup(const StringRef attribute_id) const
#define sqrtf(x)
static float normals[][3]
uint col
#define pow
#define CD_MASK_PROP_BYTE_COLOR
#define CD_MASK_MCOL
#define CD_MASK_MDEFORMVERT
#define MEM_SAFE_FREE(v)
#define CD_MASK_MTFACE
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
static ulong state[N]
static float turb(float x, float y, float z, int oct, int hard, int nb, float ampscale, float freqscale)
std::mutex Mutex
Definition BLI_mutex.hh:47
ColorSceneLinearByteEncoded4b< eAlpha::Premultiplied > ColorGeometry4b
Definition BLI_color.hh:343
#define min(a, b)
Definition sort.cc:36
struct MDeformWeight * dw
unsigned int def_nr
int corners_num
CustomData vert_data
int verts_num
char * active_color_attribute
ListBase particlesystem
ObjectRuntimeHandle * runtime
float loc[3]
struct Depsgraph * depsgraph
struct ParticleSystemModifierData * psmd
struct Scene * scene
struct ParticleSystem * psys
struct Object * ob
ChildParticle * child
ParticleData * particles
ParticleSettings * part
struct ParticleCacheKey ** childcache
struct ParticleCacheKey ** pathcache
struct CurveMapping * falloff_curve
struct Object * object
struct ColorBand * coba
char vertex_attribute_name[68]
float tin
Definition RE_texture.h:83
float trgba[4]
Definition RE_texture.h:84
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
static void sample_dummy_point_density(int resolution, float *values)
void RE_point_density_free(PointDensity *pd)
void RE_point_density_minmax(Depsgraph *depsgraph, PointDensity *pd, float r_min[3], float r_max[3])
void RE_point_density_sample(Depsgraph *depsgraph, PointDensity *pd, const int resolution, float *values)
void RE_point_density_fix_linking()
static void pointdensity_cache_object(PointDensity *pd, Object *ob)
static void init_pointdensityrangedata(PointDensity *pd, PointDensityRangeData *pdr, float *density, float *vec, float *age, float *col, CurveMapping *density_curve, float velscale)
static void accum_density(void *userdata, int index, const float co[3], float squared_dist)
static void pointdensity_cache_vertex_weight(PointDensity *pd, Object *ob, Mesh *mesh, float *data_color)
static void point_data_pointers(PointDensity *pd, float **r_data_velocity, float **r_data_life, float **r_data_color)
static void particle_system_minmax(Depsgraph *depsgraph, Scene *scene, Object *object, ParticleSystem *psys, float radius, float min[3], float max[3])
static int pointdensity(PointDensity *pd, const float texvec[3], TexResult *texres, float r_vec[3], float *r_age, float r_col[3])
void RE_point_density_cache(Depsgraph *depsgraph, PointDensity *pd)
static void pointdensity_cache_psys(Depsgraph *depsgraph, Scene *scene, PointDensity *pd, Object *ob, ParticleSystem *psys)
static void pointdensity_color(PointDensity *pd, TexResult *texres, float age, const float vec[3], const float col[3])
@ POINT_DATA_LIFE
@ POINT_DATA_VEL
@ POINT_DATA_COLOR
static float density_falloff(PointDensityRangeData *pdr, int index, float squared_dist)
static void alloc_point_data(PointDensity *pd)
static void pointdensity_cache_vertex_normal(Mesh *mesh, float *data_color)
static blender::Mutex sample_mutex
static void cache_pointdensity(Depsgraph *depsgraph, Scene *scene, PointDensity *pd)
static void pointdensity_cache_vertex_color(PointDensity *pd, Object *, Mesh *mesh, float *data_color)
static int point_data_used(PointDensity *pd)
static void free_pointdensity(PointDensity *pd)
static void point_density_sample_func(void *__restrict data_v, const int iter, const TaskParallelTLS *__restrict)