Blender V4.3
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
9#include <cmath>
10#include <cstdio>
11#include <cstdlib>
12
13#include "MEM_guardedalloc.h"
14
15#include "BLI_blenlib.h"
16#include "BLI_kdopbvh.h"
17#include "BLI_math_color.h"
18#include "BLI_math_matrix.h"
19#include "BLI_math_vector.h"
20#include "BLI_noise.h"
21#include "BLI_task.h"
22#include "BLI_utildefines.h"
23
24#include "DNA_meshdata_types.h"
25#include "DNA_object_types.h"
26#include "DNA_particle_types.h"
27#include "DNA_texture_types.h"
28
29#include "BKE_colorband.hh"
30#include "BKE_colortools.hh"
31#include "BKE_customdata.hh"
32#include "BKE_deform.hh"
33#include "BKE_mesh.hh"
34#include "BKE_object.hh"
35#include "BKE_particle.h"
36#include "BKE_scene.hh"
37
38#include "DEG_depsgraph.hh"
40
41#include "RE_texture.h"
42
43static ThreadMutex sample_mutex = PTHREAD_MUTEX_INITIALIZER;
44
45enum {
49};
50
52{
53 int pd_bitflag = 0;
54
55 if (pd->source == TEX_PD_PSYS) {
58 {
59 pd_bitflag |= POINT_DATA_VEL;
60 }
63 {
64 pd_bitflag |= POINT_DATA_LIFE;
65 }
66 }
67 else if (pd->source == TEX_PD_OBJECT) {
68 if (ELEM(pd->ob_color_source,
72 {
73 pd_bitflag |= POINT_DATA_COLOR;
74 }
75 }
76
77 return pd_bitflag;
78}
79
81 float **r_data_velocity,
82 float **r_data_life,
83 float **r_data_color)
84{
85 const int data_used = point_data_used(pd);
86 const int totpoint = pd->totpoints;
87 float *data = pd->point_data;
88 int offset = 0;
89
90 if (data_used & POINT_DATA_VEL) {
91 if (r_data_velocity) {
92 *r_data_velocity = data + offset;
93 }
94 offset += 3 * totpoint;
95 }
96 else {
97 if (r_data_velocity) {
98 *r_data_velocity = nullptr;
99 }
100 }
101
102 if (data_used & POINT_DATA_LIFE) {
103 if (r_data_life) {
104 *r_data_life = data + offset;
105 }
106 offset += totpoint;
107 }
108 else {
109 if (r_data_life) {
110 *r_data_life = nullptr;
111 }
112 }
113
114 if (data_used & POINT_DATA_COLOR) {
115 if (r_data_color) {
116 *r_data_color = data + offset;
117 }
118 offset += 3 * totpoint;
119 }
120 else {
121 if (r_data_color) {
122 *r_data_color = nullptr;
123 }
124 }
125}
126
127/* additional data stored alongside the point density BVH,
128 * accessible by point index number to retrieve other information
129 * such as particle velocity or lifetime */
131{
132 const int totpoints = pd->totpoints;
133 int data_used = point_data_used(pd);
134 int data_size = 0;
135
136 if (data_used & POINT_DATA_VEL) {
137 /* store 3 channels of velocity data */
138 data_size += 3;
139 }
140 if (data_used & POINT_DATA_LIFE) {
141 /* store 1 channel of lifetime data */
142 data_size += 1;
143 }
144 if (data_used & POINT_DATA_COLOR) {
145 /* store 3 channels of RGB data */
146 data_size += 3;
147 }
148
149 if (data_size) {
150 pd->point_data = static_cast<float *>(
151 MEM_callocN(sizeof(float) * data_size * totpoints, "particle point data"));
152 }
153}
154
156 Depsgraph *depsgraph, Scene *scene, PointDensity *pd, Object *ob, ParticleSystem *psys)
157{
159 ParticleCacheKey *cache;
160 ParticleSimulationData sim = {nullptr};
161 ParticleData *pa = nullptr;
162 float cfra = BKE_scene_ctime_get(scene);
163 int i;
164 // int childexists = 0; /* UNUSED */
165 int total_particles;
166 int data_used;
167 float *data_vel, *data_life;
168 float partco[3];
169 const bool use_render_params = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
170
171 data_used = point_data_used(pd);
172
173 if (!psys_check_enabled(ob, psys, use_render_params)) {
174 return;
175 }
176
177 sim.depsgraph = depsgraph;
178 sim.scene = scene;
179 sim.ob = ob;
180 sim.psys = psys;
181 sim.psmd = psys_get_modifier(ob, psys);
182
183 /* in case ob->world_to_object isn't up-to-date */
184 invert_m4_m4(ob->runtime->world_to_object.ptr(), ob->object_to_world().ptr());
185
186 total_particles = psys->totpart + psys->totchild;
187 psys_sim_data_init(&sim);
188
189 pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6);
190 pd->totpoints = total_particles;
192 point_data_pointers(pd, &data_vel, &data_life, nullptr);
193
194#if 0 /* UNUSED */
195 if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT)) {
196 childexists = 1;
197 }
198#endif
199
200 for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) {
201
202 if (psys->part->type == PART_HAIR) {
203 /* hair particles */
204 if (i < psys->totpart && psys->pathcache) {
205 cache = psys->pathcache[i];
206 }
207 else if (i >= psys->totpart && psys->childcache) {
208 cache = psys->childcache[i - psys->totpart];
209 }
210 else {
211 continue;
212 }
213
214 cache += cache->segments; /* use endpoint */
215
216 copy_v3_v3(state.co, cache->co);
217 zero_v3(state.vel);
218 state.time = 0.0f;
219 }
220 else {
221 /* emitter particles */
222 state.time = cfra;
223
224 if (!psys_get_particle_state(&sim, i, &state, false)) {
225 continue;
226 }
227
228 if (data_used & POINT_DATA_LIFE) {
229 if (i < psys->totpart) {
230 state.time = (cfra - pa->time) / pa->lifetime;
231 }
232 else {
233 ChildParticle *cpa = (psys->child + i) - psys->totpart;
234 float pa_birthtime, pa_dietime;
235
236 state.time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
237 }
238 }
239 }
240
241 copy_v3_v3(partco, state.co);
242
244 mul_m4_v3(ob->world_to_object().ptr(), partco);
245 }
246 else if (pd->psys_cache_space == TEX_PD_OBJECTLOC) {
247 sub_v3_v3(partco, ob->loc);
248 }
249 else {
250 /* TEX_PD_WORLDSPACE */
251 }
252
253 BLI_bvhtree_insert(static_cast<BVHTree *>(pd->point_tree), i, partco, 1);
254
255 if (data_vel) {
256 data_vel[i * 3 + 0] = state.vel[0];
257 data_vel[i * 3 + 1] = state.vel[1];
258 data_vel[i * 3 + 2] = state.vel[2];
259 }
260 if (data_life) {
261 data_life[i] = state.time;
262 }
263 }
264
265 BLI_bvhtree_balance(static_cast<BVHTree *>(pd->point_tree));
266
267 psys_sim_data_free(&sim);
268}
269
271 Object * /*ob*/,
272 Mesh *mesh,
273 float *data_color)
274{
275 const blender::Span<int> corner_verts = mesh->corner_verts();
276 const int totloop = mesh->corners_num;
277 char layername[MAX_CUSTOMDATA_LAYER_NAME];
278 int i;
279
280 BLI_assert(data_color);
281
282 if (!CustomData_has_layer(&mesh->corner_data, CD_PROP_BYTE_COLOR)) {
283 return;
284 }
286 &mesh->corner_data, CD_PROP_BYTE_COLOR, pd->vertex_attribute_name, layername);
287 const MLoopCol *mcol = static_cast<const MLoopCol *>(
288 CustomData_get_layer_named(&mesh->corner_data, CD_PROP_BYTE_COLOR, layername));
289 if (!mcol) {
290 return;
291 }
292
293 /* Stores the number of MLoops using the same vertex, so we can normalize colors. */
294 int *mcorners = static_cast<int *>(
295 MEM_callocN(sizeof(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].r);
302 }
303 else {
304 float col[3];
305 rgb_uchar_to_float(col, &mcol[i].r);
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 *>(
336 CustomData_get_layer(&mesh->vert_data, CD_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) {
380 mask.lmask |= CD_MASK_PROP_BYTE_COLOR;
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
774 INIT_MINMAX(min, max);
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(). */
815 cache_pointdensity(depsgraph, scene, pd);
817}
818
820 PointDensity *pd,
821 float r_min[3],
822 float r_max[3])
823{
824 using namespace blender;
826 Object *object = pd->object;
827 if (object == nullptr) {
828 zero_v3(r_min);
829 zero_v3(r_max);
830 return;
831 }
832 if (pd->source == TEX_PD_PSYS) {
833 ParticleSystem *psys;
834
835 if (pd->psys == 0) {
836 zero_v3(r_min);
837 zero_v3(r_max);
838 return;
839 }
840 psys = static_cast<ParticleSystem *>(BLI_findlink(&object->particlesystem, pd->psys - 1));
841 if (psys == nullptr) {
842 zero_v3(r_min);
843 zero_v3(r_max);
844 return;
845 }
846
847 particle_system_minmax(depsgraph, scene, object, psys, pd->radius, r_min, r_max);
848 }
849 else {
850 const float radius[3] = {pd->radius, pd->radius, pd->radius};
851 if (const std::optional<Bounds<float3>> bb = BKE_object_boundbox_get(object)) {
852 copy_v3_v3(r_min, bb->min);
853 copy_v3_v3(r_max, bb->max);
854 /* Adjust texture space to include density points on the boundaries. */
855 sub_v3_v3(r_min, radius);
856 add_v3_v3(r_max, radius);
857 }
858 else {
859 zero_v3(r_min);
860 zero_v3(r_max);
861 }
862 }
863}
864
871
872static void point_density_sample_func(void *__restrict data_v,
873 const int iter,
874 const TaskParallelTLS *__restrict /*tls*/)
875{
876 SampleCallbackData *data = (SampleCallbackData *)data_v;
877
878 const int resolution = data->resolution;
879 const int resolution2 = resolution * resolution;
880 const float *min = data->min, *dim = data->dim;
881 PointDensity *pd = data->pd;
882 float *values = data->values;
883
884 if (!pd || !pd->point_tree) {
885 return;
886 }
887
888 size_t z = size_t(iter);
889 for (size_t y = 0; y < resolution; y++) {
890 for (size_t x = 0; x < resolution; x++) {
891 size_t index = z * resolution2 + y * resolution + x;
892 float texvec[3];
893 float age, vec[3], col[3];
894 TexResult texres;
895
896 copy_v3_v3(texvec, min);
897 texvec[0] += dim[0] * float(x) / float(resolution);
898 texvec[1] += dim[1] * float(y) / float(resolution);
899 texvec[2] += dim[2] * float(z) / float(resolution);
900
901 pointdensity(pd, texvec, &texres, vec, &age, col);
902 pointdensity_color(pd, &texres, age, vec, col);
903
904 copy_v3_v3(&values[index * 4 + 0], texres.trgba);
905 values[index * 4 + 3] = texres.tin;
906 }
907 }
908}
909
911 PointDensity *pd,
912 const int resolution,
913 float *values)
914{
915 Object *object = pd->object;
916 float min[3], max[3], dim[3];
917
918 /* TODO(sergey): Implement some sort of assert() that point density
919 * was cached already.
920 */
921
922 if (object == nullptr) {
923 sample_dummy_point_density(resolution, values);
924 return;
925 }
926
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:396
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 void * CustomData_get_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
void CustomData_validate_layer_name(const CustomData *data, eCustomDataType type, blender::StringRef name, char *outname)
const CustomData_MeshMasks CD_MASK_BAREMESH
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
support for deformation groups and hooks.
int BKE_object_defgroup_active_index_get(const Object *ob)
Definition deform.cc:601
int BKE_id_defgroup_name_index(const ID *id, blender::StringRef name)
Definition deform.cc:543
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:2150
bool psys_check_enabled(struct Object *ob, struct ParticleSystem *psys, bool use_render_params)
Definition particle.cc:706
float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *birthtime, float *dietime)
Definition particle.cc:4478
void psys_sim_data_free(struct ParticleSimulationData *sim)
Definition particle.cc:629
void psys_sim_data_init(struct ParticleSimulationData *sim)
Definition particle.cc:588
bool psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, bool always)
Definition particle.cc:4886
float BKE_scene_ctime_get(const Scene *scene)
Definition scene.cc:2317
#define BLI_assert(a)
Definition BLI_assert.h:50
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 struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void rgb_uchar_to_float(float r_col[3], const unsigned char col_ub[3])
void unit_m4(float m[4][4])
Definition rct.c:1127
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 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
float BLI_noise_generic_turbulence(float noisesize, float x, float y, float z, int oct, bool hard, int noisebasis)
Definition noise.c: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:230
void BLI_mutex_lock(ThreadMutex *mutex)
Definition threads.cc:345
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition threads.cc:350
pthread_mutex_t ThreadMutex
Definition BLI_threads.h:83
#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)
#define MAX_CUSTOMDATA_LAYER_NAME
#define CD_MASK_PROP_BYTE_COLOR
#define CD_MASK_MCOL
#define CD_MASK_MDEFORMVERT
#define CD_MASK_MTFACE
@ CD_PROP_BYTE_COLOR
@ CD_MDEFORMVERT
Object is a sort of wrapper for general info.
@ OB_MESH
@ PART_HAIR
@ PART_DRAW_PARENT
@ TEX_INT
@ TEX_PD_FALLOFF_CURVE
@ TEX_PD_TURBULENCE
@ 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_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_OBJECT
@ TEX_PD_PSYS
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
pow(value.r - subtrahend, 2.0)") .do_static_compilation(true)
const Depsgraph * depsgraph
#define sqrtf(x)
draw_view in_light_buf[] float
uint col
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
static ulong state[N]
static float turb(float x, float y, float z, int oct, int hard, int nb, float ampscale, float freqscale)
#define min(a, b)
Definition sort.c:32
struct MDeformWeight * dw
unsigned int def_nr
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:87
float trgba[4]
Definition RE_texture.h:88
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 ThreadMutex sample_mutex
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)
@ POINT_DATA_LIFE
@ POINT_DATA_VEL
@ POINT_DATA_COLOR
static void pointdensity_color(PointDensity *pd, TexResult *texres, float age, const float vec[3], const float col[3])
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 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)