Cleanup: style, use braces for render
[blender.git] / source / blender / render / intern / source / pointdensity.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup render
22  */
23
24 #include <math.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27
28 #include "MEM_guardedalloc.h"
29
30 #include "BLI_math.h"
31 #include "BLI_blenlib.h"
32 #include "BLI_noise.h"
33 #include "BLI_kdopbvh.h"
34 #include "BLI_utildefines.h"
35 #include "BLI_task.h"
36
37 #include "BLT_translation.h"
38
39 #include "DNA_mesh_types.h"
40 #include "DNA_meshdata_types.h"
41 #include "DNA_object_types.h"
42 #include "DNA_particle_types.h"
43 #include "DNA_texture_types.h"
44
45 #include "BKE_colorband.h"
46 #include "BKE_deform.h"
47 #include "BKE_lattice.h"
48 #include "BKE_object.h"
49 #include "BKE_particle.h"
50 #include "BKE_scene.h"
51 #include "BKE_colortools.h"
52
53 #include "DEG_depsgraph.h"
54 #include "DEG_depsgraph_query.h"
55
56 #include "render_types.h"
57 #include "texture.h"
58
59 #include "RE_render_ext.h"
60 #include "RE_shader_ext.h"
61
62 static ThreadMutex sample_mutex = PTHREAD_MUTEX_INITIALIZER;
63
64 static int point_data_used(PointDensity *pd)
65 {
66   int pd_bitflag = 0;
67
68   if (pd->source == TEX_PD_PSYS) {
69     if ((pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) ||
70         (pd->color_source == TEX_PD_COLOR_PARTVEL) ||
71         (pd->color_source == TEX_PD_COLOR_PARTSPEED)) {
72       pd_bitflag |= POINT_DATA_VEL;
73     }
74     if ((pd->color_source == TEX_PD_COLOR_PARTAGE) ||
75         (pd->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE)) {
76       pd_bitflag |= POINT_DATA_LIFE;
77     }
78   }
79   else if (pd->source == TEX_PD_OBJECT) {
80     if (ELEM(pd->ob_color_source,
81              TEX_PD_COLOR_VERTCOL,
82              TEX_PD_COLOR_VERTWEIGHT,
83              TEX_PD_COLOR_VERTNOR)) {
84       pd_bitflag |= POINT_DATA_COLOR;
85     }
86   }
87
88   return pd_bitflag;
89 }
90
91 static void point_data_pointers(PointDensity *pd,
92                                 float **r_data_velocity,
93                                 float **r_data_life,
94                                 float **r_data_color)
95 {
96   const int data_used = point_data_used(pd);
97   const int totpoint = pd->totpoints;
98   float *data = pd->point_data;
99   int offset = 0;
100
101   if (data_used & POINT_DATA_VEL) {
102     if (r_data_velocity) {
103       *r_data_velocity = data + offset;
104     }
105     offset += 3 * totpoint;
106   }
107   else {
108     if (r_data_velocity) {
109       *r_data_velocity = NULL;
110     }
111   }
112
113   if (data_used & POINT_DATA_LIFE) {
114     if (r_data_life) {
115       *r_data_life = data + offset;
116     }
117     offset += totpoint;
118   }
119   else {
120     if (r_data_life) {
121       *r_data_life = NULL;
122     }
123   }
124
125   if (data_used & POINT_DATA_COLOR) {
126     if (r_data_color) {
127       *r_data_color = data + offset;
128     }
129     offset += 3 * totpoint;
130   }
131   else {
132     if (r_data_color) {
133       *r_data_color = NULL;
134     }
135   }
136 }
137
138 /* additional data stored alongside the point density BVH,
139  * accessible by point index number to retrieve other information
140  * such as particle velocity or lifetime */
141 static void alloc_point_data(PointDensity *pd)
142 {
143   const int totpoints = pd->totpoints;
144   int data_used = point_data_used(pd);
145   int data_size = 0;
146
147   if (data_used & POINT_DATA_VEL) {
148     /* store 3 channels of velocity data */
149     data_size += 3;
150   }
151   if (data_used & POINT_DATA_LIFE) {
152     /* store 1 channel of lifetime data */
153     data_size += 1;
154   }
155   if (data_used & POINT_DATA_COLOR) {
156     /* store 3 channels of RGB data */
157     data_size += 3;
158   }
159
160   if (data_size) {
161     pd->point_data = MEM_callocN(sizeof(float) * data_size * totpoints, "particle point data");
162   }
163 }
164
165 static void pointdensity_cache_psys(
166     Depsgraph *depsgraph, Scene *scene, PointDensity *pd, Object *ob, ParticleSystem *psys)
167 {
168   ParticleKey state;
169   ParticleCacheKey *cache;
170   ParticleSimulationData sim = {NULL};
171   ParticleData *pa = NULL;
172   float cfra = BKE_scene_frame_get(scene);
173   int i /*, childexists*/ /* UNUSED */;
174   int total_particles;
175   int data_used;
176   float *data_vel, *data_life;
177   float partco[3];
178   const bool use_render_params = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
179
180   data_used = point_data_used(pd);
181
182   if (!psys_check_enabled(ob, psys, use_render_params)) {
183     return;
184   }
185
186   sim.depsgraph = depsgraph;
187   sim.scene = scene;
188   sim.ob = ob;
189   sim.psys = psys;
190   sim.psmd = psys_get_modifier(ob, psys);
191
192   /* in case ob->imat isn't up-to-date */
193   invert_m4_m4(ob->imat, ob->obmat);
194
195   total_particles = psys->totpart + psys->totchild;
196   psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
197
198   pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6);
199   pd->totpoints = total_particles;
200   alloc_point_data(pd);
201   point_data_pointers(pd, &data_vel, &data_life, NULL);
202
203 #if 0 /* UNUSED */
204   if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
205     childexists = 1;
206 #endif
207
208   for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) {
209
210     if (psys->part->type == PART_HAIR) {
211       /* hair particles */
212       if (i < psys->totpart && psys->pathcache) {
213         cache = psys->pathcache[i];
214       }
215       else if (i >= psys->totpart && psys->childcache) {
216         cache = psys->childcache[i - psys->totpart];
217       }
218       else {
219         continue;
220       }
221
222       cache += cache->segments; /* use endpoint */
223
224       copy_v3_v3(state.co, cache->co);
225       zero_v3(state.vel);
226       state.time = 0.0f;
227     }
228     else {
229       /* emitter particles */
230       state.time = cfra;
231
232       if (!psys_get_particle_state(&sim, i, &state, 0)) {
233         continue;
234       }
235
236       if (data_used & POINT_DATA_LIFE) {
237         if (i < psys->totpart) {
238           state.time = (cfra - pa->time) / pa->lifetime;
239         }
240         else {
241           ChildParticle *cpa = (psys->child + i) - psys->totpart;
242           float pa_birthtime, pa_dietime;
243
244           state.time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
245         }
246       }
247     }
248
249     copy_v3_v3(partco, state.co);
250
251     if (pd->psys_cache_space == TEX_PD_OBJECTSPACE) {
252       mul_m4_v3(ob->imat, partco);
253     }
254     else if (pd->psys_cache_space == TEX_PD_OBJECTLOC) {
255       sub_v3_v3(partco, ob->loc);
256     }
257     else {
258       /* TEX_PD_WORLDSPACE */
259     }
260
261     BLI_bvhtree_insert(pd->point_tree, i, partco, 1);
262
263     if (data_vel) {
264       data_vel[i * 3 + 0] = state.vel[0];
265       data_vel[i * 3 + 1] = state.vel[1];
266       data_vel[i * 3 + 2] = state.vel[2];
267     }
268     if (data_life) {
269       data_life[i] = state.time;
270     }
271   }
272
273   BLI_bvhtree_balance(pd->point_tree);
274
275   if (psys->lattice_deform_data) {
276     end_latt_deform(psys->lattice_deform_data);
277     psys->lattice_deform_data = NULL;
278   }
279 }
280
281 static void pointdensity_cache_vertex_color(PointDensity *pd,
282                                             Object *UNUSED(ob),
283                                             Mesh *mesh,
284                                             float *data_color)
285 {
286   const MLoop *mloop = mesh->mloop;
287   const int totloop = mesh->totloop;
288   const MLoopCol *mcol;
289   char layername[MAX_CUSTOMDATA_LAYER_NAME];
290   int i;
291
292   BLI_assert(data_color);
293
294   if (!CustomData_has_layer(&mesh->ldata, CD_MLOOPCOL)) {
295     return;
296   }
297   CustomData_validate_layer_name(&mesh->ldata, CD_MLOOPCOL, pd->vertex_attribute_name, layername);
298   mcol = CustomData_get_layer_named(&mesh->ldata, CD_MLOOPCOL, layername);
299   if (!mcol) {
300     return;
301   }
302
303   /* Stores the number of MLoops using the same vertex, so we can normalize colors. */
304   int *mcorners = MEM_callocN(sizeof(int) * pd->totpoints, "point density corner count");
305
306   for (i = 0; i < totloop; i++) {
307     int v = mloop[i].v;
308
309     if (mcorners[v] == 0) {
310       rgb_uchar_to_float(&data_color[v * 3], &mcol[i].r);
311     }
312     else {
313       float col[3];
314       rgb_uchar_to_float(col, &mcol[i].r);
315       add_v3_v3(&data_color[v * 3], col);
316     }
317
318     ++mcorners[v];
319   }
320
321   /* Normalize colors by averaging over mcorners.
322    * All the corners share the same vertex, ie. occupy the same point in space.
323    */
324   for (i = 0; i < pd->totpoints; i++) {
325     if (mcorners[i] > 0) {
326       mul_v3_fl(&data_color[i * 3], 1.0f / mcorners[i]);
327     }
328   }
329
330   MEM_freeN(mcorners);
331 }
332
333 static void pointdensity_cache_vertex_weight(PointDensity *pd,
334                                              Object *ob,
335                                              Mesh *mesh,
336                                              float *data_color)
337 {
338   const int totvert = mesh->totvert;
339   const MDeformVert *mdef, *dv;
340   int mdef_index;
341   int i;
342
343   BLI_assert(data_color);
344
345   mdef = CustomData_get_layer(&mesh->vdata, CD_MDEFORMVERT);
346   if (!mdef) {
347     return;
348   }
349   mdef_index = defgroup_name_index(ob, pd->vertex_attribute_name);
350   if (mdef_index < 0) {
351     mdef_index = ob->actdef - 1;
352   }
353   if (mdef_index < 0) {
354     return;
355   }
356
357   for (i = 0, dv = mdef; i < totvert; ++i, ++dv, data_color += 3) {
358     MDeformWeight *dw;
359     int j;
360
361     for (j = 0, dw = dv->dw; j < dv->totweight; ++j, ++dw) {
362       if (dw->def_nr == mdef_index) {
363         copy_v3_fl(data_color, dw->weight);
364         break;
365       }
366     }
367   }
368 }
369
370 static void pointdensity_cache_vertex_normal(PointDensity *pd,
371                                              Object *UNUSED(ob),
372                                              Mesh *mesh,
373                                              float *data_color)
374 {
375   MVert *mvert = mesh->mvert, *mv;
376   int i;
377
378   BLI_assert(data_color);
379
380   for (i = 0, mv = mvert; i < pd->totpoints; i++, mv++, data_color += 3) {
381     normal_short_to_float_v3(data_color, mv->no);
382   }
383 }
384
385 static void pointdensity_cache_object(PointDensity *pd, Object *ob)
386 {
387   float *data_color;
388   int i;
389   MVert *mvert = NULL, *mv;
390   Mesh *mesh = ob->data;
391
392 #if 0 /* UNUSED */
393   CustomData_MeshMasks mask = CD_MASK_BAREMESH;
394   mask.fmask |= CD_MASK_MTFACE | CD_MASK_MCOL;
395   switch (pd->ob_color_source) {
396     case TEX_PD_COLOR_VERTCOL:
397       mask.lmask |= CD_MASK_MLOOPCOL;
398       break;
399     case TEX_PD_COLOR_VERTWEIGHT:
400       mask.vmask |= CD_MASK_MDEFORMVERT;
401       break;
402   }
403 #endif
404
405   mvert = mesh->mvert; /* local object space */
406   pd->totpoints = mesh->totvert;
407   if (pd->totpoints == 0) {
408     return;
409   }
410
411   pd->point_tree = BLI_bvhtree_new(pd->totpoints, 0.0, 4, 6);
412   alloc_point_data(pd);
413   point_data_pointers(pd, NULL, NULL, &data_color);
414
415   for (i = 0, mv = mvert; i < pd->totpoints; i++, mv++) {
416     float co[3];
417
418     copy_v3_v3(co, mv->co);
419
420     switch (pd->ob_cache_space) {
421       case TEX_PD_OBJECTSPACE:
422         break;
423       case TEX_PD_OBJECTLOC:
424         mul_m4_v3(ob->obmat, co);
425         sub_v3_v3(co, ob->loc);
426         break;
427       case TEX_PD_WORLDSPACE:
428       default:
429         mul_m4_v3(ob->obmat, co);
430         break;
431     }
432
433     BLI_bvhtree_insert(pd->point_tree, i, co, 1);
434   }
435
436   switch (pd->ob_color_source) {
437     case TEX_PD_COLOR_VERTCOL:
438       pointdensity_cache_vertex_color(pd, ob, mesh, data_color);
439       break;
440     case TEX_PD_COLOR_VERTWEIGHT:
441       pointdensity_cache_vertex_weight(pd, ob, mesh, data_color);
442       break;
443     case TEX_PD_COLOR_VERTNOR:
444       pointdensity_cache_vertex_normal(pd, ob, mesh, data_color);
445       break;
446   }
447
448   BLI_bvhtree_balance(pd->point_tree);
449 }
450
451 static void cache_pointdensity(Depsgraph *depsgraph, Scene *scene, PointDensity *pd)
452 {
453   if (pd == NULL) {
454     return;
455   }
456
457   if (pd->point_tree) {
458     BLI_bvhtree_free(pd->point_tree);
459     pd->point_tree = NULL;
460   }
461
462   if (pd->source == TEX_PD_PSYS) {
463     Object *ob = pd->object;
464     ParticleSystem *psys;
465
466     if (!ob || !pd->psys) {
467       return;
468     }
469
470     psys = BLI_findlink(&ob->particlesystem, pd->psys - 1);
471     if (!psys) {
472       return;
473     }
474
475     pointdensity_cache_psys(depsgraph, scene, pd, ob, psys);
476   }
477   else if (pd->source == TEX_PD_OBJECT) {
478     Object *ob = pd->object;
479     if (ob && ob->type == OB_MESH) {
480       pointdensity_cache_object(pd, ob);
481     }
482   }
483 }
484
485 static void free_pointdensity(PointDensity *pd)
486 {
487   if (pd == NULL) {
488     return;
489   }
490
491   if (pd->point_tree) {
492     BLI_bvhtree_free(pd->point_tree);
493     pd->point_tree = NULL;
494   }
495
496   if (pd->point_data) {
497     MEM_freeN(pd->point_data);
498     pd->point_data = NULL;
499   }
500   pd->totpoints = 0;
501 }
502
503 typedef struct PointDensityRangeData {
504   float *density;
505   float squared_radius;
506   float *point_data_life;
507   float *point_data_velocity;
508   float *point_data_color;
509   float *vec;
510   float *col;
511   float softness;
512   short falloff_type;
513   short noise_influence;
514   float *age;
515   struct CurveMapping *density_curve;
516   float velscale;
517 } PointDensityRangeData;
518
519 static float density_falloff(PointDensityRangeData *pdr, int index, float squared_dist)
520 {
521   const float dist = (pdr->squared_radius - squared_dist) / pdr->squared_radius * 0.5f;
522   float density = 0.0f;
523
524   switch (pdr->falloff_type) {
525     case TEX_PD_FALLOFF_STD:
526       density = dist;
527       break;
528     case TEX_PD_FALLOFF_SMOOTH:
529       density = 3.0f * dist * dist - 2.0f * dist * dist * dist;
530       break;
531     case TEX_PD_FALLOFF_SOFT:
532       density = pow(dist, pdr->softness);
533       break;
534     case TEX_PD_FALLOFF_CONSTANT:
535       density = pdr->squared_radius;
536       break;
537     case TEX_PD_FALLOFF_ROOT:
538       density = sqrtf(dist);
539       break;
540     case TEX_PD_FALLOFF_PARTICLE_AGE:
541       if (pdr->point_data_life) {
542         density = dist * MIN2(pdr->point_data_life[index], 1.0f);
543       }
544       else {
545         density = dist;
546       }
547       break;
548     case TEX_PD_FALLOFF_PARTICLE_VEL:
549       if (pdr->point_data_velocity) {
550         density = dist * len_v3(&pdr->point_data_velocity[index * 3]) * pdr->velscale;
551       }
552       else {
553         density = dist;
554       }
555       break;
556   }
557
558   if (pdr->density_curve && dist != 0.0f) {
559     curvemapping_initialize(pdr->density_curve);
560     density = curvemapping_evaluateF(pdr->density_curve, 0, density / dist) * dist;
561   }
562
563   return density;
564 }
565
566 static void accum_density(void *userdata, int index, const float co[3], float squared_dist)
567 {
568   PointDensityRangeData *pdr = (PointDensityRangeData *)userdata;
569   float density = 0.0f;
570
571   UNUSED_VARS(co);
572
573   if (pdr->point_data_velocity) {
574     pdr->vec[0] += pdr->point_data_velocity[index * 3 + 0];  // * density;
575     pdr->vec[1] += pdr->point_data_velocity[index * 3 + 1];  // * density;
576     pdr->vec[2] += pdr->point_data_velocity[index * 3 + 2];  // * density;
577   }
578   if (pdr->point_data_life) {
579     *pdr->age += pdr->point_data_life[index];  // * density;
580   }
581   if (pdr->point_data_color) {
582     add_v3_v3(pdr->col, &pdr->point_data_color[index * 3]);  // * density;
583   }
584
585   density = density_falloff(pdr, index, squared_dist);
586
587   *pdr->density += density;
588 }
589
590 static void init_pointdensityrangedata(PointDensity *pd,
591                                        PointDensityRangeData *pdr,
592                                        float *density,
593                                        float *vec,
594                                        float *age,
595                                        float *col,
596                                        struct CurveMapping *density_curve,
597                                        float velscale)
598 {
599   pdr->squared_radius = pd->radius * pd->radius;
600   pdr->density = density;
601   pdr->falloff_type = pd->falloff_type;
602   pdr->vec = vec;
603   pdr->age = age;
604   pdr->col = col;
605   pdr->softness = pd->falloff_softness;
606   pdr->noise_influence = pd->noise_influence;
607   point_data_pointers(
608       pd, &pdr->point_data_velocity, &pdr->point_data_life, &pdr->point_data_color);
609   pdr->density_curve = density_curve;
610   pdr->velscale = velscale;
611 }
612
613 static int pointdensity(PointDensity *pd,
614                         const float texvec[3],
615                         TexResult *texres,
616                         float r_vec[3],
617                         float *r_age,
618                         float r_col[3])
619 {
620   int retval = TEX_INT;
621   PointDensityRangeData pdr;
622   float density = 0.0f, age = 0.0f;
623   float vec[3] = {0.0f, 0.0f, 0.0f}, col[3] = {0.0f, 0.0f, 0.0f}, co[3];
624   float turb, noise_fac;
625   int num = 0;
626
627   texres->tin = 0.0f;
628
629   init_pointdensityrangedata(pd,
630                              &pdr,
631                              &density,
632                              vec,
633                              &age,
634                              col,
635                              (pd->flag & TEX_PD_FALLOFF_CURVE ? pd->falloff_curve : NULL),
636                              pd->falloff_speed_scale * 0.001f);
637   noise_fac = pd->noise_fac * 0.5f; /* better default */
638
639   copy_v3_v3(co, texvec);
640
641   if (point_data_used(pd)) {
642     /* does a BVH lookup to find accumulated density and additional point data *
643      * stores particle velocity vector in 'vec', and particle lifetime in 'time' */
644     num = BLI_bvhtree_range_query(pd->point_tree, co, pd->radius, accum_density, &pdr);
645     if (num > 0) {
646       age /= num;
647       mul_v3_fl(vec, 1.0f / num);
648       mul_v3_fl(col, 1.0f / num);
649     }
650
651     /* reset */
652     density = 0.0f;
653     zero_v3(vec);
654     zero_v3(col);
655   }
656
657   if (pd->flag & TEX_PD_TURBULENCE) {
658     turb = BLI_gTurbulence(pd->noise_size,
659                            texvec[0] + vec[0],
660                            texvec[1] + vec[1],
661                            texvec[2] + vec[2],
662                            pd->noise_depth,
663                            0,
664                            pd->noise_basis);
665
666     turb -= 0.5f; /* re-center 0.0-1.0 range around 0 to prevent offsetting result */
667
668     /* now we have an offset coordinate to use for the density lookup */
669     co[0] = texvec[0] + noise_fac * turb;
670     co[1] = texvec[1] + noise_fac * turb;
671     co[2] = texvec[2] + noise_fac * turb;
672   }
673
674   /* BVH query with the potentially perturbed coordinates */
675   num = BLI_bvhtree_range_query(pd->point_tree, co, pd->radius, accum_density, &pdr);
676   if (num > 0) {
677     age /= num;
678     mul_v3_fl(vec, 1.0f / num);
679     mul_v3_fl(col, 1.0f / num);
680   }
681
682   texres->tin = density;
683   if (r_age != NULL) {
684     *r_age = age;
685   }
686   if (r_vec != NULL) {
687     copy_v3_v3(r_vec, vec);
688   }
689   if (r_col != NULL) {
690     copy_v3_v3(r_col, col);
691   }
692
693   return retval;
694 }
695
696 static void pointdensity_color(
697     PointDensity *pd, TexResult *texres, float age, const float vec[3], const float col[3])
698 {
699   texres->tr = texres->tg = texres->tb = texres->ta = 1.0f;
700
701   if (pd->source == TEX_PD_PSYS) {
702     float rgba[4];
703
704     switch (pd->color_source) {
705       case TEX_PD_COLOR_PARTAGE:
706         if (pd->coba) {
707           if (BKE_colorband_evaluate(pd->coba, age, rgba)) {
708             texres->talpha = true;
709             copy_v3_v3(&texres->tr, rgba);
710             texres->tin *= rgba[3];
711             texres->ta = texres->tin;
712           }
713         }
714         break;
715       case TEX_PD_COLOR_PARTSPEED: {
716         float speed = len_v3(vec) * pd->speed_scale;
717
718         if (pd->coba) {
719           if (BKE_colorband_evaluate(pd->coba, speed, rgba)) {
720             texres->talpha = true;
721             copy_v3_v3(&texres->tr, rgba);
722             texres->tin *= rgba[3];
723             texres->ta = texres->tin;
724           }
725         }
726         break;
727       }
728       case TEX_PD_COLOR_PARTVEL:
729         texres->talpha = true;
730         mul_v3_v3fl(&texres->tr, vec, pd->speed_scale);
731         texres->ta = texres->tin;
732         break;
733       case TEX_PD_COLOR_CONSTANT:
734       default:
735         break;
736     }
737   }
738   else {
739     float rgba[4];
740
741     switch (pd->ob_color_source) {
742       case TEX_PD_COLOR_VERTCOL:
743         texres->talpha = true;
744         copy_v3_v3(&texres->tr, col);
745         texres->ta = texres->tin;
746         break;
747       case TEX_PD_COLOR_VERTWEIGHT:
748         texres->talpha = true;
749         if (pd->coba && BKE_colorband_evaluate(pd->coba, col[0], rgba)) {
750           copy_v3_v3(&texres->tr, rgba);
751           texres->tin *= rgba[3];
752         }
753         else {
754           copy_v3_v3(&texres->tr, col);
755         }
756         texres->ta = texres->tin;
757         break;
758       case TEX_PD_COLOR_VERTNOR:
759         texres->talpha = true;
760         copy_v3_v3(&texres->tr, col);
761         texres->ta = texres->tin;
762         break;
763       case TEX_PD_COLOR_CONSTANT:
764       default:
765         break;
766     }
767   }
768 }
769
770 static void sample_dummy_point_density(int resolution, float *values)
771 {
772   memset(values, 0, sizeof(float) * 4 * resolution * resolution * resolution);
773 }
774
775 static void particle_system_minmax(Depsgraph *depsgraph,
776                                    Scene *scene,
777                                    Object *object,
778                                    ParticleSystem *psys,
779                                    float radius,
780                                    float min[3],
781                                    float max[3])
782 {
783   const float size[3] = {radius, radius, radius};
784   const float cfra = BKE_scene_frame_get(scene);
785   ParticleSettings *part = psys->part;
786   ParticleSimulationData sim = {NULL};
787   ParticleData *pa = NULL;
788   int i;
789   int total_particles;
790   float mat[4][4], imat[4][4];
791
792   INIT_MINMAX(min, max);
793   if (part->type == PART_HAIR) {
794     /* TOOD(sergey): Not supported currently. */
795     return;
796   }
797
798   unit_m4(mat);
799
800   sim.depsgraph = depsgraph;
801   sim.scene = scene;
802   sim.ob = object;
803   sim.psys = psys;
804   sim.psmd = psys_get_modifier(object, psys);
805
806   invert_m4_m4(imat, object->obmat);
807   total_particles = psys->totpart + psys->totchild;
808   psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
809
810   for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) {
811     float co_object[3], co_min[3], co_max[3];
812     ParticleKey state;
813     state.time = cfra;
814     if (!psys_get_particle_state(&sim, i, &state, 0)) {
815       continue;
816     }
817     mul_v3_m4v3(co_object, imat, state.co);
818     sub_v3_v3v3(co_min, co_object, size);
819     add_v3_v3v3(co_max, co_object, size);
820     minmax_v3v3_v3(min, max, co_min);
821     minmax_v3v3_v3(min, max, co_max);
822   }
823
824   if (psys->lattice_deform_data) {
825     end_latt_deform(psys->lattice_deform_data);
826     psys->lattice_deform_data = NULL;
827   }
828 }
829
830 void RE_point_density_cache(struct Depsgraph *depsgraph, PointDensity *pd)
831 {
832   Scene *scene = DEG_get_evaluated_scene(depsgraph);
833
834   /* Same matricies/resolution as dupli_render_particle_set(). */
835   BLI_mutex_lock(&sample_mutex);
836   cache_pointdensity(depsgraph, scene, pd);
837   BLI_mutex_unlock(&sample_mutex);
838 }
839
840 void RE_point_density_minmax(struct Depsgraph *depsgraph,
841                              struct PointDensity *pd,
842                              float r_min[3],
843                              float r_max[3])
844 {
845   Scene *scene = DEG_get_evaluated_scene(depsgraph);
846   Object *object = pd->object;
847   if (object == NULL) {
848     zero_v3(r_min);
849     zero_v3(r_max);
850     return;
851   }
852   if (pd->source == TEX_PD_PSYS) {
853     ParticleSystem *psys;
854
855     if (pd->psys == 0) {
856       zero_v3(r_min);
857       zero_v3(r_max);
858       return;
859     }
860     psys = BLI_findlink(&object->particlesystem, pd->psys - 1);
861     if (psys == NULL) {
862       zero_v3(r_min);
863       zero_v3(r_max);
864       return;
865     }
866
867     particle_system_minmax(depsgraph, scene, object, psys, pd->radius, r_min, r_max);
868   }
869   else {
870     float radius[3] = {pd->radius, pd->radius, pd->radius};
871     BoundBox *bb = BKE_object_boundbox_get(object);
872
873     if (bb != NULL) {
874       BLI_assert((bb->flag & BOUNDBOX_DIRTY) == 0);
875       copy_v3_v3(r_min, bb->vec[0]);
876       copy_v3_v3(r_max, bb->vec[6]);
877       /* Adjust texture space to include density points on the boundaries. */
878       sub_v3_v3(r_min, radius);
879       add_v3_v3(r_max, radius);
880     }
881     else {
882       zero_v3(r_min);
883       zero_v3(r_max);
884     }
885   }
886 }
887
888 typedef struct SampleCallbackData {
889   PointDensity *pd;
890   int resolution;
891   float *min, *dim;
892   float *values;
893 } SampleCallbackData;
894
895 static void point_density_sample_func(void *__restrict data_v,
896                                       const int iter,
897                                       const ParallelRangeTLS *__restrict UNUSED(tls))
898 {
899   SampleCallbackData *data = (SampleCallbackData *)data_v;
900
901   const int resolution = data->resolution;
902   const int resolution2 = resolution * resolution;
903   const float *min = data->min, *dim = data->dim;
904   PointDensity *pd = data->pd;
905   float *values = data->values;
906
907   if (!pd || !pd->point_tree) {
908     return;
909   }
910
911   size_t z = (size_t)iter;
912   for (size_t y = 0; y < resolution; ++y) {
913     for (size_t x = 0; x < resolution; ++x) {
914       size_t index = z * resolution2 + y * resolution + x;
915       float texvec[3];
916       float age, vec[3], col[3];
917       TexResult texres;
918
919       copy_v3_v3(texvec, min);
920       texvec[0] += dim[0] * (float)x / (float)resolution;
921       texvec[1] += dim[1] * (float)y / (float)resolution;
922       texvec[2] += dim[2] * (float)z / (float)resolution;
923
924       pointdensity(pd, texvec, &texres, vec, &age, col);
925       pointdensity_color(pd, &texres, age, vec, col);
926
927       copy_v3_v3(&values[index * 4 + 0], &texres.tr);
928       values[index * 4 + 3] = texres.tin;
929     }
930   }
931 }
932
933 /* NOTE 1: Requires RE_point_density_cache() to be called first.
934  * NOTE 2: Frees point density structure after sampling.
935  */
936 void RE_point_density_sample(Depsgraph *depsgraph,
937                              PointDensity *pd,
938                              const int resolution,
939                              float *values)
940 {
941   Object *object = pd->object;
942   float min[3], max[3], dim[3];
943
944   /* TODO(sergey): Implement some sort of assert() that point density
945    * was cached already.
946    */
947
948   if (object == NULL) {
949     sample_dummy_point_density(resolution, values);
950     return;
951   }
952
953   BLI_mutex_lock(&sample_mutex);
954   RE_point_density_minmax(depsgraph, pd, min, max);
955   BLI_mutex_unlock(&sample_mutex);
956   sub_v3_v3v3(dim, max, min);
957   if (dim[0] <= 0.0f || dim[1] <= 0.0f || dim[2] <= 0.0f) {
958     sample_dummy_point_density(resolution, values);
959     return;
960   }
961
962   SampleCallbackData data;
963   data.pd = pd;
964   data.resolution = resolution;
965   data.min = min;
966   data.dim = dim;
967   data.values = values;
968   ParallelRangeSettings settings;
969   BLI_parallel_range_settings_defaults(&settings);
970   settings.use_threading = (resolution > 32);
971   BLI_task_parallel_range(0, resolution, &data, point_density_sample_func, &settings);
972
973   free_pointdensity(pd);
974 }
975
976 void RE_point_density_free(struct PointDensity *pd)
977 {
978   free_pointdensity(pd);
979 }
980
981 void RE_point_density_fix_linking(void)
982 {
983 }